Merge pull request #1438 from pj64d-merge/memlocks
[Debugger] Add memory locks feature (interpreter)
This commit is contained in:
commit
1a6c579d3e
|
@ -321,6 +321,13 @@ void CInterpreterCPU::ExecuteCPU()
|
||||||
if (CDebugSettings::HaveDebugger())
|
if (CDebugSettings::HaveDebugger())
|
||||||
{
|
{
|
||||||
g_Debugger->CPUStepStarted();
|
g_Debugger->CPUStepStarted();
|
||||||
|
|
||||||
|
if (SkipOp())
|
||||||
|
{
|
||||||
|
g_Settings->SaveBool(Debugger_SkipOp, false);
|
||||||
|
PROGRAM_COUNTER += 4;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if (PROGRAM_COUNTER > 0x80000300 && PROGRAM_COUNTER < 0x80380000)
|
/* if (PROGRAM_COUNTER > 0x80000300 && PROGRAM_COUNTER < 0x80380000)
|
||||||
|
|
|
@ -238,6 +238,21 @@ CBreakpoints::BPSTATE CBreakpoints::WriteBPExists64(uint32_t address)
|
||||||
return BP_NOT_SET;
|
return BP_NOT_SET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CBreakpoints::BPSTATE CBreakpoints::WriteBPExistsInChunk(uint32_t address, uint32_t nBytes)
|
||||||
|
{
|
||||||
|
uint32_t endAddr = address + nBytes;
|
||||||
|
|
||||||
|
for (breakpoints_t::iterator breakpoint = m_WriteMem.begin(); breakpoint != m_WriteMem.end(); breakpoint++)
|
||||||
|
{
|
||||||
|
uint32_t wbpAddr = breakpoint->first;
|
||||||
|
if (wbpAddr >= address && wbpAddr < endAddr)
|
||||||
|
{
|
||||||
|
return BP_SET;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return BP_NOT_SET;
|
||||||
|
}
|
||||||
|
|
||||||
CBreakpoints::BPSTATE CBreakpoints::ExecutionBPExists(uint32_t address, bool bRemoveTemp)
|
CBreakpoints::BPSTATE CBreakpoints::ExecutionBPExists(uint32_t address, bool bRemoveTemp)
|
||||||
{
|
{
|
||||||
breakpoints_t::const_iterator itr = m_Execution.find(address);
|
breakpoints_t::const_iterator itr = m_Execution.find(address);
|
||||||
|
@ -283,3 +298,35 @@ void CBreakpoints::UpdateAlignedWriteBP()
|
||||||
m_WriteMem64.insert(breakpoints_t::value_type((itr->first & ~0x7), false));
|
m_WriteMem64.insert(breakpoints_t::value_type((itr->first & ~0x7), false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CBreakpoints::ToggleMemLock(uint32_t address)
|
||||||
|
{
|
||||||
|
if (m_MemLocks.count(address) == 0)
|
||||||
|
{
|
||||||
|
m_MemLocks.insert(address);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_MemLocks.erase(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBreakpoints::MemLockExists(uint32_t address, int nBytes)
|
||||||
|
{
|
||||||
|
for (memlocks_t::const_iterator itr = m_MemLocks.begin(); itr != m_MemLocks.end(); itr++)
|
||||||
|
{
|
||||||
|
if (*itr >= address && *itr < (address + nBytes))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBreakpoints::ClearMemLocks()
|
||||||
|
{
|
||||||
|
m_MemLocks.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t CBreakpoints::NumMemLocks()
|
||||||
|
{
|
||||||
|
return m_MemLocks.size();
|
||||||
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ public:
|
||||||
typedef std::map<uint32_t /*address*/, bool /*bTemporary*/> breakpoints_t;
|
typedef std::map<uint32_t /*address*/, bool /*bTemporary*/> breakpoints_t;
|
||||||
typedef breakpoints_t::const_iterator breakpoint_t;
|
typedef breakpoints_t::const_iterator breakpoint_t;
|
||||||
|
|
||||||
|
typedef std::set<uint32_t> memlocks_t;
|
||||||
|
|
||||||
enum BPSTATE
|
enum BPSTATE
|
||||||
{
|
{
|
||||||
BP_NOT_SET,
|
BP_NOT_SET,
|
||||||
|
@ -40,6 +42,7 @@ public:
|
||||||
BPSTATE WriteBPExists16(uint32_t address);
|
BPSTATE WriteBPExists16(uint32_t address);
|
||||||
BPSTATE WriteBPExists32(uint32_t address);
|
BPSTATE WriteBPExists32(uint32_t address);
|
||||||
BPSTATE WriteBPExists64(uint32_t address);
|
BPSTATE WriteBPExists64(uint32_t address);
|
||||||
|
BPSTATE WriteBPExistsInChunk(uint32_t address, uint32_t nBytes);
|
||||||
BPSTATE ExecutionBPExists(uint32_t address, bool bRemoveTemp = false);
|
BPSTATE ExecutionBPExists(uint32_t address, bool bRemoveTemp = false);
|
||||||
|
|
||||||
bool RBPAdd(uint32_t address);
|
bool RBPAdd(uint32_t address);
|
||||||
|
@ -59,6 +62,11 @@ public:
|
||||||
|
|
||||||
void BPClear();
|
void BPClear();
|
||||||
|
|
||||||
|
void ToggleMemLock(uint32_t address);
|
||||||
|
bool MemLockExists(uint32_t address, int nBytes);
|
||||||
|
void ClearMemLocks(void);
|
||||||
|
size_t NumMemLocks(void);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void UpdateAlignedWriteBP(void);
|
void UpdateAlignedWriteBP(void);
|
||||||
void UpdateAlignedReadBP(void);
|
void UpdateAlignedReadBP(void);
|
||||||
|
@ -66,4 +74,6 @@ private:
|
||||||
breakpoints_t m_ReadMem, m_ReadMem16, m_ReadMem32, m_ReadMem64;
|
breakpoints_t m_ReadMem, m_ReadMem16, m_ReadMem32, m_ReadMem64;
|
||||||
breakpoints_t m_WriteMem, m_WriteMem16, m_WriteMem32, m_WriteMem64;
|
breakpoints_t m_WriteMem, m_WriteMem16, m_WriteMem32, m_WriteMem64;
|
||||||
breakpoints_t m_Execution;
|
breakpoints_t m_Execution;
|
||||||
|
|
||||||
|
memlocks_t m_MemLocks;
|
||||||
};
|
};
|
|
@ -583,7 +583,7 @@ void CDebugCommandsView::ShowAddress(uint32_t address, bool top)
|
||||||
const char* annotation = NULL;
|
const char* annotation = NULL;
|
||||||
bool bLoadStoreAnnotation = false;
|
bool bLoadStoreAnnotation = false;
|
||||||
|
|
||||||
if (OpInfo.IsLoadStore())
|
if (OpInfo.IsLoadStoreCommand())
|
||||||
{
|
{
|
||||||
for (int offset = -4; offset > -24; offset -= 4)
|
for (int offset = -4; offset > -24; offset -= 4)
|
||||||
{
|
{
|
||||||
|
@ -1413,7 +1413,7 @@ LRESULT CDebugCommandsView::OnCommandListRightClicked(NMHDR* pNMHDR)
|
||||||
EnableMenuItem(hPopupMenu, ID_POPUPMENU_FOLLOWJUMP, MF_DISABLED | MF_GRAYED);
|
EnableMenuItem(hPopupMenu, ID_POPUPMENU_FOLLOWJUMP, MF_DISABLED | MF_GRAYED);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_SelectedOpInfo.IsLoadStore())
|
if (m_SelectedOpInfo.IsLoadStoreCommand())
|
||||||
{
|
{
|
||||||
m_FollowAddress = g_Reg->m_GPR[m_SelectedOpCode.base].UW[0] + (int16_t)m_SelectedOpCode.offset;
|
m_FollowAddress = g_Reg->m_GPR[m_SelectedOpCode.base].UW[0] + (int16_t)m_SelectedOpCode.offset;
|
||||||
}
|
}
|
||||||
|
|
|
@ -219,6 +219,14 @@ LRESULT CDebugMemoryView::OnClicked(WORD /*wNotifyCode*/, WORD wID, HWND, BOOL&
|
||||||
m_Breakpoints->WBPClear();
|
m_Breakpoints->WBPClear();
|
||||||
RefreshMemory(true);
|
RefreshMemory(true);
|
||||||
break;
|
break;
|
||||||
|
case ID_POPUPMENU_TOGGLELOCK:
|
||||||
|
m_Breakpoints->ToggleMemLock(m_CtxMenuAddr);
|
||||||
|
RefreshMemory(true);
|
||||||
|
break;
|
||||||
|
case ID_POPUPMENU_CLEARLOCKS:
|
||||||
|
m_Breakpoints->ClearMemLocks();
|
||||||
|
RefreshMemory(true);
|
||||||
|
break;
|
||||||
case ID_POPUPMENU_VIEWDISASM:
|
case ID_POPUPMENU_VIEWDISASM:
|
||||||
m_Debugger->Debug_ShowCommandsLocation(m_CtxMenuAddr, true);
|
m_Debugger->Debug_ShowCommandsLocation(m_CtxMenuAddr, true);
|
||||||
break;
|
break;
|
||||||
|
@ -248,6 +256,10 @@ LRESULT CDebugMemoryView::OnMemoryRightClicked(LPNMHDR lpNMHDR)
|
||||||
{
|
{
|
||||||
EnableMenuItem(hPopupMenu, ID_POPUPMENU_CLEARALLBPS, MF_DISABLED | MF_GRAYED);
|
EnableMenuItem(hPopupMenu, ID_POPUPMENU_CLEARALLBPS, MF_DISABLED | MF_GRAYED);
|
||||||
}
|
}
|
||||||
|
if (m_Breakpoints->NumMemLocks() == 0)
|
||||||
|
{
|
||||||
|
EnableMenuItem(hPopupMenu, ID_POPUPMENU_CLEARLOCKS, MF_DISABLED | MF_GRAYED);
|
||||||
|
}
|
||||||
|
|
||||||
POINT mouse;
|
POINT mouse;
|
||||||
GetCursorPos(&mouse);
|
GetCursorPos(&mouse);
|
||||||
|
@ -721,12 +733,17 @@ void CDebugMemoryView::SelectColors(uint32_t vaddr, bool changed, COLORREF& bgCo
|
||||||
|
|
||||||
CSymbols::LeaveCriticalSection();
|
CSymbols::LeaveCriticalSection();
|
||||||
|
|
||||||
|
bool bLocked = m_Breakpoints->MemLockExists(vaddr, 1);
|
||||||
bool bHaveReadBP = m_Breakpoints->ReadBPExists8(vaddr) == CBreakpoints::BP_SET;
|
bool bHaveReadBP = m_Breakpoints->ReadBPExists8(vaddr) == CBreakpoints::BP_SET;
|
||||||
bool bHaveWriteBP = m_Breakpoints->WriteBPExists8(vaddr) == CBreakpoints::BP_SET;
|
bool bHaveWriteBP = m_Breakpoints->WriteBPExists8(vaddr) == CBreakpoints::BP_SET;
|
||||||
|
|
||||||
fgHiColor = RGB(0x00, 0x00, 0x00);
|
fgHiColor = RGB(0x00, 0x00, 0x00);
|
||||||
|
|
||||||
if (bHaveReadBP && bHaveWriteBP)
|
if (bLocked)
|
||||||
|
{
|
||||||
|
bgColor = RGB(0xDD, 0xAA, 0xAA);
|
||||||
|
}
|
||||||
|
else if (bHaveReadBP && bHaveWriteBP)
|
||||||
{
|
{
|
||||||
bgColor = RGB(0xAA, 0xDD, 0xDD);
|
bgColor = RGB(0xAA, 0xDD, 0xDD);
|
||||||
}
|
}
|
||||||
|
|
|
@ -394,14 +394,13 @@ void CDebuggerUI::CPUStepStarted()
|
||||||
|
|
||||||
// Memory breakpoints
|
// Memory breakpoints
|
||||||
|
|
||||||
OPCODE Opcode = R4300iOp::m_Opcode;
|
COpInfo opInfo(R4300iOp::m_Opcode);
|
||||||
uint32_t op = Opcode.op;
|
|
||||||
|
|
||||||
if (op >= R4300i_LDL && op <= R4300i_SD && op != R4300i_CACHE) // Read and write instructions
|
if (opInfo.IsLoadStoreCommand()) // Read and write instructions
|
||||||
{
|
{
|
||||||
uint32_t memoryAddress = g_Reg->m_GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset;
|
uint32_t memoryAddress = opInfo.GetLoadStoreAddress();
|
||||||
|
|
||||||
if ((op <= R4300i_LWU || (op >= R4300i_LL && op <= R4300i_LD))) // Read instructions
|
if (opInfo.IsLoadCommand()) // Read instructions
|
||||||
{
|
{
|
||||||
m_ScriptSystem->HookCPURead()->InvokeByParamInRange(memoryAddress);
|
m_ScriptSystem->HookCPURead()->InvokeByParamInRange(memoryAddress);
|
||||||
|
|
||||||
|
@ -419,20 +418,19 @@ void CDebuggerUI::CPUStepStarted()
|
||||||
{
|
{
|
||||||
uint32_t dmaRomAddr = g_Reg->PI_CART_ADDR_REG & 0x0FFFFFFF;
|
uint32_t dmaRomAddr = g_Reg->PI_CART_ADDR_REG & 0x0FFFFFFF;
|
||||||
uint32_t dmaRamAddr = g_Reg->PI_DRAM_ADDR_REG | 0x80000000;
|
uint32_t dmaRamAddr = g_Reg->PI_DRAM_ADDR_REG | 0x80000000;
|
||||||
uint32_t dmaLen = g_Reg->m_GPR[Opcode.rt].UW[0] + 1;
|
uint32_t dmaLen = opInfo.GetStoreValueUnsigned() + 1;
|
||||||
uint32_t endAddr = dmaRamAddr + dmaLen;
|
|
||||||
|
|
||||||
m_DMALog->AddEntry(dmaRomAddr, dmaRamAddr, dmaLen);
|
m_DMALog->AddEntry(dmaRomAddr, dmaRamAddr, dmaLen);
|
||||||
|
|
||||||
CBreakpoints::breakpoints_t breakpoints = m_Breakpoints->WriteMem();
|
if (m_Breakpoints->WriteBPExistsInChunk(dmaRamAddr, dmaLen))
|
||||||
for (CBreakpoints::breakpoints_t::iterator breakpoint = breakpoints.begin(); breakpoint != breakpoints.end(); breakpoint++)
|
|
||||||
{
|
|
||||||
uint32_t wbpAddr = breakpoint->first;
|
|
||||||
if (wbpAddr >= dmaRamAddr && wbpAddr < endAddr)
|
|
||||||
{
|
{
|
||||||
goto breakpoint_hit;
|
goto breakpoint_hit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_Breakpoints->MemLockExists(memoryAddress, opInfo.NumBytesToStore()))
|
||||||
|
{
|
||||||
|
g_Settings->SaveBool(Debugger_SkipOp, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,15 @@ public:
|
||||||
|
|
||||||
OPCODE m_OpCode;
|
OPCODE m_OpCode;
|
||||||
|
|
||||||
|
COpInfo()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline COpInfo(OPCODE opcode):
|
||||||
|
m_OpCode(opcode)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
bool IsStaticJump()
|
bool IsStaticJump()
|
||||||
{
|
{
|
||||||
// j, jal
|
// j, jal
|
||||||
|
@ -131,11 +140,16 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsLoadStore()
|
inline bool IsLoadStoreCommand()
|
||||||
{
|
{
|
||||||
return (m_OpCode.op >= R4300i_LDL && m_OpCode.op <= R4300i_SD && m_OpCode.op != R4300i_CACHE);
|
return (m_OpCode.op >= R4300i_LDL && m_OpCode.op <= R4300i_SD && m_OpCode.op != R4300i_CACHE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool IsLoadCommand()
|
||||||
|
{
|
||||||
|
return (m_OpCode.op <= R4300i_LWU || (m_OpCode.op >= R4300i_LL && m_OpCode.op <= R4300i_LD));
|
||||||
|
}
|
||||||
|
|
||||||
bool IsStackShift()
|
bool IsStackShift()
|
||||||
{
|
{
|
||||||
return (m_OpCode.op == R4300i_ADDIU || m_OpCode.op == R4300i_ADDI) && m_OpCode.rt == 29;
|
return (m_OpCode.op == R4300i_ADDIU || m_OpCode.op == R4300i_ADDI) && m_OpCode.rt == 29;
|
||||||
|
@ -323,4 +337,53 @@ public:
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline uint32_t GetLoadStoreAddress()
|
||||||
|
{
|
||||||
|
return g_Reg->m_GPR[m_OpCode.base].UW[0] + (int16_t)m_OpCode.offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint32_t GetStoreValueUnsigned()
|
||||||
|
{
|
||||||
|
return g_Reg->m_GPR[m_OpCode.rt].UW[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int NumBytesToLoad()
|
||||||
|
{
|
||||||
|
switch (m_OpCode.op)
|
||||||
|
{
|
||||||
|
case R4300i_LB:
|
||||||
|
case R4300i_LBU:
|
||||||
|
return 1;
|
||||||
|
case R4300i_LH:
|
||||||
|
case R4300i_LHU:
|
||||||
|
return 2;
|
||||||
|
case R4300i_LD:
|
||||||
|
case R4300i_LDL:
|
||||||
|
case R4300i_LDR:
|
||||||
|
case R4300i_LDC1:
|
||||||
|
return 8;
|
||||||
|
default:
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int NumBytesToStore()
|
||||||
|
{
|
||||||
|
switch (m_OpCode.op)
|
||||||
|
{
|
||||||
|
case R4300i_SB:
|
||||||
|
return 1;
|
||||||
|
case R4300i_SH:
|
||||||
|
return 2;
|
||||||
|
case R4300i_SD:
|
||||||
|
case R4300i_SDL:
|
||||||
|
case R4300i_SDR:
|
||||||
|
case R4300i_SDC1:
|
||||||
|
case R4300i_SDC2:
|
||||||
|
return 8;
|
||||||
|
default:
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
|
@ -685,7 +685,7 @@ BEGIN
|
||||||
PUSHBUTTON "...",IDC_SYMBOLS_BTN,357,1,17,15
|
PUSHBUTTON "...",IDC_SYMBOLS_BTN,357,1,17,15
|
||||||
PUSHBUTTON "Skip",IDC_SKIP_BTN,376,1,27,15,WS_DISABLED
|
PUSHBUTTON "Skip",IDC_SKIP_BTN,376,1,27,15,WS_DISABLED
|
||||||
PUSHBUTTON "Step",IDC_STEP_BTN,404,1,27,15,WS_DISABLED
|
PUSHBUTTON "Step",IDC_STEP_BTN,404,1,27,15,WS_DISABLED
|
||||||
PUSHBUTTON "St.Ovr", IDC_STEPOVER_BTN, 432, 1, 27, 15, WS_DISABLED
|
PUSHBUTTON "St.Ovr",IDC_STEPOVER_BTN,432,1,27,15,WS_DISABLED
|
||||||
PUSHBUTTON "Go",IDC_GO_BTN,460,1,27,15,WS_DISABLED
|
PUSHBUTTON "Go",IDC_GO_BTN,460,1,27,15,WS_DISABLED
|
||||||
LTEXT "PC",IDC_PC_STATIC,292,24,8,9
|
LTEXT "PC",IDC_PC_STATIC,292,24,8,9
|
||||||
EDITTEXT IDC_PC_EDIT,303,22,44,12,ES_UPPERCASE | ES_AUTOHSCROLL,WS_EX_RIGHT
|
EDITTEXT IDC_PC_EDIT,303,22,44,12,ES_UPPERCASE | ES_AUTOHSCROLL,WS_EX_RIGHT
|
||||||
|
@ -1735,6 +1735,9 @@ BEGIN
|
||||||
MENUITEM "Toggle write breakpoint", ID_POPUPMENU_TOGGLEWBP
|
MENUITEM "Toggle write breakpoint", ID_POPUPMENU_TOGGLEWBP
|
||||||
MENUITEM "Clear all breakpoints", ID_POPUPMENU_CLEARALLBPS
|
MENUITEM "Clear all breakpoints", ID_POPUPMENU_CLEARALLBPS
|
||||||
MENUITEM SEPARATOR
|
MENUITEM SEPARATOR
|
||||||
|
MENUITEM "Toggle lock", ID_POPUPMENU_TOGGLELOCK
|
||||||
|
MENUITEM "Clear locks", ID_POPUPMENU_CLEARLOCKS
|
||||||
|
MENUITEM SEPARATOR
|
||||||
MENUITEM "View disassembly...", ID_POPUPMENU_VIEWDISASM
|
MENUITEM "View disassembly...", ID_POPUPMENU_VIEWDISASM
|
||||||
MENUITEM SEPARATOR
|
MENUITEM SEPARATOR
|
||||||
MENUITEM "Add symbol...", ID_POPUPMENU_ADDSYMBOL
|
MENUITEM "Add symbol...", ID_POPUPMENU_ADDSYMBOL
|
||||||
|
|
|
@ -621,6 +621,8 @@
|
||||||
#define ID_POPUPMENU_VIEWMEMORY 40036
|
#define ID_POPUPMENU_VIEWMEMORY 40036
|
||||||
#define ID_POPUPMENU_TOGGLEBP 40039
|
#define ID_POPUPMENU_TOGGLEBP 40039
|
||||||
#define ID_POPUPMENU_CLEARBPS 40040
|
#define ID_POPUPMENU_CLEARBPS 40040
|
||||||
|
#define ID_POPUPMENU_TOGGLELOCK 40041
|
||||||
|
#define ID_POPUPMENU_CLEARLOCKS 40042
|
||||||
#define ID_POPUPMENU_ROMDIRECTORY 40137
|
#define ID_POPUPMENU_ROMDIRECTORY 40137
|
||||||
#define ID_POPUPMENU_REFRESHROMLIST 40138
|
#define ID_POPUPMENU_REFRESHROMLIST 40138
|
||||||
#define ID_POPUPMENU_PLAYGAME 40152
|
#define ID_POPUPMENU_PLAYGAME 40152
|
||||||
|
@ -636,7 +638,7 @@
|
||||||
#ifdef APSTUDIO_INVOKED
|
#ifdef APSTUDIO_INVOKED
|
||||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||||
#define _APS_NEXT_RESOURCE_VALUE 194
|
#define _APS_NEXT_RESOURCE_VALUE 194
|
||||||
#define _APS_NEXT_COMMAND_VALUE 40041
|
#define _APS_NEXT_COMMAND_VALUE 40043
|
||||||
#define _APS_NEXT_CONTROL_VALUE 1445
|
#define _APS_NEXT_CONTROL_VALUE 1445
|
||||||
#define _APS_NEXT_SYMED_VALUE 102
|
#define _APS_NEXT_SYMED_VALUE 102
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue