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 


CE Request
Goto page 1, 2  Next
 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine
View previous topic :: View next topic  
Author Message
Zephiles
Advanced Cheater
Reputation: 0

Joined: 04 Feb 2016
Posts: 56

PostPosted: Tue Jun 14, 2016 10:29 pm    Post subject: CE Request Reply with quote

Since Cheat Engine cannot handle results that are bigger than 4 bytes, I was wondering if this would be a possibility:

The current addresses that I am looking at are 8 bytes long and are in the form of Big Endian. They are used to handle the main clock in the game. Because of this, I was wondering if a custom type could be made that would take these 8 bytes and then convert them into minutes.

An example would be that if the clock was currently at 10:45 (10 hours 45 minutes), then the displayed time in Cheat Engine would be 645. So can this sort of thing be done?

Edit: Something similar to this has been done by mgr.inz.Player. This is what he has:

Code:

alloc(ConvertRoutine,1024)
alloc(TypeName,256)
alloc(ByteSize,4)
alloc(data,16)
label(data1)
label(data2)
alloc(UsesFloat,1)

TypeName:
db 'toFloat(QWord Big Endian)',0

ByteSize:
dd 8

data1:
dq ffffffffffffffff

data2:
dd 5F800000

data3:
dd (float)1000.0

UsesFloat:
db 1

ConvertRoutine:
[64-bit]
lea rsp,[rsp-8]

mov rax,[rcx]
bswap rax
mov [rsp],rax

bt [rsp+4],1F
fild qword ptr [rsp]     // dividend
jae @f
fadd [data2]
@@:
bt [data1+4],1F
fild qword ptr [data1] // divisor
jae @f
fadd [data2]
@@:

fdivp
fmul [data3]
fstp [rsp]
mov eax,[rsp]

lea rsp,[rsp+8]
ret
[/64-bit]


With this custom type, the values would be like this:
0x0000000000000001 would be 5.421010862E-17
0x0000000000000002 would be 1.084202172E-16
0x8000000000000000 would be 500
0xF000000000000000 would be 937.5
0xFF00000000000000 would be 996.09375
0xFFFFFFFFFFFFFFFF would be 1000.0
Back to top
View user's profile Send private message
Zephiles
Advanced Cheater
Reputation: 0

Joined: 04 Feb 2016
Posts: 56

PostPosted: Mon Jun 20, 2016 4:55 pm    Post subject: Reply with quote

Since I'm not getting any responses, is it safe to assume this isn't doable?
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 458

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

PostPosted: Mon Jun 20, 2016 5:36 pm    Post subject: Reply with quote

it can be done. just as you said, convert it to a human readable value.
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
ParkourPenguin
I post too much
Reputation: 140

Joined: 06 Jul 2014
Posts: 4297

PostPosted: Mon Jun 20, 2016 6:08 pm    Post subject: Reply with quote

You can read from & write to that address directly using the bytes, right? Use Lua or even asm to convert it to/from whatever type of value you want.

If you would like someone else to do this, provide more information. Namely, the function that relates that qword to the actual time. If you don't know how to get that, copy and paste a dozen or so states approximately evenly distributed across the full range of values (with respect to either the time in the game or that qword) including that qword, the time it is in the game, and what you want the displayed value to be.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
Zephiles
Advanced Cheater
Reputation: 0

Joined: 04 Feb 2016
Posts: 56

PostPosted: Sat Jun 25, 2016 5:02 pm    Post subject: Reply with quote

After getting help from some people, I have figured out that the clock speed of the game that I am using this for is 40,500,000/sec, or 2,430,000,000/min. So basically, for the custom type that I am requesting, you would just need to calculate the current value in 8 Byte Big Endian, and then divide the result by 2430000000.

I would assume you would only need to edit the current 4 Byte Big Endian custom type a bit to calculate for 8 bytes instead of 4, and then add in the division afterwards.

Since it's apparently this simple, is any additional information required to make this custom type? I would attempt to make this myself, but I really don't have a clue how to do it.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 140

Joined: 06 Jul 2014
Posts: 4297

PostPosted: Sat Jun 25, 2016 6:16 pm    Post subject: Reply with quote

