mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2024-12-28 04:23:36 +01:00
Updated README and TODO files
This commit is contained in:
parent
9a3433c52a
commit
4fceab4533
4 changed files with 71 additions and 355 deletions
17
Makefile
17
Makefile
|
@ -71,10 +71,6 @@ define n
|
|||
|
||||
endef
|
||||
|
||||
ifeq ("$(wildcard $(config))","")
|
||||
$(error "Configuration files are missing. Did you ./configure?")
|
||||
endif
|
||||
|
||||
# Module-scope variables.
|
||||
$(foreach mod, $(modules), $(eval \
|
||||
mod-$(mod)-c = $(notdir $(wildcard src/$(mod)/*.c)) $n\
|
||||
|
@ -131,6 +127,9 @@ endef
|
|||
all: $(config) $(target-std) $(target-lib) $(target-g1a)
|
||||
@ printf '\e[32;1mmsg \u00bb\e[0m All done!\n'
|
||||
|
||||
$(config):
|
||||
$(error "Configuration files are missing. Did you ./configure?")
|
||||
|
||||
build:
|
||||
$(if $(VERBOSE),,@ printf '\e[35;1mdir \u00bb\e[0m mkdir $@\n')
|
||||
$(if $(VERBOSE),,@) mkdir -p $@
|
||||
|
@ -212,10 +211,7 @@ mrproper: clean
|
|||
|
||||
distclean: mrproper
|
||||
|
||||
install:
|
||||
p7 send -f $(target-g1a)
|
||||
|
||||
install_lib: $(target-std) $(target-lib)
|
||||
install: $(target-std) $(target-lib)
|
||||
mkdir -p $(folder)
|
||||
install -m 644 $^ $(folder)
|
||||
install -m 644 -T demo/gintdemo.ld $(folder)/linker.ld
|
||||
|
@ -223,4 +219,7 @@ install_lib: $(target-std) $(target-lib)
|
|||
install -m 644 include/*.h $(folder)/gint
|
||||
@ printf '\e[32;1mmsg \u00bb\e[0m All installed!\n'
|
||||
|
||||
.PHONY: all clean mrproper distclean install install_lib help
|
||||
install_demo:
|
||||
p7 send -f $(target-g1a)
|
||||
|
||||
.PHONY: all clean mrproper distclean install install_demo help
|
||||
|
|
87
README.md
87
README.md
|
@ -2,54 +2,77 @@ gint project
|
|||
============
|
||||
|
||||
gint (pronounce 'guin') is a low-level library for fx-9860G calculators. It
|
||||
provides the tools needed to develop programs under Linux using the gcc
|
||||
toolchain (sh3eb-elf).
|
||||
provides a mostly free-standing runtime support for the platform, and can be
|
||||
used to develop add-ins under Linux along with the gcc toolchain (`sh3eb-elf`
|
||||
target) and the [fxSDK](http://git.planet-casio.com/lephe/fxsdk).
|
||||
|
||||
By the way, gint is free software; you may use it for any purpose, share it,
|
||||
modify it and share you changes. No credit of any kind is needed, though
|
||||
appreciated.
|
||||
gint is free software: you may use it for any purpose, share it, modify it and
|
||||
share your changes. No credit of any kind is required, though appreciated.
|
||||
|
||||
|
||||
Programming interface
|
||||
---------------------
|
||||
|
||||
Because of its free-standing design, gint's API provides direct and efficient
|
||||
access to the low-level MPU features, among which:
|
||||
* Extensive keyboard control, including replication of the system behavior for
|
||||
office applications and event-driven decisions for games
|
||||
* Hardware timers running at over 10 MHz, allowing microsecond-level control
|
||||
* Unlimited mappings of callbacks to Real-Time Clock events (requires build)
|
||||
* Access to processor register for debugging information, determination of
|
||||
processor speed (overclock is on the TODO list), backlight management...
|
||||
|
||||
The library also offers powerful higher-level features:
|
||||
* A gray engine that works by rapidly swapping monochrome images
|
||||
* Blazingly fast drawing functions when working with the fxSDK
|
||||
* C Standard functions such as the `printf()` family.
|
||||
|
||||
|
||||
Interrupt handler
|
||||
-----------------
|
||||
|
||||
The interrupt handler is the lowest-level part of the library. It directly
|
||||
accesses the peripheral modules and performs keyboard analyzes, swaps screen
|
||||
buffers, etc.
|
||||
|
||||
gint does not allow user programs to use their own handlers. However, it is
|
||||
possible to map interrupt-driven events to user callbacks using the public API
|
||||
(which is not possible with the system's interrupt handler). This may be
|
||||
particularly useful for timers and RTC (the 16 Hz interrupt can be used as a
|
||||
basis for a physical engine).
|
||||
|
||||
|
||||
|
||||
Public Interface
|
||||
----------------
|
||||
|
||||
gint's API provides access to keyboard, timers, clock and more. It does some
|
||||
powerful drawing and offers reliable multi-getkey, a gray engine, facilitates
|
||||
register access and implements a few standard functions.
|
||||
accesses the peripheral modules and workarounds the system to perform keyboard
|
||||
analyzes directly on hardware or timer management.
|
||||
|
||||
gint does not allow user programs to use their own handlers, but it allows them
|
||||
to complete the original handler if they want to use interrupts that are not
|
||||
supported by the library. It is also possible to map various interrupt-driven
|
||||
events to user-provided callbacks using the API, which is not allowed by the
|
||||
operating system. This is particularly useful for timers and the Real-Time
|
||||
Clock (the 16 Hz interrupt can be used to run a physical engine, while the 1 Hz
|
||||
interrupt can be used in a real-time management game).
|
||||
|
||||
|
||||
Building and installing
|
||||
-----------------------
|
||||
|
||||
There are some dependencies:
|
||||
* The `sh3eb-elf` toolchain somewhere in the PATH
|
||||
* The fxSDK installed and available in the PATH
|
||||
To build and install gint, you will need the following components:
|
||||
* The `sh3eb-elf` toolchain linked somewhere in the PATH
|
||||
* The [fxSDK](http://git.planet-casio.com/lephe/fxsdk) installed and available
|
||||
in the PATH
|
||||
|
||||
The easiest way to build gint is simply to enter a terminal and execute `make`.
|
||||
This will build the following components :
|
||||
The classical way to build gint is to enter a terminal and use the usual:
|
||||
|
||||
$ ./configure
|
||||
$ make
|
||||
# make install
|
||||
|
||||
This will build and install the following components in the storage folder of
|
||||
the fxSDK:
|
||||
* `libgint.a`, the gint library
|
||||
* `libc.a`, a (very) few standard procedures
|
||||
* `libc.a`, the partial standard library
|
||||
* The libgint headers for development
|
||||
|
||||
The following additional files will be generated in the working directory:
|
||||
* `gintdemo.g1a`, a test application
|
||||
|
||||
The common `clean`, `mrproper`, and `distclean` rules will clean the directory.
|
||||
|
||||
The usual `clean`, `mrproper`, and `distclean` rules will clean the directory.
|
||||
There are configuration options, which can be obtained using
|
||||
`./configure --help`. Most of them customize size limits, if a project needs to
|
||||
extend them. The true free-standing program may build the library using the
|
||||
`--no-syscalls` switch, but some features will be disabled (dynamic
|
||||
allocation...).
|
||||
|
||||
|
||||
Source organization
|
||||
|
@ -65,8 +88,6 @@ components:
|
|||
* Other source files in `/src/module`: contain multiple functions that always
|
||||
work together, or are lightweight enough not to be separated. Their names
|
||||
often begin with `module_`.
|
||||
* Other files in `/src/module`: the `display` module contains a font, I think.
|
||||
* Other files in `/src/module`: the `display` module contains a font.
|
||||
|
||||
The demo application is in the `demo` directory.
|
||||
|
||||
The `doc` folder contains some documentation.
|
||||
|
|
16
TODO
16
TODO
|
@ -3,19 +3,21 @@ Bugs to fix:
|
|||
- Lost keyboard control at startup (could not reproduce)
|
||||
|
||||
Simple improvements:
|
||||
- bopti: Monochrome bitmaps blending modes
|
||||
- bopti: Partial transparency
|
||||
- demo: Try 284x124 at (-60, -28) (all disadvantages)
|
||||
- display: Rectangle-based drawing functions
|
||||
- tales: Test all font encodings
|
||||
- time: Compute CLOCKS_PER_SEC
|
||||
- core: Add VBR handlers debugging information (if possible)
|
||||
Larger improvements:
|
||||
- errno: Introduce errno and use it more or less everywhere
|
||||
- bopti: Monochrome bitmaps blending modes
|
||||
- bopti: Handle partial transparency
|
||||
- core: Implement all callbacks and a complete user API
|
||||
|
||||
Modules to implement:
|
||||
- Serial communication
|
||||
- Sound playback and synthesizing
|
||||
- Handle errors within errno
|
||||
Other whole modules:
|
||||
- Serial communication through 3-pin
|
||||
- USB communication
|
||||
- Sound playback and synthesizing (if possible)
|
||||
- Overclock (relaunch clocks when overclocking)
|
||||
|
||||
Things to investigate:
|
||||
- Packed bit fields alignment
|
||||
|
|
306
doc/bopti.md
306
doc/bopti.md
|
@ -1,306 +0,0 @@
|
|||
|
||||
# gint documentation: bitmap rendering #
|
||||
|
||||
|
||||
*Warning: this is a draft. The current implementation of bopti is different*
|
||||
*from this description, though similar.*
|
||||
|
||||
|
||||
|
||||
## Basics
|
||||
|
||||
The bitmap drawing module, *bopti*, is based on video-ram (vram) bitwise
|
||||
operations. The images are made of layers that describe (more or less) which
|
||||
pixels of the image an operation applies to. Rendering the image consists in
|
||||
applying an operation function to the existing vram pixels.
|
||||
|
||||
*bopti* makes an extensive use of longword operations and 4-alignment to take
|
||||
advantage of the bit-based structure of the monochrome vram and enhance
|
||||
performance. Among all possible optimizations, avoiding direct pixel access has
|
||||
proven to be the most efficient.
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## Operations
|
||||
|
||||
Operations are functions applied to update a vram longword in accordance with
|
||||
an operation mask. Bits that are set in the mask indicate pixels which have to
|
||||
be updated by the operation. Bits that are reset indicate pixels that must not
|
||||
be changed.
|
||||
|
||||
All the point is, the functions must not access the bit information in the mask
|
||||
or the vram data individually. They must operate globally using longword
|
||||
bitwise instructions, so that performance is maintained.
|
||||
|
||||
Consider for instance a logical and operation (`(a, b) -> a & b`).
|
||||
Operating on pixels would need to move some data, test the value of a bit in
|
||||
the mask, edit the vram data, and eventually shift both the data and the mask,
|
||||
for all of the 32 pixels.
|
||||
One could not expect this from happening in less than 150 processor cycles
|
||||
(in comparison, using generic-purpose `setPixel()`-like functions would be at
|
||||
least 10 times as long). The smarter method operates directly on the longword
|
||||
parameters, and performs `data = data & ~mask`, which is 2 processor cycles
|
||||
long.
|
||||
|
||||
The following operations are defined by *bopti*:
|
||||
|
||||
- `Draw `: Draws black pixels.
|
||||
- `Alpha `: Erases non-transparent pixels.
|
||||
- `Change `: Changes the pixels' color.
|
||||
- `Lighten `: Lightens gray pixels.
|
||||
- `Lighten2`: Lightens gray pixels more.
|
||||
- `Darken `: Darkens gray pixels.
|
||||
- `Darken2 `: Darkens gray pixels more.
|
||||
|
||||
To perform an operation, *bopti* uses the mask data, which is taken from a
|
||||
layer, and calls the associated operation function. Every operation has its
|
||||
default layer mask (except `change`), but this setting may be overridden.
|
||||
*bopti* allows user programs to use any monochrome image as a mask for an
|
||||
operation. For instance, a black rectangle may be drawn by any of the operation
|
||||
functions, resulting in various results.
|
||||
|
||||
An additional operation, `fill`, is defined by the library. It does all the job
|
||||
necessary to render the full image, which often falls back to performing the
|
||||
operations that correspond to the kind of image.
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## Operation on gray pixels
|
||||
|
||||
*Detailed article: [Gray engine](gray-engine)*
|
||||
|
||||
Gray pixels are made of four colors represented by pairs of bits. Arguments
|
||||
`light` and `dark` of gray operation functions are longwords containing the
|
||||
least significant and most significant of these bits, respectively.
|
||||
|
||||
white = 0 [00]
|
||||
lightgray = 1 [01]
|
||||
darkgray = 2 [10]
|
||||
black = 3 [11]
|
||||
|
||||
The `Lighten` operation affects pixels as if decrementing their value (white
|
||||
pixels are not changed), and `darken` does the opposite (black pixels are not
|
||||
changed).
|
||||
Operations `Lighten2` and `darken2` do the same two times.
|
||||
|
||||
From this description, and considering two bits `light` and `dark`, it follows
|
||||
that:
|
||||
|
||||
```c
|
||||
lighten2 (light, dark) = (0, light & dark)
|
||||
lighten (light, dark) = (light & dark, light & ~dark)
|
||||
darken (light, dark) = (light | dark, light | ~dark)
|
||||
darken2 (light, dark) = (1, light | dark)
|
||||
```
|
||||
|
||||
This does not take account of a possible operation mask. See section
|
||||
[Operation functions](#operation-functions) for more flexible functions.
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## Partial transparency
|
||||
|
||||
*bopti* allows monochrome images to have semi-transparent pixels. Consider for
|
||||
example a white background. An opaque black pixel will render black, while a
|
||||
1/3-transparent black pixel will render dark gray, and a 2/3-transparent black
|
||||
pixel will render light gray. Which means that:
|
||||
|
||||
* 1/3-transparent white pixels form the mask for `lighten2`
|
||||
* 2/3-transparent white pixels form the mask for `lighten`
|
||||
* 2/3-transparent black pixels form the mask for `darken`
|
||||
* 1/3-transparent black pixels form the mask for `darken2`
|
||||
|
||||
Partial transparency on gray pixels is not allowed. Apart from the complexity
|
||||
of the generic partial transparency rendering operation, semi-transparent gray
|
||||
pixels are not of any use.
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## Operation functions
|
||||
|
||||
Operations on monochrome buffers are defined as functions of two parameters:
|
||||
the vram data longword to update, `data`, and the operation mask, `x`. Every
|
||||
of these functions must satisfy `f(data, 0) = data`.
|
||||
|
||||
Operations on gray buffers take three arguments: `light` and `dark`, which are
|
||||
longwords from the [gray buffers](gray-engine), and the operation mask `x`.
|
||||
They update both longwords and return them. These functions must satisfy
|
||||
`f(light, dark, 0) = (light, dark)`.
|
||||
|
||||
The functions for each of the operations are the following:
|
||||
|
||||
~~~c
|
||||
# Draw function
|
||||
draw(data, x) = data | x
|
||||
|
||||
# Alpha function
|
||||
alpha(data, x) = data & ~x
|
||||
|
||||
# Change function
|
||||
change(data, x) = data ^ x
|
||||
|
||||
# Lighten function
|
||||
lighten(light, dark, x) = (light & (dark | ~x), (light | ~x) & (x ^ dark))
|
||||
|
||||
# Lighten2 function
|
||||
lighten2(light, dark, x) = (light & ~x, (light | ~x) & dark)
|
||||
|
||||
# Darken function
|
||||
darken(light, dark, x) = (light | (dark & x), (light & x) | (x ^ dark))
|
||||
|
||||
# Darken2 function
|
||||
darken2(light, dark, x) = (light | x, (light & x) | dark)
|
||||
~~~
|
||||
|
||||
One could easily check that these functions do their jobs when `x = 1` and
|
||||
leave the data unchanged when `x = 0`.
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## Image format
|
||||
|
||||
Images are made of *layers*, each of which describe the mask for an operation.
|
||||
When an image is rendered, *bopti* draws some of those layers in the vram
|
||||
using the operation functions.
|
||||
|
||||
* Non-transparent monochrome images only have one layer, which describes the
|
||||
mask for the `draw` operation.
|
||||
* Transparent monochrome images have two layers. The first describes the mask
|
||||
for the `draw` operation, while the other is the `alpha` operation mask (which
|
||||
means that it indicates which pixels are not transparent).
|
||||
* Non-transparent gray images also have two layers: one for each
|
||||
[gray buffer](gray-engine). Both are for the `draw` operation.
|
||||
* Transparent gray images have three layers. Two of them constitute the two-bit
|
||||
color information for the `draw` operation, and the third is the `alpha`
|
||||
operation mask.
|
||||
* Semi-transparent monochrome images also have three layers. Two are used to
|
||||
store the two-bit transparency level information (0 is opaque, 3 is fully
|
||||
transparent), and the third indicates the color.
|
||||
|
||||
Layers are encoded as a bit map. The image is split into a *grid*, which is
|
||||
made of 32-pixel *columns*, and an *end*.
|
||||
|
||||
32 32 32 end
|
||||
+------+------+------+---+
|
||||
| | | | |
|
||||
| | | | |
|
||||
| | | | |
|
||||
+------+------+------+---+
|
||||
|
||||
Bitmap
|
||||
|
||||
The first bytes of the layer data is the column data. Each column is encoded
|
||||
as a 32-bit integer array from top to bottom. Columns are written from left to
|
||||
right. The end is encoded as an 8-bit or 16-bit integer array depending on its
|
||||
size, and written from top to bottom. Additionally, 0 to 3 NUL (0x00) bytes are
|
||||
added to make the layer size a multiple of 4 (to allow 32-bit access to the
|
||||
column data of the following layer).
|
||||
|
||||
In case of big images (see the image structure below), the end is expanded to
|
||||
a 32-pixel column to improve performance.
|
||||
|
||||
The image itself is a structure of the following kind (in case of small
|
||||
images):
|
||||
|
||||
```c
|
||||
struct Image
|
||||
{
|
||||
unsigned char magic;
|
||||
unsigned char format;
|
||||
|
||||
unsigned char width;
|
||||
unsigned char height;
|
||||
|
||||
const uint32_t data[];
|
||||
|
||||
} __attribute__((aligned(4)));
|
||||
```
|
||||
|
||||
For bigger images (`width` > 255 or `height` > 255), both `width` and `height`
|
||||
are set to `0` and the actual size information is written on two shorts just
|
||||
where the data resides:
|
||||
|
||||
```c
|
||||
struct BigImage
|
||||
{
|
||||
unsigned char magic;
|
||||
unsigned char format;
|
||||
|
||||
unsigned char null_width; /* contains 0 */
|
||||
unsigned char null_height; /* contains 0 */
|
||||
|
||||
unsigned short width;
|
||||
unsigned short height;
|
||||
|
||||
const uint32_t data[];
|
||||
|
||||
} __attribute__((aligned(4)));
|
||||
```
|
||||
|
||||
This does not create a memory loss because a two-byte gap was needed to make
|
||||
the data 4-aligned.
|
||||
|
||||
* The `magic` number, which is common to all the file formats of *gint*,
|
||||
identifies the file type and version of the structure. *bopti* will not render
|
||||
an image which is not encoded for its specific version.
|
||||
|
||||
* The `format` attribute describes the layer distribution, as specified by the
|
||||
following enum:
|
||||
|
||||
```c
|
||||
enum ImageFormat
|
||||
{
|
||||
ImageFormat_Mono = 0x01,
|
||||
ImageFormat_MonoAlpha = 0x09,
|
||||
ImageFormat_Gray = 0x06,
|
||||
ImageFormat_GrayAlpha = 0x0e,
|
||||
ImageFormat_GreaterAlpha = 0x31,
|
||||
|
||||
ImageFormat_ColorMask = 0x07,
|
||||
ImageFormat_AlphaMask = 0x38,
|
||||
};
|
||||
```
|
||||
|
||||
`Alpha` refers to uniform transparency. The only format that supports
|
||||
partial transparency is `GreaterAlpha`, and it is always encoded as
|
||||
monochrome (because using gray pixels would lead to 9 different colors,
|
||||
which is rather unoptimized). Gray images with partial transparency
|
||||
will be refused by *fxconv*.
|
||||
|
||||
|
||||
* The `width` and `height` attributes are exactly what you expect.
|
||||
|
||||
* The `data` is simply made of all the layers put one after another. Layers are
|
||||
put in the following order:
|
||||
|
||||
[0] Monochrome `draw` layer
|
||||
[1] Dark gray `draw` layer
|
||||
[2] Light gray `draw` layer
|
||||
[3] Uniform `alpha` layer
|
||||
[4] First semi-`alpha` layer
|
||||
[5] Second semi-`alpha` layer
|
||||
|
||||
Not every format uses the six layers, of course. The layers used by
|
||||
each format may be found by reading the position of the `1`'s in the
|
||||
corresponding `enum ImageFormat` entry. Layers that are not needed are
|
||||
skipped.
|
Loading…
Reference in a new issue