Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


Title: Unknown scan returns 0 in multi‑segment cus

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting
View previous topic :: View next topic  
Author Message
xxhehe
Expert Cheater
Reputation: 0

Joined: 11 Mar 2015
Posts: 163

PostPosted: Sun Jun 28, 2026 4:32 am    Post subject: Title: Unknown scan returns 0 in multi‑segment cus Reply with quote

'm writing a Lua script for VBA‑M that scans multiple memory segments (some valid only in GBC or GBA mode). Exact value scan works, but unknown initial value scan (soUnknownValue) always returns 0 results – even though the same segments contain valid data (confirmed by exact scan).



What I tried:

ms.firstScan() with full parameters (soUnknownValue, vtByte, …)

ms.scan() with ScanOption = soUnknownValue

using FoundList (createFoundList + initialize)

protection flags set to "" or "*X*C*W"

removing any ScanValue assignment

Segments resolve correctly (base addresses print), and exact scan yields hundreds of matches. Unknown scan still outputs "Total matches found (unknown): 0". Same behavior for Byte, Word, Dword, etc.

CE 7.7 , target is VBA‑M 32‑bit on Windows 10.

I suspect a known limitation when scanning non‑contiguous regions, or I need to call something after firstScan. Any concrete hints would help.

Simplified script (key parts):
[firstScanUnknown function and relevant setup]

