IO API
The Microsoft Flight Simulator 2024 IO API permits you to read from and write to files that are included as part of the package that the module belongs to.
This API replaces some features provided by the standard C and C++ libraries (std::open
, std::read
, etc…) with asynchronous functions. The change to an asynchronous API is required since packages in Microsoft Flight Simulator 2024 are streamed and this introduces potential lag and stutter to the game if a non-asynchronous file operation blocks the simulation while trying to read an inaccessible or not-yet-available file from the VFS. The asynchronous functions of the IO API do not need to stop the simulation to read a file, thus allowing a better user experience. This does mean, however, that the API relies on callbacks to deal with requested file operations.
The functions available for this API are as follows:
Function | Description |
---|---|
fsIOOpen |
Open a file, ready to be read from or written to. |
fsIORead |
Read from a previously opened file. |
fsIOOpenRead |
Open a file, and read some data from it, all in the same operation. |
fsIOWrite |
Write to a previously opened file. |
fsIOClose |
Close a previously opened file. |
fsIOIsOpen |
Check to see if a file is currently open or not. |
fsIOInProgress |
Check to see if there are any operations currently in porgress on a file or not. |
fsIOIsDone |
Check to see if all operations on a file are finished or not. |
fsIOHasError |
Check to see if a given file has previously triggered an error. |
fsIOGetLastError |
Retrieve the last error that a file caused to be generated. |
fsIOGetFileSize |
Get the size (in bytes) of a file. |
You can find a sample project to use as a reference when using the Event API here:
Structs And Enums
This API has the following structs and enums that will be used by some of the functions and/or callbacks:
Enum | Description |
---|---|
FsIOErr |
This enum is used for the transmission of error information. |
FsIOOpenFlags |
This enum contains the bit-flag definitions used when opening files. |
Typedefs
When using this API the following typedefs exist to help:
FsIOFile
The ID of a file open with different IO API functions.
typedef unsigned long long FsIOFile;
#define FS_IO_ERROR_FILE 0
FsIOFileOpenCallback
This defines the callback called when an open file operation is finished:
typedef void(*FsIOFileOpenCallback)(FsIOFile file, void* pUserData);
It has the following parameters:
Parameters | Description |
---|---|
file |
The file that has been opened. |
pUserData |
A pointer given with the callback by the user. |
FsIOFileReadCallback
This defines the callback called when a read operation on a file is completed:
typedef void(*FsIOFileReadCallback)(FsIOFile file, char* outBuffer, int byteOffset, int byteRead, void* pUserData
It has the following parameters:
Parameters | Description |
---|---|
file |
The file from which the data has been read from. |
outBuffer |
This is a buffer containing the data read from the file. This is the same buffer which would have been given to the function that initiated the read operation. |
byteOffset |
This is the offset (in bytes) from which the data began getting read from the file. This should be the same value which would have been given to the function that initiated the read operation. |
byteRead |
This is the number of bytes of data that has been read from the file. |
pUserData |
A pointer given with the callback by the user. |
FsIOFileWriteCallback
This defines the callback returned when a write operation on a file is completed:
typedef void(*FsIOFileWriteCallback)(FsIOFile file, const char* pInBuffer, int byteOffset, int bytesWritten, void* pUserData);
It has the following parameters:
Parameters | Description |
---|---|
file |
The file from which the data has been written to. |
outBuffer |
This is a buffer containing the data that was written to the file. |
byteOffset |
This is the offset (in bytes) at which the data began getting written to the file. |
byteRead |
This is the number of bytes of data that has been written to the file. |
pUserData |
A pointer given with the callback by the user. |
Infinite Loops
It may be tempting to use the fsIOIsOpen
and fsIOHasError
functions to create a loop that checks when an open action has finished - and thus not rely on callbacks - by creating a kind of "active wait" code setup, something similar to the following code:
FsIOFile file = fsIOOpen("myFile", FsIOOpenFlag_RDONLY, myOpenCallback, nullptr);
// "Active wait" loop
while (!fsIOIsOpen(file) || !fsIOHasError(file))
{
// Do nothing or maybe sleep
}
// Continue processing
However, not only is this a waste of resources as it keeps a thread open and busy doing nothing, it may lead to a situation where you create an infinite loop which will never end. Indeed, to process opening, reading, or writing, the game may need to continue to update some other managers and continue to run frames. But, by using the while
loop, the code will block the module and the simulation engine may then wait for the module to continue to run, and therefor not update the other managers. It is for this reason that we strongly recommend that you do not do this and instead rely on the specified callbacks for open/read/write operations.
Inaccessible Files
It is important to note that many files will not be accessible to the IO API due to the way that packages are encrypted and archived. Specifically, the following file types will not be accessible within the main package:
*.cfg
*.xml
*.gltf
Trying to open these will cause an FsIOErr_AccessNotAllowed
error. If you need to access data from one of these types of files, then you can workaround this limitation by creating a Copy asset group, and duplicating the files you want to read from into it. These files will not be encrypted or archived and will thus be accessible to the IO API, however be aware that this means that the files will not be protected against tampering or viewing by users.
Also note that even if a package file is not encrypted or archived, you cannot write to it unless it is part of the /work/
directory. See the fsIOOpen
page for more details on package paths.