File access
MegaZeux has supported reading and writing data to files since version 2.60, and since then this capability has been augmented and improved to allow for the use of external resources in a number of different ways. Apart from counter interfaces to directly manipulate the contents of a file, file access encompasses specific interfaces for reading and writing robots and Robotic, MZMs, and entire MZX worlds.
The Basics
MZX supports basic file reading and writing through the use of specific keyword counters, which fall into two obvious categories: "fread" counters for reading, and "fwrite" counters for writing.
First, a file must be opened for reading/writing, using the following syntax:
set "filename.ext" to "fread_open" set "filename.ext" to "fwrite_open"
Note that it is perfectly acceptable to have a file open for both reading and writing at the same time. However, "fwrite_open" clears the contents of whatever file it opens and starts editing a new, blank file. So MZX also provides the "fwrite_modify" and "fwrite_append" functions, which preserve the contents of the file being opened. "fwrite_modify" places the write cursor at the beginning of the file, while "fwrite_append" starts writing at the end of the file.
The cursor, or in other words the place in the file currently be read from or written to, is maintained in the counters "fread_pos" and "fwrite_pos". These are separate values that do not interfere with one another, since it is after all quite common to have one file open for reading and another for writing. The cursors are automatically advanced when read/write operations are performed on the file, but they can also be set manually to navigate around the file. Before the port, when counters were only 16-bits, there existed "fread_page" and "fwrite_page" counters for working with files larger than 64KB in size. Since counters became 32-bit, however, these have been rendered obsolete, and fread_pos/fwrite_pos rendered absolute. Additionally, this has allowed for a convenient way to seek to the end of the file, by setting the appropriate "_pos" counter to -1.
Reading and writing actual data can be done in a few different ways. The simplest of these is simply to use the counters "fread" and "fwrite" as placeholders for data to be read from or written to the open file. "fwrite" must always be assigned TO (except for certain syntax related to strings, see below), but "fread" can be interpolated into robotic code just like any other counter, and will be evaluated each time it is encountered. Evaluation, in this case, entails reading one byte from the file, and advancing fread_pos by one. So for example:
set "counter" to "('fread'+('fread'<<8)+('fread'<<16)+('fread'<<24))"
This would read four bytes stored in little-endian format from the file, and combine them together to form a single 32-bit value. (See the articles on expressions and bitwise-math for more information on this code.)
This is a somewhat contrived application, since another way to read from and write to a file is to use "fread_counter" and "fwrite_counter". These were originally intended to conveniently read and write full counter values, instead of just bytes. Currently they are out of date, and work on 16-bit values instead of the 32-bit values MZX uses now. However, there are plans to update them to work on 32-bit values in the near future.
Finally, MZX provides reading and writing of arbitrary length strings. Originally, the method for doing this was very limited. The "fread" and "fwrite" counters were overloaded to work with string values. A quirk with the way strings are handled forced a nonstandard syntax here, however: instead of
set "fwrite" to "$string"
it was (and is) necessary to use
set "$string" to "fwrite"
This method is limited in its usefulness because it requires the use of a terminating character, which is not user-definable. Instead of choosing something sensible and widely used, like a null byte (i.e. 0x00), Exophase chose to make the terminator an asterisk (*).