mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-09-22 17:20:05 +00:00
Compare commits
16
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b8a9949649 | ||
|
|
8948206661 | ||
|
|
ec7600cac8 | ||
|
|
af26066f68 | ||
|
|
841cf3d1aa | ||
|
|
d3fcd77a1a | ||
|
|
020444a540 | ||
|
|
2c98c5e970 | ||
|
|
9bd2f8aa1c | ||
|
|
c93638ce1c | ||
|
|
e7243a2c28 | ||
|
|
1318aad83b | ||
|
|
7013797369 | ||
|
|
81fb7a40a3 | ||
|
|
dd43fd2564 | ||
|
|
c8723613df |
@@ -5,6 +5,11 @@ currently only supports local-machine Windows x64 debugging with PDBs, with
|
||||
plans to expand and port in the future. In the future we'll expand to also
|
||||
support native Linux debugging and DWARF debug info.
|
||||
|
||||
The RAD Debugger is currently in *ALPHA*. In order to get the debugger bullet-
|
||||
proof, it'd greatly help out if you submitted the issues you find here, along
|
||||
with any information you can gather, like dump files (along with the build you
|
||||
used), instructions to reproduce, test executables, and so on.
|
||||
|
||||
You can download pre-built binaries for the debugger
|
||||
[here](https://github.com/EpicGames/raddebugger/releases).
|
||||
|
||||
@@ -13,8 +18,10 @@ unifying the underlying debug info format. In that pursuit we've built
|
||||
the RADDBG debug info format, which is what the debugger parses and uses. To
|
||||
work with existing toolchains, we convert PDB (and eventually PE/ELF files
|
||||
with embedded DWARF) into the RADDBG format on-demand. This conversion process
|
||||
is currently unoptimized but quite fast for smaller PDB files (in many cases
|
||||
faster than many other programs simply deserialize the PDBs).
|
||||
is currently an unoptimized reference version. Nevertheless it's still quite
|
||||
fast for smaller PDB files (in many cases faster than many other programs
|
||||
simply deserialize the PDBs). It is much slower for much larger projects at the
|
||||
moment, but we expect this will vastly improve overtime.
|
||||
|
||||
The RADDBG format is currently specified in code, in the files within the
|
||||
`src/raddbg_format` folder. The other relevant folders for working with the
|
||||
@@ -78,9 +85,12 @@ build
|
||||
You should see the following output:
|
||||
|
||||
```
|
||||
[debug mode]
|
||||
[msvc compile]
|
||||
[default mode, assuming `raddbg` build]
|
||||
metagen_main.c
|
||||
searching path/to/codebase/src... 591 files found
|
||||
parsing metadesk... 25 metadesk files parsed
|
||||
searching C:\devel\raddebugger/src... 299 files found
|
||||
parsing metadesk... 12 metadesk files parsed
|
||||
gathering tables... 37 tables found
|
||||
generating layer code...
|
||||
raddbg.cpp
|
||||
|
||||
@@ -43,12 +43,12 @@ if "%asan%"=="1" set auto_compile_flags=%auto_compile_flags% -fsanitize=add
|
||||
:: --- Compile/Link Line Definitions ------------------------------------------
|
||||
set cl_common= /I..\src\ /I..\local\ /nologo /FC /Z7 /MP
|
||||
set clang_common= -I..\src\ -I..\local\ -maes -mssse3 -msse4 -gcodeview -fdiagnostics-absolute-paths -Wall -Wno-missing-braces -Wno-unused-function -Wno-writable-strings -Wno-unused-value -Wno-unused-variable -Wno-unused-local-typedef -Wno-deprecated-register -Wno-deprecated-declarations -Wno-unused-but-set-variable -Wno-single-bit-bitfield-constant-conversion -Xclang -flto-visibility-public-std -D_USE_MATH_DEFINES -Dstrdup=_strdup -Dgnu_printf=printf
|
||||
set cl_debug= cl /Od /D_DEBUG %cl_common%
|
||||
set cl_release= cl /O2 /DNDEBUG %cl_common%
|
||||
set clang_debug= clang -g -O0 /D_DEBUG %clang_common%
|
||||
set clang_release= clang -g -O3 /DNDEBUG %clang_common%
|
||||
set cl_link= /link /natvis:%~dp0\src\natvis\base.natvis
|
||||
set clang_link= -Xlinker /natvis:%~dp0\src\natvis\base.natvis
|
||||
set cl_debug= call cl /Od /D_DEBUG %cl_common%
|
||||
set cl_release= call cl /O2 /DNDEBUG %cl_common%
|
||||
set clang_debug= call clang -g -O0 /D_DEBUG %clang_common%
|
||||
set clang_release= call clang -g -O3 /DNDEBUG %clang_common%
|
||||
set cl_link= /link /natvis:"%~dp0\src\natvis\base.natvis"
|
||||
set clang_link= -Xlinker /natvis:"%~dp0\src\natvis\base.natvis"
|
||||
set cl_out= /out:
|
||||
set clang_out= -o
|
||||
|
||||
|
||||
@@ -1516,6 +1516,7 @@ ctrl_thread__next_demon_event(Arena *arena, CTRL_Msg *msg, DEMON_RunCtrls *run_c
|
||||
out_evt->stack_base = demon_stack_base_vaddr_from_thread(event->thread);
|
||||
out_evt->tls_root = demon_tls_root_vaddr_from_thread(event->thread);
|
||||
out_evt->rip_vaddr = event->instruction_pointer;
|
||||
out_evt->string = event->string;
|
||||
}break;
|
||||
case DEMON_EventKind_LoadModule:
|
||||
{
|
||||
|
||||
+1
-1
@@ -653,7 +653,7 @@ dbgi_parse_thread_entry_point(void *p)
|
||||
}
|
||||
if(os_now_microseconds()-start_wait_t > 10000000 && og_dbg_props.size < MB(64))
|
||||
{
|
||||
os_graphical_message(1, str8_lit("RADDBG INTERNAL DEVELOPMENT MESSAGE"), str8_lit("this is taking a while... indicative of something that seemed like a bug that Jeff hit before. attach with debugger now & see where the callstack is?"));
|
||||
// os_graphical_message(1, str8_lit("RADDBG INTERNAL DEVELOPMENT MESSAGE"), str8_lit("this is taking a while... indicative of something that seemed like a bug that Jeff hit before. attach with debugger now & see where the callstack is?"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
////////////////////////////////
|
||||
//~ rjf: Globals
|
||||
|
||||
global GetThreadDescriptionFunctionType *demon_w32_GetThreadDescription = 0;
|
||||
|
||||
global B32 demon_w32_resume_needed = 0;
|
||||
global DWORD demon_w32_resume_pid = 0;
|
||||
global DWORD demon_w32_resume_tid = 0;
|
||||
@@ -26,6 +28,17 @@ global String8List demon_w32_environment = {0};
|
||||
////////////////////////////////
|
||||
//~ rjf: Helpers
|
||||
|
||||
internal U64
|
||||
demon_w32_hash_from_string(String8 string)
|
||||
{
|
||||
U64 result = 5381;
|
||||
for(U64 i = 0; i < string.size; i += 1)
|
||||
{
|
||||
result = ((result << 5) + result) + string.str[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal DEMON_W32_Ext*
|
||||
demon_w32_ext_alloc(void){
|
||||
DEMON_W32_Ext *result = demon_w32_proc_ext_free;
|
||||
@@ -351,6 +364,11 @@ demon_os_init(void){
|
||||
demon_w32_ext_arena = arena_alloc();
|
||||
demon_w32_detach_proc_arena = arena_alloc();
|
||||
|
||||
// rjf: load Windows 10+ GetThreadDescription API
|
||||
{
|
||||
demon_w32_GetThreadDescription = (GetThreadDescriptionFunctionType *)GetProcAddress(GetModuleHandleA("Kernel32.dll"), "GetThreadDescription");
|
||||
}
|
||||
|
||||
// rjf: setup environment variables
|
||||
{
|
||||
CHAR *this_proc_env = GetEnvironmentStrings();
|
||||
@@ -771,6 +789,19 @@ demon_os_run(Arena *arena, DEMON_OS_RunCtrls *ctrls){
|
||||
DWORD sus_result = SuspendThread(thread_ext->thread.handle);
|
||||
(void)sus_result;
|
||||
|
||||
// rjf: unpack thread name
|
||||
String8 thread_name = {0};
|
||||
if(demon_w32_GetThreadDescription != 0)
|
||||
{
|
||||
WCHAR *thread_name_w = 0;
|
||||
HRESULT hr = demon_w32_GetThreadDescription(evt.u.CreateThread.hThread, &thread_name_w);
|
||||
if(SUCCEEDED(hr))
|
||||
{
|
||||
thread_name = str8_from_16(arena, str16_cstring((U16 *)thread_name_w));
|
||||
LocalFree(thread_name_w);
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: determine if this is the halter thread
|
||||
B32 is_halter = (evt.dwThreadId == demon_w32_halter_thread_id);
|
||||
|
||||
@@ -780,6 +811,7 @@ demon_os_run(Arena *arena, DEMON_OS_RunCtrls *ctrls){
|
||||
e->process = demon_ent_handle_from_ptr(process);
|
||||
e->thread = demon_ent_handle_from_ptr(thread);
|
||||
e->code = evt.dwThreadId;
|
||||
e->string = thread_name;
|
||||
}
|
||||
}
|
||||
}break;
|
||||
@@ -1140,6 +1172,48 @@ demon_os_run(Arena *arena, DEMON_OS_RunCtrls *ctrls){
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: gather new thread-names
|
||||
if(demon_w32_GetThreadDescription != 0)
|
||||
{
|
||||
for(DEMON_Entity *process = demon_ent_root->first;
|
||||
process != 0;
|
||||
process = process->next)
|
||||
{
|
||||
if(process->kind != DEMON_EntityKind_Process) { continue; }
|
||||
for(DEMON_Entity *thread = process->first;
|
||||
thread != 0;
|
||||
thread = thread->next)
|
||||
{
|
||||
if(thread->kind != DEMON_EntityKind_Thread) { continue; }
|
||||
DEMON_W32_Ext *thread_ext = demon_w32_ext(thread);
|
||||
if(thread_ext->thread.last_name_hash == 0 ||
|
||||
thread_ext->thread.name_gather_time_us+1000000 <= os_now_microseconds())
|
||||
{
|
||||
String8 name = {0};
|
||||
{
|
||||
WCHAR *thread_name_w = 0;
|
||||
HRESULT hr = demon_w32_GetThreadDescription(thread_ext->thread.handle, &thread_name_w);
|
||||
if(SUCCEEDED(hr))
|
||||
{
|
||||
name = str8_from_16(scratch.arena, str16_cstring((U16 *)thread_name_w));
|
||||
LocalFree(thread_name_w);
|
||||
}
|
||||
}
|
||||
U64 name_hash = demon_w32_hash_from_string(name);
|
||||
if(name.size != 0 && name_hash != thread_ext->thread.last_name_hash)
|
||||
{
|
||||
DEMON_Event *e = demon_push_event(arena, &result, DEMON_EventKind_SetThreadName);
|
||||
e->process = demon_ent_handle_from_ptr(process);
|
||||
e->thread = demon_ent_handle_from_ptr(thread);
|
||||
e->string = push_str8_copy(arena, name);
|
||||
}
|
||||
thread_ext->thread.name_gather_time_us = os_now_microseconds();
|
||||
thread_ext->thread.last_name_hash = name_hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(allen): handle errors? if (!got_new_event) ? if (!good_state) ?
|
||||
|
||||
// TODO(allen): per-Architecture
|
||||
|
||||
@@ -35,6 +35,8 @@ union DEMON_W32_Ext
|
||||
struct{
|
||||
HANDLE handle;
|
||||
U64 thread_local_base;
|
||||
U64 last_name_hash;
|
||||
U64 name_gather_time_us;
|
||||
} thread;
|
||||
struct{
|
||||
HANDLE handle;
|
||||
@@ -68,6 +70,7 @@ struct DEMON_W32_EntityNode
|
||||
DEMON_Entity *entity;
|
||||
};
|
||||
|
||||
typedef HRESULT GetThreadDescriptionFunctionType(HANDLE hThread, WCHAR **ppszThreadDescription);
|
||||
|
||||
////////////////////////////////
|
||||
//~ NOTE(allen): Win32 Demon Exceptions
|
||||
@@ -352,6 +355,7 @@ struct DEMON_PeOptionalHeader32Plus
|
||||
////////////////////////////////
|
||||
//~ rjf: Helpers
|
||||
|
||||
internal U64 demon_w32_hash_from_string(String8 string);
|
||||
internal DEMON_W32_Ext* demon_w32_ext_alloc(void);
|
||||
internal DEMON_W32_Ext* demon_w32_ext(DEMON_Entity *entity);
|
||||
|
||||
|
||||
+82
-3
@@ -1852,6 +1852,7 @@ df_entity_change_parent(DF_StateDeltaHistory *hist, DF_Entity *entity, DF_Entity
|
||||
internal void
|
||||
df_entity_equip_txt_pt(DF_Entity *entity, TxtPt point)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->text_point = point;
|
||||
entity->flags |= DF_EntityFlag_HasTextPoint;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -1860,6 +1861,7 @@ df_entity_equip_txt_pt(DF_Entity *entity, TxtPt point)
|
||||
internal void
|
||||
df_entity_equip_txt_pt_alt(DF_Entity *entity, TxtPt point)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->text_point_alt = point;
|
||||
entity->flags |= DF_EntityFlag_HasTextPointAlt;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -1868,6 +1870,7 @@ df_entity_equip_txt_pt_alt(DF_Entity *entity, TxtPt point)
|
||||
internal void
|
||||
df_entity_equip_entity_handle(DF_Entity *entity, DF_Handle handle)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->entity_handle = handle;
|
||||
entity->flags |= DF_EntityFlag_HasEntityHandle;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -1876,6 +1879,7 @@ df_entity_equip_entity_handle(DF_Entity *entity, DF_Handle handle)
|
||||
internal void
|
||||
df_entity_equip_b32(DF_Entity *entity, B32 b32)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->b32 = b32;
|
||||
entity->flags |= DF_EntityFlag_HasB32;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -1884,6 +1888,7 @@ df_entity_equip_b32(DF_Entity *entity, B32 b32)
|
||||
internal void
|
||||
df_entity_equip_u64(DF_Entity *entity, U64 u64)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->u64 = u64;
|
||||
entity->flags |= DF_EntityFlag_HasU64;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -1892,6 +1897,7 @@ df_entity_equip_u64(DF_Entity *entity, U64 u64)
|
||||
internal void
|
||||
df_entity_equip_rng1u64(DF_Entity *entity, Rng1U64 range)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->rng1u64 = range;
|
||||
entity->flags |= DF_EntityFlag_HasRng1U64;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -1900,6 +1906,7 @@ df_entity_equip_rng1u64(DF_Entity *entity, Rng1U64 range)
|
||||
internal void
|
||||
df_entity_equip_color_rgba(DF_Entity *entity, Vec4F32 rgba)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
Vec3F32 rgb = v3f32(rgba.x, rgba.y, rgba.z);
|
||||
Vec3F32 hsv = hsv_from_rgb(rgb);
|
||||
Vec4F32 hsva = v4f32(hsv.x, hsv.y, hsv.z, rgba.w);
|
||||
@@ -1909,6 +1916,7 @@ df_entity_equip_color_rgba(DF_Entity *entity, Vec4F32 rgba)
|
||||
internal void
|
||||
df_entity_equip_color_hsva(DF_Entity *entity, Vec4F32 hsva)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->color_hsva = hsva;
|
||||
entity->flags |= DF_EntityFlag_HasColor;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -1917,6 +1925,7 @@ df_entity_equip_color_hsva(DF_Entity *entity, Vec4F32 hsva)
|
||||
internal void
|
||||
df_entity_equip_death_timer(DF_Entity *entity, F32 seconds_til_death)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->flags |= DF_EntityFlag_DiesWithTime;
|
||||
entity->life_left = seconds_til_death;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -1925,6 +1934,7 @@ df_entity_equip_death_timer(DF_Entity *entity, F32 seconds_til_death)
|
||||
internal void
|
||||
df_entity_equip_cfg_src(DF_Entity *entity, DF_CfgSrc cfg_src)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->cfg_src = cfg_src;
|
||||
df_entity_notify_mutation(entity);
|
||||
}
|
||||
@@ -1934,6 +1944,7 @@ df_entity_equip_cfg_src(DF_Entity *entity, DF_CfgSrc cfg_src)
|
||||
internal void
|
||||
df_entity_equip_ctrl_machine_id(DF_Entity *entity, CTRL_MachineID machine_id)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->ctrl_machine_id = machine_id;
|
||||
entity->flags |= DF_EntityFlag_HasCtrlMachineID;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -1942,6 +1953,7 @@ df_entity_equip_ctrl_machine_id(DF_Entity *entity, CTRL_MachineID machine_id)
|
||||
internal void
|
||||
df_entity_equip_ctrl_handle(DF_Entity *entity, CTRL_Handle handle)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->ctrl_handle = handle;
|
||||
entity->flags |= DF_EntityFlag_HasCtrlHandle;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -1950,6 +1962,7 @@ df_entity_equip_ctrl_handle(DF_Entity *entity, CTRL_Handle handle)
|
||||
internal void
|
||||
df_entity_equip_arch(DF_Entity *entity, Architecture arch)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->arch = arch;
|
||||
entity->flags |= DF_EntityFlag_HasArch;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -1958,6 +1971,7 @@ df_entity_equip_arch(DF_Entity *entity, Architecture arch)
|
||||
internal void
|
||||
df_entity_equip_ctrl_id(DF_Entity *entity, U32 id)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->ctrl_id = id;
|
||||
entity->flags |= DF_EntityFlag_HasCtrlID;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -1966,6 +1980,7 @@ df_entity_equip_ctrl_id(DF_Entity *entity, U32 id)
|
||||
internal void
|
||||
df_entity_equip_stack_base(DF_Entity *entity, U64 stack_base)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->stack_base = stack_base;
|
||||
entity->flags |= DF_EntityFlag_HasStackBase;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -1974,6 +1989,7 @@ df_entity_equip_stack_base(DF_Entity *entity, U64 stack_base)
|
||||
internal void
|
||||
df_entity_equip_tls_root(DF_Entity *entity, U64 tls_root)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->tls_root = tls_root;
|
||||
entity->flags |= DF_EntityFlag_HasTLSRoot;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -1982,6 +1998,7 @@ df_entity_equip_tls_root(DF_Entity *entity, U64 tls_root)
|
||||
internal void
|
||||
df_entity_equip_vaddr_rng(DF_Entity *entity, Rng1U64 range)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->vaddr_rng = range;
|
||||
entity->flags |= DF_EntityFlag_HasVAddrRng;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -1990,6 +2007,7 @@ df_entity_equip_vaddr_rng(DF_Entity *entity, Rng1U64 range)
|
||||
internal void
|
||||
df_entity_equip_vaddr(DF_Entity *entity, U64 vaddr)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
entity->vaddr = vaddr;
|
||||
entity->flags |= DF_EntityFlag_HasVAddr;
|
||||
df_entity_notify_mutation(entity);
|
||||
@@ -1999,8 +2017,20 @@ df_entity_equip_vaddr(DF_Entity *entity, U64 vaddr)
|
||||
|
||||
internal void
|
||||
df_entity_equip_name(DF_StateDeltaHistory *hist, DF_Entity *entity, String8 name)
|
||||
{
|
||||
df_require_entity_nonnil(entity, return);
|
||||
if(entity->name.size != 0)
|
||||
{
|
||||
df_name_release(hist, entity->name);
|
||||
}
|
||||
if(name.size != 0)
|
||||
{
|
||||
entity->name = df_name_alloc(hist, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
entity->name = str8_zero();
|
||||
}
|
||||
entity->name_generation += 1;
|
||||
df_entity_notify_mutation(entity);
|
||||
}
|
||||
@@ -7094,34 +7124,61 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt)
|
||||
case DF_CoreCmdKind_LoadUser:
|
||||
case DF_CoreCmdKind_LoadProfile:
|
||||
{
|
||||
String8 new_path = params.file_path;
|
||||
B32 load_cfg[DF_CfgSrc_COUNT] = {0};
|
||||
for(DF_CfgSrc src = (DF_CfgSrc)0; src < DF_CfgSrc_COUNT; src = (DF_CfgSrc)(src+1))
|
||||
{
|
||||
load_cfg[src] = (core_cmd_kind == df_g_cfg_src_load_cmd_kind_table[src]);
|
||||
}
|
||||
|
||||
//- rjf: normalize path
|
||||
String8 new_path = path_normalized_from_string(scratch.arena, params.file_path);
|
||||
|
||||
//- rjf: path -> data
|
||||
FileProperties props = {0};
|
||||
String8 data = {0};
|
||||
{
|
||||
OS_Handle file = os_file_open(OS_AccessFlag_Shared|OS_AccessFlag_Read, new_path);
|
||||
props = os_properties_from_file(file);
|
||||
data = os_string_from_file_range(scratch.arena, file, r1u64(0, props.size));
|
||||
os_file_close(file);
|
||||
}
|
||||
|
||||
//- rjf: investigate file path/data
|
||||
B32 file_is_okay = 1;
|
||||
if(props.modified != 0 && data.size != 0 && !str8_match(str8_prefix(data, 9), str8_lit("// raddbg"), 0))
|
||||
{
|
||||
file_is_okay = 0;
|
||||
}
|
||||
|
||||
//- rjf: set new config paths
|
||||
if(file_is_okay)
|
||||
{
|
||||
for(DF_CfgSrc src = (DF_CfgSrc)0; src < DF_CfgSrc_COUNT; src = (DF_CfgSrc)(src+1))
|
||||
{
|
||||
if(load_cfg[src])
|
||||
{
|
||||
arena_clear(df_state->cfg_path_arenas[src]);
|
||||
df_state->cfg_paths[src] = path_normalized_from_string(df_state->cfg_path_arenas[src], params.file_path);
|
||||
df_state->cfg_paths[src] = push_str8_copy(df_state->cfg_path_arenas[src], new_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: get config files
|
||||
DF_Entity *cfg_files[DF_CfgSrc_COUNT] = {0};
|
||||
if(file_is_okay)
|
||||
{
|
||||
for(DF_CfgSrc src = (DF_CfgSrc)0; src < DF_CfgSrc_COUNT; src = (DF_CfgSrc)(src+1))
|
||||
{
|
||||
String8 path = df_cfg_path_from_src(src);
|
||||
cfg_files[src] = df_entity_from_path(path, DF_EntityFromPathFlag_OpenMissing|DF_EntityFromPathFlag_OpenAsNeeded);
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: load files
|
||||
String8 cfg_data[DF_CfgSrc_COUNT] = {0};
|
||||
U64 cfg_timestamps[DF_CfgSrc_COUNT] = {0};
|
||||
if(file_is_okay)
|
||||
{
|
||||
for(DF_CfgSrc src = (DF_CfgSrc)0; src < DF_CfgSrc_COUNT; src = (DF_CfgSrc)(src+1))
|
||||
{
|
||||
DF_Entity *file_entity = cfg_files[src];
|
||||
@@ -7136,22 +7193,29 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt)
|
||||
}
|
||||
os_file_close(file);
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: determine if we need to save config
|
||||
B32 cfg_save[DF_CfgSrc_COUNT] = {0};
|
||||
if(file_is_okay)
|
||||
{
|
||||
for(DF_CfgSrc src = (DF_CfgSrc)0; src < DF_CfgSrc_COUNT; src = (DF_CfgSrc)(src+1))
|
||||
{
|
||||
cfg_save[src] = (load_cfg[src] && cfg_files[src]->flags & DF_EntityFlag_IsMissing);
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: determine if we need to reload config
|
||||
B32 cfg_load[DF_CfgSrc_COUNT] = {0};
|
||||
B32 cfg_load_any = 0;
|
||||
if(file_is_okay)
|
||||
{
|
||||
for(DF_CfgSrc src = (DF_CfgSrc)0; src < DF_CfgSrc_COUNT; src = (DF_CfgSrc)(src+1))
|
||||
{
|
||||
cfg_load[src] = (load_cfg[src] && ((cfg_save[src] == 0 && df_state->cfg_cached_timestamp[src] != cfg_timestamps[src]) || cfg_files[src]->timestamp == 0));
|
||||
cfg_load[src] = (load_cfg[src] && cfg_timestamps[src] != 0 && ((cfg_save[src] == 0 && df_state->cfg_cached_timestamp[src] != cfg_timestamps[src]) || cfg_files[src]->timestamp == 0));
|
||||
cfg_load_any = cfg_load_any || cfg_load[src];
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: load => build new config table
|
||||
if(cfg_load_any)
|
||||
@@ -7169,6 +7233,8 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt)
|
||||
// NOTE(rjf): must happen before `save`. we need to create a default before saving, which
|
||||
// occurs in the 'apply' path.
|
||||
//
|
||||
if(file_is_okay)
|
||||
{
|
||||
for(DF_CfgSrc src = (DF_CfgSrc)0; src < DF_CfgSrc_COUNT; src = (DF_CfgSrc)(src+1))
|
||||
{
|
||||
if(cfg_load[src])
|
||||
@@ -7179,8 +7245,11 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt)
|
||||
df_state->cfg_cached_timestamp[src] = cfg_timestamps[src];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: save => dispatch write
|
||||
if(file_is_okay)
|
||||
{
|
||||
for(DF_CfgSrc src = (DF_CfgSrc)0; src < DF_CfgSrc_COUNT; src = (DF_CfgSrc)(src+1))
|
||||
{
|
||||
if(cfg_save[src])
|
||||
@@ -7190,6 +7259,16 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt)
|
||||
df_cmd_list_push(arena, cmds, ¶ms, df_cmd_spec_from_core_cmd_kind(cmd_kind));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: bad file -> alert user
|
||||
if(!file_is_okay)
|
||||
{
|
||||
DF_CmdParams p = params;
|
||||
p.string = push_str8f(scratch.arena, "\"%S\" appears to refer to an existing file which is not a RADDBG config file. This would overwrite the file.", new_path);
|
||||
df_cmd_params_mark_slot(&p, DF_CmdParamSlot_String);
|
||||
df_cmd_list_push(arena, cmds, &p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_Error));
|
||||
}
|
||||
}break;
|
||||
|
||||
//- rjf: loading/applying stateful config changes
|
||||
|
||||
@@ -1355,6 +1355,7 @@ internal DF_CoreCmdKind df_core_cmd_kind_from_string(String8 string);
|
||||
|
||||
//- rjf: nil
|
||||
internal B32 df_entity_is_nil(DF_Entity *entity);
|
||||
#define df_require_entity_nonnil(entity, if_nil_stmts) do{if(df_entity_is_nil(entity)){if_nil_stmts;}}while(0)
|
||||
|
||||
//- rjf: handle <-> entity conversions
|
||||
internal U64 df_index_from_entity(DF_Entity *entity);
|
||||
|
||||
+45
-119
@@ -3222,6 +3222,7 @@ df_window_update_and_render(Arena *arena, OS_EventList *events, DF_Window *ws, D
|
||||
}
|
||||
avg_ui_hash_chain_length = chain_length_sum / chain_count;
|
||||
}
|
||||
ui_labelf("Target Hz: %.2f", 1.f/df_dt());
|
||||
ui_labelf("Ctrl Run Index: %I64u", ctrl_run_idx());
|
||||
ui_labelf("Window %p", window);
|
||||
ui_set_next_pref_width(ui_children_sum(1));
|
||||
@@ -4333,7 +4334,6 @@ df_window_update_and_render(Arena *arena, OS_EventList *events, DF_Window *ws, D
|
||||
{
|
||||
DF_CoreCmdKind cmds[] =
|
||||
{
|
||||
DF_CoreCmdKind_Commands,
|
||||
DF_CoreCmdKind_Targets,
|
||||
DF_CoreCmdKind_Scheduler,
|
||||
DF_CoreCmdKind_CallStack,
|
||||
@@ -4352,7 +4352,6 @@ df_window_update_and_render(Arena *arena, OS_EventList *events, DF_Window *ws, D
|
||||
};
|
||||
U32 codepoints[] =
|
||||
{
|
||||
'c',
|
||||
't',
|
||||
's',
|
||||
'k',
|
||||
@@ -4454,19 +4453,32 @@ df_window_update_and_render(Arena *arena, OS_EventList *events, DF_Window *ws, D
|
||||
UI_Key help_menu_key = ui_key_from_string(ui_key_zero(), str8_lit("_help_menu_key_"));
|
||||
UI_CtxMenu(help_menu_key) UI_PrefWidth(ui_em(40.f, 1.f))
|
||||
{
|
||||
ui_label(str8_lit_comp(RADDBG_TITLE_STRING_LITERAL));
|
||||
ui_spacer(ui_em(0.75f, 1.f));
|
||||
ui_label_multiline(ui_top_font_size()*30.f, str8_lit("If you run into issues, please send an email describing them to:"));
|
||||
UI_Row UI_TextAlignment(UI_TextAlign_Center) UI_TextColor(df_rgba_from_theme_color(DF_ThemeColor_WeakText)) ui_label(str8_lit_comp(RADDBG_TITLE_STRING_LITERAL));
|
||||
ui_spacer(ui_em(0.25f, 1.f));
|
||||
UI_Row
|
||||
UI_PrefWidth(ui_text_dim(10, 1))
|
||||
UI_TextAlignment(UI_TextAlign_Center)
|
||||
UI_Padding(ui_pct(1, 0))
|
||||
{
|
||||
ui_labelf("Search for commands by pressing ");
|
||||
DF_CmdSpec *spec = df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_Commands);
|
||||
UI_TextColor(df_rgba_from_theme_color(DF_ThemeColor_PlainText))
|
||||
UI_Flags(UI_BoxFlag_DrawBorder)
|
||||
UI_TextAlignment(UI_TextAlign_Center)
|
||||
df_cmd_binding_button(spec);
|
||||
}
|
||||
ui_spacer(ui_em(0.25f, 1.f));
|
||||
UI_Row UI_TextAlignment(UI_TextAlign_Center) ui_label(str8_lit("Submit issues to the GitHub at:"));
|
||||
UI_TextAlignment(UI_TextAlign_Center)
|
||||
{
|
||||
UI_Signal email_sig = ui_buttonf("ryan.fleury@epicgames.com");
|
||||
if(email_sig.hovering) UI_Tooltip
|
||||
UI_Signal url_sig = ui_buttonf("github.com/EpicGames/raddebugger");
|
||||
if(url_sig.hovering) UI_Tooltip
|
||||
{
|
||||
ui_labelf("Copy To Clipboard");
|
||||
}
|
||||
if(email_sig.clicked)
|
||||
if(url_sig.clicked)
|
||||
{
|
||||
os_set_clipboard_text(str8_lit("ryan.fleury@epicgames.com"));
|
||||
os_set_clipboard_text(str8_lit("https://github.com/EpicGames/raddebugger"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5632,7 +5644,6 @@ df_window_update_and_render(Arena *arena, OS_EventList *events, DF_Window *ws, D
|
||||
}
|
||||
UI_TextColor(df_rgba_from_theme_color(view_is_selected ? DF_ThemeColor_PlainText : DF_ThemeColor_WeakText))
|
||||
UI_PrefWidth(ui_pct(1, 0))
|
||||
UI_FontSize(ui_top_font_size()*(view_is_selected ? 1.f : 0.75f))
|
||||
ui_label(label);
|
||||
UI_PrefWidth(ui_em(2.35f, 1.f)) UI_TextAlignment(UI_TextAlign_Center)
|
||||
UI_Font(df_font_from_slot(DF_FontSlot_Icons))
|
||||
@@ -7737,84 +7748,6 @@ df_text_search_thread_entry_point(void *p)
|
||||
#endif
|
||||
}
|
||||
|
||||
internal DF_TextSearchMatchArray
|
||||
df_text_search_match_array_from_hash_needle(Arena *arena, U128 hash, String8 needle, DF_TextSliceFlags text_slice_flags, TxtPt start_pt)
|
||||
{
|
||||
// TODO(rjf): [ ] @de2ctrl text searching lookup -- wound up with DE_Hash
|
||||
DF_TextSearchMatchArray result = {0};
|
||||
{
|
||||
//- rjf: hash -> slot/stripe info
|
||||
U64 little_hash = df_text_search_little_hash_from_hash(hash);
|
||||
U64 slot_idx = little_hash%df_gfx_state->tsrch_slot_count;
|
||||
DF_TextSearchCacheSlot *slot = &df_gfx_state->tsrch_slots[slot_idx];
|
||||
U64 stripe_idx = slot_idx%df_gfx_state->tsrch_stripe_count;
|
||||
OS_Handle stripe_rw_mutex = df_gfx_state->tsrch_stripe_rw_mutexes[stripe_idx];
|
||||
|
||||
//- rjf: find matches from existing node
|
||||
B32 found_node = 0;
|
||||
{
|
||||
os_rw_mutex_take_r(stripe_rw_mutex);
|
||||
for(DF_TextSearchCacheNode *node = slot->first; node != 0; node = node->next)
|
||||
{
|
||||
if(MemoryMatchStruct(&node->hash, &hash) &&
|
||||
str8_match(node->needle, needle, StringMatchFlag_CaseInsensitive) &&
|
||||
node->flags == text_slice_flags)
|
||||
{
|
||||
found_node = 1;
|
||||
result = df_text_search_match_array_from_chunk_list(arena, &node->search_matches);
|
||||
U64 time_current_us = os_now_microseconds();
|
||||
ins_atomic_u64_eval_assign(&node->last_time_touched_us, time_current_us);
|
||||
break;
|
||||
}
|
||||
}
|
||||
os_rw_mutex_drop_r(stripe_rw_mutex);
|
||||
}
|
||||
|
||||
//- rjf: no existing node -> allocate new
|
||||
if(found_node == 0)
|
||||
{
|
||||
os_rw_mutex_take_w(stripe_rw_mutex);
|
||||
{
|
||||
Arena *node_arena = arena_alloc();
|
||||
DF_TextSearchCacheNode *node = push_array(node_arena, DF_TextSearchCacheNode, 1);
|
||||
node->arena = node_arena;
|
||||
node->hash = hash;
|
||||
node->needle = push_str8_copy(node_arena, needle);
|
||||
node->flags = text_slice_flags;
|
||||
node->start_pt = start_pt;
|
||||
DLLPushBack(slot->first, slot->last, node);
|
||||
}
|
||||
os_rw_mutex_drop_w(stripe_rw_mutex);
|
||||
os_condition_variable_signal(df_gfx_state->tsrch_wakeup_cv);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal DF_TextSearchMatchArray
|
||||
df_text_search_match_array_from_entity_needle(Arena *arena, DF_Entity *entity, String8 needle, DF_TextSliceFlags flags, TxtPt start_pt)
|
||||
{
|
||||
// TODO(rjf): [ ] @de2ctrl text search lookup
|
||||
DF_TextSearchMatchArray matches = {0};
|
||||
#if !DE2CTRL
|
||||
if(entity->kind == DF_EntityKind_File && needle.size != 0)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
String8 path = df_full_path_from_entity(scratch.arena, entity);
|
||||
DE_PipelineHint hint = zero_struct;
|
||||
DE_Key path2hash_key = de_key_path(DE_KeyFunc_HashFromPath, path, entity->timestamp);
|
||||
DE_Val *path2hash_val = de_user_peek_lookup(de_user, de_shared, &hint, &path2hash_key);
|
||||
DE_Hash hash = path2hash_val->hash;
|
||||
if(!de_hash_is_empty(&hash))
|
||||
{
|
||||
matches = df_text_search_match_array_from_hash_needle(arena, hash, needle, flags, start_pt);
|
||||
}
|
||||
scratch_end(scratch);
|
||||
}
|
||||
#endif
|
||||
return matches;
|
||||
}
|
||||
|
||||
internal int
|
||||
df_text_search_match_array_qsort_compare(TxtPt *a, TxtPt *b)
|
||||
{
|
||||
@@ -8304,19 +8237,13 @@ df_cfg_strings_from_gfx(Arena *arena, String8 root_path, DF_CfgSrc source)
|
||||
|
||||
//- rjf: serialize fonts
|
||||
if(source == DF_CfgSrc_User)
|
||||
{
|
||||
String8 code_font_path_absolute = f_path_from_tag(df_gfx_state->cfg_font_tags[DF_FontSlot_Code]);
|
||||
String8 main_font_path_absolute = f_path_from_tag(df_gfx_state->cfg_font_tags[DF_FontSlot_Main]);
|
||||
String8 code_font_path_relative = path_relative_dst_from_absolute_dst_src(arena, code_font_path_absolute, root_path);
|
||||
String8 main_font_path_relative = path_relative_dst_from_absolute_dst_src(arena, main_font_path_absolute, root_path);
|
||||
{
|
||||
str8_list_push(arena, &strs, str8_lit("/// fonts /////////////////////////////////////////////////////////////////////\n"));
|
||||
str8_list_push(arena, &strs, str8_lit("\n"));
|
||||
str8_list_pushf(arena, &strs, "code_font: \"%S\"\n", code_font_path_relative);
|
||||
str8_list_pushf(arena, &strs, "main_font: \"%S\"\n", main_font_path_relative);
|
||||
str8_list_pushf(arena, &strs, "code_font: \"%S\"\n", df_gfx_state->cfg_code_font_path);
|
||||
str8_list_pushf(arena, &strs, "main_font: \"%S\"\n", df_gfx_state->cfg_main_font_path);
|
||||
str8_list_push(arena, &strs, str8_lit("\n"));
|
||||
}
|
||||
}
|
||||
|
||||
ProfEnd();
|
||||
return strs;
|
||||
@@ -10980,6 +10907,8 @@ df_gfx_init(OS_WindowRepaintFunctionType *window_repaint_entry_point, DF_StateDe
|
||||
df_gfx_state->cmd2view_slots = push_array(arena, DF_String2ViewSlot, df_gfx_state->cmd2view_slot_count);
|
||||
df_gfx_state->string_search_arena = arena_alloc();
|
||||
df_gfx_state->repaint_hook = window_repaint_entry_point;
|
||||
df_gfx_state->cfg_main_font_path_arena = arena_alloc();
|
||||
df_gfx_state->cfg_code_font_path_arena = arena_alloc();
|
||||
df_clear_bindings();
|
||||
|
||||
// rjf: register gfx layer views
|
||||
@@ -11002,20 +10931,6 @@ df_gfx_init(OS_WindowRepaintFunctionType *window_repaint_entry_point, DF_StateDe
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: set up background text searching thread
|
||||
{
|
||||
df_gfx_state->tsrch_slot_count = 64;
|
||||
df_gfx_state->tsrch_stripe_count = df_gfx_state->tsrch_slot_count/8;
|
||||
df_gfx_state->tsrch_slots = push_array(df_gfx_state->arena, DF_TextSearchCacheSlot, df_gfx_state->tsrch_slot_count);
|
||||
df_gfx_state->tsrch_stripe_rw_mutexes = push_array(df_gfx_state->arena, OS_Handle, df_gfx_state->tsrch_stripe_count);
|
||||
for(U64 stripe_idx = 0; stripe_idx < df_gfx_state->tsrch_stripe_count; stripe_idx += 1)
|
||||
{
|
||||
df_gfx_state->tsrch_stripe_rw_mutexes[stripe_idx] = os_rw_mutex_alloc();
|
||||
}
|
||||
df_gfx_state->tsrch_wakeup_mutex = os_mutex_alloc();
|
||||
df_gfx_state->tsrch_wakeup_cv = os_condition_variable_alloc();
|
||||
//df_gfx_state->tsrch_thread = os_launch_thread(df_text_search_thread_entry_point, 0, 0);
|
||||
}
|
||||
ProfEnd();
|
||||
}
|
||||
|
||||
@@ -11206,13 +11121,7 @@ df_gfx_begin_frame(Arena *arena, DF_CmdList *cmds)
|
||||
f_tag_from_static_data_string(&df_g_default_code_font_bytes),
|
||||
f_tag_from_static_data_string(&df_g_icon_font_bytes),
|
||||
};
|
||||
for(DF_FontSlot slot = (DF_FontSlot)0; slot < DF_FontSlot_COUNT; slot = (DF_FontSlot)(slot+1))
|
||||
{
|
||||
if(f_tag_match(f_tag_zero(), df_gfx_state->cfg_font_tags[slot]))
|
||||
{
|
||||
df_gfx_state->cfg_font_tags[slot] = defaults[slot];
|
||||
}
|
||||
}
|
||||
MemoryZeroArray(df_gfx_state->cfg_font_tags);
|
||||
{
|
||||
DF_CfgVal *code_font_val = df_cfg_val_from_string(table, str8_lit("code_font"));
|
||||
DF_CfgVal *main_font_val = df_cfg_val_from_string(table, str8_lit("main_font"));
|
||||
@@ -11220,17 +11129,34 @@ df_gfx_begin_frame(Arena *arena, DF_CmdList *cmds)
|
||||
DF_CfgNode *main_font_cfg = main_font_val->last;
|
||||
String8 code_font_relative_path = code_font_cfg->first->string;
|
||||
String8 main_font_relative_path = main_font_cfg->first->string;
|
||||
if(code_font_cfg != &df_g_nil_cfg_node)
|
||||
{
|
||||
arena_clear(df_gfx_state->cfg_code_font_path_arena);
|
||||
df_gfx_state->cfg_code_font_path = push_str8_copy(df_gfx_state->cfg_code_font_path_arena, code_font_relative_path);
|
||||
}
|
||||
if(main_font_cfg != &df_g_nil_cfg_node)
|
||||
{
|
||||
arena_clear(df_gfx_state->cfg_main_font_path_arena);
|
||||
df_gfx_state->cfg_main_font_path = push_str8_copy(df_gfx_state->cfg_main_font_path_arena, main_font_relative_path);
|
||||
}
|
||||
String8 code_font_path = path_absolute_dst_from_relative_dst_src(scratch.arena, code_font_relative_path, cfg_folder);
|
||||
String8 main_font_path = path_absolute_dst_from_relative_dst_src(scratch.arena, main_font_relative_path, cfg_folder);
|
||||
if(code_font_cfg != &df_g_nil_cfg_node && code_font_relative_path.size != 0)
|
||||
if(os_file_path_exists(code_font_path) && code_font_cfg != &df_g_nil_cfg_node && code_font_relative_path.size != 0)
|
||||
{
|
||||
df_gfx_state->cfg_font_tags[DF_FontSlot_Code] = f_tag_from_path(code_font_path);
|
||||
}
|
||||
if(main_font_cfg != &df_g_nil_cfg_node && main_font_relative_path.size != 0)
|
||||
if(os_file_path_exists(main_font_path) && main_font_cfg != &df_g_nil_cfg_node && main_font_relative_path.size != 0)
|
||||
{
|
||||
df_gfx_state->cfg_font_tags[DF_FontSlot_Main] = f_tag_from_path(main_font_path);
|
||||
}
|
||||
}
|
||||
for(DF_FontSlot slot = (DF_FontSlot)0; slot < DF_FontSlot_COUNT; slot = (DF_FontSlot)(slot+1))
|
||||
{
|
||||
if(f_tag_match(f_tag_zero(), df_gfx_state->cfg_font_tags[slot]))
|
||||
{
|
||||
df_gfx_state->cfg_font_tags[slot] = defaults[slot];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: build windows & panel layouts
|
||||
|
||||
+5
-12
@@ -726,16 +726,11 @@ struct DF_GfxState
|
||||
// rjf: running theme state
|
||||
DF_Theme cfg_theme_target;
|
||||
DF_Theme cfg_theme;
|
||||
Arena *cfg_main_font_path_arena;
|
||||
Arena *cfg_code_font_path_arena;
|
||||
String8 cfg_main_font_path;
|
||||
String8 cfg_code_font_path;
|
||||
F_Tag cfg_font_tags[DF_FontSlot_COUNT];
|
||||
|
||||
// rjf: text search state
|
||||
U64 tsrch_slot_count;
|
||||
U64 tsrch_stripe_count;
|
||||
DF_TextSearchCacheSlot *tsrch_slots;
|
||||
OS_Handle *tsrch_stripe_rw_mutexes;
|
||||
OS_Handle tsrch_wakeup_mutex;
|
||||
OS_Handle tsrch_wakeup_cv;
|
||||
OS_Handle tsrch_thread;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
@@ -960,14 +955,12 @@ internal void df_set_search_string(String8 string);
|
||||
internal String8 df_push_search_string(Arena *arena);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Background Text Searching Thread
|
||||
//~ rjf: Text Searching
|
||||
|
||||
internal void df_text_search_match_chunk_list_push(Arena *arena, DF_TextSearchMatchChunkList *list, U64 cap, DF_TextSearchMatch *match);
|
||||
internal DF_TextSearchMatchArray df_text_search_match_array_from_chunk_list(Arena *arena, DF_TextSearchMatchChunkList *chunks);
|
||||
internal U64 df_text_search_little_hash_from_hash(U128 hash);
|
||||
internal void df_text_search_thread_entry_point(void *p);
|
||||
internal DF_TextSearchMatchArray df_text_search_match_array_from_hash_needle(Arena *arena, U128 hash, String8 needle, DF_TextSliceFlags text_slice_flags, TxtPt start_pt);
|
||||
internal DF_TextSearchMatchArray df_text_search_match_array_from_entity_needle(Arena *arena, DF_Entity *entity, String8 needle, DF_TextSliceFlags flags, TxtPt start_pt);
|
||||
internal int df_text_search_match_array_qsort_compare(TxtPt *a, TxtPt *b);
|
||||
internal void df_text_search_match_array_sort_in_place(DF_TextSearchMatchArray *array);
|
||||
internal DF_TextSearchMatch df_text_search_match_array_find_nearest__linear_scan(DF_TextSearchMatchArray *array, TxtPt pt, Side side);
|
||||
|
||||
+10
-3
@@ -8596,7 +8596,8 @@ DF_VIEW_UI_FUNCTION_DEF(Theme)
|
||||
color < DF_ThemeColor_COUNT;
|
||||
color = (DF_ThemeColor)(color+1))
|
||||
{
|
||||
UI_PrefWidth(ui_em(28.5f, 1)) UI_PrefHeight(ui_children_sum(1.f)) UI_CtxMenu(color_ctx_menu_keys[color]) UI_Padding(ui_em(1.5f, 1.f))
|
||||
UI_CtxMenu(color_ctx_menu_keys[color]) UI_Padding(ui_em(1.5f, 1.f))
|
||||
UI_PrefWidth(ui_em(28.5f, 1)) UI_PrefHeight(ui_children_sum(1.f))
|
||||
{
|
||||
// rjf: build title
|
||||
UI_Row
|
||||
@@ -8817,8 +8818,10 @@ DF_VIEW_UI_FUNCTION_DEF(Theme)
|
||||
"###color_%I64x", (U64)color);
|
||||
UI_Parent(color_row)
|
||||
{
|
||||
Vec4F32 text_rgba = rgba;
|
||||
text_rgba.w = ClampBot(text_rgba.w, 0.2f);
|
||||
Vec4F32 bg_color = ui_top_background_color();
|
||||
Vec4F32 default_text_color = ui_top_text_color();
|
||||
F32 default_fallback_factor = clamp_1f32(r1f32(0.3f, 1), dot_4f32(normalize_4f32(rgba), normalize_4f32(bg_color))) - 0.3f;
|
||||
Vec4F32 text_rgba = mix_4f32(rgba, default_text_color, default_fallback_factor);
|
||||
UI_WidthFill UI_TextColor(text_rgba) ui_label(df_g_theme_color_display_string_table[color]);
|
||||
ui_set_next_pref_width(ui_top_pref_height());
|
||||
UI_HeightFill UI_Column UI_Padding(ui_em(0.3f, 1))
|
||||
@@ -8846,6 +8849,10 @@ DF_VIEW_UI_FUNCTION_DEF(Theme)
|
||||
DF_CmdParams p = df_cmd_params_from_panel(ws, panel);
|
||||
df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FocusPanel));
|
||||
}
|
||||
if(color_row_sig.hovering) UI_Tooltip
|
||||
{
|
||||
ui_label(df_g_theme_color_display_string_table[color]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+406
-285
@@ -2,11 +2,11 @@
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Settings
|
||||
//~ rjf: Build Settings
|
||||
|
||||
#define RADDBG_VERSION_MAJOR 0
|
||||
#define RADDBG_VERSION_MINOR 9
|
||||
#define RADDBG_VERSION_PATCH 0
|
||||
#define RADDBG_VERSION_PATCH 1
|
||||
#define RADDBG_VERSION_STRING_LITERAL Stringify(RADDBG_VERSION_MAJOR) "." Stringify(RADDBG_VERSION_MINOR) "." Stringify(RADDBG_VERSION_PATCH)
|
||||
#if defined(NDEBUG)
|
||||
# define RADDBG_TITLE_STRING_LITERAL "The RAD Debugger (" RADDBG_VERSION_STRING_LITERAL " ALPHA) - " __DATE__ ""
|
||||
@@ -18,122 +18,362 @@
|
||||
#define DE2CTRL 1
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: 2024/1 tasks
|
||||
//~ rjf: Hot, High Priority Tasks (Complete Unusability, Crashes, Fire-Worthy)
|
||||
//
|
||||
// [ ] @bug bug notes from casey
|
||||
// [ ] ** If you put a full path to a TTF font into the code_font/main_font variables of the config file,
|
||||
// it continually rewrites it each time you launch. The first time you launch, with your hand-edited
|
||||
// font path, it works correctly and the font loads, but it rewrites it from an absolute path to a
|
||||
// relative path. The second time you launch, with the relative path, it doesn't work (you get no text
|
||||
// at all), and it rewrites it from relative back to absolute, but to the wrong path (prepending
|
||||
// C:/users/casey/AppData/ to the previous path, even though that was not at all where the font ever
|
||||
// was) The font path will now remain "stable" in the sense that it won't rewrite it anymore. But you
|
||||
// cannot use the debugger because it's the wrong font path, so you get no text.
|
||||
// [ ] When I click in the theme window on something like "Code (Meta)", it opens up a tiny window, which
|
||||
// only shows a tiny bit of what I imagine is the entire color picker? It makes the picker unusable
|
||||
// because more of the UI for it is clipped and cannot be accessed.
|
||||
// [ ] Clicking anywhere in the color picker that isn't a button closes the color picker for some reason?
|
||||
// [ ] In a "hover watch" (where you hover over a variable and it shows a pop-up watch window), if you expand
|
||||
// an item near the bottom of the listing, it will be clipped to the bottom of the listing instead of
|
||||
// showing the actual items (ie., it doesn't resize the listing based on what's actually visible)
|
||||
// [ ] ** Thread/process control bullet-proofing, including solo-step mode
|
||||
// [ ] ** ASAN targets
|
||||
// [ ] ** prevent overwriting non-config files when choosing config paths
|
||||
// [ ] ** while typing, "Alt" Windows menu things should not happen
|
||||
//
|
||||
// [ ] @bug @feature @cleanup general feedback from casey
|
||||
// [ ] ** I don't like how panels get dimmer when they are not active, because it makes them harder for me to read. Is there a way to turn this off?
|
||||
// [ ] ** I couldn't figure out how to really view threads in the debugger. The only place I found a thread list was in "The Scheduler", but it only lists threads by ID, which is hard to use. I can hover over them to get the stack, which helps, but it would be much nicer if the top function was displayed in the window by default next to the thread.
|
||||
// [ ] ** It would be nice if thread listings displayed the name of the thread, instead of just the ID.
|
||||
// [ ] ** Scrollbars are barely visible for me, for some reason. I could not find anything in the theme that would fill them with a solid, bright color. Instead they are just a thin outline and the same color as the scroll bar background.
|
||||
// [ ] It seems like the code is compiled as a console app for some reason, so when you run it, it locks up your console. I worked around this by making a bat file that does a "start" of it, but, it seems like this would not be what people would expect (at least on Windows?)
|
||||
// [ ] Dragging a window tab (like Locals or Registers or whatnot) and canceling with ESC should revert the window tab to where it was. Currently, it leaves the window tab reordered if you dragged over its window and shuffled its position.
|
||||
// [ ] Many of the UI elements, like the menus, would like better if they had a little bit of margin. Having the text right next to the edges, and with no line spacing, makes it harder to read things quickly.
|
||||
// [ ] Menus take too long to show up. I would prefer it if they were instant. The animation doesn't really provide any useful cues, since I know where the menu came from.
|
||||
// [ ] Theme window should include font scaling. I was able to find the comm-and for increasing the font scale, but I imagine most people wouldn't think to look there.
|
||||
// [ ] The way the "commands" view worked was idiosyncratic. All the other views stay up, but that one goes away whenever I select a command for some reason.
|
||||
// [ ] Also, I could not move the commands window anywhere AFAICT. It seems to just pop up over whatever window I currently have selected. This would make sense for a hotkey (which I assume is the way it was designed), but it seems like it should be permanent if you can select it from the View menu.
|
||||
// [ ] If the command window is not wide enough, you cannot read the description of a command because it doesn't word-wrap, nor can you hover over it to get the description in a tooltip (AFAICT).
|
||||
// [ ] It'd be nice to have a "goto byte" option for source views, for jumping to error messages that are byte-based instead of line-based.
|
||||
// [ ] Pressing the left mouse button on the menu bar and dragging does not move through the menus as expected - instead, it opens the one you clicked down on, then does nothing until you release, at which point it opens the menu you released on.
|
||||
// [ ] Similarly, pressing the left mouse button on a menu and dragging to an item, then releasing, does not trigger that item as expected. Instead, it is a nop, and it waits for you to click again on the item.
|
||||
// [ ] I was a little confused about what a profile file was. I understood what the user file was, but the profile file sounded like it should perhaps be per-project, yet it sounded like it was meant to be somewhat global? I don't have any feedback here because it probably will make sense once I use the debugger more, but I just thought I'd make a note to say that I was confused about it after reading the manual, so perhaps you could elaborate a little more on it in there.
|
||||
// [ ] I found the "non-windowness" of the source view area confusing. Since everything else is a tab, it was weird that it was a "phantom non-tab window" that gets replaced by an automatically opened tab once you step.
|
||||
// [ ] Working with panels felt cumbersome. I couldn't figure out any way to quickly arrange the display without manually selecting "split panel" and "close panel" and stuff from the menu, which took a long time.
|
||||
// [ ] I found the "context menu" convention to be confusing. For example, if I left-click on a tab, it selects the tab. If I right-click on a tab, it opens the context menu. However, if I left-click on a module, it opens the context window. It seems like maybe menus should be right, and left should do the default action, more consistently?
|
||||
// [ ] I found the "drill down" convention to be confusing, too. For example, if I click on a target, it opens a new tab with that target in it. By contrast, if I click on "browse" in the module window, it replaces that window temporarily with a browsing window.
|
||||
// [ ] More tooltips would be helpful. For example, I don't know what the "rotation arrow" icon next to executables means in the "This PC" window
|
||||
// [ ] Hovering over disassembly highlights blocks of instructions, which I assume correspond to source lines. But perhaps it should also highlight the source lines? The inverse hover works (you hover over source, and it highlights ASM), but ASM->source doesn't.
|
||||
// [ ] It seems like clicking on a breakpoint red circle should perhaps disable the breakpoint, rather than delete it? Since breakpoints can have a fair bit of state, it seems like it might be annoying to have it all be deleted if you accidentally click. Unless you are planning on adding undo? Actually, that's probably something you should do: keep a breakpoint history that is in the breakpoint window that you can open up when you want, and it just has a stack of all your recently deleted breakpoints? That solves the problem better.
|
||||
// [ ] I had to go into the user file to change the font. That should probably be in the theme window?
|
||||
// [ ] Launching the debugger with an invalid code_font/main_font name doesn't have any fallback, so you just get no text at all. Probably should use a fallback font when font loading fails
|
||||
// [ ] Setting the code_font/main_font values to a font name doesn't work. Should probably make note that you have to set it to a path to a TTF, since that's not normally how Windows fonts work.
|
||||
// [ ] Having inactive tabs use smaller fonts doesn't work very well for readability. I feel like just normal->bold is a better choice than small font->large font.
|
||||
// [ ] The hex format for color values in the config file was a real mindbender. It's prefixed with "0x", so I was assuming it was either Windows Big Endian (0xAARRGGBB) or Mac Little Endian (0xAABBGGRR). To my surprise, it was neither - it was actually web format (RRGGBBAA), which I was not expecting because that is normally written with a number sign (#AARRGGBB) not an 0x.
|
||||
// [ ] Clicking on either side of a scroll bar is idiosyncratic. Normally, that is "page up" / "page down", but here it is "smooth scroll upward" / "smooth scroll downward" for some reason?
|
||||
// [ ] Hitting ESC during a color picker drag should abort the color picking and revert to the previous color. Currently, it just accepts the last drag result as the new color.
|
||||
// [ ] It was not clear to me why a small "tab picker" appeared when I got to a certain number of tabs. It seemed to appear even if the tabs were quite large, and there was no need to a drop-down menu to pick them. It feels like either it should always be there, or it should only show up if at least one tab gets small enough to have its name cut off?
|
||||
// [ ] It feels like "expansion" icons should only show next to things that can actually be expanded.
|
||||
// [ ] It wasn't clear to me how you save a user or profile file. I can see how to load them, but not how you save them. Obviously I can just copy the files myself in the shell, but it seemed weird that there was no "save" option in the menus.
|
||||
// [ ] ** I can't seem to get the .raddbg files to update consistently, or
|
||||
// something. I can't seem to reproduce it reliably, but sometimes when I
|
||||
// rebuild, for example, it seems to keep using the old PDB data
|
||||
// effectively - like it doesn't think it needs to update the raddbg file,
|
||||
// or something? But if I manually delete the raddbg file and relaunch,
|
||||
// then it will have the new debug info. It would be nice if there was
|
||||
// some kind of way to interrogate this in the debugger so I can send a
|
||||
// more constructive report, like some way to get a hash of the PDB that
|
||||
// is thinks it has converted to the RAD format, and then a way I can hash
|
||||
// the PDB on the drive, or something, so I can figure out if they are
|
||||
// mismatching for sure?
|
||||
//
|
||||
//*[ ] @cleanup @feature double & triple click select in source views
|
||||
//*[ ] @bug disasm animation & go-to-address
|
||||
// [ ] ** In solo-stepping mode, if I step over something like CreateFileA, it
|
||||
// pseudo-hangs the debugger. I can't seem to do anything else, including
|
||||
// "Kill All". I have to close the debugger and restart it, AFAICT?
|
||||
//
|
||||
//*[ ] @bug table column boundaries should be checked against *AFTER* table contents, not before
|
||||
//*[ ] @cleanup @feature autocomplete lister should respect position in edited expression, tabbing through should autocomplete but not exit, etc.
|
||||
//*[ ] @cleanup @feature figure out 'watch window state' question, and how watch windows relate to targets, entities, & so on
|
||||
//*[ ] @feature undo/redo
|
||||
//*[ ] @feature proper "go back" + "go forward" history navigations
|
||||
// [ ] ** I tried to debug a console program, and "step into" didn't seem to
|
||||
// work. Instead, it just started running the program, but the program
|
||||
// seemed to hang, and then the debugger pseudo-hung with a continual
|
||||
// progress bar in the disassembly window. I had to close and restart. Is
|
||||
// console app debugging not working yet, perhaps?
|
||||
//
|
||||
// [ ] @bug view-snapping in scroll-lists, accounting for mapping between visual positions & logical positions (variably sized rows in watch, table headers, etc.)
|
||||
// [ ] @bug selected frame should be keyed by run_idx or something so that it can gracefully reset to the top frame when running
|
||||
// [ ] Setting the code_font/main_font values to a font name doesn't work.
|
||||
// Should probably make note that you have to set it to a path to a TTF,
|
||||
// since that's not normally how Windows fonts work.
|
||||
|
||||
// [ ] ** Converter performance & heuristics for asynchronously doing it early
|
||||
//
|
||||
// [ ] @cleanup collapse DF_CfgNodes into just being MD trees, find another way to encode config source - don't need it at every node
|
||||
// [ ] disasm animation & go-to-address
|
||||
//
|
||||
// [ ] @feature fancy "escape hatch" view rules
|
||||
// [ ] visualize mismatched source code and debug info
|
||||
// [ ] visualize remapped files (via path map)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Hot, Medium Priority Tasks (Low-Hanging-Fruit Features, UI Jank, Cleanup)
|
||||
//
|
||||
// [ ] I was a little confused about what a profile file was. I understood
|
||||
// what the user file was, but the profile file sounded like it should
|
||||
// perhaps be per-project, yet it sounded like it was meant to be somewhat
|
||||
// global? I don't have any feedback here because it probably will make
|
||||
// sense once I use the debugger more, but I just thought I'd make a note
|
||||
// to say that I was confused about it after reading the manual, so
|
||||
// perhaps you could elaborate a little more on it in there.
|
||||
//
|
||||
// [ ] ** "Find Name" may not be working as advertised. In the description, it
|
||||
// says you can jump to a file, but if I type in the complete filename of
|
||||
// a file in the project and hit return, it just turns red and says it
|
||||
// couldn't find it. This happens even if the file is already open in a
|
||||
// tab.
|
||||
// [ ] "Find Name" would be a lot more useful if you could type partial
|
||||
// things, and it displayed a list, more like what happens in a
|
||||
// traditional text editor. Typing the entire name of a function to jump
|
||||
// to it is too laborious.
|
||||
//
|
||||
// [ ] Right-clicking on a thread in the Scheduler window pops up a context
|
||||
// menu, but you can't actually see it because the tooltip for the thread
|
||||
// draws on top of it, so you can't see the menu.
|
||||
//
|
||||
// [ ] In a "hover watch" (where you hover over a variable and it shows a pop-
|
||||
// up watch window), if you expand an item near the bottom of the listing,
|
||||
// it will be clipped to the bottom of the listing instead of showing the
|
||||
// actual items (ie., it doesn't resize the listing based on what's
|
||||
// actually visible)
|
||||
//
|
||||
// [ ] ** Function breakpoints should show up in the source listing. Without
|
||||
// them being visible, it is confusing when you run and you stop there,
|
||||
// because you're like "wait why did it stop" and then you later remember
|
||||
// that's because there was a function breakpoint there.
|
||||
//
|
||||
// [ ] ** One very nice feature of RemedyBG that I use all the time is the
|
||||
// ability to put "$err, hr" into the watch window, which will just show
|
||||
// the value of GetLastError() as a string. This is super useful for
|
||||
// debugging, so you don't have to litter your own code with it.
|
||||
//
|
||||
// [ ] Tooltip Coverage:
|
||||
// [ ] lock icon
|
||||
// [ ] "rotation arrow" icon next to executables
|
||||
//
|
||||
// [ ] Using the word "symbol" in "Code (Symbol)" seems like a bad idea, since
|
||||
// you're referring to non-identifier characters, but in a debugger
|
||||
// "symbol" usually means something defined in the debug information.
|
||||
//
|
||||
// [ ] I LOVE ALT-W to add watch under cursor, but I would prefer to have it
|
||||
// add what's under the MOUSE cursor instead of the keyboard cursor. Can
|
||||
// we get a command for that so I can bind ALT-W to that instead?
|
||||
//
|
||||
// [ ] For theme editing, when you hove the mouse over a theme color entry and
|
||||
// it highlights that entry, it might help to temporarily change that
|
||||
// color to white (or the inverse of the background color, or whatever) so
|
||||
// that the user can see what things on the screen use that theme color.
|
||||
//
|
||||
// [ ] I couldn't figure out how to affect the "dim" color in constants that
|
||||
// have alternating bright/dim letters to show sections of a number. Is
|
||||
// this in the theme colors somewhere?
|
||||
//
|
||||
// [ ] For breakpoint-on-function, it would be great if it showed a list of
|
||||
// (partial) matches as you type, so you can stop typing once it gets the
|
||||
// right function instead of having to type the entire function name.
|
||||
//
|
||||
// [ ] Hovering over a source tab that is clipped should probably display the
|
||||
// full thing that was in that tab (like the whole filename, etc.). Right
|
||||
// now, hovering does nothing AFAICT.
|
||||
//
|
||||
// [ ] ** I couldn't figure out how to really view threads in the debugger.
|
||||
// The only place I found a thread list was in "The Scheduler", but it
|
||||
// only lists threads by ID, which is hard to use. I can hover over them
|
||||
// to get the stack, which helps, but it would be much nicer if the top
|
||||
// function was displayed in the window by default next to the thread.
|
||||
// [ ] ** It would be nice if thread listings displayed the name of the
|
||||
// thread, instead of just the ID.
|
||||
//
|
||||
// [ ] ** Scrollbars are barely visible for me, for some reason. I could not
|
||||
// find anything in the theme that would fill them with a solid, bright
|
||||
// color. Instead they are just a thin outline and the same color as the
|
||||
// scroll bar background.
|
||||
//
|
||||
// [ ] Dragging a window tab (like Locals or Registers or whatnot) and
|
||||
// canceling with ESC should revert the window tab to where it was.
|
||||
// Currently, it leaves the window tab reordered if you dragged over its
|
||||
// window and shuffled its position.
|
||||
//
|
||||
// [ ] Many of the UI elements, like the menus, would like better if they had
|
||||
// a little bit of margin. Having the text right next to the edges, and
|
||||
// with no line spacing, makes it harder to read things quickly.
|
||||
//
|
||||
// [ ] Menus take too long to show up. I would prefer it if they were instant.
|
||||
// The animation doesn't really provide any useful cues, since I know
|
||||
// where the menu came from.
|
||||
//
|
||||
// [ ] Theme window should include font scaling. I was able to find the
|
||||
// command for increasing the font scale, but I imagine most people
|
||||
// wouldn't think to look there.
|
||||
// [ ] I had to go into the user file to change the font. That should probably
|
||||
// be in the theme window?
|
||||
//
|
||||
// [ ] The way the "commands" view worked was idiosyncratic. All the other
|
||||
// views stay up, but that one goes away whenever I select a command for
|
||||
// some reason.
|
||||
// [ ] Also, I could not move the commands window anywhere AFAICT. It seems
|
||||
// to just pop up over whatever window I currently have selected. This
|
||||
// would make sense for a hotkey (which I assume is the way it was
|
||||
// designed), but it seems like it should be permanent if you can select
|
||||
// it from the View menu.
|
||||
// [ ] If the command window is not wide enough, you cannot read the
|
||||
// description of a command because it doesn't word-wrap, nor can you
|
||||
// hover over it to get the description in a tooltip (AFAICT).
|
||||
//
|
||||
// [ ] It'd be nice to have a "goto byte" option for source views, for jumping
|
||||
// to error messages that are byte-based instead of line-based.
|
||||
//
|
||||
// [ ] Pressing the left mouse button on the menu bar and dragging does not
|
||||
// move through the menus as expected - instead, it opens the one you
|
||||
// clicked down on, then does nothing until you release, at which point it
|
||||
// opens the menu you released on.
|
||||
// [ ] Similarly, pressing the left mouse button on a menu and dragging to an
|
||||
// item, then releasing, does not trigger that item as expected. Instead,
|
||||
// it is a nop, and it waits for you to click again on the item.
|
||||
//
|
||||
// [ ] Working with panels felt cumbersome. I couldn't figure out any way to
|
||||
// quickly arrange the display without manually selecting "split panel"
|
||||
// and "close panel" and stuff from the menu, which took a long time.
|
||||
// - @polish @feature ui for dragging tab -> bundling panel split options
|
||||
//
|
||||
// [ ] I found the "context menu" convention to be confusing. For example, if
|
||||
// I left-click on a tab, it selects the tab. If I right-click on a tab,
|
||||
// it opens the context menu. However, if I left-click on a module, it
|
||||
// opens the context window. It seems like maybe menus should be right,
|
||||
// and left should do the default action, more consistently?
|
||||
//
|
||||
// [ ] Hovering over disassembly highlights blocks of instructions, which I
|
||||
// assume correspond to source lines. But perhaps it should also highlight
|
||||
// the source lines? The inverse hover works (you hover over source, and
|
||||
// it highlights ASM), but ASM->source doesn't.
|
||||
//
|
||||
// [ ] It wasn't clear to me how you save a user or profile file. I can see
|
||||
// how to load them, but not how you save them. Obviously I can just copy
|
||||
// the files myself in the shell, but it seemed weird that there was no
|
||||
// "save" option in the menus.
|
||||
//
|
||||
// [ ] @cleanup @feature double & triple click select in source views
|
||||
// [ ] @feature hovering truncated text in UI for some amount of time -> show
|
||||
// tooltip with full text
|
||||
// [ ] @feature disasm keyboard navigation & copy/paste
|
||||
// [ ] @feature debug info overrides (both path-based AND module-based)
|
||||
// [ ] configure tab size
|
||||
// [ ] run-to-line needs to work if no processes are running
|
||||
// - place temp bp, attach "die on hit" flag or something like that?
|
||||
// [ ] auto-scroll output window
|
||||
//
|
||||
// [ ] C++ single & multi inheritance member visualization in watch window
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Hot, Low Priority Tasks (UI Opinions, Less-Serious Jank, Preferences, Cleanup)
|
||||
//
|
||||
// [ ] ** In the call stack, I would like to be able to click quickly and move
|
||||
// around the stack. Right now, you can do that with the first and third
|
||||
// column, but the second column drops down a context menu. Since right
|
||||
// click is already for context menus, can it not just be that double-
|
||||
// clicking any column jumps to that stack frame?
|
||||
//
|
||||
// [ ] ** I find it really hard to read the code with the heavyweight lines
|
||||
// running through it for breakpoints and stepping and things. Is there a
|
||||
// way to turn the lines off? AFAICT they are based on thread and
|
||||
// breakpoint color, so you can't really control the line drawing? I might
|
||||
// be fine with them, but they would have to be much more light (like
|
||||
// alpha 0.1 or something)
|
||||
//
|
||||
// [ ] It's confusing that ENTER is the way you expand and collapse things in
|
||||
// the watch window, but then also how you edit them if they are not
|
||||
// expandable? It seems like this should be consistent (one way to edit,
|
||||
// one way to expand/collapse, that are distinct)
|
||||
//
|
||||
// [ ] I didn't understand the terminology "Equip With Color". Does that just
|
||||
// mean specify the color used to display it? Is "Apply Color" perhaps a
|
||||
// bit more user-friendly?
|
||||
//
|
||||
// [ ] The cursor feels a bit too huge vertically.
|
||||
//
|
||||
// [ ] The hex format for color values in the config file was a real
|
||||
// mindbender. It's prefixed with "0x", so I was assuming it was either
|
||||
// Windows Big Endian (0xAARRGGBB) or Mac Little Endian (0xAABBGGRR). To
|
||||
// my surprise, it was neither - it was actually web format (RRGGBBAA),
|
||||
// which I was not expecting because that is normally written with a
|
||||
// number sign (#AARRGGBB) not an 0x.
|
||||
//
|
||||
// [ ] Clicking on either side of a scroll bar is idiosyncratic. Normally,
|
||||
// that is "page up" / "page down", but here it is "smooth scroll upward"
|
||||
// / "smooth scroll downward" for some reason?
|
||||
//
|
||||
// [ ] Hitting ESC during a color picker drag should abort the color picking
|
||||
// and revert to the previous color. Currently, it just accepts the last
|
||||
// drag result as the new color.
|
||||
//
|
||||
// [ ] It was not clear to me why a small "tab picker" appeared when I got to
|
||||
// a certain number of tabs. It seemed to appear even if the tabs were
|
||||
// quite large, and there was no need to a drop-down menu to pick them. It
|
||||
// feels like either it should always be there, or it should only show up
|
||||
// if at least one tab gets small enough to have its name cut off?
|
||||
//
|
||||
// [ ] can it ignore stepping into _RTC_CheckStackVars generated functions?
|
||||
// [ ] mouse back button should make view to go back after I double clicked
|
||||
// on function to open it
|
||||
// [ ] middle mouse button on tab should close it
|
||||
// [ ] pressing random keyboard keys in source code advances text cursor like
|
||||
// you were inputting text, very strange.
|
||||
// [ ] Alt+8 to switch to disassembly would be nice (regardless on which
|
||||
// panel was previous, don't want to use ctrl+, multiple times)
|
||||
// Alt+8 for disasm and Alt+6 for memory view are shortcuts I often use
|
||||
// in VS
|
||||
// [ ] what's up with decimal number coloring where every group of 3 are in
|
||||
// different color? can I turn it off? And why sometimes digits in number
|
||||
// start with brighter color, but sometimes with darker - shouldn't it
|
||||
// always have the same color ordering?
|
||||
// [ ] it would be nice to have "show in explorer" for right click on source
|
||||
// file tab (opens explorer & selects the file)
|
||||
// [ ] it would be nice if Alt+o in source file would switch between .h and
|
||||
// .c/cpp file (just look for same name in same folder)
|
||||
// [ ] in watch window when I enter some new expression and then click mouse
|
||||
// away from cell, then it should behave the same as if I pressed enter.
|
||||
// Currently it does the same as if I have pressed esc and I have lost my
|
||||
// expression
|
||||
// [ ] default font size is too small for me - not only source code, but
|
||||
// menus/tab/watch names (which don't resize). Maybe you could query
|
||||
// Windows for initial font size?
|
||||
// [ ] zooming behaves very strangely - sometimes it zooms source code,
|
||||
// sometimes both source code and menu/tab/watch font size, sometimes
|
||||
// just menu/tab/watch font size not source size.
|
||||
// [ ] icon fonts glyphs sometimes disappear for specific font size, but they
|
||||
// reappear if you go +1 higher or -1 lower. Mostly red triangle in watch
|
||||
// values for "unknown identifier". But also yellow arrow in call stack
|
||||
// disappears if font size gets too large.
|
||||
// [ ] undo close tab would be nice. If not for everything, then at least
|
||||
// just for source files
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Hot, Feature Tasks (Not really "low priority" but less urgent than fixes)
|
||||
//
|
||||
// [ ] For the Scheduler window, it would be nice if you could dim or
|
||||
// folderize threads that are not your threads - eg., if a thread doesn't
|
||||
// have any resolved stack pointers in your executable code, then you can
|
||||
// ignore it when you are focusing on your own code. I don't know what the
|
||||
// best way to detect this is, other than by walking the call stack... one
|
||||
// way might be to just have a way to separate threads you've named from
|
||||
// threads you haven't? Or, there could even be a debugger-specific API
|
||||
// that you use to tag them. Just some way that would make it easier to
|
||||
// focus on your own threads.
|
||||
//
|
||||
// [ ] autocomplete lister should respect position in edited expression,
|
||||
// tabbing through should autocomplete but not exit, etc.
|
||||
//
|
||||
// [ ] Fancy View Rules
|
||||
// [ ] table column boundaries should be checked against *AFTER* table
|
||||
// contents, not before
|
||||
// [ ] `text[:lang]` - interpret memory as text, in lang `lang`
|
||||
// [ ] `disasm:arch` - interpret memory as machine code for isa `arch`
|
||||
// [ ] `memory` - view memory in usual memory hex-editor view
|
||||
// NOTE(rjf): When the visualization system is solid, layers like dasm, txti, and so on
|
||||
// can be dispensed with, as things like the source view, disasm view, or memory view will
|
||||
// simply be specializations of the general purpose viz system.
|
||||
// NOTE(rjf): When the visualization system is solid, layers like dasm, txti,
|
||||
// and so on can be dispensed with, as things like the source view, disasm
|
||||
// view, or memory view will simply be specializations of the general purpose
|
||||
// viz system.
|
||||
// [ ] view rule hook for standalone visualization ui, granted its own
|
||||
// tab
|
||||
//
|
||||
// [ ] @feature view rule hook for standalone visualization ui, granted its own tab
|
||||
// [ ] @feature hovering truncated text in UI for some amount of time -> show tooltip with full text
|
||||
// [ ] search-in-all-files
|
||||
//
|
||||
// [ ] @cleanup straighten out index/number space & types & terminology for scroll lists
|
||||
// [ ] @cleanup simplification pass over eval visualization pipeline & types, including view rule hooks
|
||||
// [ ] @cleanup naming pass over eval visualization part of the frontend, "blocks" vs. "canvas" vs. "expansion" - etc.
|
||||
// [ ] Memory View
|
||||
// [ ] memory view mutation controls
|
||||
// [ ] memory view user-made annotations
|
||||
//
|
||||
// [ ] @feature disasm keyboard navigation & copy/paste
|
||||
// [ ] @feature debug info overrides (both path-based AND module-based)
|
||||
// [ ] undo/redo
|
||||
// [ ] proper "go back" + "go forward" history navigations
|
||||
//
|
||||
// [ ] @polish globally disable/configure default view rule-like things (string viz for u8s in particular)
|
||||
// [ ] @polish configure tab size
|
||||
//
|
||||
// [ ] @polish @feature ui for dragging tab -> bundling panel split options
|
||||
// [ ] @polish @feature visualize mismatched source code and debug info
|
||||
// [ ] @polish @feature visualize remapped files (via path map)
|
||||
// [ ] @polish @feature run-to-line needs to work if no processes are running - place temp bp, attach "die on hit" flag or something like that?
|
||||
// [ ] globally disable/configure default view rule-like things (string
|
||||
// viz for u8s in particular)
|
||||
// [ ] globally disable/configure bp/ip lines in source view
|
||||
//
|
||||
// [ ] @feature processor/data breakpoints
|
||||
// [ ] @feature automatically snap to search matches when searching source files
|
||||
// [ ] @feature entity views: filtering & reordering
|
||||
//
|
||||
// [ ] @cleanup central worker thread pool - eliminate per-layer thread pools
|
||||
//
|
||||
// [ ] @feature search-in-all-files
|
||||
// [ ] @feature memory view mutation controls
|
||||
// [ ] @feature memory view user-made annotations
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: 2024/2 tasks
|
||||
//~ rjf: Cold, Clean-up Tasks That Probably Only Ryan Notices
|
||||
// (E.G. Because They Are Code-Related Or Because Nobody Cares)
|
||||
//
|
||||
// [ ] @perf ue/chromium testing
|
||||
// [ ] @perf converter perf
|
||||
// [ ] @perf frontend perf
|
||||
// [ ] @bug view-snapping in scroll-lists, accounting for mapping between
|
||||
// visual positions & logical positions (variably sized rows in watch,
|
||||
// table headers, etc.)
|
||||
// [ ] @bug selected frame should be keyed by run_idx or something so that it
|
||||
// can gracefully reset to the top frame when running
|
||||
// [ ] @cleanup collapse DF_CfgNodes into just being MD trees, find another way
|
||||
// to encode config source - don't need it at every node
|
||||
// [ ] @cleanup straighten out index/number space & types & terminology for
|
||||
// scroll lists
|
||||
// [ ] @cleanup simplification pass over eval visualization pipeline & types,
|
||||
// including view rule hooks
|
||||
// [ ] @cleanup naming pass over eval visualization part of the frontend,
|
||||
// "blocks" vs. "canvas" vs. "expansion" - etc.
|
||||
// [ ] @cleanup central worker thread pool - eliminate per-layer thread pools
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Cold, Unsorted Notes (Deferred Until Existing Lists Mostly Exhausted)
|
||||
//
|
||||
// [ ] @feature types -> auto view rules (don't statefully fill view rules given types, just query if no other view rule is present, & autofill when editing)
|
||||
// [ ] @feature eval system -> somehow evaluate breakpoint hit counts? "meta" variables?
|
||||
// [ ] @feature types -> auto view rules (don't statefully fill view rules
|
||||
// given types, just query if no other view rule is present, & autofill
|
||||
// when editing)
|
||||
// [ ] @feature eval system -> somehow evaluate breakpoint hit counts? "meta"
|
||||
// variables?
|
||||
// [ ] @feature watch window labels
|
||||
// [ ] @feature scheduler -> thread grid view?
|
||||
// [ ] @feature global entry point overrides (settings)
|
||||
//
|
||||
// [ ] @feature disasm view improvement features
|
||||
// [ ] interleaved src/dasm view
|
||||
@@ -143,7 +383,9 @@
|
||||
// [ ] serializing eval view maps
|
||||
// [ ] view rule editors in hover-eval
|
||||
// [ ] view rule hook coverage
|
||||
// [ ] `each:(expr addition)` - apply some additional expression to all elements in an array/linked list would be useful to look at only a subset of an array of complex structs
|
||||
// [ ] `each:(expr addition)` - apply some additional expression to all
|
||||
// elements in an array/linked list would be useful to look at only a
|
||||
// subset of an array of complex structs
|
||||
// [ ] `slider:(min max)` view rule
|
||||
// [ ] `v2f32` view rule
|
||||
// [ ] `v3` view rule
|
||||
@@ -153,48 +395,10 @@
|
||||
// [ ] smart scopes - expression operators for "grab me the first type X"
|
||||
// [ ] "pinning" watch expressions, to attach it to a particular ctrl_ctx
|
||||
//
|
||||
// [ ] @feature header file for target -> debugger communication; printf, log, etc.
|
||||
// [ ] @feature header file for target -> debugger communication; printf, log,
|
||||
// etc.
|
||||
// [ ] @feature just-in-time debugging
|
||||
// [ ] @feature step-out-of-loop
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Unsorted User Notes
|
||||
//
|
||||
//-[ ] jeff notes
|
||||
// [ ] keyboard controls & copy/paste in disasm view
|
||||
// [ ] disasm animation unexpected and/or annoying
|
||||
//
|
||||
//-[ ] notes from allen
|
||||
// [ ] 'browse' in modules debug info map editor
|
||||
// [ ] debug info map revisit... ctrl thread needs to know string -> string, not just handle -> string
|
||||
// [ ] panel-split options in right-click menu. maybe just do the full
|
||||
// 'contextual ctx menu stack' thing here? then ctx menus buried deep in
|
||||
// the callstack still gather all the right stuff...
|
||||
// [ ] ui color pallette inspector/editor - function which takes ui_box -> theme_color
|
||||
// [ ] watch-window-wide view rule
|
||||
//
|
||||
//-[ ] short-term major issues from martins
|
||||
// [ ] F10/F5 is not stepping over line, if line invokes macro with bunch of code (if checks, functions
|
||||
// calls) then debugger thinks there is a breakpoint on every condition? or every function call? so
|
||||
// I hits my breakpoint multiple times when I just want to get over it
|
||||
//
|
||||
//-[ ] short-term minor issues from martins
|
||||
// [ ] can it ignore stepping into _RTC_CheckStackVars generated functions?
|
||||
// [ ] mouse back button should make view to go back after I double clicked on function to open it
|
||||
// [ ] middle mouse button on tab should close it
|
||||
// [ ] pressing random keyboard keys in source code advances text cursor like you were inputting text, very strange.
|
||||
// [ ] Alt+8 to switch to disassembly would be nice (regardless on which panel was previous, don't want to use ctrl+, multiple times)
|
||||
// Alt+8 for disasm and Alt+6 for memory view are shortcuts I often use in VS
|
||||
// [ ] what's up with decimal number coloring where every group of 3 are in different color? can I turn it off? And why sometimes digits in number start with brighter color, but sometimes with darker - shouldn't it always have the same color ordering?
|
||||
// [ ] it would be nice to have "show in explorer" for right click on source file tab (opens explorer & selects the file)
|
||||
// [ ] it would be nice if Alt+o in source file would switch between .h and .c/cpp file (just look for same name in same folder)
|
||||
// [ ] in watch window when I enter some new expression and then click mouse away from cell, then it should behave the same as if I pressed enter. Currently it does the same as if I have pressed esc and I have lost my expression
|
||||
// [ ] navigation in watch window cells (not text editing, but which cell is selected) is bad - home/end/pgup/pgdown buttons navigate not where I expect (and with ctrl combination too)
|
||||
// [ ] for big source files the scrollbar element for active position is a bit to small - maybe have min size it never goes below (like 50px or maybe exactly 1 line of source code in height)
|
||||
// [ ] default font size is too small for me - not only source code, but menus/tab/watch names (which don't resize). Maybe you could query Windows for initial font size?
|
||||
// [ ] zooming behaves very strangely - sometimes it zooms source code, sometimes both source code and menu/tab/watch font size, sometimes just menu/tab/watch font size not source size.
|
||||
// [ ] icon fonts glyphs sometimes disappear for specific font size, but they reappear if you go +1 higher or -1 lower. Mostly red triangle in watch values for "unknown identifier". But also yellow arrow in call stack disappears if font size gets too large.
|
||||
// [ ] undo close tab would be nice. If not for everything, then at least just for source files
|
||||
//
|
||||
//-[ ] long-term future notes from martins
|
||||
// [ ] core dump saving/loading
|
||||
@@ -204,163 +408,29 @@
|
||||
// - it seems python has a top-level linked list of interpreter states,
|
||||
// which should allow the debugger to map native callstacks to python
|
||||
// code
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Long-Term Deferred Polish & Improvements
|
||||
//
|
||||
// [ ] fancy string runs can include "weakness" information for text truncation... can prioritize certain parts of strings to be truncated before others. would be good for e.g. the middle of a path
|
||||
// [ ] fancy string runs can include "weakness" information for text truncation
|
||||
// ... can prioritize certain parts of strings to be truncated before
|
||||
// others. would be good for e.g. the middle of a path
|
||||
// [ ] ui code maintenance, simplification, design, & robustness pass
|
||||
// [ ] page-up & page-down correct handling in keyboard nav
|
||||
// [ ] collapse context menus & command lister into same codepaths. filter by context. parameterize by context.
|
||||
// [ ] collapse context menus & command lister into same codepaths. filter by
|
||||
// context. parameterize by context.
|
||||
// [ ] collapse text cells & command lister & etc. into same codepath (?)
|
||||
// [ ] nested context menus
|
||||
// [ ] unified top-level cursor/typing/lister helper
|
||||
// [ ] font selection lister
|
||||
// [ ] font cache eviction (both for font tags, closing fp handles, and rasterizations)
|
||||
// [ ] font cache eviction (both for font tags, closing fp handles, and
|
||||
// rasterizations)
|
||||
// [ ] frontend speedup opportunities
|
||||
// [ ] tables in UI -> currently building per-row, could probably cut down on # of boxes and # of draws by doing per-column in some cases?
|
||||
// [ ] font cache layer -> can probably cache (string*font*size) -> (run) too (not just rasterization)... would save a *lot*, there is a ton of work just in looking up & stitching stuff repeatedly
|
||||
// [ ] tables in UI -> currently building per-row, could probably cut down on
|
||||
// # of boxes and # of draws by doing per-column in some cases?
|
||||
// [ ] font cache layer -> can probably cache (string*font*size) -> (run) too
|
||||
// (not just rasterization)... would save a *lot*, there is a ton of work
|
||||
// just in looking up & stitching stuff repeatedly
|
||||
// [ ] convert UI layout pass to not be naive recursive version
|
||||
// [ ] (big change) parallelize window ui build codepaths per-panel
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Completed Tasks
|
||||
//
|
||||
// [x] adding watches to source locations
|
||||
// [x] tab overflow buttons
|
||||
// [x] "working set" of targets, just used 'enabled' slot on target entities
|
||||
// [x] convert hover-eval ui to a frontend-wide global ui concept, so that we can have watch-hover trees from anywhere
|
||||
// [x] annotate code slices with relevant watches
|
||||
// [x] ability to duplicate targets easily
|
||||
// [x] ability to label targets separately from their EXE
|
||||
//
|
||||
// [x] txti layer needs lexing
|
||||
// [x] dbgi autoconversion layer needs to work reliably
|
||||
// [x] new dbgi system on frontend
|
||||
// [x] new bini system on frontend
|
||||
// [x] new dbgi system needs in-parallel typegraph builders
|
||||
// [x] eval is busted
|
||||
// [x] fail or debug non-text
|
||||
// [x] clean loading
|
||||
// [x] watch pins
|
||||
// [x] snapping should still work if a file is loading while the snap first occurs
|
||||
// [x] keyboard usage (set-next-statement, run-to-line, etc.)
|
||||
// [x] go-to-name (both file & symbol)
|
||||
//
|
||||
// [x] in-memory disassembly view
|
||||
// [x] visualize conversion tasks as they occur
|
||||
// [x] raddbg.exe self-sufficiency => built-in converter execution mode
|
||||
// [x] move path-mapping fallback from pending-entity into code view
|
||||
// [x] per-target entry point overrides
|
||||
// [x] logic on when double click on callstack entry goes to source or disassembly is very confusing,
|
||||
// because it seems it matters whether disassembly tab is in same panel as source, or is placed in
|
||||
// different panel in VS double clicking on stack stays in disassembly if disassembly tab is currently
|
||||
// active. Otherwise if source is active, it goes to source code (regardless if disasm is open/visible
|
||||
// or not)
|
||||
// [x] global variable (just regular C++ bool in the same file) does not show value when hovering over source
|
||||
// code, or when put into watch window.
|
||||
//
|
||||
// [x] debugger ui thread needs wakeup when a debug event is hit
|
||||
// [x] ctrl thread needs to re-resolve breakpoints as modules/threads come in during a run
|
||||
// [x] automatically pull in members from containing struct in member functions
|
||||
// when looking up locals
|
||||
// [x] iron out weird state machine bugs with hover-eval
|
||||
//
|
||||
// [x] thread-local eval
|
||||
// [x] tabs in source code render as squares
|
||||
//
|
||||
// [x] breakpoint stop-conditions
|
||||
// [x] first-chance exception hitting (d3d11 as an example offender)
|
||||
// [x] soft-halt refresh
|
||||
//
|
||||
// [x] conditional breakpoints cannot be submitted if they don't compile
|
||||
// need to (a) visualize and (b) equip the ctrl thread with a 'halt on
|
||||
// new debug info feature', which can be done repeatedly until something
|
||||
// compiles (?)
|
||||
//
|
||||
// [x] outputdebugstring logs
|
||||
//
|
||||
// [x] memory view
|
||||
//
|
||||
// [x] when application starts then the focus is on cmd.exe window of application not
|
||||
// debugger. This means if I press F11 to step into main(), the application cmd.exe will go fullscreen
|
||||
// hiding debugger (F11 key for ConEmu I use makes it go fullscreen)
|
||||
// [x] I'd prefer if ctrl+click on word would go to function definition, not double click
|
||||
// double clicking in source code should select word - which easy way to double click and ctrl+c to copy
|
||||
// it, pretty much standard thing in any text editorr/viewer and triple click for selecting whole line
|
||||
// [x] command line DF_CfgSrc -> explicitly visualize as temporary, provide UI
|
||||
// path to make permanent (in either user or profile?)
|
||||
//
|
||||
// [x] memory view annotations: bytes in a range of memory actually have a
|
||||
// *stack* of possible interpretations, for any particular low-level
|
||||
// representation (assuming 1 is fine for this case). a U32 member in
|
||||
// a local struct on the stack has 3 layers: U32 -> local -> stack.
|
||||
// each of these are useful information about that U32's range of bytes.
|
||||
// so, the memory view annotation system ought to be expanded to support-
|
||||
// ing stacks of annotations, and gracefully visualizing multiple nested
|
||||
// ones. after that is supported, we can use the type info to derive the
|
||||
// lowest level representation of some bytes. each stack can only have
|
||||
// one low-level type. that low-level type, then, can be used to directly
|
||||
// interpret the bytes - the others can be used to show the "conceptual
|
||||
// stack".
|
||||
//
|
||||
// [x] entity tree ui replacement (scheduler, modules, breakpoints, pins)
|
||||
// [x] theme menu
|
||||
// [x] complete transition to UI_ScrollPt coordinate space scrolling - eliminate
|
||||
// old scrolls & scroll regions
|
||||
// [x] settings menu
|
||||
// [x] exception filter settings & controls in ctrl layer
|
||||
//
|
||||
// [x] @polish @cleanup convert eval/watch to scroll list
|
||||
// [x] @feature memory view keyboard navigation
|
||||
// [x] @bug fix general ui line edit editing rules - conflicting with navigation, etc.
|
||||
// [x] @polish have expander space even if not used in watch window
|
||||
// [x] @bug references do not expand properly
|
||||
// [x] @bug panel deletion improper size bug
|
||||
// [x] @bug panel serialization/deserialization bug?
|
||||
// [x] unfinished char/string literal lexing
|
||||
//
|
||||
// [x] C++ problems in watch window: evaluating "this" shows no members. The type seems correct reference
|
||||
// to struct (which is local variable) does not show any members, like I have "tm_mem_zone_rt& z = ..."
|
||||
// in source code, and doing "z" produces no children, nor does "&z" but then at least it shows correct
|
||||
// address as value. if I ask for member of this when currently inside of member function (like "m_zone_stack")
|
||||
// it shows "unknown identifier m_zone_stack" but "this->m_zone_stack" works fine!
|
||||
// [x] if I write x'z in watch window and press enter, it only shows x and loses 'z - it does not show it, but when I edit cell then 'z comes back. It pretends I entered just x and shows x value.
|
||||
// [x] it seems the glyph advance for default font size is kind of wrong, as characters are a blitted a bit over top of each other
|
||||
//
|
||||
// [x] @bug deleting a watch tree while it is expanded causes cursor to go back to first row - cannot simply increment cursor. maybe keep in same spot, but rebuild viz blocks?
|
||||
// [x] @bug do not squish partially-cut-off view rule block uis
|
||||
// [x] @feature "solo step", or "solo mode" freeze-all-unselected-threads-on-step-commands
|
||||
// [x] @feature typing autocomplete lister
|
||||
// [x] @feature directional navigation of panel focus
|
||||
// [x] @cleanup @feature cache eviction in texture cache & hash store
|
||||
//
|
||||
//- 2023/12/7
|
||||
//
|
||||
// [x] @bug hash store cache eviction can only work if user never blindly tries to go from hash -> data, because
|
||||
// they must be able to retry... hmm...
|
||||
// [x] txt cell revamp. keyboard focus in both default & non w/ multiple options, helper lister, etc.
|
||||
// [x] `bitmap:(w:width, h:height, [fmt:fmt])` - interpret memory as raw bitmap data
|
||||
// [x] `geo:n[ topology stride]` - interpret memory as geometry
|
||||
// [x] cursor helper -> upgraded txt cell. classify inputs & show dropdowns (locals, globals, types, view rules, etc.)
|
||||
// [x] @bug page-up and page-down in src view, when near the end of file
|
||||
//
|
||||
//- 2023/12/8
|
||||
//
|
||||
// [x] @bug parse `unsigned int` correctly in eval parser
|
||||
// [x] @bug ., + operators should work on registers
|
||||
// [x] @bug straighten out register eval problems
|
||||
// [x] @cleanup finish ui_em transition
|
||||
//
|
||||
//- 2023/12/22
|
||||
//
|
||||
// [x] @bug set-bp-while-running seems to not resume after soft-halt, might be a soft-halt bug
|
||||
// [x] @bug weird view snapping in watch scrolling down
|
||||
//
|
||||
//- 2024/01/10
|
||||
//
|
||||
// [x] @feature allow `,count`, `,x`, `,b` style watch window expression extensions, which add to view rule, for VS-like behavior fastpaths
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Includes
|
||||
|
||||
@@ -466,12 +536,14 @@ struct IPCInfo
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Top-Level Execution Globals
|
||||
//~ rjf: Globals
|
||||
|
||||
#define IPC_SHARED_MEMORY_BUFFER_SIZE MB(16)
|
||||
StaticAssert(IPC_SHARED_MEMORY_BUFFER_SIZE > sizeof(IPCInfo), ipc_buffer_size_requirement);
|
||||
read_only global String8 ipc_shared_memory_name = str8_lit_comp("_raddbg_ipc_shared_memory_");
|
||||
read_only global String8 ipc_semaphore_name = str8_lit_comp("_raddbg_ipc_semaphore_");
|
||||
global U64 frame_time_us_history[64] = {0};
|
||||
global U64 frame_time_us_history_idx = 0;
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Frontend Entry Points
|
||||
@@ -488,9 +560,44 @@ update_and_render(OS_Handle repaint_window_handle, void *user_data)
|
||||
geo_user_clock_tick();
|
||||
tex_user_clock_tick();
|
||||
|
||||
//- rjf: pick delta-time
|
||||
// TODO(rjf): maximize, given all windows and their monitors
|
||||
F32 dt = 1.f/os_default_refresh_rate();
|
||||
//- rjf: pick target hz
|
||||
// TODO(rjf): maximize target, given all windows and their monitors
|
||||
F32 target_hz = os_default_refresh_rate();
|
||||
if(frame_time_us_history_idx > 32)
|
||||
{
|
||||
// rjf: calculate average frame time out of the last N
|
||||
U64 num_frames_in_history = Min(ArrayCount(frame_time_us_history), frame_time_us_history_idx);
|
||||
U64 frame_time_history_sum_us = 0;
|
||||
for(U64 idx = 0; idx < num_frames_in_history; idx += 1)
|
||||
{
|
||||
frame_time_history_sum_us += frame_time_us_history[idx];
|
||||
}
|
||||
U64 frame_time_history_avg_us = frame_time_history_sum_us/num_frames_in_history;
|
||||
|
||||
// rjf: pick among a number of sensible targets to snap to, given how well
|
||||
// we've been performing
|
||||
F32 possible_alternate_hz_targets[] = {target_hz, 60.f, 120.f, 144.f, 240.f};
|
||||
F32 best_target_hz = target_hz;
|
||||
S64 best_target_hz_frame_time_us_diff = max_S64;
|
||||
for(U64 idx = 0; idx < ArrayCount(possible_alternate_hz_targets); idx += 1)
|
||||
{
|
||||
F32 candidate = possible_alternate_hz_targets[idx];
|
||||
if(candidate <= target_hz)
|
||||
{
|
||||
U64 candidate_frame_time_us = 1000000/(U64)candidate;
|
||||
S64 frame_time_us_diff = (S64)frame_time_history_avg_us - (S64)candidate_frame_time_us;
|
||||
if(abs_s64(frame_time_us_diff) < best_target_hz_frame_time_us_diff)
|
||||
{
|
||||
best_target_hz = candidate;
|
||||
best_target_hz_frame_time_us_diff = frame_time_us_diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
target_hz = best_target_hz;
|
||||
}
|
||||
|
||||
//- rjf: target Hz -> delta time
|
||||
F32 dt = 1.f/target_hz;
|
||||
|
||||
//- rjf: get events from the OS
|
||||
OS_EventList events = {0};
|
||||
@@ -499,6 +606,9 @@ update_and_render(OS_Handle repaint_window_handle, void *user_data)
|
||||
events = os_get_events(scratch.arena, df_gfx_state->num_frames_requested == 0);
|
||||
}
|
||||
|
||||
//- rjf: begin measuring actual per-frame work
|
||||
U64 begin_time_us = os_now_microseconds();
|
||||
|
||||
//- rjf: bind change
|
||||
if(df_gfx_state->bind_change_active)
|
||||
{
|
||||
@@ -717,6 +827,12 @@ update_and_render(OS_Handle repaint_window_handle, void *user_data)
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: determine frame time, record into history
|
||||
U64 end_time_us = os_now_microseconds();
|
||||
U64 frame_time_us = end_time_us-begin_time_us;
|
||||
frame_time_us_history[frame_time_us_history_idx%ArrayCount(frame_time_us_history)] = frame_time_us;
|
||||
frame_time_us_history_idx += 1;
|
||||
|
||||
scratch_end(scratch);
|
||||
ProfEnd();
|
||||
}
|
||||
@@ -1066,6 +1182,7 @@ entry_point(int argc, char **argv)
|
||||
////////////////////////////////
|
||||
//~ rjf: Low-Level Entry Points
|
||||
|
||||
//- rjf: windows
|
||||
#if OS_WINDOWS
|
||||
|
||||
global DWORD g_saved_exception_code = 0;
|
||||
@@ -1137,7 +1254,10 @@ int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int n
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//- rjf: linux
|
||||
#elif OS_LINUX
|
||||
|
||||
int main(int argument_count, char **arguments)
|
||||
{
|
||||
static TCTX main_thread_tctx = {0};
|
||||
@@ -1145,4 +1265,5 @@ int main(int argument_count, char **arguments)
|
||||
entry_point(argument_count, arguments);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+18
-12
@@ -903,7 +903,7 @@ ui_begin_build(OS_EventList *events, OS_Handle window, UI_NavActionList *nav_act
|
||||
UI_FixedX(anchor.x) UI_FixedY(anchor.y) UI_PrefWidth(ui_children_sum(1.f)) UI_PrefHeight(ui_children_sum(1.f)) UI_Focus(ui_state->ctx_menu_open)
|
||||
{
|
||||
ui_set_next_child_layout_axis(Axis2_Y);
|
||||
ui_state->ctx_menu_root = ui_build_box_from_stringf(UI_BoxFlag_DrawDropShadow|(ui_state->ctx_menu_open*UI_BoxFlag_DefaultFocusNavY), "###ctx_menu_%I64x", window.u64[0]);
|
||||
ui_state->ctx_menu_root = ui_build_box_from_stringf(UI_BoxFlag_Clickable|UI_BoxFlag_DrawDropShadow|(ui_state->ctx_menu_open*UI_BoxFlag_DefaultFocusNavY), "###ctx_menu_%I64x", window.u64[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1015,16 +1015,6 @@ ui_end_build(void)
|
||||
ui_ctx_menu_close();
|
||||
}
|
||||
|
||||
//- rjf: close ctx menu if unconsumed clicks
|
||||
for(OS_Event *event = ui_events()->first; event != 0; event = event->next)
|
||||
{
|
||||
if(event->kind == OS_EventKind_Press && os_handle_match(event->window, ui_window()) &&
|
||||
(event->key == OS_Key_LeftMouseButton || event->key == OS_Key_RightMouseButton))
|
||||
{
|
||||
ui_ctx_menu_close();
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: stick ctx menu to anchor
|
||||
if(ui_state->ctx_menu_touched_this_frame)
|
||||
{
|
||||
@@ -1214,6 +1204,22 @@ ui_end_build(void)
|
||||
root->rect.y1 = root->rect.y0 + dim_2f32(rect).y * ui_state->ctx_menu_open_t;
|
||||
}
|
||||
|
||||
//- rjf: fall-through interact with context menu
|
||||
if(ui_state->ctx_menu_open)
|
||||
{
|
||||
ui_signal_from_box(ui_state->ctx_menu_root);
|
||||
}
|
||||
|
||||
//- rjf: close ctx menu if unconsumed clicks
|
||||
for(OS_Event *event = ui_events()->first; event != 0; event = event->next)
|
||||
{
|
||||
if(event->kind == OS_EventKind_Press && os_handle_match(event->window, ui_window()) &&
|
||||
(event->key == OS_Key_LeftMouseButton || event->key == OS_Key_RightMouseButton))
|
||||
{
|
||||
ui_ctx_menu_close();
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: hover cursor
|
||||
{
|
||||
UI_Box *hot = ui_box_from_key(ui_state->hot_box_key);
|
||||
@@ -2304,7 +2310,7 @@ ui_signal_from_box(UI_Box *box)
|
||||
B32 ctx_menu_is_ancestor = 0;
|
||||
ProfScope("check context menu ancestor")
|
||||
{
|
||||
for(UI_Box *parent = box->parent; !ui_box_is_nil(parent); parent = parent->parent)
|
||||
for(UI_Box *parent = box; !ui_box_is_nil(parent); parent = parent->parent)
|
||||
{
|
||||
if(parent == ui_state->ctx_menu_root)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user