Get all specific file names from directory

Usage:
Code:
alloc 2@ 100
format 2@ "CLEO/audio/*.mp3"
call @load_file_names 2 max_filenames 1000 wildcard 2@ _name_array 0@ _index_of_highest_loaded_name 1@
for 31@ = 0 to 1@
    call @get_nth_file_name 2 name_array 0@ n 31@ _returned_name 30@
    chatmsg "%d. %s" -1 31@ 30@
end


Functions to copy+paste somewhere at the end of your code:
Code:
:get_nth_file_name
{
    Input params:
    0@ = pointer to array of pointers, each leading to filename
    1@ = n (starting with 0)
   
    Usage:
    call @get_nth_file_name 2 name_array 0@ n 0 _returned_name 30@
}
1@ *= 4 // each pointer has 4 bytes
005A: 0@ += 1@  // (int)
0A8D: 31@ = read_memory 0@ size 4 virtual_protect 0
ret 1 31@


:load_file_names
{
    Input params:
    0@ = filenames limit
    1@ = wildcard (e.g. "CLEO/audio/*.mp3")
   
    Usage:
    call @load_file_names 2 max_filenames 1000 wildcard 2@ _name_array 0@ _index_of_highest_loaded_name 1@
}
0085: 24@ = 0@  // copy of max_filenames
24@ *= 4
24@ += 4
alloc 26@ 24@ // pointer to pointers (4000 will allow to store 1000 pointers, so if there is 1001 files found then the code will possibly crash)
//chatmsg "base addr = %X" -1 26@

0085: 25@ = 26@ // 25@ is a copy to manipulate (26@, the begining of array, will be returned)
31@ = 0  // loaded file count
alloc 30@ 400       // max length of a single file name (if larger is encountered the code will possibly crash)
if 0AE6: 29@ = find_first_file 1@ get_filename_to 30@
then          
    repeat
    wait 0
        0C17: 28@ = strlen 30@                      
        alloc 27@ 28@                    // additional byte to end the string is not required because we will not store the ".mp3"
        0AA5: call 0x8220AD num_params 3 pop 3 27@ "%[^.]" 30@      // just so the title doesn't contain ".mp3" at the end  
        31@ += 1
       
        //chatmsg "string addr = %X at %X" -1 27@ 25@
        0A8C: write_memory 25@ size 4 value 27@ virtual_protect 0 // save the pointer in our array of pointers

        25@ += 4
       
        if 003B:   31@ == 0@
        then
            printf "Max number (%d) of files was reached. Rest is ignored." 5000 0@
            break
        end
    until 8AE7: 30@ = find_next_file 29@
   
    0AE8: find_close 29@
    0A8C: write_memory 25@ size 4 value 0 virtual_protect 0
else
    printf "No files found at all using: %s" 10000 1@
end

free 30@

31@ -= 1
ret 2 26@ 31@

:release_file_names
{
    If you use @load_file_names function consecutively without releasing the memory, then it will take too much of it.
   
    Input params:
    0@ = name_array (pointer to array of pointers to allocated memory)
   
    Usage:
    call @release_file_names 1 name_array 0@
}
0A8D: 31@ = read_memory 0@ size 4 virtual_protect 0
repeat
wait 0
    free 31@
    0@ += 4
    0A8D: 31@ = read_memory 0@ size 4 virtual_protect 0
until 31@ == 0
ret 0



Full working example:
Code:
{$CLEO .cs}
0000: NOP

repeat
wait 50
until 0AFA: is_samp_structures_available

0B34: samp register_client_command "show_names" to_label @cmd_show_names
0B34: samp register_client_command "reload_names" to_label @cmd_reload_names

alloc 2@ 100
format 2@ "CLEO/audio/*.mp3"
call @load_file_names 2 max_filenames 1000 wildcard 2@ _name_array 0@ _index_of_highest_loaded_name 1@  //(_index_of_highest_loaded_name = how_many_loaded - 1)

