  | 
				
				Cheat Engine The Official Site of Cheat Engine   
				
 
				 | 
			 
		 
		 
	
		| View previous topic :: View next topic   | 
	 
	
	
		| Author | 
		Message | 
	 
	
		Corroder Grandmaster Cheater Supreme
  Reputation: 75
  Joined: 10 Apr 2015 Posts: 1668
 
  | 
		
			
				 Posted: Sat Mar 03, 2018 2:17 am    Post subject: Implementing Lua Scripting To Creating CE Mp3 Player | 
				        | 
			 
			
				
  | 
			 
			
				In connection to these topics :
 
 
http://forum.cheatengine.org/viewtopic.php?t=584021
 
http://forum.cheatengine.org/viewtopic.php?t=606901
 
 
which already answerd by the 'play MP3 sound in CE function' creator : mgr.inz.Player
 
as also knew as ones  most respected Cheat Engine / CEF users.
 
 
So, the fisrt thing I want to do is to thank so much to mgr.inz.Player and also Dark Byte as
 
Cheat Engine creator.
 
 
Form those topics above, I have created a 'Simple MP3 Player' by followed 'play MP3 sound in CE function'
 
including added and modified some functions and use pure Cheat Engine Lua scripting. 
 
My goal by doing this project is for learning purpose and more than it is to prove and show if CE not only use
 
for memory hacking, it also can use for other purpose, specially for Lua scripting.
 
 
The project as below :
 
 
--================================================================--
 
-- Project name 	        : CRDR-MP3Player-Ver.4.0 
 
-- Creator     		: Corroder a.k.a VCLBro
 
-- Created date   	: 28-02-2018
 
-- Scripting Language 	: Lua 5.3 compatible Lua 5.1, Lua 5.2
 
-- Scripting IDE	        : CE 6.7 Lua Engine
 
-- Special thanks to	: mgr.inz.Player, Dark Byte, CEF Members
 
-- Purpose		        : Learning, show CE not only use for hack
 
--================================================================--
 
--  Note :
 
-- 1.All Form GUI on this project made use Lua Scripting 
 
-- 2.GUI Images and Icons, has store as stream files
 
-- 3.Some notes has added inside script code for references
 
-- 4.NOT FOR COMMERCIAL USE  
 
--================================================================--
 
 
 What inside this project ? :
 
 
 A. Work with Lua Table
 
 
1.Function to save and load lua table to a file
 
 
 	  | Code: | 	 		  do
 
local function exportstring( s )
 
 s = string.format( "%q",s )
 
 s = string.gsub( s,"\\\n","\\n" )
 
 s = string.gsub( s,"\r","\\r" )
 
 s = string.gsub( s,string.char(26),"\"..string.char(26)..\"" )
 
 return s
 
end
 
 
function table.save(  tbl,filename )
 
 local charS,charE = "   ","\n"
 
 local file,err
 
 if not filename then
 
 file =  { write = function( self,newstr ) self.str = self.str..newstr end, str = "" }
 
 charS,charE = "",""
 
 elseif filename == true or filename == 1 then
 
 charS,charE,file = "","",io.tmpfile()
 
 else
 
 file,err = io.open( filename, "w" )
 
 if err then return _,err end
 
 end
 
 local tables,lookup = { tbl },{ [tbl] = 1 }
 
 file:write( "return {"..charE )
 
 for idx,t in ipairs( tables ) do
 
 if filename and filename ~= true and filename ~= 1 then
 
 file:write( "-- Table: {"..idx.."}"..charE )
 
 end
 
 file:write( "{"..charE )
 
 local thandled = {}
 
 for i,v in ipairs( t ) do
 
 thandled[i] = true
 
 if type( v ) ~= "userdata" then
 
 if type( v ) == "table" then
 
 if not lookup[v] then
 
 table.insert( tables, v )
 
 lookup[v] = #tables
 
 end
 
 file:write( charS.."{"..lookup[v].."},"..charE )
 
 elseif type( v ) == "function" then
 
 file:write( charS.."loadstring("..exportstring(string.dump( v )).."),"..charE )
 
 else
 
 local value =  ( type( v ) == "string" and exportstring( v ) ) or tostring( v )
 
 file:write(  charS..value..","..charE )
 
 end
 
 end
 
 end
 
 for i,v in pairs( t ) do
 
 if (not thandled[i]) and type( v ) ~= "userdata" then
 
 if type( i ) == "table" then
 
 if not lookup[i] then
 
 table.insert( tables,i )
 
 lookup[i] = #tables
 
 end
 
 file:write( charS.."[{"..lookup[i].."}]=" )
 
 else
 
 local index = ( type( i ) == "string" and "["..exportstring( i ).."]" ) or string.format( "[%d]",i )
 
 file:write( charS..index.."=" )
 
 end
 
 if type( v ) == "table" then
 
 if not lookup[v] then
 
 table.insert( tables,v )
 
 lookup[v] = #tables
 
 end
 
 file:write( "{"..lookup[v].."},"..charE )
 
 elseif type( v ) == "function" then
 
 file:write( "loadstring("..exportstring(string.dump( v )).."),"..charE )
 
 else
 
 local value =  ( type( v ) == "string" and exportstring( v ) ) or tostring( v )
 
 file:write( value..","..charE )
 
 end
 
 end
 
 end
 
 file:write( "},"..charE )
 
 end
 
 file:write( "}" )
 
 if not filename then
 
 return file.str.."--|"
 
 elseif filename == true or filename == 1 then
 
 file:seek ( "set" )
 
 return file:read( "*a" ).."--|"
 
 else
 
 file:close()
 
 return 1
 
 end
 
end
 
 
function table.load( sfile )
 
 local tables, err, _
 
 if string.sub( sfile,-3,-1 ) == "--|" then
 
 tables,err = loadstring( sfile )
 
 else
 
 tables,err = loadfile( sfile )
 
 end
 
 if err then return _,err
 
 end
 
 tables = tables()
 
 for idx = 1,#tables do
 
 local tolinkv,tolinki = {},{}
 
 for i,v in pairs( tables[idx] ) do
 
 if type( v ) == "table" and tables[v[1]] then
 
 table.insert( tolinkv,{ i,tables[v[1]] } )
 
 end
 
 if type( i ) == "table" and tables[i[1]] then
 
 table.insert( tolinki,{ i,tables[i[1]] } )
 
 end
 
 end
 
 for _,v in ipairs( tolinkv ) do
 
 tables[idx][v[1]] = v[2]
 
 end
 
 for _,v in ipairs( tolinki ) do
 
 tables[idx][v[2]],tables[idx][v[1]] =  tables[idx][v[1]],nil
 
 end
 
 end
 
 return tables[1]
 
 end
 
