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 


"Custom beep" for CETRAINER Trainer
Goto page 1, 2  Next
 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting
View previous topic :: View next topic  
Author Message
mgr.inz.Player
I post too much
Reputation: 148

Joined: 07 Nov 2008
Posts: 4188
Location: W kraju nad Wisla. UTC+01:00

PostPosted: Fri Nov 09, 2012 10:33 am    Post subject: "Custom beep" for CETRAINER Trainer Reply with quote

Sun Nov 11, 2012 4:40:06; edited 11 times in total

OK, we already have our trainer as CT file. Everything works. And we want custom Beep sound.


Your current LUA script looks like this:
Code:
--TRAINERGENERATORSTART--
(...)

strings_add(getAutoAttachList(), "gameprocessname.exe")
gBeepOnAction=true
form_show(CETrainer)

function AboutClick()
  showMessage(gAboutText)
end
gAboutText=[[TEXT]]

function CloseClick()
  closeCE()
  return caFree --onClick doesn't care, but onClose would like a result
end

function onOpenProcess(processid)
  xmplayer_stop()
  (...)or something(...)
end

--TRAINERGENERATORSTOP--




What to do:

1) add WAV file to table, name it "CustomBeep.wav" (better use 22050Hz), you must know its size.
2) replace all beep() with CustomBeep.Play()

3) comment out those (place -- at the beginning of line):
- strings_add(getAutoAttachList(), "gameprocessname.exe")
- whole onOpenProcess function (if you have one)

4) add this at the end of LUA script:
Code:
CustomBeep =
{
  WINMMAndWaveFileLoaded = false,

  Play = function ()
    if not CustomBeep.WINMMAndWaveFileLoaded then return end
    autoAssemble([[createthread([400500])]],true) -- it's for CE process, use LOCAL
  end,

  Prepare = function ()

    openProcess('cheatengine-x86_64.exe')
    openProcess('cheatengine-i386.exe')

    -- now we attached to CE itself

    local callingConvention = ''
    if cheatEngineIs64Bit() then
      callingConvention =
  [[push rbp
  mov rbp,rsp
  sub rsp,30
  mov r8d,5
  mov rdx,0
  mov rcx,MemoryForWave
  call winmm.PlaySoundA
  leave
  ret]]
    else
      callingConvention =
  [[push 5
  push 0
  push MemoryForWave
  call winmm.PlaySoundA
  ret]]
    end

    local AAScript =
  [[loadlibrary(winmm.dll)
  alloc(CodePlaySound,]]..(CustomBeep.WaveFileSize+100)..[[)
  label(MemoryForWave)

  CodePlaySound+40:
  MemoryForWave:

  CodePlaySound:
  ]]..callingConvention..[[

  400500:
  dd CodePlaySound
  dd 0
  dd MemoryForWave
  dd 0]]

    if not autoAssemble(AAScript) then return end

    local filename = os.getenv("TEMP")..'\\CustomBeep.wav'
    tablefile_saveToFile(findTableFile("CustomBeep.wav"),filename)
    readRegionFromFile(filename,readInteger(0x400508))
    os.remove(filename)

    CustomBeep.WINMMAndWaveFileLoaded = true
  end,

  AttachList = {},
  AttachTimer = nil,

  AttachTimerOnTimer = function (timer)
    for i=1,#CustomBeep.AttachList do               -- go through process names
      if openProcess(CustomBeep.AttachList[i]) then -- check if process opened successfully
        object_destroy(CustomBeep.AttachTimer)      -- destroy and nil timer
        CustomBeep.AttachTimer = nil
        CustomBeep.OnOpenProcess() -- trigger OnOpenProcess
        break
      end
    end
  end,

  AttachTo = function (processName)
    table.insert(CustomBeep.AttachList,processName)
    if CustomBeep.AttachTimer == nil then
      CustomBeep.AttachTimer = createTimer(nil,false)
      timer_setInterval(CustomBeep.AttachTimer,1000)
      timer_onTimer(CustomBeep.AttachTimer,CustomBeep.AttachTimerOnTimer)
      timer_setEnabled(CustomBeep.AttachTimer,true)
    end
  end
}