Code:
-------------------------------------------------------------------------------
-- 首次扫描(精确)
-------------------------------------------------------------------------------
function firstScanExact()
    lastResults = {}
    lastVarType = nil
    lastScanType = "exact"
    print("Starting new EXACT first scan...")

    -- 选择数据类型
    local typeCode = inputQuery("选择数据类型",
        "请输入数据类型代号:\n1=字节  2=2字节  3=4字节  4=8字节\n5=浮点  6=双精度  7=字符串", "1")
    if typeCode == nil then print("Cancelled.") return end
    typeCode = tonumber(typeCode)
    local varType
    if typeCode == 1 then varType = vtByte
    elseif typeCode == 2 then varType = vtWord
    elseif typeCode == 3 then varType = vtDword
    elseif typeCode == 4 then varType = vtQword
    elseif typeCode == 5 then varType = vtSingle
    elseif typeCode == 6 then varType = vtDouble
    elseif typeCode == 7 then varType = vtString
    else varType = vtByte end
    lastVarType = varType
    print("Using type: " .. tostring(varType))

    local val = inputQuery("首次搜索", "请输入要搜索的数值(十进制):", "0")
    if val == nil then print("Cancelled.") return end

    local validSegments = getValidSegments()
    if #validSegments == 0 then print("No valid segments.") return end

    local allResults = {}
    for _, segInfo in ipairs(validSegments) do
        local startAddr = segInfo.base
        local stopAddr = startAddr + segInfo.size
        print(string.format("Scanning: 0x%X - 0x%X", startAddr, stopAddr))

        local ms = createMemScan()
        ms.ScanOption = soExactValue
        ms.VarType = varType
        ms.ScanValue = val
        ms.Hexadecimal = false
        ms.ScanWritable = 'scanDontCare'
        ms.ScanExecutable = 'scanDontCare'
        ms.ScanCopyOnWrite = 'scanDontCare'
        ms.StartAddress = startAddr
        ms.StopAddress = stopAddr
        ms.firstScan()
        ms.waitTillDone()

        local results = ms.Results
        if results then
            for _, addr in ipairs(results) do
                local currentVal = readValueAt(addr, varType)
                if currentVal ~= nil then
                    addResultUnique(allResults, addr, currentVal)
                end
            end
        end
        ms.destroy()
    end

    lastResults = allResults
    print(string.format("Total matches found: %d", #lastResults))
    printResults(allResults)
    if ADD_TO_LIST then addToAddressList(allResults) end
end

-------------------------------------------------------------------------------
-- 首次扫描(模糊 - 未知初始值)
-------------------------------------------------------------------------------
function firstScanUnknown()
    lastResults = {}
    lastVarType = nil
    lastScanType = "unknown"
    print("Starting UNKNOWN first scan...")

    -- 选择数据类型
    local typeCode = inputQuery("选择数据类型",
        "请输入数据类型代号:\n1=字节  2=2字节  3=4字节  4=8字节\n5=浮点  6=双精度  7=字符串", "1")
    if typeCode == nil then print("Cancelled.") return end
    typeCode = tonumber(typeCode)
    local varType
    if typeCode == 1 then varType = vtByte
    elseif typeCode == 2 then varType = vtWord
    elseif typeCode == 3 then varType = vtDword
    elseif typeCode == 4 then varType = vtQword
    elseif typeCode == 5 then varType = vtSingle
    elseif typeCode == 6 then varType = vtDouble
    elseif typeCode == 7 then varType = vtString
    else varType = vtByte end
    lastVarType = varType
    print("Using type: " .. tostring(varType))

    local validSegments = getValidSegments()
    if #validSegments == 0 then print("No valid segments.") return end

    local allResults = {}
    for _, segInfo in ipairs(validSegments) do
        local startAddr = segInfo.base
        local stopAddr = startAddr + segInfo.size
        print(string.format("Scanning (unknown): 0x%X - 0x%X", startAddr, stopAddr))

        local ms = createMemScan()
        ms.ScanOption = soUnknownValue          -- 未知初始值
        ms.VarType = varType
        -- 未知初始值不需要 ScanValue,不设置或设为空字符串均可
        ms.ScanValue = ""                       -- 设为空字符串,CE 会忽略
        ms.Hexadecimal = false
        ms.ScanWritable = 'scanDontCare'
        ms.ScanExecutable = 'scanDontCare'
        ms.ScanCopyOnWrite = 'scanDontCare'
        ms.StartAddress = startAddr
        ms.StopAddress = stopAddr
        ms.firstScan()                          -- 统一使用 firstScan()
        ms.waitTillDone()

        local results = ms.Results
        if results then
            for _, addr in ipairs(results) do
                local currentVal = readValueAt(addr, varType)
                if currentVal ~= nil then
                    addResultUnique(allResults, addr, currentVal)
                end
            end
        end
        ms.destroy()
    end

    lastResults = allResults
    print(string.format("Total matches found (unknown): %d", #lastResults))
    printResults(allResults)
    if ADD_TO_LIST then addToAddressList(allResults) end
end

-------------------------------------------------------------------------------
-- 再次扫描(根据上次扫描类型自动适配)
-------------------------------------------------------------------------------
function nextScan()
    if not lastResults or #lastResults == 0 then
        print("No previous results. Please do a first scan first.")
        return
    end
    if not lastVarType then
        print("Unknown data type. Please do a first scan first.")
        return
    end

    local isString = (lastVarType == vtString)

    -- 根据上次扫描类型决定再次扫描的选项
    local conditionOptions
    if lastScanType == "exact" then
        conditionOptions = {"等于", "不等于", "大于", "小于", "增大了", "减小了", "变化了", "未变化"}
    else  -- "unknown"
        conditionOptions = {"增大了", "减小了", "变化了", "未变化"}
    end

    local condListStr = ""
    for i, opt in ipairs(conditionOptions) do
        condListStr = condListStr .. i .. "=" .. opt .. "  "
    end

    local condCode = inputQuery("选择比较条件",
        "请输入条件代号:\n" .. condListStr, "1")
    if condCode == nil then print("Cancelled.") return end
    condCode = tonumber(condCode)
    if condCode < 1 or condCode > #conditionOptions then
        print("Invalid condition, using 1")
        condCode = 1
    end
    local compareType = conditionOptions[condCode]
    print("Using condition: " .. compareType)

    local compareVal = nil
    -- 只有“等于/不等于/大于/小于”需要输入数值
    if compareType == "等于" or compareType == "不等于" or compareType == "大于" or compareType == "小于" then
        local val = inputQuery("再次搜索", "请输入要比较的数值(十进制):", "0")
        if val == nil then print("Cancelled.") return end
        compareVal = val
    end

    local newResults = {}
    for _, entry in ipairs(lastResults) do
        local currentVal = readValueAt(entry.addr, lastVarType)
        if currentVal ~= nil then
            if meetsExactCondition(currentVal, compareVal, compareType, entry.lastVal, isString) then
                addResultUnique(newResults, entry.addr, currentVal)  -- 去重
            end
        end
    end

    lastResults = newResults
    print(string.format("After filtering, matches found: %d", #lastResults))
    printResults(newResults)
    if ADD_TO_LIST then addToAddressList(newResults) end
end
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 474

Joined: 09 May 2003
Posts: 25973
Location: The netherlands

PostPosted: Sun Jun 28, 2026 5:16 am    Post subject: Reply with quote

soUnknownValue always returns 0 results. You must do a normal scan afterwards to get results (e.g. unchanged)
_________________
Tools give you results. Knowledge gives you control.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
xxhehe
Expert Cheater
Reputation: 0

Joined: 11 Mar 2015
Posts: 163

PostPosted: Sun Jun 28, 2026 6:24 am    Post subject: Reply with quote

Dark Byte wrote:
soUnknownValue always returns 0 results. You must do a normal scan afterwards to get results (e.g. unchanged)


Your hint — "soUnknownValue always returns 0. Do a normal scan afterwards" — fixed my problem. I'd been misusing soUnknownValue for a while.

Now I have a working multi‑segment fuzzy scanner for VBA‑M.

Thanks for Cheat Engine and the community support.
Code:
-------------------------------------------------------------------------------
-- 首次扫描(精确)
-------------------------------------------------------------------------------
function firstScanExact()
    lastResults = {}
    lastVarType = nil
    lastScanType = "exact"
    print("Starting new EXACT first scan...")

    local typeCode = inputQuery("选择数据类型",
        "请输入数据类型代号:\n1=字节  2=2字节  3=4字节  4=8字节\n5=浮点  6=双精度  7=字符串", "1")
    if typeCode == nil then print("Cancelled.") return end
    typeCode = tonumber(typeCode)
    local varType
    if typeCode == 1 then varType = vtByte
    elseif typeCode == 2 then varType = vtWord
    elseif typeCode == 3 then varType = vtDword
    elseif typeCode == 4 then varType = vtQword
    elseif typeCode == 5 then varType = vtSingle
    elseif typeCode == 6 then varType = vtDouble
    elseif typeCode == 7 then varType = vtString
    else varType = vtByte end
    lastVarType = varType
    print("Using type: " .. tostring(varType))

    local val = inputQuery("首次搜索", "请输入要搜索的数值(十进制):", "0")
    if val == nil then print("Cancelled.") return end

    local validSegments = getValidSegments()
    if #validSegments == 0 then print("No valid segments.") return end

    local allResults = {}
    local addrSet = {}          -- 去重字典
    for _, segInfo in ipairs(validSegments) do
        local startAddr = segInfo.base
        local stopAddr = startAddr + segInfo.size
        print(string.format("Scanning: 0x%X - 0x%X", startAddr, stopAddr))

        local ms = createMemScan()
        ms.ScanOption = soExactValue
        ms.VarType = varType
        ms.ScanValue = val
        ms.Hexadecimal = false
        ms.ScanWritable = 'scanDontCare'
        ms.ScanExecutable = 'scanDontCare'
        ms.ScanCopyOnWrite = 'scanDontCare'
        ms.StartAddress = startAddr
        ms.StopAddress = stopAddr
        ms.firstScan()
        ms.waitTillDone()

        local results = ms.Results
        if results then
            for _, addr in ipairs(results) do
                if not addrSet[addr] then
                    local currentVal = readValueFast(addr, varType)
                    if currentVal ~= nil then
                        addrSet[addr] = true
                        table.insert(allResults, {addr = addr, lastVal = currentVal})
                    end
                end
            end
        end
        ms.destroy()
    end

    lastResults = allResults
    print(string.format("Total matches found: %d", #lastResults))
    printResults(allResults)
    if ADD_TO_LIST then addToAddressList(allResults) end
end

-------------------------------------------------------------------------------
-- 首次扫描(模糊)
-------------------------------------------------------------------------------
function firstScanUnknown()
    lastResults = {}
    lastVarType = nil
    lastScanType = "unknown"
    print("Starting UNKNOWN first scan...")

    local typeCode = inputQuery("选择数据类型",
        "请输入数据类型代号:\n1=字节  2=2字节  3=4字节  4=8字节\n5=浮点  6=双精度  7=字符串", "1")
    if typeCode == nil then print("Cancelled.") return end
    typeCode = tonumber(typeCode)
    local varType
    if typeCode == 1 then varType = vtByte
    elseif typeCode == 2 then varType = vtWord
    elseif typeCode == 3 then varType = vtDword
    elseif typeCode == 4 then varType = vtQword
    elseif typeCode == 5 then varType = vtSingle
    elseif typeCode == 6 then varType = vtDouble
    elseif typeCode == 7 then varType = vtString
    else varType = vtByte end
    lastVarType = varType
    print("Using type: " .. tostring(varType))

    local validSegments = getValidSegments()
    if #validSegments == 0 then print("No valid segments.") return end

    local allResults = {}
    local addrSet = {}          -- 去重字典
    for _, segInfo in ipairs(validSegments) do
        local startAddr = segInfo.base
        local stopAddr = startAddr + segInfo.size
        print(string.format("Scanning unknown->unchanged: 0x%X - 0x%X", startAddr, stopAddr))

        local ms = createMemScan()

        -- 未知初始值
        ms.firstScan(
            soUnknownValue, varType, rtRounded,
            nil, nil, startAddr, stopAddr,
            "",                     -- 保护标志:空表示所有内存
            fsmNotAligned, "",
            false, false, false, false
        )
        ms.waitTillDone()

        -- 未变化
        ms.nextScan(
            soUnchanged, rtRounded,
            nil, nil,
            false, false, false, false, false
        )
        ms.waitTillDone()

        -- 读取结果
        local fl = createFoundList(ms)
        if fl then
            fl.initialize()
            local count = fl.Count
            if count and count > 0 then
                for i = 0, count - 1 do
                    local addrStr = fl.getAddress(i)
                    if addrStr then
                        local addr = tonumber(addrStr, 16)
                        if addr and not addrSet[addr] then
                            local val = readValueFast(addr, varType)
                            if val ~= nil then
                                addrSet[addr] = true
                                table.insert(allResults, {addr = addr, lastVal = val})
                            end
                        end
                    end
                    if i % 1000 == 0 then processMessages() end
                end
            end
            fl.deinitialize()
            fl.destroy()
        end
        ms.destroy()
    end

    lastResults = allResults
    print(string.format("Total matches found (unknown->unchanged): %d", #lastResults))
    printResults(allResults)
    if ADD_TO_LIST then addToAddressList(allResults) end
end

-------------------------------------------------------------------------------
-- 再次扫描(通用)
-------------------------------------------------------------------------------
function nextScan()
    if not lastResults or #lastResults == 0 then
        print("No previous results. Please do a first scan first.")
        return
    end
    if not lastVarType then
        print("Unknown data type. Please do a first scan first.")
        return
    end

    local isString = (lastVarType == vtString)

    local conditionOptions
    if lastScanType == "exact" then
        conditionOptions = {"等于", "不等于", "大于", "小于", "增大了", "减小了", "变化了", "未变化"}
    else
        conditionOptions = {"增大了", "减小了", "变化了", "未变化"}
    end

    local condListStr = ""
    for i, opt in ipairs(conditionOptions) do
        condListStr = condListStr .. i .. "=" .. opt .. "  "
    end

    local condCode = inputQuery("选择比较条件",
        "请输入条件代号:\n" .. condListStr, "1")
    if condCode == nil then print("Cancelled.") return end
    condCode = tonumber(condCode)
    if condCode < 1 or condCode > #conditionOptions then
        print("Invalid condition, using 1")
        condCode = 1
    end
    local compareType = conditionOptions[condCode]
    print("Using condition: " .. compareType)

    local compareVal = nil
    if compareType == "等于" or compareType == "不等于" or compareType == "大于" or compareType == "小于" then
        local val = inputQuery("再次搜索", "请输入要比较的数值(十进制):", "0")
        if val == nil then print("Cancelled.") return end
        compareVal = val
    end

    local newResults = {}
    local addrSet = {}          -- 确保新结果也去重(虽然理论上不会重复,但安全起见)
    for _, entry in ipairs(lastResults) do
        local currentVal = readValueFast(entry.addr, lastVarType)
        if currentVal ~= nil and not addrSet[entry.addr] then
            if meetsCondition(currentVal, compareVal, compareType, entry.lastVal, isString) then
                addrSet[entry.addr] = true
                table.insert(newResults, {addr = entry.addr, lastVal = currentVal})
            end
        end
    end

    lastResults = newResults
    print(string.format("After filtering, matches found: %d", #lastResults))
    printResults(newResults)
    if ADD_TO_LIST then addToAddressList(newResults) end
end
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites