Windows Strugging with file_find_first

M

Marasmusine

Guest
Hello, can anyone help me. The documentation on file functions and the "sandbox" don't give me enough detail to figure out how to do this. I'm am using GMS2 on Windows.

I want my program to read some .wav files (they aren't internal assets as I'd like the user to have the option of changing them), and I want them to be in the working directory (i.e. the same location as the executable)

When testing the program with the debugger, I can see the working directory is "C:\ProgramData\GameMakerStudio2\Cache\runtimes\runtime-2.1.3.189\windows"

I've made a folder there, \audio, and placed the audio files within (in subfolders)

I call a script (init_fx), passing the path as an argument to use as a mask for file_find_first. For example:

Code:
init_fx(program_directory+"\\AUDIO\\percussion\\*.*")
The debugger shows argument0 is "C:\ProgramData\GameMakerStudio2\Cache\runtimes\runtime-2.1.3.189\windows\AUDIO\percussion\*.*"

However, in init_fx

Code:
file = file_find_first(argument0, 0)
is a null string.

I don't know if:
  • The mask isn't correct (am I using wildchars correctly?)
  • I'm prevented from finding the file because of the way the sandbox works?
 
I

icuurd12b42

Guest
try working_directory. using this variable should snoop the program directory if the files are not in the user app data directory as part of the sandboxing system... but you may want to instruct your users to save their wav file in the app data folder which the game should have created... you can create the folders
working_directory+"\\AUDIO"
and
working_directory+"\\AUDIO\\percussion""
when the game starts to ensure those exists in the game app data and provide your users a location all ready for them to use
 
M

Marasmusine

Guest
Thanks for the reply. (I mispoke when I said I wanted the files in the working directory, I meant program directory. )

But I have now copied the AUDIO folder to the working directory (in %appdata%)

The debugger shows the argument I'm passing to file_find_first is the correct path (although, pro tip, you have to drop the initial backslash from any strings you add to working_directory, which isn't the case with program_directory).

file_find_first is still returning a null string.
 
pro tip, you have to drop the initial backslash from any strings you add to working_directory
It's a pro-tip for those who haven't read the manual:

From working_directory page:
NOTE: the working_directory variable will return the path including the final backslash.
You could try dropping the working_directory altogether and just use the relative path, as it should default to that location anyway.

I also saw someone recommend trying game_save_id as an alternative.

Finally, in another post, @Wraithious seems to say that .wav files weren't able to be loaded, only .ogg files. Maybe he can confirm that if he sees this.
 
Last edited:
M

Marasmusine

Guest
It's a pro-tip for those who haven't read the manual:
Well there's egg on my face, thanks!

So I've tried dropping the working_directory, but no luck. game_save_id is in local %appdata% - ultimately that's no use for me as I need to program to read files bundled with it.

Finally, in another post, @Wraithious seems to say that .wav files weren't able to be loaded, only .ogg files. Maybe he can confirm that if he sees this.
I had read that it only works with .ogg too, that's not a problem right now - I'll be happy if I can get the program to simply count how many files are in the folder so I can allocate array space.

I thought perhaps I could use get_open_filename to allow the user to point to the folder with the files in, but it looks like it can only return an individual file. It seems that Gamemaker might not be versatile enough to do what I want it to do.
 

TsukaYuriko