As has already been said in a previous topic of yours (among other topics), custom types cannot completely support value types larger than 4 bytes.
Here's a couple Lua functions that will do what you want.
Code:
function readTimeMinutes(address)
  local b,r = readBytes(address, 8, true),0
  for _,v in ipairs(b) do
    r = (r << 8) | v
  end
  return r / 2430000000
end

function writeTimeMinutes(address, value)
  value = math.floor(tonumber(value) * 2430000000)
  local b = {}
  for i=0,7 do
    b[8-i] = (value >> i*8) & 0xff
  end
  writeBytes(address, b)
end


If you're fine with a precision around 1.77 minutes, it's possible to make a custom type that only writes to the most significant dword.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
Zephiles
Advanced Cheater
Reputation: 0

Joined: 04 Feb 2016
Posts: 56

PostPosted: Sat Jun 25, 2016 7:13 pm    Post subject: Reply with quote

OK, so how exactly do I use these functions with my table?
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 140

Joined: 06 Jul 2014
Posts: 4297

PostPosted: Sat Jun 25, 2016 8:32 pm    Post subject: Reply with quote

Any way you want (using Lua).
Code:
autoAssemble("globalalloc(timeMinutes,8)")
local minutesBackup = 0

if timeUpdateT then timeUpdateT.destroy() end
timeUpdateT = createTimer()
timeUpdateT.Interval = 100
timeUpdateT.OnTimer = function(sender)
  local real = readTimeMinutes(address)
  local user = readDouble("timeMinutes")
  if user == minutesBackup then
    writeDouble("timeMinutes", real)
    minutesBackup = real
  else
    writeTimeMinutes(address, user)
    minutesBackup = user
  end
end

Replace "address" with the address of the time in game (e.g. if you register it as a symbol, use "symbolname" w/ quotes). The symbol timeMinutes contains the time in minutes as a double.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
Zephiles
Advanced Cheater
Reputation: 0

Joined: 04 Feb 2016
Posts: 56

PostPosted: Sat Jun 25, 2016 9:59 pm    Post subject: Reply with quote

Ok I ran the script earlier and it worked, but now it's not working. I'm getting an error every time I try to run the script now. I have no idea what went wrong. This is what it says:

