Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature request] Watch Expression #2375

Open
maskelihileci opened this issue Oct 21, 2022 · 5 comments
Open

[Feature request] Watch Expression #2375

maskelihileci opened this issue Oct 21, 2022 · 5 comments

Comments

@maskelihileci
Copy link

maskelihileci commented Oct 21, 2022

I've heard that this plugin won't work anymore after Cheat Engine new versions, so sorry about that.
It is a plugin that I use all the time and I think it should be one of the main features of the cheat engine.

It is a plugin where you can follow the values of the registers at the time of the event, the calls to the stacks, everything without interrupting the games.

https://forum.cheatengine.org/viewtopic.php?t=592301 The subject is here.

I don't think it will be difficult to write again, I hope you have time for that, thanks for your efforts

@fade2gray
Copy link

Your link was incorrectly formatted.
https://forum.cheatengine.org/viewtopic.php?t=592301

@maskelihileci
Copy link
Author

Your link was incorrectly formatted. https://forum.cheatengine.org/viewtopic.php?t=592301

I fixed it.

Repository owner deleted a comment from XBOX360VERSUCHONE Oct 22, 2022
@cheat-engine
Copy link
Owner

cheat-engine commented Oct 24, 2022

here's a lua script that basically does something similar:

if miWatchExpression==nil then
  mvf=getMemoryViewForm()
  miWatchExpression=createMenuItem(mvf)
  miWatchExpression.Caption='Watch expression'
  mvf.debuggerpopup.Items.insert(mvf.Findoutwhataddressesthisinstructionaccesses1.MenuIndex, miWatchExpression)
end

