Lephe
c9264a06d5
Changes in the driver and world system: * Rewrite driver logic to include more advanced concepts. The notion of binding a driver to a device is introduced to formalize wait(); power management is now built-in instead of being handled by the drivers (for instance DMA). The new driver model is described in great detail in <gint/drivers.h> * Formalized the concept of "world switch" where the hardware state is saved and later restored. As a tool, the world switch turns out to be very stable, and allows a lot of hardware manipulation that would be edgy at best when running in the OS world. * Added a GINT_DRV_SHARED flag for drivers to specify that their state is shared between worlds and not saved/restored. This has a couple of uses. * Exposed a lot more of the internal driver/world system as their is no particular downside to it. This includes stuff in <gint/drivers.h> and the driver's state structures in <gint/drivers/states.h>. This is useful for debugging and for cracked concepts, but there is no API stability guarantee. * Added a more flexible driver level system that allows any 2-digit level to be used. Feature changes: * Added a CPU driver that provides the VBR change as its state save. Because the whole context switch relied on interrupts being disabled anyway, there is no longer an inversion of control when setting the VBR; this is just part of the CPU driver's configuration. The CPU driver may also support other features such as XYRAM block transfer in the future. * Moved gint_inthandler() to the INTC driver under the name intc_handler(), pairing up again with intc_priority(). * Added a reentrant atomic lock based on the test-and-set primitive. Interrupts are disabled with IMASK=15 for the duration of atomic operations. * Enabled the DMA driver on SH7305-based fx-9860G. The DMA provides little benefit on this platform because the RAM is generally faster and buffers are ultimately small. The DMA is still not available on SH3-based fx-9860G models. * Solved an extremely obnoxious bug in timer_spin_wait() where the timer is not freed, causing the callback to be called when interrupts are re-enabled. This increments a random value on the stack. As a consequence of the change, removed the long delays in the USB driver since they are not actually needed. Minor changes: * Deprecated some of the elements in <gint/hardware.h>. There really is no good way to "enumerate" devices yet. * Deprecated gint_switch() in favor of a new function gint_world_switch() which uses the GINT_CALL abstraction. * Made the fx-9860G VRAM 32-aligned so that it can be used for tests with the DMA. Some features of the driver and world systems have not been implemented yet, but may be in the future: * Some driver flags should be per-world in order to create multiple gint worlds. This would be useful in Yatis' hypervisor. * A GINT_DRV_LAZY flag would be useful for drivers that don't want to be started up automatically during a world switch. This is relevant for drivers that have a slow start/stop sequence. However, this is tricky to do correctly as it requires dynamic start/stop and also tracking which world the current hardware state belongs to. |
||
---|---|---|
cmake | ||
include/gint | ||
src | ||
.gitignore | ||
CMakeLists.txt | ||
README.md | ||
TODO | ||
fx9860g.ld | ||
fxcg50.ld | ||
giteapc.make |
README.md
gint project
gint (pronounce “guin”) is an add-in unikernel for CASIO calculators of the fx-9860G II and fx-CG 50 families. It provides a mostly free-standing runtime and is used to develop add-ins under Linux, along with specialized GCC toolchains and the fxSDK.
When running in an add-in, gint takes control of the calculator's hardware from the operating system, and manages it with its own drivers. It exposes a new, richer API that takes advantage of the full capabilities of the machine.
This is free software: you may use it for any purpose, share it, modify it, and share your changes. Credit is not required, but please let me know!
gint also includes third-party code that is distributed under its own license. Currently, this includes:
- A stripped-down version of the TinyMT random number generator
(GitHub repository) by
Mutsuo Saito and Makoto Matsumoto. See
src/3rdparty/tinymt32/LICENSE.txt
. - A stripped-down version of the Grisu2b floating-point representation
algorithm
with α=-59 and γ=-56, by Florian Loitsch. See
src/3rdparty/grisu2b_59_56/README
for details, and the original code here.
Programming interface
Because of its free-standing design, gint's API provides direct and efficient access to low-level MPU features, which includes:
- Multi-key management with event systems suitable for games
- Hardware timers with sub-millisecond and sub-microsecond resolution
- Fast screen drivers with DMAC on fx-CG 50
- Efficient and user-extendable interrupt management
- Safe access to on-chip and DSP memory areas
- Hardware-driven memory primitives (DMA, DSP)
The library also offers powerful higher-level features:
- An enhanced version of the system's GetKey() and GetKeyWait()
- A gray engine that works by rapidly swapping monochrome images on fx-9860G II
- Blazingly fast rendering functions (image rendering is 10 times faster tha MonochromeLib)
- Integrated font management
A couple of libraries extend these features, including:
- libprof: Profiling and performance evaluation
- libimg: Versatile image transformations
- OpenLibm: A port of the standard math library
- Integration with a Newlib port by Memallox (unstable)
Installing with GiteaPC
gint can be installed automatically with GiteaPC.
% giteapc install Lephenixnoir/gint
Normally you don't use gint directly, instead the fxSDK provides project templates that are set up to use gint. Please see the fxSDK README file for details.
Building and installing manually
gint is built using the fxSDK, which provides a suitable
CMake environment for the calculator. gint is always installed in the
compiler's install path (as given by sh-elf-gcc --print-search-dirs
) which is
detected automatically, so normally you don't need to set the install prefix.
fx-CG 50 developers probably want a g3a wrapper as well; the reference implementation is Tari's mkg3a. This is needed at the very last compilation step to create the g3a file. On Arch Linux, you can use the AUR/mkg3a package maintained directly by Tari.
Building for fx-9860G II
fxsdk build-fx
will invoke CMake and make. If you have specific configuration
options, run once with -c
to configure.
% fxsdk build-fx -c <OPTIONS...>
Run without -c
to build. This configures automatically.
% fxsdk build-fx
The available options are:
-DGINT_STATIC_GRAY=1
: Put the gray engine's VRAMs in static RAM instead of usingmalloc()
Building for fx-CG 50
Same as fx-9860G II, except the command is fxsdk build-cg
instead of fxsdk build-fx
.
The available options are:
-DGINT_USER_VRAM=1
: Store all VRAMs in the user stack (takes up 350k/512k)
Using in CMake-based add-ins
Find the Gint
module and link against Gint::Gint
.
find_module(Gint 2.1 REQUIRED)
target_link_libraries(<target_name> Gint::Gint)
Using in Makefile-based add-ins
Projects created with the fxSDK link with gint out-of-the-box. If you're not using the fxSDK, you will need to:
- Build with
-ffreestanding -fstrict-volatile-bitfields
; - Link with
-T fx9860g.ld
and-lgint-fx
on fx-9860G; - Link with
-T fxcg50.ld
and-lgint-cg
on fx-CG 50.
If you don't have a standard library such as
Memallox's port of newlib, you also need -nostdlib
. I
typically use -m3 -mb
or -m4-nofpu -mb
to specify the platform, but that
may not even be necessary.