☄️
Forum Staff
Moderator
Use relative file paths instead of absolute file paths - that is, assume that the correct folder is already chosen and build your path starting from that. That's how the file functions work internally (any file path you provide will be searched for relative to all valid read/write locations), so don't work against it. Your path (or in this case, mask) is simply AUDIO/percussion/*.*.

Finally, in another post, @Wraithious seems to say that .wav files weren't able to be loaded, only .ogg files. Maybe he can confirm that if he sees this.
audio_create_stream reads OGG Vorbis files.
audio_create_buffer_sound uses raw PCM data. Loading WAV files without their header as audio buffers gets you as close to "loading WAV files" as possible.
 
M

Marasmusine

Guest
Thank-you for the reply. I tried your suggestion for the relative file path, and I still get a null string. I've also tried the example in the file_find_first documentation - "C:\temp\*.doc'" - and put AUDIO in the top-level direcory ("C:/AUDIO/percusion/*.*"); tried using fa_readonly attribute; tried *.wav instead of *.* (yes, I know, I'll be switching to .ogg later).

I think what I need is a working example, I'll have a look around. Thank-you again to everyone who replied.
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
I'm pretty sure that you have to include the files in the game for GMS to be able to read them later (as an included file resource). Users would still be able to copy over them with their own sounds, but the initial file should be in the project. Note, I could be wrong about this as it's not something I've actually attempted to do...
 

TsukaYuriko

☄️
Forum Staff
Moderator
Thank-you for the reply. I tried your suggestion for the relative file path, and I still get a null string. I've also tried the example in the file_find_first documentation - "C:\temp\*.doc'" - and put AUDIO in the top-level direcory ("C:/AUDIO/percusion/*.*"); tried using fa_readonly attribute; tried *.wav instead of *.* (yes, I know, I'll be switching to .ogg later).
Putting anything in the root directory of your hard drive and expecting not to run into permission issues is playing with fire at its finest.

To rule out issues with your file finding, first, check if a specific file in the directory you are trying to use is even visible to your game. To do this, perform a file_exists check on it - if the file path is correct but the file appears to not exist, you have no permissions for that directory. If you can't see files, you can't search for them, but unless you verify this, you might be trying to fix your file finding code when the real problem lies elsewhere.

A common example of this gone wrong would be placing a game in Program Files or the root of C: - you may or may not have any permissions there. If you don't and your game assumes you do, things will break.

I'm pretty sure that you have to include the files in the game for GMS to be able to read them later (as an included file resource). Users would still be able to copy over them with their own sounds, but the initial file should be in the project. Note, I could be wrong about this as it's not something I've actually attempted to do...
On it! :p

Tested on runtime 2.1.3.189, VM and YYC.

Code:
show_message(file_exists("test.txt"));
Shows 0 if test.txt does not exist.
Shows 1 if test.txt exists, even if I manually created it in the executable's folder after compiling.

Nah.
 
M

Marasmusine

Guest
I tried file_exists for a specific file, with every combination of path previously mentioned, and got a fat 0 every time.

Next, instead of using the debugger, I built the executable zip, extracted it, and copied the AUDIO folder over. This time file_exists returned 1.

Success! Note that I did have to use program_directory for it to work:
Code:
file_exists(program_directory+"/AUDIO/percussion/fx_cowbell.wav")
Okay, show_message is a pretty useful debug function as I could figure out what was going off in the final build.

This does make development a bit more laborious, I suppose I'll have to keep some internal sound assets for quick testing and debugging.

Thanks again, Tskua!
 

TsukaYuriko

☄️
Forum Staff
Moderator
So it works when compiled but not in a test run? That's odd... especially since this is not a scenario in which using absolute file paths is necessary. The example I posted above proves this, and just to be 100% safe, I just tested it again in debug mode. Adding the file as an included file results in a 1, deleting it afterwards and performing the check again results in a 0, not having it included and adding it manually turns a 0 into a 1. Every imaginable scenario works as expected for me.

This may or may not be related to your use of a starting slash for the file path...? I can't see anything else that could cause issues in this regard. For read operations, the local storage (appdata) and the game bundle (exe directory) are checked, in that order, so this should be handled 100% automatically if the file is located in any of these directories. If that is not the case, it may prompt for further investigation, as the behavior is anything but normal (unless my installation is the one that's screwed up :p).

Edit: Tested it with a starting slash. Suddenly 0 even though the file exists. There we go.


On the topic of functions that are useful for debugging: show_debug_message! It's show_message but instead of opening a popup window and freezing the game, it outputs the message to the console inside the IDE. Great for outputting lots of debug data at once, or for outputting debug data frequently.
There is of course also the debug module which lets you check (or change) the value of basically anything while the game is running (or paused, respectively).
 
Top