Added docs to distro builder.
This commit is contained in:
parent
7981304429
commit
de881b1b3e
2 changed files with 192 additions and 45 deletions
|
@ -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
|
||||
|
|
|
@ -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".
|
||||
|
||||
|
||||
|
Loading…
Add table
Reference in a new issue