end | 	  
 
 
 
2.Get a table length
 
 
 	  | Code: | 	 		  function tablelength(T)
 
 local count = 0
 
 for _ in pairs(T) do count = count + 1 end
 
 return count
 
end | 	  
 
 
 
3.Clearing / empty a table
 
 
 	  | Code: | 	 		  function clearTable(tb)
 
 for i, v in pairs(tb) do
 
 tb[i] = nil
 
 end
 
end
 
-- [table] = {} also use to clear a table, but in fact with this function but in fact the table still store a nil value
 
 | 	  
 
 
 
B. Function to convert seconds to time format HH:MM:SS or 00:00:00
 
 
 	  | Code: | 	 		  function SecondsToClock(seconds)
 
 local seconds = tonumber(seconds)
 
 if seconds <= 0 then
 
 return "00:00:00";
 
 else
 
 hours = string.format("%02.f", math.floor(seconds/3600));
 
 mins = string.format("%02.f", math.floor(seconds/60 - (hours*60)));
 
 secs = string.format("%02.f", math.floor(seconds - hours*3600 - mins *60));
 
 return hours..":"..mins..":"..secs
 
 end
 
end | 	  
 
 
	
 
 C. Other functions or and logics to create custom GUI, etc
 
 
What about this CRDR-MP3Player-Ver.4.0 player ?
 
1. Common mp3 player functions : Play, Stop, Resume, Pause
 
2. Added : Mute / Un-mute volume
 
3. Added : Filtering mp3 files when browsing on PC/Extrnal storage
 
4. Added : Created mp3 songs playlist which editable and save
 
5. Added : Automatic load last saved songs playlist
 
6. Added : Option to play single song or play songs shuffle
 
7. Added : Song info when playing -> Title, Path, Duration, File Size
 
8. Added : Song play elapsed time with custom progress bar
 
9. Added : MP3 player skin theme selector
 
10. Added : Loud speaker control -> Balance, Left/Right Volume, Bass/Treble Volume
 
 
 On future update (plan) : 
 
- Added 'media seek = fast forward / back'
 
- Added 'sound visualization'
 
 
Download Source Code (CT file) :
 
 
https://mega.nz/#!Xw8FVZAB!cUOGWWogAvdB5Xxv8XzgSCZcfJDiYVV7Y6JZUPHqQSs
 
 
NOTE 2 :
 
This project is not perfect, it's possible contain some error (I hope not). Anyhow, if you think you can create better then goes on, 
 
then use this project as your motivation. 
 
Even I can do same thing like this using other programming language such as VB, C++ and others but
 
the main purpose from this project is to prove and show if CE is not iuse for hacking only. 
 
It's more than it if on right hands...
 
 
 
EDIT : 18/03/2018
 
CRDR-MP3 Player V.5
 
https://youtu.be/pwBsDrFQEic
 
 
Download source code / CT file CRDR-MP3-Player-V5:
 
https://mega.nz/#!jtkjmQ7Z!_DC-ri1R_CEMQN-mkTBgzH1celOtwBf97GMrxZ_Nc8c
 
 
 
Also if you want play MIDI file format, add this : 
 
 
 	  | Code: | 	 		  function playMID(path)  
 
 if not initializeMP3Player() then return end
 
 MP3PlayerSendCommand('close midifile')
 
 MP3PlayerSendCommand(string.format('open "%s" type sequencer alias midifile',path))
 
 MP3PlayerSendCommand('play midifile')
 
end | 	  
 
 
To play WMA file format (example with openDialog to locate wma file)
 
 
 	  | Code: | 	 		  function playWMA() -- work
 
 if not initializeMP3Player() then return end
 
 load_dialog = createOpenDialog(self)
 
 load_dialog.InitalDir = os.getenv('%USERPROFILE%')
 
-- load_dialog.Filter = 'MP3 files|*.mp3|*'
 
 load_dialog.Filter = 'Audio files|*.mp3;*.mid;*.wav;*.wma|Mp3 files (*.mp3)|*.MP3|Mid files (*.mid)|*.MID|Wav files (*.wav)|*.WAV|Wma files (*.wma)|*.WMA|*'
 
 load_dialog.execute()
 
 local file = load_dialog.FileName
 
 s_file = string.sub(file, -4)
 
 print(s_file)
 
 if s_file == '.wma' then
 
 MP3PlayerSendCommand('play '..file)
 
 else
 
 print('not WMA file...')
 
 end
 
end | 	  
 
 
Cheers...
 
Corroder
 _________________
 Stealing Code From Stolen Code...
 
And Admit It.. Hmmm....Typically LOL 
  Last edited by Corroder on Thu Mar 15, 2018 4:01 am; edited 3 times in total | 
			 
		  | 
	 
	
		| Back to top | 
		 | 
	 
	
		  | 
	 
	
		AylinCE Grandmaster Cheater Supreme
  Reputation: 37
  Joined: 16 Feb 2017 Posts: 1530
 
  | 
		
			
				 Posted: Sat Mar 03, 2018 8:03 am    Post subject:  | 
				       | 
			 
			
				
  | 
			 
			
				Nice work, original work. Congratulations.
 
still foreign to me a lot of coding.
 
I guess I'm used to 'UDF1' coding.
 
'CreateTable' is an encoding I still can not figure out.
 
It also opens and the sliding menu is great. You do it for the 2nd time.
 
I noticed something;
 
Still does not install multiple song list.
 
Songs single, single loading.
 
A file, 'Ctrl + A' or list selection can not be made.  
 
Without changing any letters in this file,
 
By registering as a trainer,
 
Do we have a chance to open it in another trainer?
 
The writer's identity and identity are present,
 
