Lephe
e5abe03b89
This commit introduces a large architectural change. Unlike previous models of the fx-9860G series, the G-III models have a new user RAM address different from 8801c000. The purpose of this change is to dynamically load GMAPPED functions to this address by querying the TLB, and call them through a function pointer whose address is determined when loading. Because of the overhead of using a function pointer in both assembly and C code, changes have been made to avoid GMAPPED functions altogether. Current, only cpu_setVBR() and gint_inth_callback() are left, the second being used specifically to enable TLB misses when needed. * Add a .gint.mappedrel section for the function pointers holding addresses to GMAPPED functions; add function pointers for cpu_setVBR() and gint_inth_callback() * Move rram to address 0 instead of the hardcoded 0x8801c000 * Load GMAPPED functions at their linked address + the physical address user RAM is mapped, to and compute their function pointers * Remove the GMAPPED macro since no user function needs it anymore * Add section flags "ax" (code) or "aw" (data) to every custom .section in assembler code, as they default to unpredictable values that can cause the section to be marked NOLOAD by the linker * Update the main kernel, TMU, ETMU and RTC interrupt handlers to use the new indirect calling method This is made possible by new MMU functions giving direct access to the physical area behind any virtualized page. * Add an mmu_translate() function to query the TLB * Add an mmu_uram() function to access user RAM from P1 The exception catching mechanism has been modified to avoid the use of GMAPPED functions altogether. * Set SR.BL=0 and SR.IMASK=15 before calling exception catchers * Move gint_exc_skip() to normal text ROM * Also fix registers not being popped off the stack before a panic The timer drivers have also been modified to avoid GMAPPED functions. * Invoke timer_stop() through gint_inth_callback() and move it to ROM * Move and expand the ETMU driver to span 3 blocks at 0xd00 (ETMU4) * Remove the timer_clear() function by inlining it into the ETMU handler (TCR is provided within the storage block of each timer) * Also split src/timer/inth.s into src/timer/inth-{tmu,etmu}.s Additionally, VBR addresses are now determined at runtime to further reduce hardcoded memory layout addresses in the linker script. * Determine fx-9860G VBR addresses dynamically from mmu_uram() * Determine fx-CG 50 VBR addresses dynamically from mmu_uram() * Remove linker symbols for VBR addresses Comments and documentation have been updated throughout the code to reflect the changes. |
||
---|---|---|
include/gint | ||
make | ||
src | ||
.gitignore | ||
Makefile | ||
README.md | ||
TODO | ||
configure | ||
fx9860g.ld | ||
fxcg50.ld |
README.md
gint project
gint (pronounce 'guin') is a development system for Casio fx-9860G II and fx-CG 50 calculators. It provides a mostly free-standing runtime and is used to develop add-ins under Linux, along with specialized GCC toolchains and the fxSDK.
gint is a modular kernel that implements its own drivers for the calculator's hardware, overriding the operating system and its syscalls. It is a drop-in replacement from fxlib, with which it is mostly incompatible. gint exposes a new, richer API to manipulate the hardware and take advantage of the full capabilities of the machine.
This is free software: you may use it for any purpose, share it, and modify it as long as you 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 only includes:
- A stripped-down version of the TinyMT random number generator
(GitHub repository) by
Mutsuo Saito and Makoto Matsumoto. See
src/std/tinymt32/LICENSE.txt
.
Programming interface
Because of its free-standing design, gint's API provides direct and efficient access to the low-level MPU features, among which:
- 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
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 drawing functions when working with the fxSDK (image rendering is 10 times faster than MonochromeLib)
- Integrated font management with the fxSDK
- Integration with a Newlib port by Memallox (WIP)
Building and installing gint
You can choose to build gint for fx-9860G II (monochrome calculators, aka Graph 85 family), fx-CG 50 (color calculators, aka Prizm or Graph 90 family), or both. There are a few dependencies:
- A suitable GCC toolchain in the
PATH
. You can absolutely not build gint with your system compiler!- The tutorial on Planète Casio builds an
sh-elf
that works everywhere - For fx-9860G II,
sh3eb-elf
is strongly advised - For fx-CG 50,
sh4eb-elf
(with-m4-nofpu
) is slightly better butsh3eb-elf
is completely fine
- The tutorial on Planète Casio builds an
- The fxSDK installed and available in the PATH. You
will need
fxconv
to build gint, and if you intend to develop add-ins for fx-9860G II, you probably wantfxg1a
as well. All these tools are built by default.
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.
The build process is detailed below for both platforms, the principle is the same. You can build both targets at the same time by reading the two sections.
By default gint will be installed in the appropriate compiler folder, which
is $PREFIX/
for libraries and linker scripts, and $PREFIX/include/gint/
for
headers, where PREFIX
is obtained by running
${toolchain}-gcc --print-search-dirs
and reading the line that starts with
install:
. You can change this with the --prefix
configure option, but
normally you don't need to.
Building for fx-9860G II
Create a build directory and configure in it:
% mkdir build.fx && cd build.fx
% ../configure --target=fx9860g
Then build the source and install the library files to the selected directory.
You might need root access if you selected a target directory owned by root
with --prefix
, or if you built your compiler as root.
% make
% make install
Building for fx-CG 50
Create a build directory and configure in it. The default toolchain is
sh4eb-elf
, if you wish to build with sh3eb-elf
, you need to add a
command-line option --toolchain=sh3eb-elf
.
% mkdir build.cg && cd build.cg
% ../configure --target=fxcg50
Then build the source and install the library files to the selected directory.
% make
% make install
Using gint
To use gint as your runtime environment, the bare minimum is:
- Build with
-ffreestanding
; - 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.
Typically you might want to do this with the fxSDK, which hides most of the details and makes it easy to roll add-ins.