miWatchExpression.OnClick=function(sender)
  local started=false
  local address=mvf.DisassemblerView.SelectedAddress
  local d=createDisassembler()
  d.disassemble(address)
  local equation=d.LastDisassembleData.parameters:match("%[(.+)%]")
  if equation==nil then return end
  equation=equation:upper()
  d.destroy()

  local f=createForm(false)
  f.PopupMode='pmNone'
  f.Caption=string.format('Equation evaluator for %.8x',address)
  f.BorderStyle='bsSizeable'
  f.Position='poScreenCenter'

  local lblExpression=createLabel(f)
  lblExpression.Caption='Expression'

  local lblDataType=createLabel(f)
  lblDataType.Caption='Data Type'

  local edtExpression=createEdit(f)
  edtExpression.Text=equation

  local cbDataType=createComboBox(f)

  local btnStart=createButton(f)
  local btnClear=createButton(f)

  btnStart.AutoSize=true
  btnStart.Caption=' Start '

  btnClear.AutoSize=true
  btnClear.Caption='Clear'

  btnStart.AnchorSideRight.Control=f
  btnStart.AnchorSideRight.Side=asrRight
  btnStart.AnchorSideTop.Control=f
  btnStart.AnchorSideTop.Side=asrTop
  btnStart.BorderSpacing.Top=(getScreenDPI()/96)*8
  btnStart.BorderSpacing.Right=(getScreenDPI()/96)*8
  btnStart.Anchors="[akRight, akTop]"

  btnClear.AnchorSideTop.Control=edtExpression
  btnClear.AnchorSideTop.Side=asrBottom
  btnClear.AnchorSideRight.Control=btnStart
  btnClear.AnchorSideRight.Side=asrRight
  btnClear.AnchorSideLeft.Control=btnStart
  btnClear.AnchorSideLeft.Side=asrLeft
  btnClear.Anchors="[akLeft, akRight, akTop]"
  btnClear.BorderSpacing.Top=(getScreenDPI()/96)*3

  lblExpression.AnchorSideTop.Control=edtExpression
  lblExpression.AnchorSideTop.Side=asrCenter
  lblExpression.AnchorSideLeft.Control=f
  lblExpression.AnchorSideLeft.Side=asrLeft
  lblExpression.Anchors="[akTop, akLeft]"
  lblExpression.BorderSpacing.Left=(getScreenDPI()/96)*8

  edtExpression.AnchorSideTop.Control=btnStart
  edtExpression.AnchorSideTop.Side=asrTop
  edtExpression.AnchorSideLeft.Control=lblExpression
  edtExpression.AnchorSideLeft.Side=asrRight
  edtExpression.AnchorSideRight.Control=btnStart
  edtExpression.AnchorSideRight.Side=asrLeft
  edtExpression.BorderSpacing.Right=(getScreenDPI()/96)*8
  edtExpression.BorderSpacing.Left=(getScreenDPI()/96)*8
  edtExpression.Anchors="[akTop, akLeft, akRight]"

  cbDataType.AnchorSideLeft.Control=edtExpression
  cbDataType.AnchorSideLeft.Side=asrLeft
  cbDataType.AnchorSideTop.Control=edtExpression
  cbDataType.AnchorSideTop.Side=asrBottom
  cbDataType.Width=(getScreenDPI()/96)*100
  cbDataType.BorderSpacing.Top=(getScreenDPI()/96)*3
  cbDataType.Items.Text=[[Integer
  Opcode
  Float
  Double
  String
  Array of bytes]]
  cbDataType.Anchors="[akLeft, akTop]"
  cbDataType.Style='csDropDownList'
  cbDataType.ItemIndex=0

  lblDataType.AnchorSideRight.Control=lblExpression
  lblDataType.AnchorSideRight.Side=asrRight
  lblDataType.AnchorSideTop.Control=cbDataType
  lblDataType.AnchorSideTop.Side=asrCenter
  lblDataType.Anchors="[akTop, akRight]"

  local cbHexadecimal=createCheckBox(f)
  cbHexadecimal.Caption='Hex'
  cbHexadecimal.AnchorsideTop.Control=lblDataType
  cbHexadecimal.AnchorsideTop.Side=asrBottom
  cbHexadecimal.AnchorsideLeft.Control=lblDataType
  cbHexadecimal.AnchorsideLeft.Side=asrLeft
  cbHexadecimal.Anchors="[akTop, akLeft]"
  cbHexadecimal.BorderSpacing.Top=(getScreenDPI()/96)*3

  local results=createListView(f)
  results.AnchorSideLeft.Control=f
  results.AnchorSideLeft.Side=asrLeft
  results.AnchorSideTop.Control=cbHexadecimal
  results.AnchorSideTop.Side=asrBottom
  results.AnchorSideBottom.Control=f
  results.AnchorSideBottom.Side=asrBottom
  results.AnchorSideRight.Control=f
  results.AnchorSideRight.Side=asrRight
  results.BorderSpacing.Top=(getScreenDPI()/96)*4
  results.BorderSpacing.Left=(getScreenDPI()/96)*8
  results.BorderSpacing.Right=(getScreenDPI()/96)*8
  results.BorderSpacing.Bottom=(getScreenDPI()/96)*8
  results.ViewStyle='vsReport'
  local c1=results.Columns.add()
  local c2=results.Columns.add()
  c1.Caption='Address/Value'
  c2.Caption='Data'

  c1.Width=(getScreenDPI()/96)*90
  c2.Width=(getScreenDPI()/96)*90

  --results.

  results.Anchors="[akTop, akLeft, akBottom, akRight]"
  results.AutoWidthLastColumn=true
  results.ColumnClick=false



  f.AutoSize=true
  f.Show()


  local parsers={}
  --[[
  Integer
  Opcode
  Float
  Double
  String
  Array of bytes

  --]]
  parsers[0]=function(address) --integer
    if cbHexadecimal.checked then
      return string.format("%x", readInteger(address))
    else
      return tostring(readInteger(address))
    end
  end

  parsers[1]=function(address) --opcode
    return tostring(disassemble(address))
  end

  parsers[2]=function(address) --float
    return tostring(readFloat(address))
  end

  parsers[3]=function(address) --double
    return tostring(readDouble(address))
  end

  parsers[4]=function(address) --string
    return tostring(readString(address,200))
  end

  parsers[5]=function(address) --aob
    local r=readBytes(address,16)
    if r then
      local o=''
      for i=1,#r do
        o=o..string.format("%.2x ",r[i])
      end
    else
      return "nil"
    end
  end

  local function getDataString(address)
    local index=cbDataType.ItemIndex
    local parser=parsers[index]

    if parser then
      return parser(address)
    else
      return 'invalid type'
    end
  end

  btnClear.OnClick=function(sender)
    results.clear()
  end

  --todo: timer to update values afterwards ?

  btnStart.OnClick=function(sender)

    started=true
    local expression=edtExpression.text:upper()
    debug_setBreakpoint(address,function()
      --printf("BP hit")
      if f==nil then return nil end

      local v=getAddressSafe(expression)
      if v then


        local found=false
        for i=0,results.Items.Count-1 do
          if results.Items[i].Data==v then
            found=true
            break
          end
        end

        if found then return nil end --todo: perhaps refresh the value, or use a timer?

        vs=string.format("%.8x",v)
        li=results.Items.add()
        li.Caption=vs
        li.SubItems.add(getDataString(v))
        li.Data=v
      else
        debug_removeBreakpoint(address)
        messageDialog('Expression '..expression..' failed to return a value', mtError)
      end

    end)
  end

  f.OnClose=function(sender,ca)
    f=nil
    if started then
      debug_removeBreakpoint(address)
    end
    return caFree
  end