there is no need to make a new table.
 
It will be more accurate to present original articles and works to members.
 
'AddFile' with this file, we will apply your previous coding?
 
 
Thanks @Corroder.
 _________________
  | 
			 
		  | 
	 
	
		| Back to top | 
		 | 
	 
	
		  | 
	 
	
		AylinCE Grandmaster Cheater Supreme
  Reputation: 37
  Joined: 16 Feb 2017 Posts: 1530
 
  | 
		
			
				 Posted: Sat May 16, 2020 9:37 am    Post subject:  | 
				       | 
			 
			
				
  | 
			 
			
				@Corroder, MP3 code, if it returns to the beginning,
 
(In simple MP3 player mode)
 
Can we add and use "findTableFile" to the table without "TrainerOrigin"?
 
MP3 files will be in the table (add file).
 
How should we code to execute from table memory?
 
 
This code did not work;
 
 
 
 	  | Code: | 	 		  local mp3File9 = findTableFile('music111.mp3').Stream
 
 
playMP3(mp3File9) | 	  
 
 
Is there a solution?
 _________________
  | 
			 
		  | 
	 
	
		| Back to top | 
		 | 
	 
	
		  | 
	 
	
		Corroder Grandmaster Cheater Supreme
  Reputation: 75
  Joined: 10 Apr 2015 Posts: 1668
 
  | 
		
			
				 Posted: Sat May 16, 2020 11:51 am    Post subject:  | 
				       | 
			 
			
				
  | 
			 
			
				I think not to use mciSendString, but use memoryStream.
 
 
Example:
 
 
 	  | Code: | 	 		  --- Music MP3 Function
 
if oldcreateMemoryStream==nil then oldcreateMemoryStream = createMemoryStream end
 
function createMemoryStream()
 
 local obj = oldcreateMemoryStream()
 
 local oldwrite=obj.write
 
 obj.write = function (t,n)  -- override default write
 
 local count=0
 
 for _,v in ipairs(t) do
 
 if count==n then break end
 
 oldwrite({v},1)
 
 count=count+1
 
 end
 
 end
 
 obj.writeDword = function (v) obj.write(dwordToByteTable(v)) end
 
 obj.writeWord = function (v) obj.write(wordToByteTable(v)) end
 
 return obj
 
 end
 
--convertMP3ToRIFFMP3(stream)
 