while true
wait 1000
end

:cmd_show_names
if 1@ > -1
then
    chatmsg "{00FF00}File names:" -1
   
    for 31@ = 0 to 1@
        call @get_nth_file_name 2 name_array 0@ n 31@ _returned_name 30@
       
        chatmsg "%d. %s" -1 31@ 30@
        //chatmsg "%d. %s {AAAAAA} - addr = %X" -1 31@ 30@ 30@
    end
else
    chatmsg "{FF0000}ERROR: {FFFFFF}No names were loaded..." -1
end
samp.CmdRet()

:cmd_reload_names
call @release_file_names 1 _name_array 0@
call @load_file_names 2 max_filenames 1000 wildcard 2@ _name_array 0@ _index_of_highest_loaded_name 1@
samp.CmdRet()





:get_nth_file_name
{
    Input params:
    0@ = pointer to array of pointers, each leading to filename
    1@ = n (starting with 0)
   
    Usage:
    call @get_nth_file_name 2 name_array 0@ n 0 _returned_name 30@
}
1@ *= 4 // each pointer has 4 bytes
005A: 0@ += 1@  // (int)
0A8D: 31@ = read_memory 0@ size 4 virtual_protect 0
ret 1 31@


:load_file_names
{
    Input params:
    0@ = filenames limit
    1@ = wildcard (e.g. "CLEO/audio/*.mp3")
   
    Usage:
    call @load_file_names 2 max_filenames 1000 wildcard 2@ _name_array 0@ _index_of_highest_loaded_name 1@
}
0085: 24@ = 0@  // copy of max_filenames
24@ *= 4
24@ += 4
alloc 26@ 24@ // pointer to pointers (4000 will allow to store 1000 pointers, so if there is 1001 files found then the code will possibly crash)
//chatmsg "base addr = %X" -1 26@

0085: 25@ = 26@ // 25@ is a copy to manipulate (26@, the begining of array, will be returned)
31@ = 0  // loaded file count
alloc 30@ 400       // max length of a single file name (if larger is encountered the code will possibly crash)
if 0AE6: 29@ = find_first_file 1@ get_filename_to 30@
then          
    repeat
    wait 0
        0C17: 28@ = strlen 30@                      
        alloc 27@ 28@                    // additional byte to end the string is not required because we will not store the ".mp3"
        0AA5: call 0x8220AD num_params 3 pop 3 27@ "%[^.]" 30@      // just so the title doesn't contain ".mp3" at the end  
        31@ += 1
       
        //chatmsg "string addr = %X at %X" -1 27@ 25@
        0A8C: write_memory 25@ size 4 value 27@ virtual_protect 0 // save the pointer in our array of pointers

        25@ += 4
       
        if 003B:   31@ == 0@
        then
            printf "Max number (%d) of files was reached. Rest is ignored." 5000 0@
            break
        end
    until 8AE7: 30@ = find_next_file 29@
   
    0AE8: find_close 29@
    0A8C: write_memory 25@ size 4 value 0 virtual_protect 0
else
    printf "No files found at all using: %s" 10000 1@
end

free 30@

31@ -= 1
ret 2 26@ 31@

:release_file_names
{
    If you use @load_file_names function consecutively without releasing the memory, then it will take too much of it.
   
    Input params:
    0@ = name_array (pointer to array of pointers to allocated memory)
   
    Usage:
    call @release_file_names 1 name_array 0@
}
0A8D: 31@ = read_memory 0@ size 4 virtual_protect 0
repeat
wait 0
    free 31@
    0@ += 4
    0A8D: 31@ = read_memory 0@ size 4 virtual_protect 0
until 31@ == 0
ret 0

Tested with:
- Cleo 4.1
- Samp 0.3.7 R1
- Sampfuncs 5.4.1-final
 

Attachments

  • names.png
    names.png
    6 KB · Views: 1,308
Top