Added docs to distro builder.

This commit is contained in:
Scott Duensing 2024-06-17 20:44:13 -05:00
parent 7981304429
commit de881b1b3e
2 changed files with 192 additions and 45 deletions

View file

@ -92,6 +92,9 @@ pushd distro
buildOverlayTool macos aarch64 $(pwd)/overlay.macos
buildOverlayTool windows x86_64 $(pwd)/overlay.windows
cp -f ../../f256lib.adoc .
asciidoctor-pdf -o f256lib.pdf f256lib.adoc
popd
if [[ -f ../f256dev.7z ]]; then

View file

@ -538,6 +538,11 @@ do {
TIP: Take a look at the `f256dev\examples\sprites` program and `f256dev\f256lib\f_file.c` from the *_F256lib_* source code for kernel usage examples.
IMPORTANT: Using these kernel functions along with file I/O statements or `getchar()`
can result in missing an event. File I/O and keyboard reading have their own
kernel polling loops and will discard any events they aren't waiting on for
themselves.
==== kernelCall
[,c]
@ -582,8 +587,8 @@ Failing to call this often enough can starve the kernel of event objects.
=== DMA
At the moment, DMA access is... hit and miss. Feel free to try it but don't expect
it to be stable. More DMA features will be available in the future.
IMPORTANT: At the moment, DMA access is... hit and miss. Feel free to try it
but don't expect it to be stable. More DMA features will be available in the future.
==== dma2dFill
@ -893,7 +898,7 @@ on the screen refresh, the bitmaps are:
On startup, all three bitmaps are assigned to each associated graphics layer,
but are not visible. The three bitmaps are located at the following memory
addresses:
addresses at the top of the far memory available to the Vicky graphics chip:
* Page 0 - 0x6c000 -> 0x7ebff
* Page 1 - 0x58000 -> 0x6abff
@ -1067,6 +1072,11 @@ Like bitmaps and sprites, each
void tileDefineTileMap(byte t, uint32_t address, byte tileSize, uint16_t mapSizeX, uint16_t mapSizeY);
----
Defines a tile map from a block of RAM. `t` is which map to define (0 to 2).
`address` is where in near or far memory the map data is located. `tileSize`
specifies the size of your tiles (either 8 or 16). Finally, `mapSizeX` and
`mapSizeY` determine the size of the map.
==== tileDefineTileSet
[,c]
@ -1074,6 +1084,11 @@ void tileDefineTileMap(byte t, uint32_t address, byte tileSize, uint16_t mapSize
void tileDefineTileSet(byte t, uint32_t address, bool square);
----
Specifies where in memory to find a given tile set. `t` determines which of the
eight available (0 to 7) tile sets we're defining. `address` is where in near
or far memory the tile data is located. `square` indicates if the tile data
in memory is laid out in a square or a single tile width vertical strip.
==== tileSetScroll
[,c]
@ -1081,6 +1096,10 @@ void tileDefineTileSet(byte t, uint32_t address, bool square);
void tileSetScroll(byte t, byte xPixels, uint16_t xTiles, byte yPixels, uint16_t yTiles);
----
Changes the position of a given tile map `t`. `xPixels` and `yPixels` allow
for fine scrolling of the tile map while `xTiles` and `yTiles` determine the
upper left tile to be displayed.
==== tileSetVisible
[,c]
@ -1088,68 +1107,193 @@ void tileSetScroll(byte t, byte xPixels, uint16_t xTiles, byte yPixels, uint16_t
void tileSetVisible(byte t, bool v);
----
Determines the visibility `v` of a particular tile map `t` (0 to 2).
=== File I/O
fileDirEntT
File I/O from the MicroKernel is mapped to standard C library file routines
with a few minor changes for how the F256 handles drives.
int8_t fileClose(uint8_t *fd);
int8_t fileCloseDir(char *dir);
int8_t fileMakeDir(char *dir);
uint8_t *fileOpen(char *fname, char *mode);
char *fileOpenDir(char *name);
int16_t fileRead(void *buf, uint16_t nbytes, uint16_t nmemb, uint8_t *fd);
fileDirEntT *fileReadDir(char *dir);
int8_t fileRemoveDir(char *dir);
int8_t fileRename(char *name, char *to);
int8_t fileSeek(uint8_t *fd, uint32_t offset, uint8_t whence);
int8_t fileUnlink(char *name);
int16_t fileWrite(void *buf, uint16_t nbytes, uint16_t nmemb, uint8_t *fd);
Supported functions are listed below. For usage details, see the documentation
for the standard C library.
#define _DE_ISREG(t) (t == 0)
#define _DE_ISDIR(t) (t == 1)
#define _DE_ISLBL(t) (t == 2)
#define _DE_ISLNK(t) (0)
* `int closedir(DIR *dirp);`
* `int fclose(FILE *stream);`
* `FILE *fopen(const char *pathname, const char *mode);`
* `size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);`
* `int fseek(FILE *stream, long offset, int whence);`
* `size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);`
* `int mkdir(const char *pathname, mode_t mode);`
* `DIR *opendir(const char *name);`
* `struct dirent *readdir(DIR *dirp);`
* `int rename(const char *oldpath, const char *newpath);`
* `void rewind(FILE *stream);`
* `int rmdir(const char *pathname);`
* `int unlink(const char *pathname);`
The following macros are available for identifying which type of directory
entry is being returned in `dirent->d_type`:
* `_DE_ISREG(d_type)`
* `_DE_ISDIR(d_type)`
* `_DE_ISLBL(d_type)`
* `_DE_ISLNK(d_type)`
NOTE: Seeking is only supported forward from the start of the file.
`SEEK_SET` is defined for use as `whence`.
Currently not supported by IEC drives.
NOTE: Not all IEC devices support subdirectories.
NOTE: Pathnames on the F256 use the backslash (`\`) to delimit
subdirectories. Similar to Windows, the F256 uses the concept of a "drive".
Unlike Windows, drives are numbered, not lettered, and start at `0` which is
the built-in SD card reader. An example path with a drive and subdirectory
looks like this: `0:\DOCS\README.TXT`
IMPORTANT: Do not mix kernel access with file I/O. Using file I/O inside
a kernel event loop will cause the loop to miss events!
#define closedir fileCloseDir
#define DIR char
#define dirent fileDirEntS
#define FILE uint8_t
#define fclose fileClose
#define fopen fileOpen
#define fread fileRead
#define fseek fileSeek
#define fwrite fileWrite
#define mkdir(d,m) fileMakeDir(d)
#define opendir fileOpenDir
#define readdir fileReadDir
#define rename fileRename
#define rewind(s) (void)fileSeek(s, 0, SEEK_SET)
#define rmdir fileRemoveDir
#define SEEK_SET 0
#define STDIN 0
#define STDOUT 1
#define unlink fileUnlink
=== Platform
void __putchar(char c);
int getchar(void);
The absolute lowest level features needed to make the compiler and its library
work.
==== __putchar
[,c]
----
void __putchar(char c);
----
Displays the character `c` on the screen.
==== getchar
[,c]
----
int getchar(void);
----
Reads a single key from the keyboard.
IMPORTANT: If you are using kernel functions, do not call `getchar` inside
your kernel event loop. Use the kernel event `key.PRESSED` instead to avoid
losing events. Likewise, avoid standard C library routines that expect input
from the keyboard.
== Using Code Overlays
One of the most powerful features of this toolchain is the ability to write
programs that use more than the 64k of RAM addressable by the CPU. Using the
MMU (Memory Management Unit) of the F256, *_F256lib_* is able to automatically
swap code in from far memory on demand. The only additional work needed by
the programmer is to specify which bits of code are to be relocated to far
memory. This is achieved with a `#define SEGMENT_name` statement.
Example:
[,c]
----
#define F256LIB_IMPLEMENTATION
#include "f256lib.h"
void firstSegment(int arg1, int arg2);
void secondSegment(int arg1, int arg2);
void moreFirstSegment(int arg1, int arg2);
// This is the first segment we've defined.
// The linker will place this code in the first available
// far memory slot (default 0x10000).
#define SEGMENT_FIRST
void firstSegment(int arg1, int arg2) {
printf("firstSegment = %d\n", arg1 + arg2);
secondSegment(arg1, arg2);
}
// This is the second segment we've defined.
// The linker will place this code in the next available
// far memory slot (default 0x12000).
#define SEGMENT_SECOND
void secondSegment(int arg1, int arg2) {
printf("secondSegment = %d\n", arg1 + arg2);
moreFirstSegment(arg1, arg2);
}
// Back to the first segment.
// The linker will place this code immediately
// after the previous first segment code.
#define SEGMENT_FIRST
void moreFirstSegment(int arg1, int arg2) {
printf("moreFirstSegment = %d\n", arg1 + arg2);
}
// Back to near memory, the 64k visible to the processor.
// By default, this segment begins at 0x300.
#define SEGMENT_MAIN
int main(int argc, char *argv[]) {
(void)argc;
(void)argv;
firstSegment(1, 2);
// Spin.
for (;;);
return 0;
}
----
TIP: When building your program, the amount of space being used in each
segment will be displayed (or an error that you have overflowed a segment).
Use this information to help decide how to segment your program.
IMPORTANT: You cannot change where the overlay tool will place your far
memory code. It always starts at `0x10000` and increments the address `0x2000` (8k)
for each additional segment. When using overlays, be careful to not overwrite
this memory with other data!
NOTE: At the moment, you can only move code into far memory, not variables.
== Embedding Binary Data
* EMBED(); arguments must be literals. You cannot use #defines or variables.
Embedding binary data (sprites, tiles, bitmaps, whatever) into your program
at a specific memory address can be easily achieved with the `EMBED` macro.
* EMBED(); names (first argument) must begin with unique prefixes. For example,
"TILES" and "TILES_PALETTE" will cause an error due to "TILES" being a
complete substring of "TILES_PALETTE".
=== EMBED
[,c]
----
EMBED(name, "filename", address)
----
Embeds the contents of `"filename"` at near or far memory `address`. The
embedded data will be available by name through the following symbols:
* `const char name_start[];`
* `const char name_end[];`
Where `name` is the prefix of each symbol.
NOTE: `EMBED` arguments *must* be literals. You cannot use #defines or variables.
NOTE: `EMBED` names (first argument) *must* begin with unique prefixes. For example,
"TILES" and "TILES_PALETTE" will cause an error due to "TILES" being a
complete substring of "TILES_PALETTE".