end

you can place it in your ce autorun folder and you should have a "Watch expression" above the "Find out what addresses this instruction accesses" menu item in the context popup of the disassembler

It's basic, but since it's lua you can add other functions quite easily

@maskelihileci
Copy link
Author

işte temelde benzer bir şey yapan bir lua betiği:

if miWatchExpression==nil then
  mvf=getMemoryViewForm()
  miWatchExpression=createMenuItem(mvf)
  miWatchExpression.Caption='Watch expression'
  mvf.debuggerpopup.Items.insert(mvf.Findoutwhataddressesthisinstructionaccesses1.MenuIndex, miWatchExpression)
end

miWatchExpression.OnClick=function(sender)
  local started=false
  local address=mvf.DisassemblerView.SelectedAddress
  local d=createDisassembler()
  d.disassemble(address)
  local equation=d.LastDisassembleData.parameters:match("%[(.+)%]")
  if equation==nil then return end
  equation=equation:upper()
  d.destroy()

  local f=createForm(false)
  f.PopupMode='pmNone'
  f.Caption=string.format('Equation evaluator for %.8x',address)
  f.BorderStyle='bsSizeable'
  f.Position='poScreenCenter'

  local lblExpression=createLabel(f)
  lblExpression.Caption='Expression'

  local lblDataType=createLabel(f)
  lblDataType.Caption='Data Type'

  local edtExpression=createEdit(f)
  edtExpression.Text=equation

  local cbDataType=createComboBox(f)

  local btnStart=createButton(f)
  local btnClear=createButton(f)

  btnStart.AutoSize=true
  btnStart.Caption=' Start '

  btnClear.AutoSize=true
  btnClear.Caption='Clear'

  btnStart.AnchorSideRight.Control=f
  btnStart.AnchorSideRight.Side=asrRight
  btnStart.AnchorSideTop.Control=f
  btnStart.AnchorSideTop.Side=asrTop
  btnStart.BorderSpacing.Top=(getScreenDPI()/96)*8
  btnStart.BorderSpacing.Right=(getScreenDPI()/96)*8
  btnStart.Anchors="[akRight, akTop]"

  btnClear.AnchorSideTop.Control=edtExpression
  btnClear.AnchorSideTop.Side=asrBottom
  btnClear.AnchorSideRight.Control=btnStart
  btnClear.AnchorSideRight.Side=asrRight
  btnClear.AnchorSideLeft.Control=btnStart
  btnClear.AnchorSideLeft.Side=asrLeft
  btnClear.Anchors="[akLeft, akRight, akTop]"
  btnClear.BorderSpacing.Top=(getScreenDPI()/96)*3

  lblExpression.AnchorSideTop.Control=edtExpression
  lblExpression.AnchorSideTop.Side=asrCenter
  lblExpression.AnchorSideLeft.Control=f
  lblExpression.AnchorSideLeft.Side=asrLeft
  lblExpression.Anchors="[akTop, akLeft]"
  lblExpression.BorderSpacing.Left=(getScreenDPI()/96)*8

  edtExpression.AnchorSideTop.Control=btnStart
  edtExpression.AnchorSideTop.Side=asrTop
  edtExpression.AnchorSideLeft.Control=lblExpression
  edtExpression.AnchorSideLeft.Side=asrRight
  edtExpression.AnchorSideRight.Control=btnStart
  edtExpression.AnchorSideRight.Side=asrLeft
  edtExpression.BorderSpacing.Right=(getScreenDPI()/96)*8
  edtExpression.BorderSpacing.Left=(getScreenDPI()/96)*8
  edtExpression.Anchors="[akTop, akLeft, akRight]"

  cbDataType.AnchorSideLeft.Control=edtExpression
  cbDataType.AnchorSideLeft.Side=asrLeft
  cbDataType.AnchorSideTop.Control=edtExpression
  cbDataType.AnchorSideTop.Side=asrBottom
  cbDataType.Width=(getScreenDPI()/96)*100
  cbDataType.BorderSpacing.Top=(getScreenDPI()/96)*3
  cbDataType.Items.Text=[[Integer
  Opcode
  Float
  Double
  String
  Array of bytes]]
  cbDataType.Anchors="[akLeft, akTop]"
  cbDataType.Style='csDropDownList'
  cbDataType.ItemIndex=0

  lblDataType.AnchorSideRight.Control=lblExpression
  lblDataType.AnchorSideRight.Side=asrRight
  lblDataType.AnchorSideTop.Control=cbDataType
  lblDataType.AnchorSideTop.Side=asrCenter
  lblDataType.Anchors="[akTop, akRight]"

  local cbHexadecimal=createCheckBox(f)
  cbHexadecimal.Caption='Hex'
  cbHexadecimal.AnchorsideTop.Control=lblDataType
  cbHexadecimal.AnchorsideTop.Side=asrBottom
  cbHexadecimal.AnchorsideLeft.Control=lblDataType
  cbHexadecimal.AnchorsideLeft.Side=asrLeft
  cbHexadecimal.Anchors="[akTop, akLeft]"
  cbHexadecimal.BorderSpacing.Top=(getScreenDPI()/96)*3

  local results=createListView(f)
  results.AnchorSideLeft.Control=f
  results.AnchorSideLeft.Side=asrLeft
  results.AnchorSideTop.Control=cbHexadecimal
  results.AnchorSideTop.Side=asrBottom
  results.AnchorSideBottom.Control=f
  results.AnchorSideBottom.Side=asrBottom
  results.AnchorSideRight.Control=f
  results.AnchorSideRight.Side=asrRight
  results.BorderSpacing.Top=(getScreenDPI()/96)*4
  results.BorderSpacing.Left=(getScreenDPI()/96)*8
  results.BorderSpacing.Right=(getScreenDPI()/96)*8
  results.BorderSpacing.Bottom=(getScreenDPI()/96)*8
  results.ViewStyle='vsReport'
  local c1=results.Columns.add()
  local c2=results.Columns.add()
  c1.Caption='Address/Value'
  c2.Caption='Data'

  c1.Width=(getScreenDPI()/96)*90
  c2.Width=(getScreenDPI()/96)*90

  --results.

  results.Anchors="[akTop, akLeft, akBottom, akRight]"
  results.AutoWidthLastColumn=true
  results.ColumnClick=false



  f.AutoSize=true
  f.Show()


  local parsers={}
  --[[
  Integer
  Opcode
  Float
  Double
  String
  Array of bytes

  --]]
  parsers[0]=function(address) --integer
    if cbHexadecimal.checked then
      return string.format("%x", readInteger(address))
    else
      return tostring(readInteger(address))
    end
  end

  parsers[1]=function(address) --opcode
    return tostring(disassemble(address))
  end

  parsers[2]=function(address) --float
    return tostring(readFloat(address))
  end

  parsers[3]=function(address) --double
    return tostring(readDouble(address))
  end

  parsers[4]=function(address) --string
    return tostring(readString(address,200))
  end

  parsers[5]=function(address) --aob
    local r=readBytes(address,16)
    if r then
      local o=''
      for i=1,#r do
        o=o..string.format("%.2x ",r[i])
      end
    else
      return "nil"
    end
  end

  local function getDataString(address)
    local index=cbDataType.ItemIndex
    local parser=parsers[index]

    if parser then
      return parser(address)
    else
      return 'invalid type'
    end
  end

  btnClear.OnClick=function(sender)
    results.clear()
  end

  --todo: timer to update values afterwards ?

  btnStart.OnClick=function(sender)

    started=true
    local expression=edtExpression.text:upper()
    debug_setBreakpoint(address,function()
      --printf("BP hit")
      if f==nil then return nil end

      local v=getAddressSafe(expression)
      if v then


        local found=false
        for i=0,results.Items.Count-1 do
          if results.Items[i].Data==v then
            found=true
            break
          end
        end

        if found then return nil end --todo: perhaps refresh the value, or use a timer?

        vs=string.format("%.8x",v)
        li=results.Items.add()
        li.Caption=vs
        li.SubItems.add(getDataString(v))
        li.Data=v
      else
        debug_removeBreakpoint(address)
        messageDialog('Expression '..expression..' failed to return a value', mtError)
      end

    end)
  end

  f.OnClose=function(sender,ca)
    f=nil
    if started then
      debug_removeBreakpoint(address)
    end
    return caFree
  end

end

ce autorun klasörünüze yerleştirebilirsiniz ve ayrıştırıcının içerik açılır penceresindeki "Bu talimatın hangi adreslere eriştiğini bulun" menü öğesinin üzerinde bir "İzle ifadesi" olmalıdır.

Bu basit, ancak lua olduğu için diğer işlevleri oldukça kolay bir şekilde ekleyebilirsiniz.

There are too many bugs.
In some addresses, the watch expression menu does not appear.
Some addresses give Expression RCX failed to return a value error.

I think I need to edit this simple lua myself so it's the way I want it anyway, thank you for your help.

@shixiangfang
Copy link

thx bro

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants