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 macos aarch64 $(pwd)/overlay.macos
|
||||||
buildOverlayTool windows x86_64 $(pwd)/overlay.windows
|
buildOverlayTool windows x86_64 $(pwd)/overlay.windows
|
||||||
|
|
||||||
|
cp -f ../../f256lib.adoc .
|
||||||
|
asciidoctor-pdf -o f256lib.pdf f256lib.adoc
|
||||||
|
|
||||||
popd
|
popd
|
||||||
|
|
||||||
if [[ -f ../f256dev.7z ]]; then
|
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.
|
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
|
==== kernelCall
|
||||||
|
|
||||||
[,c]
|
[,c]
|
||||||
|
@ -582,8 +587,8 @@ Failing to call this often enough can starve the kernel of event objects.
|
||||||
|
|
||||||
=== DMA
|
=== DMA
|
||||||
|
|
||||||
At the moment, DMA access is... hit and miss. Feel free to try it but don't expect
|
IMPORTANT: At the moment, DMA access is... hit and miss. Feel free to try it
|
||||||
it to be stable. More DMA features will be available in the future.
|
but don't expect it to be stable. More DMA features will be available in the future.
|
||||||
|
|
||||||
==== dma2dFill
|
==== dma2dFill
|
||||||
|
|
||||||
|
@ -893,7 +898,7 @@ on the screen refresh, the bitmaps are:
|
||||||
|
|
||||||
On startup, all three bitmaps are assigned to each associated graphics layer,
|
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
|
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 0 - 0x6c000 -> 0x7ebff
|
||||||
* Page 1 - 0x58000 -> 0x6abff
|
* 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);
|
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
|
==== tileDefineTileSet
|
||||||
|
|
||||||
[,c]
|
[,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);
|
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
|
==== tileSetScroll
|
||||||
|
|
||||||
[,c]
|
[,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);
|
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
|
==== tileSetVisible
|
||||||
|
|
||||||
[,c]
|
[,c]
|
||||||
|
@ -1088,68 +1107,193 @@ void tileSetScroll(byte t, byte xPixels, uint16_t xTiles, byte yPixels, uint16_t
|
||||||
void tileSetVisible(byte t, bool v);
|
void tileSetVisible(byte t, bool v);
|
||||||
----
|
----
|
||||||
|
|
||||||
|
Determines the visibility `v` of a particular tile map `t` (0 to 2).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
=== File I/O
|
=== 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);
|
Supported functions are listed below. For usage details, see the documentation
|
||||||
int8_t fileCloseDir(char *dir);
|
for the standard C library.
|
||||||
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);
|
|
||||||
|
|
||||||
#define _DE_ISREG(t) (t == 0)
|
* `int closedir(DIR *dirp);`
|
||||||
#define _DE_ISDIR(t) (t == 1)
|
* `int fclose(FILE *stream);`
|
||||||
#define _DE_ISLBL(t) (t == 2)
|
* `FILE *fopen(const char *pathname, const char *mode);`
|
||||||
#define _DE_ISLNK(t) (0)
|
* `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
|
=== Platform
|
||||||
|
|
||||||
void __putchar(char c);
|
The absolute lowest level features needed to make the compiler and its library
|
||||||
int getchar(void);
|
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
|
== 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
|
== 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,
|
=== EMBED
|
||||||
"TILES" and "TILES_PALETTE" will cause an error due to "TILES" being a
|
|
||||||
complete substring of "TILES_PALETTE".
|
[,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