Shared Stream Buffers

The goal of this DLL is to create a platform that other Game Maker DLLs can use to exchange binary data. Binary data can be written to streams and buffers and read back later. Streams and buffers can also be used directly in Game Maker (in GML), so it's also possible to read or write binary data manually.

This DLL provides little functionality on its own, it is designed to be used together with other DLLs that support Shared Stream Buffers.

Types of data

This DLL supports a number of different data types. The table below lists the most important properties of each type.

Type Size (bytes) Lowest value Highest value Resolution Other names
int8 1 -128 127 1 byte, char
uint8 1 0 255 1 unsigned byte, unsigned char
int16 2 -32.768 32.767 1 short
uint16 2 0 65.535 1 unsigned short, WORD
int32 4 -2.147.483.648 2.147.483.647 1 int
uint32 4 0 4.294.967.296 1 unsigned int, DWORD
int64 8 -9.223.372.036.854.775.808 9.223.372.036.854.775.807 1 long long
uint64 8 0 18.446.744.073.709.551.615 1 unsigned long long, QWORD
float32 4 -1.7014e38 1.7014e38 ~8 significant figures float
float64 8 -8.9885e307 8.9885e307 ~16 significant figures double
string length+1 - - - NULL-terminated string, C string

Streams

Streams are data structures that allow reading and writing of binary data. There are multiple types of streams. What happens with this data depends on the type of stream. A stream could be a simple memory buffer, but also a socket, for example. Other DLLs can add new types of streams.

If you try to read data from a stream when there isn't any data available, the function will return a default value. The value depends on the type of data you're reading:

Buffers

Buffers are data structures that store binary data. Buffers have a certain length, a reading position and a writing position. Buffers can be resized, and the reading position and writing position can be changed. All buffers are also streams: any stream function will also work for buffers. Again, there are multiple types of buffers, and other DLLs can add new types.

When using a buffer as a stream, data will be read from the reading position, and the reading position will be advanced. New data will be written to the writing position, and the writing position will be advanced. If you try to write past the end of the buffer, the buffer will be enlarged automatically.

Memory buffers

Memory buffers are buffers that store their data in RAM memory. They are very fast and useful to store data temporarily.

Other functions

Example code

Writing data to a memory buffer and storing it in a file:

var buffer;

// create a memory buffer
buffer = memorybuffer_create();

// write data to the memory buffer
stream_write_uint8(buffer, 42);
stream_write_uint8(buffer, 77);
stream_write_float32(buffer, 3.14);
stream_write_string(buffer, "hello world");

// save the data to a file
memorybuffer_write_to_file(buffer, "data.txt");

// destroy the memory buffer
memorybuffer_destroy(buffer);

Loading the file and reading the data:

var buffer, a, b, c, d;

// create a memory buffer
buffer = memorybuffer_create();

// read the data from the file
if !memorybuffer_read_from_file(buffer, "data.txt") {
    memorybuffer_destroy(buffer);
    show_message("Error: Reading data.txt failed! Make sure the file exists.");
    exit;
}

// read data from the buffer
// this should be done in exactly the same order
a = stream_read_uint8(buffer);
b = stream_uint8(buffer);
c = stream_read_float32(buffer);
d = stream_read_string(buffer);

// display the result
show_message("a = "+string(a)+"#b = "+string(b)+"#c = "+string(c)+"#d = "+d);
// output:
//   a = 42
//   b = 77
//   c = 3.14
//   d = hello world

// destroy the memory buffer
memorybuffer_destroy(buffer);

For DLL developers

If you're creating your own DLL and you want to use Shared Stream Buffers, just include SharedStreamBuffers.h in your project. This file defines a number of classes which your DLL can use as an interface to manipulate buffers. But before you can use the SharedStreamBufferInterface, you have to create a function to set the SharedStreamBufferInterface address:

#include "SharedBuffers.h"

SharedStreamBufferInterface *ssbi = NULL;

gmexport double yourdllname_init_shared_stream_buffers(double handle) {
    ssbi = (SharedStreamBufferInterface*)((uintptr_t)(handle));
    return 1;
}

This function has to be called in Game Maker before you can use the Shared Stream Buffers:

// initialize shared buffers interface for yourdllname.dll
yourdllname_init_shared_stream_buffers(shared_stream_buffers_get_handle());

After the interface address has been set, you can use any buffer or stream in your DLL:

gmexport double yourdllname_some_function(double buffer_id) {
    if(ssbi == NULL) return 0; // the interface address has not been set yet
    SharedStream *stream = ssbi->FindStream(gm_double_to_uint(id));
    if(stream == NULL) return 0;
    int32_t val1 = 12345;
    char val2[] = "Hello world"; // null-terminated string
    float val3 = 42.42f;
    stream->WriteData(&val1, sizeof(val1));
    stream->WriteData(&val2, sizeof(val2));
    stream->WriteData(&val3, sizeof(val3));
    return 1;
}

Creating your own implementation for buffers or streams

Under construction :).

Good luck!