function convertMP3ToRIFFMP3(stream)
 
 local riffmp3 = createMemoryStream()
 
 local header = {
 
 0x46464952,0x00000000,0x45564157,0x20746D66,0x0000001E,0x00020055,
 
 0x0000AC44,0x00000000,0x00000001,0x0001000C,0x00000002,0x00010001,
 
 0x61660571,0x00047463,0x2FF80000,0x61640014
 
  } -- default is 44100Hz , Stereo
 
 local rateTable = {[0] = {11025,12000,8000},   --mpeg ver2.5
 
                    [2] = {22050,24000,16000},  --mpeg ver2
 
                    [3] = {44100,48000,32000}}  --mpeg ver1
 
 local bitrateTable = {[1]={32,64,96,128,160,192,224,256,288,320,352,384,416,448},
 
                       [2]={32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384},
 
                       [3]={32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320},
 
                       [4]={32,48,56, 64, 80, 96,112,128,144,160,176,192,224,256},
 
                       [5]={ 8,16,24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160}}
 
 for i,v in ipairs(header) do riffmp3.writeDword(v) end
 
 riffmp3.writeWord(0x6174)
 
 riffmp3.writeDword(stream.Size)
 
 stream.Position = 0
 
 riffmp3.copyFrom(stream,stream.Size)
 
 riffmp3.Position = 0x4; riffmp3.writeDword(stream.Size+0x24)
 
 stream.Position = 0
 
 local chunk = stream.read( math.min(65536,stream.Size) )
 
 local DWORD = byteTableToDword( {chunk[4],chunk[3],chunk[2],chunk[1]} )
 
 
  local i=0x1
 
  while (i<=#chunk-4) do
 
  if (bAnd(DWORD,0xFFE00000)==0xFFE00000) and
 
     (bAnd(DWORD,0x60000)~=0) and
 
     (bAnd(DWORD,0xF000)~=0xF000) and
 
     (bAnd(DWORD,0xC00)~=0xC00)
 
    then
 
     --probably MPEG Audio Layer I/II/III frame header
 
     local channels    =(bAnd(bShr(DWORD, 6), 3) == 3) and 1 or 2
 
     local layer       = 3 - bAnd(bShr(DWORD,17), 3) + 1;
 
     local mpegaudioid = bAnd(bShr(DWORD,19), 3)
 
     local rateindex   = bAnd(bShr(DWORD,10), 3)
 
     local bitrateindex= bAnd(bShr(DWORD,12),15)
 
     local samplerate  = rateTable[mpegaudioid][rateindex+1]
 
     local row
 
   if     mpegaudioid==3 then row=layer -- mpeg ver1
 
     elseif layer==1       then row=4     -- mpeg ver2 and ver2.5, Layer 1
 
     else                       row=5     -- mpeg ver2 and ver2.5, Layer 2 and 3
 
     end
 
 local bitrate = bitrateTable[row][bitrateindex]
 
 riffmp3.Position = 0x16;
 
 riffmp3.writeWord(channels)
 
 riffmp3.writeDword(samplerate)
 
 riffmp3.writeDword(math.floor(bitrate*1000/8))
 
 break
 
 end
 
 if (bAnd(DWORD,0xFFFFFF00)==0x49443300) and
 
    (bAnd(DWORD,0xFF)<0xFF)
 
    --ID3 tag found
 
    then
 
    local size = bOr(bShl(chunk[i+6],7),chunk[i+7])
 
          size = bOr(bShl(size,7),chunk[i+8])
 
          size = bOr(bShl(size,7),chunk[i+9])
 
    i=i+size
 
 end
 
 DWORD = bOr( bShl(DWORD,8) , chunk[i+4] ) % 0x100000000
 
 i=i+1
 
 end
 
 chunk = nil
 
 riffmp3.Position = riffmp3.Size - 1
 
 return riffmp3
 
end
 
----
 
function sound_prepare(track)
 
  if track==nil then return nil end
 
  if knownStreams==nil then knownStreams = {} end
 
  local stream,streamID
 
-- set stream variable
 
  if type(track)=='string' then
 
  if knownStreams[track]~=nil then return track end -- check name as StreamID
 
  if findTableFile(track) then stream=findTableFile(track).Stream else return nil end
 
  elseif track.ClassName=='TMemoryStream' then
 
  stream=track else stream=track.Stream
 
  end
 
  streamID=userDataToInteger(stream)
 
  if knownStreams[streamID]~=nil then return streamID end
 
  stream.Position = 0
 
  if table.concat(stream.read(4),'-')=='82-73-70-70' then
 
  knownStreams[streamID]=stream
 
  else
 
  local riffmp3 = convertMP3ToRIFFMP3(stream)
 
  knownStreams[streamID]=riffmp3
 
  end
 
 if type(track)=='string' then knownStreams[track]=knownStreams[streamID] end
 
 return streamID
 
end
 
if oldplaySound==nil then oldplaySound=playSound end
 
---
 
function playSound(track, ...)
 
  local ID=sound_prepare(track)
 
  if ID then oldplaySound(knownStreams[ID], ...)
 
  else print('track not found') end
 
end
 
 
--- Test play
 
file = findTableFile('test.mp3')
 
playSound(file)
 
 
--- Stop play
 
file = findTableFile('silence.mp3')  -- find somewhere a file with name silence.mp3 which produce no sound
 
playSound(file) | 	  
 _________________
 Stealing Code From Stolen Code...
 
And Admit It.. Hmmm....Typically LOL  | 
			 
		  | 
	 
	
		| Back to top | 
		 | 
	 
	
		  | 
	 
	
		AylinCE Grandmaster Cheater Supreme
  Reputation: 37
  Joined: 16 Feb 2017 Posts: 1530
 
  | 
		
			
				 Posted: Sat May 16, 2020 2:42 pm    Post subject:  | 
				       | 
			 
			
				
  | 
			 
			
				 	  | Corroder wrote: | 	 		  I think not to use mciSendString, but use memoryStream.
 
 | 	  
 
 
 
Yes, I have the same code at the moment and "playSound" does not run 2 mp3s at the same time.
 
I guess it is not possible to play 5 different sounds at the same time.
 
I tried with playSound and playMP3, it didn't.
 
I think I should copy 5 "winmm.dll".   
 _________________
  | 
			 
		  | 
	 
	
		| Back to top | 
		 | 
	 
	
		  | 
	 
	
		Corroder Grandmaster Cheater Supreme
  Reputation: 75
  Joined: 10 Apr 2015 Posts: 1668
 
  | 
		
			
				 Posted: Sat May 16, 2020 3:46 pm    Post subject:  | 
				        | 
			 
			
				
  | 
			 
			
				 	  | Aylin wrote: | 	 		  I think I should copy 5 "winmm.dll".    | 	  
 
 
No you dont. If the songs are on local disk (not table file), use mciSendString like this :
 
 
 	  | Code: | 	 		  function playMulti(song1, song2,...)
 
 if not initializeMP3Player() then return end
 
 local fileName
 
 fileName = song1
 
 MP3PlayerSendCommand("open "..fileName.." type mpegvideo alias FirstSound", 0, 0, 0)
 
 MP3PlayerSendCommand("play FirstSound", 0, 0, 0)
 
 
 fileName = song2
 
 MP3PlayerSendCommand("open "..fileName.." type mpegvideo alias SecondSound", 0, 0, 0)
 
 MP3PlayerSendCommand("play SecondSound",0, 0, 0)
 
 
 -- add here until filename = song5
 
 
end
 
 
s1 = "E:\\test1.mp3"
 
s2 = "E:\\test2.mp3"
 
playMulti(s1,s2) | 	  
 
 
 
EDIT:
 
If your song2 are on table file then you need to find them and save as local files on temporary dir. and then play the sounds from there.
 
And when then delete them all when the trainer closes. As usual, we did.
 _________________
 Stealing Code From Stolen Code...
 
And Admit It.. Hmmm....Typically LOL  | 
			 
		  | 
	 
	
		| Back to top | 
		 | 
	 
	
		  | 
	 
	
		AylinCE Grandmaster Cheater Supreme
  Reputation: 37
  Joined: 16 Feb 2017 Posts: 1530
 
  | 
		
			
				 Posted: Sun May 17, 2020 6:49 am    Post subject:  | 
				       | 
			 
			
				
  | 
			 
			
				Sorry, it didn't work.
 
Also, 5 different songs are not in one command.
 
So there are 17 songs (or audio files) and they are all on separate buttons.
 
For example; I am trying to add effects to a music.
 
Commands should not be together, they should work on separate buttons.
 
Whenever I run it, it turns off the current sound and works. This shouldn't happen.
 
When I disable this code, the sound does not play at all.
 
 
 	  | Code: | 	 		    --MP3PlayerSendCommand('close MediaFile')
 
  MP3PlayerSendCommand( string.format('open "%s" type mpegvideo alias MediaFile',path) )
 
  MP3PlayerSendCommand('play MediaFile') | 	  
 
 
I think the following example is enough to understand;
 
Like a Karoeke,
 
When playing music, add sound to it.  
 _________________
  | 
			 
		  | 
	 
	
		| Back to top | 
		 | 
	 
	
		  | 
	 
	
		Corroder Grandmaster Cheater Supreme
  Reputation: 75
  Joined: 10 Apr 2015 Posts: 1668
 
  | 
		
			
				 Posted: Sun May 17, 2020 7:07 am    Post subject:  | 
				       | 
			 
			
				
  | 
			 
			
				For me this is work. I note you said 'play sound at the same time'.
 
 
 	  | Code: | 	 		  function initializeMP3Player()
 
  if initializeMP3Player_done then return true end
 
 
local script64bit=[[loadlibrary(C:\Windows\System32\winmm.dll)
 
alloc(SimpleMp3Player,4096)
 
registersymbol(SimpleMp3Player)
 
 
SimpleMp3Player:
 
lea rsp,[rsp-28]
 
lea rsi,[rcx+400]
 
 
lea rdx,[rcx+300]
 
mov r8d,80
 
xor r9d,r9d
 
call mciSendStringW
 
mov rcx,rax
 
mov rdx,rsi
 
mov r8,200
 
call mciGetErrorStringW
 
 
lea rsp,[rsp+28]
 
ret]]
 
 
local script32bit=[[loadlibrary(C:\Windows\System32\winmm.dll)
 
alloc(SimpleMp3Player,4096)
 
registersymbol(SimpleMp3Player)
 
 
SimpleMp3Player:
 
push ebp
 
mov ebp,esp
 
push ebx
 
 
mov ebx,[ebp+8]
 
 
sub esp,10
 
mov [esp],ebx
 
lea ebx,[ebx+300]
 
mov [esp+4],ebx
 
mov [esp+8],80
 
mov [esp+c],0
 
call mciSendStringW
 
 
mov ebx,[ebp+8]
 
lea ebx,[ebx+400]
 
 
sub esp,0c
 
mov [esp],eax
 
mov [esp+0x4],ebx
 
mov [esp+0x8],200
 
call mciGetErrorStringW
 
 
pop ebx
 
leave
 
ret 004]]
 
 
  if cheatEngineIs64Bit() then script = script64bit else script = script32bit end
 
  if autoAssemble(script,true)
 
  then
 
    initializeMP3Player_done = true
 
    MP3PlayerCommandMS = createMemoryStream()
 
    MP3PlayerCommandMS.Size = 2048
 
    return true
 
  else
 
    return false
 
  end
 
end
 
 
function MP3PlayerSendCommand(command)
 
  writeStringLocal(MP3PlayerCommandMS.Memory, command, true)
 
  writeBytesLocal (MP3PlayerCommandMS.Memory+2*#command, 0, 0)
 
  executeCodeLocal('SimpleMp3Player',MP3PlayerCommandMS.Memory)
 
  return readStringLocal(MP3PlayerCommandMS.Memory+1024,512,true),
 
         readStringLocal(MP3PlayerCommandMS.Memory+768,128,true)
 
end
 
 
function playMP3(path)
 
  if not initializeMP3Player() then return end
 
  MP3PlayerSendCommand('close MediaFile')
 
  MP3PlayerSendCommand( string.format('open "%s" type mpegvideo alias MediaFile',path) )
 
  MP3PlayerSendCommand('play MediaFile')
 
end
 
 
function playMulti(song1, song2,...)
 
 if not initializeMP3Player() then return end
 
 local fileName
 
 fileName = song1
 
 MP3PlayerSendCommand("open "..fileName.." type mpegvideo alias FirstSound", 0, 0, 0)
 
 MP3PlayerSendCommand("play FirstSound", 0, 0, 0)
 
 
 fileName = song2
 
 MP3PlayerSendCommand("open "..fileName.." type mpegvideo alias SecondSound", 0, 0, 0)
 
 MP3PlayerSendCommand("play SecondSound",0, 0, 0)
 
end
 
 
----- Test, change song files with your own
 
s1 = "E:\\test1.mp3"
 
s2 = "E:\\test2.mp3"
 
playMulti(s1,s2)
 
 
 | 	  
 
 
 
And here my old file with song list on a combobox.
 
 
 	  | Code: | 	 		  getLuaEngine().cbShowOnPrint.Checked=false
 
getLuaEngine().hide()
 
 
function loadTableCode(n)
 
 local t = findTableFile(n)
 
 if t ~= nil then
 
 local s = t.Stream
 
 local c = readStringLocal(s.Memory,s.Size)
 
 return c ~= nil and loadstring(c) -- return a function
 
 end
 
end
 
--
 
local f = loadTableCode('plsound.lua')
 
print(type(f))
 
if type(f) == 'function' then f() else print('not loaded') end
 
 
local Mform = createForm()
 
Mform.Width = 280
 
Mform.Height = 180
 
Mform.Position = 'poScreenCenter'
 
Mform.BorderStyle = 'bsNone'
 
Mform.Color = '0x00595959'
 
Mform.Name = 'Mform'
 
 
local TitlePanel = createPanel(Mform)
 
TitlePanel.Left = 1
 
TitlePanel.Top = 1
 
TitlePanel.Height = 30
 
TitlePanel.Width = Mform.Width - 1
 
TitlePanel.Caption = ' '
 
TitlePanel.BavelInner = 'bvRaised'
 
TitlePanel.BavelOuter = 'bvRaised'
 
TitlePanel.Color = '0x00DFF7FF'  --'0x00868686'
 
TitlePanel.Name = 'TitlePanel'
 
TitlePanel.OnMouseDown = function() Mform.DragNow() end
 
 
local TitleLabel = createLabel(TitlePanel)
 
TitleLabel.Left = 10
 
TitleLabel.Top = 7
 
TitleLabel.Font.Name = 'Armalite Rifle'
 
TitleLabel.Font.Style = 'fsBold'
 
TitleLabel.Font.Size = '12'
 
TitleLabel.Font.Color = '0x00595959'
 
TitleLabel.Caption = 'MP3 Song - Player'
 
TitleLabel.Name = 'TitleLabel'
 
 
local SongBox = createComboBox(Mform)
 
SongBox.Top = TitlePanel.Top + TitlePanel.Height + 10
 
SongBox.Left = 10
 
SongBox.Width = Mform.Width - SongBox.Left - 10
 
SongBox.Color = '0x00DFF7FF'
 
SongBox.Style = 'csDropDown'
 
SongBox.Text = 'Pick a song..'
 
SongBox.Name = 'SongBox'
 
 
MsLabel = createLabel(Mform)
 
MsLabel.Left = 10
 
MsLabel.Top = SongBox.Top + SongBox.Height + 10
 
MsLabel.Font.Name = 'Arial'
 
MsLabel.Font.Size = 9
 
MsLabel.AutoSize = false
 
MsLabel.Width = Mform.Width - MsLabel.Left - 10
 
MsLabel.Height = 50
 
MsLabel.WordWrap = true
 
MsLabel.Font.Style = 'fsBold'
 
MsLabel.Font.Color = '0x00DFF7FF'
 
MsLabel.Caption = 'Idle..'
 
MsLabel.Name = 'MsLabel'
 
 
items = combobox_getItems(SongBox)
 
strings_add(items, "Pick a song..")
 
SongBox.ItemIndex = 0
 
 
songTable = {
 
{songName = "Adele - Hello", songPath = "E:\\Lagu Film Dll\\Filmograph\\Lagu MP3\\Barat\\Adele - Hello.mp3"},
 
{songName = "Billy Joel - An Innocent Man", songPath = "E:\\Lagu Film Dll\\Filmograph\\Lagu MP3\\Barat\\Billy Joel - An Innocent Man.mp3"},
 
{songName = "Celine Dion - My Heart Will Go On", songPath = "E:\\Lagu Film Dll\\Filmograph\\Lagu MP3\\Barat\\Celine Dion - My Heart Will Go On.mp3"},
 
{songName = "Chris Brown - Dont Wake Up", songPath = "E:\\Lagu Film Dll\\Filmograph\\Lagu MP3\\Barat\\Chris Brown - Dont Wake Up.mp3"},
 
{songName = 'Kate Bush - Wuthering Height', songPath = "E:\\Lagu Film Dll\\Filmograph\\Lagu MP3\\Barat\\Kate Bush - Wuthering Height.mp3"}
 
}
 
 
for i,v in ipairs(songTable) do
 
 strings_add(items, v.songName)
 
end
 
 
function cbboxOnChange()
 
 index = getProperty(SongBox, "ItemIndex")
 
 index = songTable[index]
 
 if index == nil then
 
 MsLabel.Caption = 'Idle..'
 
 else
 
 local ss = createMemoryStream()
 
 path = index.songPath
 
 ss.loadFromFile(path)
 
 playSound(ss)
 
 ss.Destroy()
 
 MsLabel.Caption = "Playing - "..index.songName
 
 end
 
end
 
SongBox.onChange = cbboxOnChange
 
 
bStop = createButton(Mform)
 
bStop.Left = 10
 
bStop.Top = MsLabel.Top + MsLabel.Height + 20
 
bStop.Height = 25
 
bStop.Width = 70
 
bStop.Caption = 'Stop'
 
bStop.Cursor = -21
 
bStop.Name = 'bStop'
 
 
bExplo = createButton(Mform)
 
bExplo.Left = bStop.Left + bStop.Width + 25
 
bExplo.Top = MsLabel.Top + MsLabel.Height + 20
 
bExplo.Height = 25
 
bExplo.Width = 70
 
bExplo.Caption = 'Find MP3'
 
bExplo.Cursor = -21
 
bExplo.Name = 'bExplo'
 
 
bExit = createButton(Mform)
 
bExit.Width = 70
 
bExit.Left = Mform.Width - bExit.Width - 10
 
bExit.Top = MsLabel.Top + MsLabel.Height + 20
 
bExit.Height = 25
 
bExit.Caption = 'Exit'
 
bExit.Cursor = -21
 
bExit.Name = 'bExit'
 
 
function songStop()
 
 local check = MsLabel.Caption
 
 if check == 'Idle..' then
 
 showMessage("No song playing...")
 
 end
 
 playSound('silence.mp3')
 
 MsLabel.Caption = "Idle.."
 
 SongBox.ItemIndex = 0
 
 SongBox.Text = 'Pick a song..'
 
end
 
 
function GetFileName(f)
 
 local str = f
 
 local temp = ""
 
 local result = ""
 
 for i = str:len(), 1, -1 do
 
 if str:sub(i,i) ~= "/"  then
 
 temp = temp..str:sub(i,i)
 
 else
 
 break
 
 end
 
 end
 
 for j = temp:len(), 1, -1 do
 
 result = result..temp:sub(j,j)
 
 end
 
 return result
 
end
 
 
function exploMP3()
 
 load_dialog = createOpenDialog(self)
 
 load_dialog.InitalDir = os.getenv('%USERPROFILE%')
 
 load_dialog.execute()
 
 file = load_dialog.FileName
 
 a = GetFileName(file)
 
 if a == nil then
 
 return a
 
 else
 
 MsLabel.Caption = a
 
 local ss = createMemoryStream()
 
 ss.loadFromFile(file)
 
 playSound(ss)
 
 ss.destroy()
 
 end
 
end
 
 
function exit()
 
 closeCE()
 
 return caFree
 
end
 
 
bExit.onClick = exit
 
bStop.onClick = songStop
 
bExplo.onClick = exploMP3
 
Mform.Show() | 	  
 
 
plsound.lua  -- add to table file
 
 
 	  | Code: | 	 		  --- Music MP3 Function
 
-- fix CE6.4 MemoryStream write, and add other useful methods
 
if oldcreateMemoryStream==nil then oldcreateMemoryStream = createMemoryStream end
 
function createMemoryStream()
 
 local obj = oldcreateMemoryStream()
 
 local oldwrite=obj.write
 
 obj.write = function (t,n)  -- override default write
 
 local count=0
 
 for _,v in ipairs(t) do
 
 if count==n then break end
 
 oldwrite({v},1)
 
 count=count+1
 
 end
 
 end
 
 obj.writeDword = function (v) obj.write(dwordToByteTable(v)) end
 
 obj.writeWord = function (v) obj.write(wordToByteTable(v)) end
 
 return obj
 
 end
 
--convertMP3ToRIFFMP3(stream)
 
function convertMP3ToRIFFMP3(stream)
 
 local riffmp3 = createMemoryStream()
 
 local header = {
 
 0x46464952,0x00000000,0x45564157,0x20746D66,0x0000001E,0x00020055,
 
 0x0000AC44,0x00000000,0x00000001,0x0001000C,0x00000002,0x00010001,
 
 0x61660571,0x00047463,0x2FF80000,0x61640014
 
  } -- default is 44100Hz , Stereo
 
 local rateTable = {[0] = {11025,12000,8000},   --mpeg ver2.5
 
                    [2] = {22050,24000,16000},  --mpeg ver2
 
                    [3] = {44100,48000,32000}}  --mpeg ver1
 
 local bitrateTable = {[1]={32,64,96,128,160,192,224,256,288,320,352,384,416,448},
 
                       [2]={32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384},
 
                       [3]={32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320},
 
                       [4]={32,48,56, 64, 80, 96,112,128,144,160,176,192,224,256},
 
                       [5]={ 8,16,24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160}}
 
 for i,v in ipairs(header) do riffmp3.writeDword(v) end
 
 riffmp3.writeWord(0x6174)
 
 riffmp3.writeDword(stream.Size)
 
 stream.Position = 0
 
 riffmp3.copyFrom(stream,stream.Size)
 
 riffmp3.Position = 0x4; riffmp3.writeDword(stream.Size+0x24)
 
 stream.Position = 0
 
 local chunk = stream.read( math.min(65536,stream.Size) )
 
 local DWORD = byteTableToDword( {chunk[4],chunk[3],chunk[2],chunk[1]} )
 
--[[ looking for MPEG Audio frame header
 
  bits 31 through 21 must all be set; Frame sync
 
  bit 18 and bit 17, at least one set; Layer
 
  bits 15 through 12, at least one clear; bitrate index
 
  bits 11 through 10, at least one clear; sample rate index
 
  also use above to find a header
 
  bit 20 and 19; MPEG audio id
 
  bit 7 and 6; channel mode
 
  ]]
 
  local i=0x1
 
  while (i<=#chunk-4) do
 
  if (bAnd(DWORD,0xFFE00000)==0xFFE00000) and
 
     (bAnd(DWORD,0x60000)~=0) and
 
     (bAnd(DWORD,0xF000)~=0xF000) and
 
     (bAnd(DWORD,0xC00)~=0xC00)
 
    then
 
     --probably MPEG Audio Layer I/II/III frame header
 
     local channels    =(bAnd(bShr(DWORD, 6), 3) == 3) and 1 or 2
 
     local layer       = 3 - bAnd(bShr(DWORD,17), 3) + 1;
 
     local mpegaudioid = bAnd(bShr(DWORD,19), 3)
 
     local rateindex   = bAnd(bShr(DWORD,10), 3)
 
     local bitrateindex= bAnd(bShr(DWORD,12),15)
 
     local samplerate  = rateTable[mpegaudioid][rateindex+1]
 
     local row
 
   if     mpegaudioid==3 then row=layer -- mpeg ver1
 
     elseif layer==1       then row=4     -- mpeg ver2 and ver2.5, Layer 1
 
     else                       row=5     -- mpeg ver2 and ver2.5, Layer 2 and 3
 
     end
 
 local bitrate = bitrateTable[row][bitrateindex]
 
 riffmp3.Position = 0x16;
 
 riffmp3.writeWord(channels)
 
 riffmp3.writeDword(samplerate)
 
 riffmp3.writeDword(math.floor(bitrate*1000/8))
 
 break
 
 end
 
 if (bAnd(DWORD,0xFFFFFF00)==0x49443300) and
 
    (bAnd(DWORD,0xFF)<0xFF)
 
    --ID3 tag found
 
    then
 
    local size = bOr(bShl(chunk[i+6],7),chunk[i+7])
 
          size = bOr(bShl(size,7),chunk[i+8])
 
          size = bOr(bShl(size,7),chunk[i+9])
 
    i=i+size
 
 end
 
 DWORD = bOr( bShl(DWORD,8) , chunk[i+4] ) % 0x100000000
 
 i=i+1
 
 end
 
 chunk = nil
 
 riffmp3.Position = riffmp3.Size - 1
 
 return riffmp3
 
end
 
----
 
function sound_prepare(track)
 
  if track==nil then return nil end
 
  if knownStreams==nil then knownStreams = {} end
 
  local stream,streamID
 
-- set stream variable
 
  if type(track)=='string' then
 
  if knownStreams[track]~=nil then return track end -- check name as StreamID
 
  if findTableFile(track) then stream=findTableFile(track).Stream else return nil end
 
  elseif track.ClassName=='TMemoryStream' then
 
  stream=track else stream=track.Stream
 
  end
 
  streamID=userDataToInteger(stream)
 
  if knownStreams[streamID]~=nil then return streamID end
 
  stream.Position = 0
 
  if table.concat(stream.read(4),'-')=='82-73-70-70' then
 
  -- RIFF format (wave file, etc.)
 
  knownStreams[streamID]=stream
 
  else
 
  -- probably mp3 file, converting
 
  -- convertMP3ToRIFFMP3(stream)
 
  local riffmp3 = convertMP3ToRIFFMP3(stream)
 
  knownStreams[streamID]=riffmp3
 
  end
 
-- if string, use it as streamID too
 
 if type(track)=='string' then knownStreams[track]=knownStreams[streamID] end
 
 return streamID
 
end
 
if oldplaySound==nil then oldplaySound=playSound end
 
---
 
function playSound(track, ...)
 
  local ID=sound_prepare(track)
 
  if ID then oldplaySound(knownStreams[ID], ...)
 
  else print('track not found') end
 
end | 	  
 
 
You can change plSound.lua with mciSendstring module.
 
Beside, I am not really understand what exactly you want to do.
 _________________
 Stealing Code From Stolen Code...
 
And Admit It.. Hmmm....Typically LOL  | 
			 
		  | 
	 
	
		| Back to top | 
		 | 
	 
	
		  | 
	 
	
		AylinCE Grandmaster Cheater Supreme
  Reputation: 37
  Joined: 16 Feb 2017 Posts: 1530
 
  | 
		
			
				 Posted: Sun May 17, 2020 8:07 am    Post subject:  | 
				       | 
			 
			
				
  | 
			 
			
				Note; I will try the samples you provided, thanks.
 
What I am trying to say (Project);
 
 
 	  | Code: | 	 		  function CEButton1_Click(sender) --Background music
 
playMP3(path1)
 
end
 
 
function CEButton2_Click(sender) --The lady who sings the song
 
playMP3(path2)
 
end
 
 
function CEButton3_Click(sender) --The man who sings the song
 
playMP3(path3)
 
end
 
 
function CEButton4_Click(sender) --optional, add or remove (Stop) a wind.
 
if playMP3(path4) then
 
stopMP3(path4)
 
else
 
playMP3(path4)
 
end
 
end | 	  
 
 
 
When more than one button is active at the same time, it should play the songs.
 
He should play with him, without closing the current playing song.
 _________________
  | 
			 
		  | 
	 
	
		| Back to top | 
		 | 
	 
	
		  | 
	 
	
		Corroder Grandmaster Cheater Supreme
  Reputation: 75
  Joined: 10 Apr 2015 Posts: 1668
 
  | 
		
			
				 Posted: Sun May 17, 2020 8:35 am    Post subject:  | 
				       | 
			 
			
				
  | 
			 
			
				 	  | Aylin wrote: | 	 		  Note; I will try the samples you provided, thanks.
 
What I am trying to say (Project);
 
 
When more than one button is active at the same time, it should play the songs.
 
He should play with him, without closing the current playing song. | 	  
 
 
Try the script I provided before:
 
 
 	  | Code: | 	 		  function playMulti(song1, song2,...)
 
 if not initializeMP3Player() then return end
 
 local fileName
 
 fileName = song1
 
 MP3PlayerSendCommand("open "..fileName.." type mpegvideo alias FirstSound", 0, 0, 0)
 
 MP3PlayerSendCommand("play FirstSound", 0, 0, 0)
 
 
 fileName = song2
 
 MP3PlayerSendCommand("open "..fileName.." type mpegvideo alias SecondSound", 0, 0, 0)
 
 MP3PlayerSendCommand("play SecondSound",0, 0, 0)
 
end
 
 
----- Test, change song files with your own
 
s1 = "E:\\test1.mp3"
 
s2 = "E:\\test2.mp3"
 
playMulti(s1,s2) | 	  
 _________________
 Stealing Code From Stolen Code...
 
And Admit It.. Hmmm....Typically LOL  | 
			 
		  | 
	 
	
		| Back to top | 
		 | 
	 
	
		  | 
	 
	
		AylinCE Grandmaster Cheater Supreme
  Reputation: 37
  Joined: 16 Feb 2017 Posts: 1530
 
  | 
		
			
				 Posted: Sun May 17, 2020 1:32 pm    Post subject:  | 
				       | 
			 
			
				
  | 
			 
			
				And the final;
 
Run multiple mp3 files simultaneously;
 
 
 	  | Code: | 	 		  function MP3PlayerSendCommand(command)
 
  writeStringLocal(MP3PlayerCommandMS.Memory, command, true)
 
  writeBytesLocal (MP3PlayerCommandMS.Memory+2*#command, 0, 0)
 
  executeCodeLocal('SimpleMp3Player',MP3PlayerCommandMS.Memory)
 
  return readStringLocal(MP3PlayerCommandMS.Memory+1024,512,true),
 
         readStringLocal(MP3PlayerCommandMS.Memory+768,128,true)
 
end
 
 
function playMP3(path)
 
  if not initializeMP3Player() then return end
 
 
  MP3PlayerSendCommand('resume MediaFile')--('close MediaFile')
 
  MP3PlayerSendCommand( string.format('open "%s" type mpegvideo alias MediaFile',path) )
 
  MP3PlayerSendCommand('play MediaFile')
 
end
 
---------------------------------------------------
 
 
function MP3PlayerSendCommand1(command)
 
  writeStringLocal(MP3PlayerCommandMS.Memory, command, true)
 
  writeBytesLocal (MP3PlayerCommandMS.Memory+2*#command, 0, 0)
 
  executeCodeLocal('SimpleMp3Player',MP3PlayerCommandMS.Memory)
 
  return readStringLocal(MP3PlayerCommandMS.Memory+1024,512,true),
 
         readStringLocal(MP3PlayerCommandMS.Memory+768,128,true)
 
end
 
 
function playMP31(path1)
 
  if not initializeMP3Player() then return end
 
 
  MP3PlayerSendCommand1('resume MediaFile1')--('close MediaFile1')
 
  MP3PlayerSendCommand1( string.format('open "%s" type mpegvideo alias MediaFile1',path1) )
 
  MP3PlayerSendCommand1('play MediaFile1')
 
end
 
 
function stopMP3()
 
  if not initializeMP3Player() then return end
 
 
  MP3PlayerSendCommand('close MediaFile')
 
  MP3PlayerSendCommand1('close MediaFile1')
 
end | 	  
 
 
Thanks @Corroder
 
 
Now it is left to add "findTableFile" to this code.
 
There are 17 audio files. I will duplicate this code up to 17.  
 _________________
  | 
			 
		  | 
	 
	
		| Back to top | 
		 | 
	 
	
		  | 
	 
	
		Corroder Grandmaster Cheater Supreme
  Reputation: 75
  Joined: 10 Apr 2015 Posts: 1668
 
  | 
		 | 
	 
	
		| Back to top | 
		 | 
	 
	
		  | 
	 
	
		AylinCE Grandmaster Cheater Supreme
  Reputation: 37
  Joined: 16 Feb 2017 Posts: 1530
 
  | 
		
			
				 Posted: Sun May 17, 2020 2:04 pm    Post subject:  | 
				       | 
			 
			
				
  | 
			 
			
				           
 
 
This is what I was trying to say.
 
Thanks for developing.
 
50% of my project was this code.
 
Now I need to get an idea for the remaining code. I have to open a forum question.
 _________________
  | 
			 
		  | 
	 
	
		| Back to top | 
		 | 
	 
	
		  | 
	 
	
		Xenocritus Cheater
  Reputation: 0
  Joined: 27 Dec 2020 Posts: 25
 
  | 
		
			
				 Posted: Fri Jan 29, 2021 8:55 am    Post subject:  | 
				       | 
			 
			
				
  | 
			 
			
				Hi,
 
 
Im using MP3 player to replace some game's music and it works. However I have an issue.
 
 
Working Workflow:
 
- Start CE
 
- initializeMP3Player()
 
- Attach the game
 
- Run the program logic to replace
 
- It works
 
 
Not Working (seems like in a loop once Lua executed)
 
- Start CE
 
- Attach the game
 
- initializeMP3Player()
 
- Just the CE not responding
 
 
Is somehow the memory allocation entering in clonflict? I just want to attach the game and run all the Lua Scripts.
 | 
			 
		  | 
	 
	
		| 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 cannot download files in this forum
  | 
   
 
		 |