5) Add this at the end
Code:
CustomBeep.WaveFileSize = 100000
CustomBeep.Prepare()
CustomBeep.AttachTo("gameprocessname.exe")

function CustomBeep.OnOpenProcess (processid)

end

Use your wav file size.
If you want, you can use AttachTo few times for other exe names.
If you have some code inside original onOpenProcess(), paste this code inside CustomBeep.OnOpenProcess function

6) for better visual effect move form_show(CETrainer) at the very end

7) Save your current CT file as CETRAINER



Note:
if you see bugs, typos or you have questions - let me know.

_________________


Last edited by mgr.inz.Player on Sat Nov 10, 2012 9:40 pm; edited 12 times in total
Back to top
View user's profile Send private message MSN Messenger
Csimbi
Grandmaster Cheater Supreme
Reputation: 67

Joined: 14 Jul 2007
Posts: 1956

PostPosted: Fri Nov 09, 2012 11:54 am    Post subject: Reply with quote

Well, the first thing I have to say: that idea is not new, but it's great.
I've been using audio feedback in my TMK trainers (a long time ago) to give feedback that a hotkey was pressed indeed. There would be more possibilities in CE.

A few thoughts.
I am guessing that people who add custom sounds will want to have a simple way to:
- add any number of waveforms
- play them from their scripts.
So I wonder if it would be better to create an array of ID and string pairs (ID: number, string: waveform's name), and expose a function like:
play(12, 1) -- play track 12, play once (not repeat)
play(999, 1) -- play track 999, once; oops, missing -> skip
play(2, 0) -- play track 2, play forever (repeat indefinitely) <- I am going to have this one as I don't like background music on trainers.

There could be other enhancements:
- which channel to use (left, right, both)
- localization
- play a chain of tracks (i.e., play track 12, when finished, play 10, when finished, play track 4)
- add Vorbis Audio (OGG) format, too (compressed, no licensing issues for compression) to minimize table/trainer size.

In any case, the first step is to add tracks to a cheat table somehow. Perhaps via the "Table" menu or via a new tab under "Table extras". I am guessing they'll get their IDs at that point - numbering them with a +1 increment, starting from 0. Then, we'd need an AA and a LUA function to actually play the track. (Yes, I'd like to see it in AA, too.)
Saving to the XML file is easy with BASE64 encoding - however it will increase the size of the tables significantly, so I wonder if it should be done somewhat differently. I can think of two ways:
No table update; the audio tracks are simple named like the cheat table and are stored separately. I.e. table.ct, table.ct.0.wav, table.ct.1.ogg, etc.
With table update; the index table is added to the cheat table, and each entry contains the name of the file (without path) and the files are stored at the same place as the cheat table so CE can access them. I.e. table.ct, activated.wav, disabled.ogg, etc.
In case of trainers, the external audio tracks would need to be added to the executable as resources.

I don't think I can help with coding all that, but you sure have my endorsement.
Back to top
View user's profile Send private message
rockymark092
How do I cheat?
Reputation: 0

Joined: 10 Nov 2012
Posts: 1

PostPosted: Sat Nov 10, 2012 5:34 am    Post subject: Reply with quote

Nice Post
_________________
rocky
Back to top
View user's profile Send private message
mgr.inz.Player
I post too much
Reputation: 148

Joined: 07 Nov 2008
Posts: 4188
Location: W kraju nad Wisla. UTC+01:00

PostPosted: Sat Nov 10, 2012 6:31 am    Post subject: Reply with quote

I made cetrainer with this custom beep and I got feedback:
"it appear that the "trainer" instantly close after the first use"

I assume it closes/crash just after CustomBeep() function first usage. Don't know why. For me it works every time - I have winxp32bit and I'm using cheatengine-i386.exe. Maybe it doesn't work for 64bit cheatengine version.



@Csimbi, I don't know if BASE64 is the best choice. Because when we save as cetrainer and choose "protect", whole XML file is compressed, and then protected with simple encryption.

What is more "compressible" - text with hex values or Base64 text ?


Sound tracks for trainer? Really?


But yes, OGG, it would be great. I think we can add some DLL to cheat table. Created cetrainer should do this (lua script): save this DLL to disk (temp folder), then import this DLL to CE process.


@DB,
we have readBytesLocal, readIntegerLocal, ....., readStringLocal, and write____Local, getAddress with optional local and autoAssemble with optional targetself

But we don't have readRegionFromFile with optional local/targetself. This is why I have to attach CE to itself.
I know I can use ..., push filename, call PlaySoundA. But I want to use sound loaded in memory.


CheatEngine (32 and 64 bit) is always loaded into 0x0400000 ?

_________________
Back to top
View user's profile Send private message MSN Messenger
Dark Byte
Site Admin
Reputation: 342

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

PostPosted: Sat Nov 10, 2012 6:57 am    Post subject: Reply with quote

Have you tried the loadbinary aa command?
Loadbinary(address, filename)

And yes, the base addresses for both 32 and 64 are hardcoded to 00400000
P.s: I found that editing near the mz header sometimes does have strange effects. I usually use 00400500


About the crashes: it won't work in 64-bit ce, as function calling is different.
What you could do of course is execute the play from inside the target game

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Back to top
View user's profile Send private message MSN Messenger
mgr.inz.Player
I post too much
Reputation: 148

Joined: 07 Nov 2008
Posts: 4188
Location: W kraju nad Wisla. UTC+01:00

PostPosted: Sat Nov 10, 2012 8:59 am    Post subject: Reply with quote

Just installed win7 again

First change I must do is:

400020:
dd CodePlaySound
dd MemoryForWave

must be:
400020:
dd CodePlaySound
dd 0
dd MemoryForWave
dd 0

and use this
readRegionFromFile(filename, readInteger("400028"))
(instead 400024)


Edit:
this doesn't work, "access violation". Don't know why, there are three push, one call qword ptr, one jump and ret at the end
Code:
03AF0000 - 6A 05                 - push 05
03AF0002 - 6A 00                 - push 00
03AF0004 - 68 4000AF03           - push 03AF0040 : ["RIFF?"]
03AF0009 - FF 15 02000000        - call qword ptr [03AF0011] ->winmm.Ordinal2
03AF000F - EB 08                 - jmp 03AF0019
03AF0011 - 10 2F                 - adc [rdi],ch
03AF0013 - F6 FA                 - idiv dl
03AF0015 - FE 07                 - inc byte ptr [rdi]
03AF0017 - 00 00                 - add [rax],al
03AF0019 - C3                    - ret


Probably I have to use RCX, RDX and etc.

_________________
Back to top
View user's profile Send private message MSN Messenger
Bady
Newbie cheater
Reputation: 0

Joined: 23 Sep 2012
Posts: 10

PostPosted: Sat Nov 10, 2012 10:46 am    Post subject: Reply with quote

@mgr.inz.Player

Of course i can help you for this as tester ^^.

I'm on Windows 7 64 bits with an ATI card then no PhysX for me or at least the option is disabled in graphics if its usefull.

The problem is an instantly close of the trainer after the first use of blink and no sound was heard.

Dont hesitate next time, it's always a pleasure Wink.
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 342

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

PostPosted: Sat Nov 10, 2012 11:20 am    Post subject: Reply with quote

You will have to use registers yes
And allocate stackspace where the function you're going to call can store the register values if it wishes (Really, some 64-bit functions actually expect that the caller does that for them)
And make sure the stack keeps properly aligned

Again, i recommend doing funtion calls like that in the target with createThread and just use alloc/globalalloc

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Back to top
View user's profile Send private message MSN Messenger
mgr.inz.Player
I post too much
Reputation: 148

Joined: 07 Nov 2008
Posts: 4188
Location: W kraju nad Wisla. UTC+01:00

PostPosted: Sat Nov 10, 2012 11:36 am    Post subject: Reply with quote

@Bady, thank you.

@Dark Byte
You suggest me to import winmm.dll into game process because:
- most games EXE's are 32 bit
- only simple push,..., call

But what if game has protections and we can use pointers only?
Probably we can't inject DLL file with injectDLL LUA command for those. Another thing: if something goes wrong, only trainer will crash, not the game.

MessageBoxA on 32 bit:
push 0
push offset szCaption
push offset szText
push 0
call MessageBoxA

MessageBoxA on 64 bit:
sub rsp, 28h
mov r9d, 0
lea r8, szCaption
lea rdx, szText
mov rcx, 0
call MessageBoxA

I'm wondering, how it looks for PlaySoundA

_________________
Back to top
View user's profile Send private message MSN Messenger
Dark Byte
Site Admin
Reputation: 342

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

PostPosted: Sat Nov 10, 2012 2:23 pm    Post subject: Reply with quote

32 bit is
Code:

push 5
 push 0
 push MemoryForWave
call winmm.PlaySoundA


So for 64 bit it'd probably be
Code:

Sub rsp,18. //3*8 and alignment is already correct (in short, rsp must be dividable by 16/0x10, and that happens with the last call)
Mov rcx, MemoryForWave
Mov rdx, 0
Mov r8,0
Call winmm.PlaySoundA

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Back to top
View user's profile Send private message MSN Messenger
mgr.inz.Player
I post too much
Reputation: 148

Joined: 07 Nov 2008
Posts: 4188
Location: W kraju nad Wisla. UTC+01:00

PostPosted: Sat Nov 10, 2012 4:09 pm    Post subject: Reply with quote

Thanks DB. Yes it does work, partially at least.
I hear sound but then it crash with access violation or just hung.

I've downloaded lazarus for 64bit and used debugger.... this is what I've got:
And it works fully.
Code:
push rbp
mov rbp,rsp
sub rsp,30
mov r8d,5
mov rdx,0
mov rcx,MemoryForWave
call winmm.PlaySoundA
leave
ret

looks like we need those "push rbp; mov rbp,rsp" at the beginning and leave before ret. And sub rsp,30.



Final modification:
Code:
  if cheatEngineIs64Bit() then
    callingConvention =
[[push rbp
mov rbp,rsp
sub rsp,30
mov r8d,5
mov rdx,0
mov rcx,MemoryForWave
call winmm.PlaySoundA
leave
ret]]
  else
    callingConvention =
[[push 5
push 0
push MemoryForWave
call winmm.PlaySoundA
ret]]
  end

_________________
Back to top
View user's profile Send private message MSN Messenger
Csimbi
Grandmaster Cheater Supreme
Reputation: 67

Joined: 14 Jul 2007
Posts: 1956

PostPosted: Sat Nov 10, 2012 4:26 pm    Post subject: Reply with quote

mgr.inz.Player wrote:

@Csimbi, I don't know if BASE64 is the best choice. Because when we save as cetrainer and choose "protect", whole XML file is compressed, and then protected with simple encryption.

By Hex encoding you mean simply changing binary to its hex text representation and not BinHex, right? That's what I assumed for now because BinHex is Mac-specific.

Hex encoding uses 16 ASCII characters and implies an increase of 100% (in practice, every single by becomes two).
BASE64 uses 64 ASCII characters and and implies an increase of at least 33% (8 bits becomes approx. 11 bits. and there's padding).

mgr.inz.Player wrote:
What is more "compressible" - text with hex values or Base64 text ?

Typically, one never compresses that data, rather, removes the encoding and includes the binary format instead.
I understand you'd want to embed and XML file direcly in the executable, and you'd want to compress it.
I'd normally recommend using binary XML format instead - you can't beat that with any compression, however that's would mean a lot of implemenation effort, so I can see why simple compression zip or zlib might be preferred.

Since HEX encoding uses most of the time the same characters, the chances for repeating patterns is much higher. Ergo, it will appear to be compressing better. However, you have a larger amount of data to start with, so I guess the increased ratio is more or less meaningless.
If you are to use compression, you better compress the data before BASE64 encoding. But, we have audio - either wav, ogg, mp3, whatever that are already hard to compress, so I wonder if it's worth it.

I ran some tests with TotalCommander's zip compressor (max compression), please find the results attached as a screenshot.
The input files are the wav files that come with win7x64sp1 - these are not compressed in their original form; wavs can contain compressed data, too.
I took the original file, BASE64 encoded it and ZIPed up the BASE64 encoded file again.
Then, I tried ZIPing the original file, BASE64 encoding it and ZIPing up the BASE64 encoded file again.
Last, I tried MP3ing the original file (settings: vbr, 320k, high quality), BASE64 encoding it and ZIPing up the BASE64 encoded file again.
I put the stats into the table and added a few ratio calculations.

As you can see, the most significant reduction on the original file comes from MP3 compression (green colour); no surpise here, MP3 was specifically designed for that.
In the middle, you can see that BASE64 encoding is very much uniform; everything is about 137% here.
The light blue numbers on the right show you that you can use ZIP to compress the data again after BASE64 encoding.
The orange numbers show you the overall win, the ratio from WAV to the final (BASE64ed and then ZIPed).
The purple numbers show you the overall ratio from own source (adding BASE64 and ZIP to a WAV, a ZIP and an MP3 file). The first purple number is very interesting: it became smaller anyway!!!

The most important number is the initial compression - there's not much difference from there.
So, I'd go with MP3 or OGG (or, both).
Both of these are scalable depending on the quality.
OGG might yield better compression.
Opus audio would be the best (it is also an open format like Vorbis) - but it's brand new so there are no tools for that yet.

There are other binary to text encoding mechanisms (such as uuencode), but BASE64 was by far the most efficient and popular from what I've seen.

Instead of ZIP, one could use zlib. I did not run test on that however.
zlib is open and fast, so I guess you'll pick that anyway.

mgr.inz.Player wrote:
Sound tracks for trainer? Really?

It's a figure of speech. We need to establish a terminology.
I usually call any audio with a unique ID a 'track'.

I hope this helps you make a good design.



AudioCompressionTests.png
 Description:
 Filesize:  36.53 KB
 Viewed:  18892 Time(s)

AudioCompressionTests.png


Back to top
View user's profile Send private message
mgr.inz.Player
I post too much
Reputation: 148

Joined: 07 Nov 2008
Posts: 4188
Location: W kraju nad Wisla. UTC+01:00

PostPosted: Sat Nov 10, 2012 5:35 pm    Post subject: Reply with quote

There's another option. We can use free TTAEnc.exe.

1) We add tta files (converted WAVs) and TTAEnc.exe to table
2) cetrainer after execute do this:
3) inject winmm.dll to CE itself
4) extract all tta files to %temp%
5) extract ttaenc.exe file to %temp%
6) run lua os.execute to run TTAEnc.exe decompression
7) load all converted WAVE files into memory
8 ) we have table with addresses of all WAVE files loaded in memory


But, for now, I stick with easy winmm.dll and light weight WAV file for CustomBeep Razz

Making CE plugin for it must be much easier Razz I think I will make one in the future.

Of course, thanks for your help Csimbi Razz


EDIT:
OK. First post updated with everything I learned so far.

And below I attached "Blink for Borderlands2" cetrainer.
Could you (Csimbi & Bady) test it?



Borderlands2Blink.CETRAINER
 Description:

Download
 Filename:  Borderlands2Blink.CETRAINER
 Filesize:  101.28 KB
 Downloaded:  828 Time(s)


_________________
Back to top
View user's profile Send private message MSN Messenger
Csimbi
Grandmaster Cheater Supreme
Reputation: 67

Joined: 14 Jul 2007
Posts: 1956

PostPosted: Sat Nov 10, 2012 8:09 pm    Post subject: Reply with quote

I don't have it installed, sorry...
Back to top
View user's profile Send private message
Bady
Newbie cheater
Reputation: 0

Joined: 23 Sep 2012
Posts: 10

PostPosted: Sun Nov 11, 2012 9:00 am    Post subject: Reply with quote

Works perfectly and the sound is exactly appropriate and not annoying Very Happy.
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
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