| 
			
				|  | Cheat Engine The Official Site of Cheat Engine
 
 
 |  
 
	
		| View previous topic :: View next topic |  
		| Author | Message |  
		| Zephiles Advanced Cheater
 
 ![]() Reputation: 0 
 Joined: 04 Feb 2016
 Posts: 56
 
 
 | 
			
				|  Posted: Tue Jun 14, 2016 10:29 pm    Post subject: CE Request |   |  
				| 
 |  
				| 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 |  |  
		|  |  
		| Zephiles Advanced Cheater
 
 ![]() Reputation: 0 
 Joined: 04 Feb 2016
 Posts: 56
 
 
 | 
			
				|  Posted: Mon Jun 20, 2016 4:55 pm    Post subject: |   |  
				| 
 |  
				| Since I'm not getting any responses, is it safe to assume this isn't doable? |  |  
		| Back to top |  |  
		|  |  
		| Dark Byte Site Admin
 
  Reputation: 470 
 Joined: 09 May 2003
 Posts: 25807
 Location: The netherlands
 
 | 
			
				|  Posted: Mon Jun 20, 2016 5:36 pm    Post subject: |   |  
				| 
 |  
				| 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 |  |  
		|  |  
		| ParkourPenguin I post too much
 
  Reputation: 152 
 Joined: 06 Jul 2014
 Posts: 4706
 
 
 | 
			
				|  Posted: Mon Jun 20, 2016 6:08 pm    Post subject: |   |  
				| 
 |  
				| 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 |  |  
		|  |  
		| Zephiles Advanced Cheater
 
 ![]() Reputation: 0 
 Joined: 04 Feb 2016
 Posts: 56
 
 
 | 
			
				|  Posted: Sat Jun 25, 2016 5:02 pm    Post subject: |   |  
				| 
 |  
				| 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 |  |  
		|  |  
		| ParkourPenguin I post too much
 
  Reputation: 152 
 Joined: 06 Jul 2014
 Posts: 4706
 
 
 | 
			
				|  Posted: Sat Jun 25, 2016 6:16 pm    Post subject: |   |  
				| 
 |  
				| 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 |  |  
		|  |  
		| Zephiles Advanced Cheater
 
 ![]() Reputation: 0 
 Joined: 04 Feb 2016
 Posts: 56
 
 
 | 
			
				|  Posted: Sat Jun 25, 2016 7:13 pm    Post subject: |   |  
				| 
 |  
				| OK, so how exactly do I use these functions with my table? |  |  
		| Back to top |  |  
		|  |  
		| ParkourPenguin I post too much
 
  Reputation: 152 
 Joined: 06 Jul 2014
 Posts: 4706
 
 
 | 
			
				|  Posted: Sat Jun 25, 2016 8:32 pm    Post subject: |   |  
				| 
 |  
				| 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 |  |  
		|  |  
		| Zephiles Advanced Cheater
 
 ![]() Reputation: 0 
 Joined: 04 Feb 2016
 Posts: 56
 
 
 | 
			
				|  Posted: Sat Jun 25, 2016 9:59 pm    Post subject: |   |  
				| 
 |  
				| 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,
  ")..."]: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 |  |  
		|  |  
		| panraven Grandmaster Cheater
 
 ![]() Reputation: 62 
 Joined: 01 Oct 2008
 Posts: 958
 
 
 | 
			
				|  Posted: Sat Jun 25, 2016 10:10 pm    Post subject: |   |  
				| 
 |  
				| 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~
 
 
 
 
	
		
	 
		| Description: |  |  
		| Filesize: | 14.1 KB |  
		| Viewed: | 7986 Time(s) |  
		| 
  
 
 |  
 _________________
 
 - Retarded. 
 Last edited by panraven on Sat Jun 25, 2016 10:33 pm; edited 1 time in total
 |  |  
		| Back to top |  |  
		|  |  
		| ParkourPenguin I post too much
 
  Reputation: 152 
 Joined: 06 Jul 2014
 Posts: 4706
 
 
 | 
			
				|  Posted: Sat Jun 25, 2016 10:25 pm    Post subject: |   |  
				| 
 |  
				|  	  | 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 |  |  
		|  |  
		| Zephiles Advanced Cheater
 
 ![]() Reputation: 0 
 Joined: 04 Feb 2016
 Posts: 56
 
 
 | 
			
				|  Posted: Sat Jun 25, 2016 10:51 pm    Post subject: |   |  
				| 
 |  
				| 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 |  |  
		|  |  
		| ParkourPenguin I post too much
 
  Reputation: 152 
 Joined: 06 Jul 2014
 Posts: 4706
 
 
 | 
			
				|  Posted: Sun Jun 26, 2016 8:57 am    Post subject: |   |  
				| 
 |  
				| 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 |  |  
		|  |  
		| Zephiles Advanced Cheater
 
 ![]() Reputation: 0 
 Joined: 04 Feb 2016
 Posts: 56
 
 
 | 
			
				|  Posted: Sun Jun 26, 2016 12:32 pm    Post subject: |   |  
				| 
 |  
				| 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 |  |  
		|  |  
		| ParkourPenguin I post too much
 
  Reputation: 152 
 Joined: 06 Jul 2014
 Posts: 4706
 
 
 | 
			
				|  Posted: Sun Jun 26, 2016 12:35 pm    Post subject: |   |  
				| 
 |  
				|  	  | 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 |  |  
		|  |  
		|  |  
  
	| 
 
 | 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
 
 |  |