Error:[string "autoAssemble("globalalloc(timeMinutes,Cool")..."]:8: attempt to call a nil value (global 'readTimeMinutes')

And it keeps looping this until i forcefully close it via task manager.
Back to top
View user's profile Send private message
panraven
Grandmaster Cheater
Reputation: 55

Joined: 01 Oct 2008
Posts: 942

PostPosted: Sat Jun 25, 2016 10:10 pm    Post subject: Reply with quote

4byte most positive number is 0x7fffffff, which is 2147483647.

If the time usage is within 0-2147days range, the 8bytes value can be express like 2147 days 23hr 59min 59sec as 2147235959 (2147*24*60*60-1 = 0xb0fd5ff ) as largest expressed value.

The point is we don't need to express the custom type result 4byte into all the 8byte possible range with low precision (ie. cut the lower 4bytes, or divide 2430000000 ), we can limit the possible range so that the result type can be fit into 4byte acoording to usage with good precision of 1sec.
The valid 8byte range with highest ~2147day and 1 sec precision is roughly 0xb0fd600 x 40500000 = 0x 1AB404 AECCC000, within 8byte range . For 8byte value higher than this number, we can treat it as invalid value.

Code:
typename="be8bTimer" --shown as the typename in ce
bytecount=8  --number of bytes of this type
functionbasename="b8t"

function b8t_bytestovalue(b0,b1,b2,b3,b4,b5,b6,b7)
  local time = byteTableToQword{b7,b6,b5,b4,b3,b2,b1,b0}
  local sec  = math.floor(time / 40500000)
  if sec>=0 and sec < 0xB0fd600 then
    local ss = sec % 60
    local mm = math.floor(sec/60) % 60
    local hh = math.floor(sec/3600) % 24
    local dd = math.floor(sec/86400)
    return dd*1000000+hh*10000+mm*100+ss
  else
    return 0x80000000
  end
end

function b8t_valuetobytes(i,address)

  local b = readBytes(address,8,true)
  if i>=0 and i<=2147235959 then
    local ss = i % 100
    if ss<60 then
      local mm = math.floor(i/100)%100
      if mm<60 then
        local hh = math.floor(i/10000)%100
        if hh<24 then
          local dd = math.floor(i/1000000)
          local sec = dd*86400+hh*3600+mm*60+ss
          local time = sec*40500000
          b = qwordToByteTable(time)
          for i=1,4 do
            local j = 9-i
            b[i],b[j]=b[j],b[i] -- reverse
          end
        end
      end
    end
  end

  local UnPack = table.unpack or unpack
  return UnPack(b)
end
return typename,bytecount,functionbasename


Try use 'bigger than' with a suitable time value for 1st search,
and use suitable search alignment for faster scan.

If the time usage is to express more than 2147 days, this plan won't work.

bye~



be8btimer.jpg
 Description:
 Filesize:  14.1 KB
 Viewed:  6894 Time(s)

be8btimer.jpg



_________________
- Retarded.


Last edited by panraven on Sat Jun 25, 2016 10:33 pm; edited 1 time in total
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 140

Joined: 06 Jul 2014
Posts: 4297

PostPosted: Sat Jun 25, 2016 10:25 pm    Post subject: Reply with quote

Zephiles wrote:
I have no idea what went wrong.

...attempt to call a nil value (global 'readTimeMinutes')

You didn't define readTimeMinutes or writeTimeMinutes. Since that Lua code I previously posted calls those functions, you need those functions in order to run that code. So, copy those two function declarations and paste them before that script.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
Zephiles
Advanced Cheater
Reputation: 0

Joined: 04 Feb 2016
Posts: 56

PostPosted: Sat Jun 25, 2016 10:51 pm    Post subject: Reply with quote

ParkourPenguin whenever I close the game, I also get that error. Is there any way to prevent that?

And panraven, thanks for your custom type as well!
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 140

Joined: 06 Jul 2014
Posts: 4297

PostPosted: Sun Jun 26, 2016 8:57 am    Post subject: Reply with quote

You aren't getting that exact same error since those functions are still defined, but it will fail when it tries to look up values belonging to the process.

Code:
function readTimeMinutes(address)
  local b,r = readBytes(address, 8, true),0
  if not b then return nil end
  for _,v in ipairs(b) do
    r = (r << 8) | v
  end
  return r / 2430000000
end

function writeTimeMinutes(address, value)
  value = math.floor(tonumber(value) * 2430000000)
  local b = {}
  for i=0,7 do
    b[8-i] = (value >> i*8) & 0xff
  end
  return writeBytes(address, b)
end


autoAssemble("globalalloc(timeMinutes,8)")
local minutesBackup = 0

if timeUpdateT then timeUpdateT.destroy() end
timeUpdateT = createTimer()
timeUpdateT.Interval = 100
timeUpdateT.OnTimer = function(sender)
  local b = errorOnLookupFailure(false)
  local real = readTimeMinutes(address)
  local user = readDouble("timeMinutes")
  if real and user then
    if user == minutesBackup then
      writeDouble("timeMinutes", real)
      minutesBackup = real
    else
      writeTimeMinutes(address, user)
      minutesBackup = user
    end
  else
    sender.Enabled = false
  end
  errorOnLookupFailure(b)
end

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
Zephiles
Advanced Cheater
Reputation: 0

Joined: 04 Feb 2016
Posts: 56

PostPosted: Sun Jun 26, 2016 12:32 pm    Post subject: Reply with quote

Alright this works, but now there's just one small problem left.

If I reopen the game and execute the script again, the previous value that was in the address will not be reset/cleared.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 140

Joined: 06 Jul 2014
Posts: 4297

PostPosted: Sun Jun 26, 2016 12:35 pm    Post subject: Reply with quote

Code:
...
autoAssemble([[globalalloc(timeMinutes,8)
timeMinutes:
  dq 0]])
...

_________________
I don't know where I'm going, but I'll figure it out when I get there.
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 All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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