way too much, including bopti/topti, timers, and more.

pull/1/head
lephe 4 years ago
parent ae4e5d83b2
commit 3f7c0a04ad
  1. 11
      .gitignore
  2. 179
      Makefile
  3. 174
      README.md
  4. 67
      TODO
  5. 278
      configure
  6. 8
      fx9860g.ld
  7. 8
      fxcg50.ld
  8. 9
      include/core/bootlog.h
  9. 2
      include/core/memory.h
  10. 26
      include/core/mmu.h
  11. 12
      include/core/setup.h
  12. 78
      include/defs/types.h
  13. 30
      include/display/fx.h
  14. 4
      include/gint/clock.h
  15. 21
      include/gint/defs/attributes.h
  16. 48
      include/gint/defs/types.h
  17. 67
      include/gint/defs/util.h
  18. 21
      include/gint/display-cg.h
  19. 129
      include/gint/display-fx.h
  20. 32
      include/gint/display.h
  21. 12
      include/gint/drivers.h
  22. 17
      include/gint/drivers/iokbd.h
  23. 4
      include/gint/drivers/t6k11.h
  24. 26
      include/gint/gint.h
  25. 151
      include/gint/keyboard.h
  26. 86
      include/gint/keycodes.h
  27. 13
      include/gint/mpu.h
  28. 7
      include/gint/mpu/cpg.h
  29. 18
      include/gint/mpu/intc.h
  30. 5
      include/gint/mpu/pfc.h
  31. 6
      include/gint/mpu/rtc.h
  32. 22
      include/gint/rtc.h
  33. 19
      include/gint/timer.h
  34. 176
      make/Makefile
  35. 22
      src/clock/freq.c
  36. 18
      src/clock/sleep.c
  37. 44
      src/core/bootlog.c
  38. 12
      src/core/gint.c
  39. 6
      src/core/inth.S
  40. 7
      src/core/memory.c
  41. 8
      src/core/mmu.c
  42. 11
      src/core/mpu.c
  43. 44
      src/core/setup.c
  44. 51
      src/core/start.c
  45. BIN
      src/font5x6.png
  46. 118
      src/keysc/getkey.c
  47. 5
      src/keysc/iokbd.c
  48. 71
      src/keysc/keysc.c
  49. 12
      src/r61524/r61524.c
  50. 0
      src/render-cg/dclear.c
  51. 44
      src/render-fx/bopti-asm.h
  52. 110
      src/render-fx/bopti-asm.s
  53. 268
      src/render-fx/bopti.c
  54. 39
      src/render-fx/dclear.c
  55. 136
      src/render-fx/dline.c
  56. 28
      src/render-fx/dpixel.c
  57. 61
      src/render-fx/drect.c
  58. 15
      src/render-fx/dupdate.c
  59. BIN
      src/render-fx/font-default.png
  60. 28
      src/render-fx/masks.c
  61. 15
      src/render-fx/topti-asm.h
  62. 170
      src/render-fx/topti-asm.s
  63. 252
      src/render-fx/topti.c
  64. 2
      src/rtc/inth.s
  65. 26
      src/rtc/rtc.c
  66. 24
      src/t6k11/t6k11.c
  67. 16
      src/tmu/inth.s
  68. 125
      src/tmu/tmu.c

11
.gitignore vendored

@ -1,5 +1,5 @@
# Build directory
build/**
# Build directories
build*/**
# Sublime Text files
*.sublime-project
@ -7,10 +7,3 @@ build/**
# Lots of unordered project notes
notes/**
# Output files
bin/**
# Configuration files
config/**

@ -1,172 +1,59 @@
#! /usr/bin/make -f
#
# gint project Makefile
#
#---
#
# Build configuration
#
# Some rules don't care if config files are missing (eg. clean, etc)
cfg := config/Makefile.cfg
-include $(cfg)
# Those that do may use this special dependency
cfgdep := $(if $(shell [ -f $(cfg) ] || echo n),CFGDEP,$(cfg))
cf-fx := -m3 -mb -ffreestanding -nostdlib -Wall -Wextra -std=c11 -Os \
-fstrict-volatile-bitfields -I include $(cfg_macros)
cf-cg := -m4 -mb -ffreestanding -nostdlib -Wall -Wextra -std=c11 -Os \
-fstrict-volatile-bitfields -I include $(cfg_macros)
builds := $(wildcard build*)
# On fx9860g, use the sh3eb-elf toolchain; on fxcg50, prefer sh4eb-nofpu-elf
toolchain := $(if $(filter $(cfg_target),fx),sh3eb-elf,sh4eb-nofpu-elf)
# Compiler flags, assembler flags, dependency generation, archiving
cflags := $(cf-$(cfg_target))
sflags := $(cfg_macros)
dflags = -MMD -MT $@ -MF $(@:.o=.d) -MP
arflags :=
ifeq "$(builds)" ""
nobuild:
@ echo "error: you don't seem to have any build directory (build*)" >&2
@ echo "" >&2
@ echo "You can configure one like this:" >&2
@ echo " mkdir build && cd build && ../configure [options...]" >&2
@ echo "" >&2
@ false
endif
#
# File listings
# all targets
#
# Target file (cfg_target is either "fx" or "cg")
target := bin/libgint-$(cfg_target).a
# Automatic names for object and dependency files
src2obj = build/$(1:src/%=%).o
src2dep = build/$(1:src/%=%).d
all-targets := $(foreach b,$(builds),all-$b)
# Source files
src := $(shell find src -name '*.[csS]')
src_obj := $(foreach s,$(src),$(call src2obj,$s))
all: $(all-targets)
# Files with special handling
# spe := build/version.o src/display/font.bmp
spe :=
spe_obj := build/version.o $(foreach s,$(spe),$(call src2obj,$s))
# All object files
obj := $(src_obj) $(spe_obj)
# Version file
version := config/version
all-build%: build%
@ echo -e "$B::$W Making into $<$N"
@ $(MAKE) --no-print-directory -C $<
#
# Toolchain
# install targets
#
gcc = $(toolchain)-gcc
as = $(toolchain)-as
ld = $(toolchain)-ld
ar = $(toolchain)-ar
objcopy = $(toolchain)-objcopy
conv = fxconv
install-targets := $(foreach b,$(builds),install-$b)
install: $(install-targets)
#
# Version management
#
# Retrieve version information
v_file = $(shell cat $(version) | sed 's/[-.]/ /g')
v_type = $(word 1,$(v_file))
v_major = $(word 2,$(v_file))
v_minor = $(word 3,$(v_file))
v_build = $(word 4,$(v_file))
# Create the current version symbol and the new version integer
v_newbuild = $(shell echo $$(($(v_build) + 1)))
v_letter = $(shell echo -n $(v_type) | sed -r 's/^(.).*/\1/')
v_symbol = $(shell printf '0x%02x%01x%01x%04x' "'$(v_letter)'" \
$(v_major) $(v_minor) $(v_build))
install-build%: build%
@ echo -e "$B::$W Installing from $<$N"
@ $(MAKE) --no-print-directory -C $< install
#
# Build rules
# uninstall targets
#
all: $(target)
$(target): $(obj) $(version) | $(dir $(target))
$(call cmd_l,ar,$@) $(ar) -crs $(arflags) $@ $(obj)
# Assembler sources
build/%.s.o: src/%.s build/%.s.d
@ mkdir -p $(dir $@)
$(call cmd_b,as,$<) $(gcc) -c $< -o $@ $(sflags)
build/%.S.o: src/%.S build/%.S.d
@ mkdir -p $(dir $@)
$(call cmd_b,as,$<) $(gcc) -c $< -o $@ $(sflags)
# C sources
build/%.c.o: src/%.c build/%.c.d $(cfgdep)
@ mkdir -p $(dir $@)
$(call cmd_b,gcc,$<) $(gcc) -c $< -o $@ $(dflags) $(cflags)
uninstall-targets := $(foreach b,$(builds),uninstall-$b)
# Special files
$(call src2obj,src/display/font.bmp): src/display/font.bmp
@ mkdir -p $(dir $@)
$(call cmd_m,fxconv,$<) $(conv) -font $< -n gint_font -o $@
uninstall: $(uninstall-targets)
# Version symbol. ld generates a .stack section for unknown reasons; I fall
# back to removing it afterwards.
build/version.o:
@ mkdir -p $(dir $@)
@ echo "_GINT_VERSION = $(v_symbol);" > $@.txt
$(call cmd_b,ld,$@) $(ld) -r -R $@.txt -o $@
uninstall-build%: build%
@ echo -e "$B::$W Uninstalling from $<$N"
@ $(MAKE) --no-print-directory -C $< uninstall
#
# Cleaning
# Coloring tools
#
clean:
@ rm -rf build/
distclean: clean
@ rm -rf bin/
@ rm -f $(config)
#
# Utilities
#
$(version): $(src) $(wildcard include/**/*)
@ echo '$(v_type)-$(v_major).$(v_minor)-$(v_newbuild)' > $@
# Evaluated when a rule requires the configuration file but it doesn't exist
CFGDEP:
@ echo "Configuration file $(cfg) is missing. Have you configured?"
@ echo "See \`./configure --help\` for details."
@ false
B = \e[34;1m
W = \e[39;1m
N = \e[0m
# Make directories: make conveniently leaves a '/' at the end of $(dir ...)
%/:
@ mkdir -p $@
# Don't try to unlink directories once they're built (that wouldn't work =p)
.PRECIOUS: %/
# Dependency information
-include $(shell [ -d build ] && find build -name *.d)
build/%.d: ;
.PRECIOUS: build/%.d
# Do not output full commands by default
VERBOSE ?=
# Simple command output method
# $1 Program name
# $2 Argument string to display
# $3 Command color
define cmd
@ echo -e "\e[""$3"";1m>\e[0;1m $1\e[0m $2"
$(if $(VERBOSE),,@)
endef
# Some pre-colored command kinds: misc, build, link, clean, install
cmd_m = $(call cmd,$1,$2,30)
cmd_b = $(call cmd,$1,$2,32)
cmd_l = $(call cmd,$1,$2,36)
cmd_c = $(call cmd,$1,$2,31)
cmd_i = $(call cmd,$1,$2,33)
.PHONY: nobuild all all-build% install install-build%

@ -1,98 +1,112 @@
gint project
============
# gint project
gint (pronounce 'guin') is a low-level library for fx-9860G calculators. It
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).
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](http://git.planet-casio.com/lephe/fxsdk).
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.
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!
**TODO: Update this file for everything related to project organization**
Programming interface
---------------------
## 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 registers for debugging information, determination of
processor speed (overclock is on the TODO list), backlight management...
* 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:
* A gray engine that works by rapidly swapping monochrome images
* Blazingly fast drawing functions when working with the fxSDK (10 times faster
image rendering that MonochromeLib)
* C Standard functions such as the `printf()` family
* An enhanced versio 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)
Interrupt handler
-----------------
The interrupt handler is the lowest-level part of the library. It directly
accesses the peripheral modules and workarounds the system to perform keyboard
analyzes directly on hardware or timer management.
## Building and installing gint
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).
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 toolcahin in the `PATH`. You can absolutely *not* build gint
with your system compiler!
* For fx-9860G II, `sh3eb-elf` is strongly advised
* For fx-CG 50, `sh4eb-nofpu-elf` is slightly better but `sh3eb-elf` is
completely fine
* The [fxSDK](http://git.planet-casio.com/lephe/fxsdk) installed and available
in the PATH. You will need `fxsdk` and `fxconv` to build gint, and if you
intend to develop add-ins for fx-9860G II, you probably want `fxg1a` as well.
Building and installing
-----------------------
fx-CG 50 developers probably want a g3a wrapper as well; the reference
implementation is tari's [mkg3a](https://www.taricorp.net/projects/mkg3a/).
This is only necessary when creating g3a files, not to use gint.
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 classical way to build gint is to enter a terminal and use the usual:
$ ./configure
$ make
# make install
This will build the `all-lib` target and install the following components in
the storage folder of the fxSDK:
* `libgint.a`, the gint library
* `libc.a`, the partial standard library
* The libgint headers for development
When explicitly running target `all`, the following additional files will be
generated in the working directory:
* `gintdemo.g1a`, a test application
* `gintdbg.g1a`, a non-gint application used for debugging in case gint crashes
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
-------------------
gint is made of *modules*. Each module has one or more of the following
component files:
* A header file in `/include`
* An internal header file in `/include/internals`
* Single-function source files in `/src/module`: to avoid linking against the
whole library, some functions have their own object files. Their names are
those of the functions.
* 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.
The demo application is in the `demo` folder.
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.
### 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-nofpu-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](https://git.planet-casio.com/Memallox/libc), you
also need `-nostdlib`. I typically use `-m3 -mb` or `-m4 -mb` to specify the
platform, but that may not even be necessary.
Typically you might want to do this with the
[fxSDK](http://git.planet-casio.com/lephe/fxsdk), which hides most of the
details and makes it easy to roll add-ins.

67
TODO

@ -1,15 +1,61 @@
# Since compatibility
Another, more recent list of things to do:
- Complete memory functions in [core/memory.c]
- Finish the boot log in <core/bootlog.h>
- Finish the boot log in [core/bootlog.c]
- Document the SH7305 PFC in <gint/mpu/pfc.h>
- Change the description of the version number in <gint/gint.h>
- Define the version number from full Git info
- Do this display in <gint/display-fx.h> and <gint/display-cg.h>
- Remove all mentions of GINT_LAX in the code
- Write exception handlers
- Do overclock in [clock/]
- Test getkey()
* Make keysc/keysc.c/state static and review forgotten global variables
* Find out what happened to the clock frequency on fxcg50
* Implement profiling
* Save and restore interrupt masks
* More keyboard
Strange, (irreproducible?) SysERRORs on SH3?
- Happened when dealing with overclock and after a transfer
- SysERROR when add-in fully returns, nothing during execution
- Affects all add-ins of the calculator!
* Make sure interrupt for extra timers is masked when you ctx_restore to avoid
interrupts
* For modules, use #define TMU ((tmu_t *)0xdeadbeef)) instead of tmu_t *TMU
* Don't hardcode fx-cg50 stack address in fxcg50.ld for Prizm compatibility
* Implement the gint_switch()
* File management
* Drawing functions, bopti and tales
* Gray engine
* Overclock
* Add a driver init function to the r61524 driver.
* Finish the bootlog and use the keyboard to control it.
* Save driver contexts on the stack in gint_pause().
* Write the core memory functions.
- Allow arbitrary code in gint_pause() instead of just main menu?
- Dynamically detect P1 static RAM in TLB for runtime Prizm compatibility.
* Use a solid API for boot-time printing (or just use fxlib)
- Use qdiv10() (there should be no __sdivsi3 in gint)
(bootlog, timer_delay(), getkey_repeat(), int2bcd())
* Load an exception handler and a TLB miss handler.
# Before compatibility
Bugs to fix:
- Alignment of ALL .data / .rodata files is required to ensure converted data
is properly aligned
- Unpreditcable crap happens when more than 10 keys are pressed simultaneously
- Ensure heap data is freed when a task-switch results in leaving the app
is properly aligned -> Ok using ALIGN(4)
- Ensure heap data is freed when a task-switch results in leaving the app (?)
Things to do before 1.0:
- bopti: Test partial transparency
- demo: Try 284x124 at (-60, -28) (all disadvantages)
- perf: Try 284x124 at (-60, -28) (all disadvantages)
- project: Check size of *all* library structures
- project: Clean headers that have some internal definitions
- project: Get rid of 7705.h (keyboard) and 7305.h (keyboard, gint)
- time: Compute CLOCKS_PER_SEC
Things to do later:
@ -17,12 +63,8 @@ Things to do later:
- clock: Only measure if requires as option, otherwise trust {FTune}
- clock: Handle overclock (relaunch clocks when overclocking)
- clock: Split code into several files, change clock_config_t type
- core: Change interrupt priority using the gint API
- core: Register more interrupts (and understand their parameters)
- core: Remove redundant code linked to environment saves
- core: Review interrupt system (again) - this one is too slow
- display: Try to make this module lighter (lots of code in text section)
- errno: Introduce errno and use it more or less everywhere
- esper: Cleaner playback, synthesizing
- events: Allow customization of keyboard event system (option to return
| events with modifiers, etc)
@ -34,14 +76,10 @@ Things to do later:
- stdio: More serious formatted printing functions and headers
- string: Use cmp/str to implement memchr() (assembler examples)
- string: Do some tests for memcmp() and memcpy()
- string: Lighter functions?
- usb: Implement a driver
Things to investigate:
- Registers that may need to be saved within setjmp()
- Optimizing core/gint.c leads to raising of an illegal slot exception when
running the interrupt handler, although it ends on rte; lds.l @r15+, mach,
which is totally not an illegal slot.
Possibly useful modules:
- DMAC
@ -49,4 +87,3 @@ Possibly useful modules:
- TPU
- USB
- CMT on SH7305, WDT on SH7705
- ACD (SH7705 only)

278
configure vendored

@ -4,132 +4,170 @@
# Basic configuration
#
declare -A conf
# Target platform
conf_target=
target=
toolchain=
# Build options
prefix=
cflags=
# Behavior
conf[GINT_BOOT_LOG]=
conf[GINT_NO_SYSCALLS]=
cong[GINT_LAX]=
conf[GINT_EXTENDED_LIBC]=
conf[GINT_STATIC_GRAY]=
boot_log=
no_syscalls=
static_gray=
# Size limits
conf[ATEXIT_MAX]=16
conf[TIMER_SLOTS]=16
conf[EVENTS_QUEUE_SIZE]=64
atexit_max=
# Output files
output="config/Makefile.cfg"
output="Makefile.cfg"
#
# Help screen and output util
# Help screen
#
error="\e[31;1merror:\e[0m"
C_="$(echo -e '\e[30;1m')"
Cr="$(echo -e '\e[31;1m')"
Cg="$(echo -e '\e[32;1m')"
Cp="$(echo -e '\e[34;1m')"
C0="$(echo -e '\e[0m')"
help()
{
cat << EOF
cat << EOF
Configuration script for the gint library.
Usage: $0 [options...]
Platform settings (specify exactly one):
${Cg}-fx9860g$C0
Target platform is fx-9860G II: all monochrome models that support add-ins
or can be flashed to support them.
${Cg}-fxcg50$C0
Target platform is fx-CG 50; there is some compatibility with fx-CG 10/20.
Options that affect the behavior of the library $C_[${Cp}default$C_]$C0:
$Cr-boot-log $C_[${Cp}disabled$C_]$C0
Enable an on-screen log at startup if a key is kept pressed while launching
the add-in, allowing easy debug and crash diagnoses.
$Cr-no-syscalls $C_[${Cp}disabled$C_]$C0
Never use syscalls. Expect trouble with malloc() and the gray engine. Do
not trigger this switch unless you know what you are doing.
$Cr-lax $C_[${Cp}disabled$C_]$C0
Make more assumptions about functions parameters. This disables coordinate
checks in drawing functions. Be careful!
$Cr-extended-libc $C_[${Cp}disabled$C_]$C0
Enable specific C99 headers/features that are normally not required by
calculator programs. This may allow porting programs from other platforms.
$Cr-static-gray-engine $C_[${Cp}disabled$C_]$C0
Place the gray engine vram in static ram instead of using the heap. Always
use this option when using both the gray engine and -no-syscalls.
Options that customize size limits $C_[${Cp}default$C_]$C0:
$Cr-atexit-max$C0=${Cg}integer$C_ [${Cp}16$C_]$C0
Number of exit handlers that can be registered by atexit().
$Cr-timer-slots$C0=${Cg}integer$C_ [${Cp}16$C_]$C0
Number of virtual timers that may be registered at the same time.
$Cr-events-queue-size$C0=${Cg}integer$C_ [${Cp}64$C_]$C0
Number of events simultaneously stored in the event queue.
You should build out-of-tree by creating a build directory and configuring from
there.
Target selection:
--target=fx9860g|fxcg50
fx9860g covers all fx-9860G II-like monochromes models that support add-ins
or can be flashed with an OS that does. This includes SH3 and SH4 machines.
Default toolchain is 'sh3eb-elf'.
fxcg50 covers just the fx-CG 50; there is some unofficial compatibility with
fx-CG 10/20. All of these are SH4-only.
Default toolchain is 'sh4eb-nofpu-elf'.
Build options:
--toolchain=TRIPLET Build with a different toolchain
--prefix=PREFIX Install prefix (PREFIX/lib and PREFIX/include are used)
--cflags=FLAGS Additional compiler flags at end of command
Library options (disabled by default):
--boot-log Display a boot debug log at startup if a key is pressed
Used to investigate unstabilities.
--no-syscalls Cut off all syscalls (this will break things)
Only use this option if you have a good idea of which.
--static-gray Allocate gray VRAMs in static RAM instead of the heap
May help when --no-syscalls is on.
Size limits:
--atexit-max=NUM Number of exit handlers in atexit()'s array [16]
Deprecated options (to be removed):
-extended-libc Provide a few C99 headers (in the future, refer to the
newlib port by Memallox's for the standard library)
-timer-slots=<n> Number of virtual timer slots (this feature will be
moved to an independent library) [16]
-events-queue-size=<n>
Size of event queue (this mechanism is likely to
disappear in future versions) [64]
EOF
exit 0
exit 0
}
if [[ "$@" == "--help" ]]; then
help
exit 1
fi
if [[ -f make/Makefile ]]; then
echo "error: you should configure from a build directory, like this:" >&2
echo " mkdir build && cd build && ../configure [options..]" >&2
exit 1
fi
#
# Parsing arguments
#
fail=false
for arg; do case "$arg" in
-h | -? | --help) help;;
-fx9860g)
conf_target="FX9860G";;
-fxcg50)
conf_target="FXCG50";;
-boot-log) conf[GINT_BOOT_LOG]=true;;
-no-syscalls) conf[GINT_NO_SYSCALLS]=true;;
-lax) conf[GINT_LAX]=true;;
-extended-libc) conf[GINT_EXTENDED_LIBC]=true;;
-static-gray-engine) conf[GINT_STATIC_GRAY]=true;;
-atexit-max=*)
size=${arg#*=}
if [[ $size == +([0-9]) ]]; then
conf[ATEXIT_MAX]=$size
else echo -e "$error -atexit-max expects an integer value"
fail=true; fi;;
-timer-slots=*)
size=${arg#*=}
if [[ $size == +([0-9]) ]]; then
conf[TIMER_SLOTS]=$size
else echo -e "$error -timer-slots expects an integer value"
fail=true; fi;;
-events-queue-size=*)
size=${arg#*=}
if [[ $size == +([0-9]) ]]; then
conf[EVENTS_QUEUE_SIZE]=$size
else echo -e "$error -events-queue-size expects an integer"\
"value"
fail=true; fi;;
-atexit-max | -timer-slots | -events-queue-size)
echo -e "$error syntax for $arg is $arg=<integer-value>";;
*)
echo -e "$error unrecognized argument '$arg'"; fail=true;;
-h | -? | --help)
help;;
--target=*)
case ${arg#*=} in
"fx9860g")
target=fx9860g
toolchain=${toolchain:-sh3eb-elf};;
"fxcg50")
target=fxcg50
toolchain=${toolchain:-sh4eb-nofpu-elf};;
*)
echo "error: invalid target '$target'"
fail=true
esac;;
--prefix=*)
prefix=${arg#*=};;
--cflags=*)
cflags=${arg#*=};;
--boot-log)
boot_log=true;;
--no-syscalls)
no_syscalls=true;;
--static-gray)
static_gray=true;;
--atexit-max=*)
n=${arg#*=}
if [[ $n == +([0-9]) ]]; then
atexit_max=$n
else
echo -e "error: -atexit-max expects an integer value"
fail=true
fi;;
--atexit-max)
echo "error: '$arg' expects a value (see '$0 --help')";
fail=true;;
-extended-libc)
echo "warning: support for '-extended-libc' has been removed";;
-timer-slots=*)
echo "warning: support for '-timer-slots' has been removed";;
-events-queue-size=*)
echo "warning: support for '-events-queue-size' has been removed";;
esac; done
#
# Checking mandatory arguments
#
if [[ ! $conf_target ]]; then
echo -e "$error No target specified. See $0 --help."
fail=true;
if [[ -z "$target" ]]; then
echo "error: no target specified! (see '$0 --help')"
fail=true;
fi
# If no prefix is specified, install to the GCC's build folder
if [[ -z "$prefix" ]]; then
echo "No prefix specified, let's ask the compiler:"
echo " $toolchain-gcc --print-search-dirs | grep install | sed 's/install: //'"
inst=$($toolchain-gcc --print-search-dirs | grep install | sed 's/install: //')
if [[ $? != 0 ]]; then
echo "Call returned $?, giving up."
fi
echo "Got '$inst'".
if [[ ! -d $inst ]]; then
echo "Directory does not exist (or is not a directory), giving up."
fi
echo ""
prefix=$inst
fi
#
@ -138,32 +176,34 @@ fi
output_config()
{
[ ${conf_target} == "FX9860G" ] \
&& echo "cfg_target = fx" \
|| echo "cfg_target = cg"
echo -n "cfg_macros ="
echo -n " -D$conf_target"
mod=${target/98/fx}
echo "CONFIG.TARGET = ${mod:2:2}"
echo "CONFIG.TARGET.LONG = $target"
[[ $prefix ]] && echo "PREFIX = $prefix"
[[ $toolchain ]] && echo "CONFIG.TOOLCHAIN = $toolchain"
[[ $cflags ]] && echo "CONFIG.CFLAGS = $cflags"
echo -n "CONFIG.MACROS ="
echo -n " -D$(echo $target | tr 'a-z' 'A-Z')"
[[ "$boot_log" ]] && echo -n " -DGINT_BOOT_LOG"
[[ "$no_syscalls" ]] && echo -n " -DGINT_NO_SYSCALLS"
[[ "$static_gray" ]] && echo -n " -DGINT_STATIC_GRAY"
[[ "$atexit_max" ]] && echo -n " -DATEXIT_MAX=$atexit_max"
echo ""
}
[ "${conf[GINT_BOOT_LOG]}" ] && echo -n " -DGINT_BOOT_LOG"
[ "${conf[GINT_NO_SYSCALLS]}" ] && echo -n " -DGINT_NO_SYSCALLS"
[ "${conf[GINT_LAX]}" ] && echo -n " -DGINT_LAX"
[ "${conf[GINT_EXTENDED_LIBC]}" ] && echo -n " -DGINT_EXTENDED_LIBC"
[ "${conf[GINT_STATIC_GRAY]}" ] && echo -n " -DGINT_STATIC_GRAY"
if $fail; then
echo "note: output file $output has not been changed."
exit 1
fi
echo -n " -DATEXIT_MAX=${conf[ATEXIT_MAX]}"
echo -n " -DTIMER_SLOTS=${conf[TIMER_SLOTS]}"
echo -n " -DEVENTS_QUEUE_SIZE=${conf[EVENTS_QUEUE_SIZE]}"
output_config > $output
echo ""
src="Makefile"
dst="../make/Makefile"
[ "${conf[GINT_EXTENDED_LIBC]}" != "" ] && echo "cfg_ext = true"
}
[[ -L $src && $(readlink $src) == $dst ]] && rm $src
ln -s $dst $src
if $fail; then
echo "Output file $output has not been modified."
else
mkdir -p config
output_config > $output
echo "Configuration saved in $output, ready to make!"
fi
echo "Configuration saved in $output, ready to make!"

@ -130,7 +130,13 @@ SECTIONS
. = ALIGN(16);
} > ram AT> rom
_sdata = SIZEOF(.data);
/* Read-write data sub-aligned to 4 bytes (mainly from fxconv) */
.data.4 : SUBALIGN(4) {
*(.data.4)
. = ALIGN(16);
} > ram AT> rom
_sdata = SIZEOF(.data) + SIZEOF(.data.4);

@ -118,7 +118,13 @@ SECTIONS
. = ALIGN(16);
} > ram AT> rom
_sdata = SIZEOF(.data);
/* Read-write data sub-aligned to 4 bytes (mainly from fxconv) */
.data.4 : SUBALIGN(4) {
*(.data.4)
. = ALIGN(16);
} > ram AT> rom
_sdata = SIZEOF(.data) + SIZEOF(.data.4);

@ -1,5 +1,5 @@
//---
// gint:core:bootlog - Boot-time on-screen log for extreme debugging
// core:bootlog - Boot-time on-screen log for extreme debugging
//---
#ifndef GINT_CORE_BOOTLOG
@ -21,4 +21,11 @@ void bootlog_mapped(uint32_t rom, uint32_t ram);
handlers set up. */
void bootlog_kernel(void);
/* All these functions are enabled only if GINT_BOOT_LOG is defined */
#ifndef GINT_BOOT_LOG
#define bootlog_loaded(...)
#define bootlog_mapped(...)
#define bootlog_kernel(...)
#endif
#endif /* GINT_CORE_BOOTLOG */

@ -1,5 +1,5 @@
//---
// gint:core:memory - Core memory functions
// core:memory - Core memory functions
//
// These are the basic standard memory functions required by GCC.
//---

@ -1,23 +1,21 @@
//---
// gint:core:mmu - MMU-related definitions
// core:mmu - MMU-related definitions
//
// gint does not touch the MMU because the risk of interfering with the
// system is deemed too high. However, to ensure that the add-in runs
// properly, checks using read-only access to the MMU are performed.
// gint does not touch the MMU because the risk of permanently wreaking
// the system is deemed too high. However, to ensure that the add-in runs
// properly, checks using read-only accesses to the MMU are performed.
//---
#ifndef GINT_CORE_MMU
#define GINT_CORE_MMU
#include <defs/attributes.h>
#include <defs/types.h>
#include <gint/defs/attributes.h>
#include <gint/defs/types.h>
//---
// SH7705 TLB
//---
#ifdef FX9860G
/* tlb_addr_t - address part of a TLB entry */
typedef struct
{
@ -26,7 +24,7 @@ typedef struct
uint V :1;
uint ASID :8;
} PACKED(4) tlb_addr_t;
} GPACKED(4) tlb_addr_t;
/* tlb_data_t - data part of a TLB entry */
typedef struct
@ -43,7 +41,7 @@ typedef struct
uint SH :1;
uint :1;
} PACKED(4) tlb_data_t;
} GPACKED(4) tlb_data_t;
/* tlb_addr() - get the P4 address of a TLB address entry
@way TLB way (0..3)
@ -57,7 +55,7 @@ const tlb_addr_t *tlb_addr(uint way, uint E);
Returns a pointer to the entry. */
const tlb_data_t *tlb_data(uint way, uint E);
/* tlb_mapped_memort() - count amount of mapped memory
/* tlb_mapped_memory() - count amount of mapped memory
This function returns the amount of mapped text and data segment memory, in
bytes. The ranges are defined as follows:
ROM 00300000:512k
@ -68,8 +66,6 @@ const tlb_data_t *tlb_data(uint way, uint E);
@ram Pointer to amount of mapped RAM */
void tlb_mapped_memory(uint32_t *p_rom, uint32_t *p_ram);
#endif
//---
// SH7305 Unified TLB
//---
@ -82,7 +78,7 @@ typedef struct
uint V :1;
uint ASID :8;
} PACKED(4) utlb_addr_t;
} GPACKED(4) utlb_addr_t;
/* utlb_addr() - get the P4 address of a UTLB address entry
@E Entry number (should be in range 0..63)
@ -104,7 +100,7 @@ typedef struct
uint SH :1;
uint WT :1;
} PACKED(4) utlb_data_t;
} GPACKED(4) utlb_data_t;
/* utlb_data() - get the P4 address of a UTLB data entry
@E Entry number (should be in range 0..63)

@ -1,19 +1,19 @@
//---
// gint:core:setup - Installing and unloading the library
// core:setup - Installing and unloading the library
//---
#ifndef GINT_CORE_SETUP
#define GINT_CORE_SETUP
#include <defs/types.h>
#include <gint/defs/types.h>
/* Prototypes for the library management functions are in <gint/gint.h> */
/* gint_setvbr()
Changes the VBR address and the calls the configuration function while
interrupts are disabled. The configuration function must change either the
priority registers or the interrupt masks, and make sure that all the
interrupts that it leaves enabled are handled by the new VBR handlers.
Changes the VBR address and calls the configuration function while
interrupts are disabled. The configuration function must disable all
interrupts that the new handlers cannot handle, either by clearing the
priority registers or by setting the interrupt masks.
@vbr New VBR address
@configure Configuration function

@ -1,78 +0,0 @@
//---
// gint:defs:types - Type-related macros
//---
#ifndef GINT_DEFS_TYPES
#define GINT_DEFS_TYPES
#include <defs/attributes.h>
#include <stddef.h>
#include <stdint.h>
//---
// Const casts
//---
/* const_cast() - perform const casts
This is intended for initialization purposes only, like "final" in Java.
This macro is the most generic form without any type inference; using
const_cint() or const_cptr() may be more convenient for simple types */
#define const_cast(x, T) (*((T *)(&(x))))
/* const_cptr() - perform const casts on pointers */
#define const_cptr(x) (*((void **)(&(x))))
/* const_cint() - perform const casts on integers
This macro saves you from specifying the integral type that you're
manipulating, which may avoid errors if the type changes. It will only work
with the primitive types that are either mentioned in the following list or
aliased as one of the listed types.
This is to prevent unforeseen effects of tricks such as typeof(x + 0) that
promotes various small integers to ints */
#define const_cint(x) (*_Generic((x), \
char: (char *) (&(x)), \
unsigned char: (unsigned char *) (&(x)), \
short: (short *) (&(x)), \
unsigned short: (unsigned short *) (&(x)), \
int: (int *) (&(x)), \
unsigned int: (unsigned int *) (&(x)), \
long: (long *) (&(x)), \
unsigned long: (unsigned long *) (&(x)), \
long long: (long long *) (&(x)), \
unsigned long long: (unsigned long long *) (&(x)) \
))
//---
// Structure elements
//----
/* Fixed-width types for bit fields are entirely meaningless */
typedef unsigned int uint;
/* Giving a type to padding bytes is misguiding */
#define pad_nam2(c) _ ## c
#define pad_name(c) pad_nam2(c)
#define pad(bytes) uint8_t pad_name(__COUNTER__)[bytes]
/* byte_union() - union between an uint8_t 'byte' element and a bit field */
#define byte_union(name, fields) \
union { \
uint8_t byte; \
struct { fields } PACKED(1); \
} PACKED(1) name
/* word_union() - union between an uint16_t 'word' element and a bit field */
#define word_union(name, fields) \
union { \
uint16_t word; \
struct { fields } PACKED(2); \
} PACKED(2) name
/* lword_union() - union between an uint32_t 'lword' element and a bit field */
#define lword_union(name, fields) \
union { \
uint32_t lword; \
struct { fields } PACKED(4); \
} PACKED(4) name
#endif /* GINT_DEFS_TYPES */

@ -0,0 +1,30 @@
//---
// display:fx - Internal definitions for the display module on fx9860g
//---
#ifndef DISPLAY_FX
#define DISPLAY_FX
#include <gint/defs/types.h>
#include <gint/display.h>
/* masks() - compute the vram masks for a given rectangle
Since the VRAM is line-based with four uin32_t elements per row, we can
execute any operation on a rectangle by running it on each set of four
uint32_t elements.
This function calculates four uint32_t values and stores them in @mask. Each
of the 128 bits in this array represents a column of the screen, and the bit
of column c is 1 iff x1 <= c <= x2.
These masks can then be and-ed/or-ed/anything on the VRAM to draw.
@x1 @x2 Targeted screen range, horizontally (both included)
@masks Stores the result of the function (four uint32_t values) */
void masks(int x1, int x2, uint32_t *masks);
/* Font currently configured for text rendering */
extern font_t const * topti_font;
#endif /* DISPLAY_FX */

@ -5,8 +5,6 @@
#ifndef GINT_CLOCK
#define GINT_CLOCK
#include <defs/types.h>
//---
// Clock signals
//---
@ -59,7 +57,7 @@ const clock_frequency_t *clock_freq(void);
The function stops the processor until an interrupt is accepted; the
duration is not known in advance. This function should be used when the
add-in is idle, for instance while waiting for keyboard input. */
void sleep(void);
#define sleep() __asm__("sleep")
/* sleep_us() - sleep for a definite duration in microseconds

@ -5,37 +5,26 @@
#ifndef GINT_DEFS_ATTRIBUTES
#define GINT_DEFS_ATTRIBUTES
/* Generic attribute element */
#define ATTR(...) __attribute__((__VA_ARGS__))
/* Objects from specific sections */
#define SECTION(x) __attribute__((section(x)))
#define GSECTION(x) __attribute__((section(x)))
/* Objects from the .gint.data and .gint.bss sections */
#define GDATA __attribute__((section(".gint.data")))
#define GBSS __attribute__((section(".gint.bss")))
/* Additional sections that are only needed on SH3 */
#define GDATA3 __attribute__((section(".gint.data.sh3")))
#define GBSS3 __attribute__((section(".gint.bss.sh3")))
/* Initialization functions */
#define PRETEXT __attribute__((section(".pretext")))
/* Unused parameters or variables */
#define UNUSED __attribute__((unused))
#define GUNUSED __attribute__((unused))
/* Functions that *must* be inlined */
#define INLINE __attribute__((always_inline)) inline
/* Short static functions defined in header files */
#define HDRFUNC __attribute__((always_inline)) static inline
/* Constructors and destructors */
#define CTOR(x) __attribute__((constructor ((x) + 101))) PRETEXT
#define DTOR(x) __attribute__((destructor ((x) + 101)))
#define GINLINE __attribute__((always_inline)) inline
/* Aligned variables */
#define ALIGNED(x) __attribute__((aligned(x)))
#define GALIGNED(x) __attribute__((aligned(x)))
/* Packed structures. I require explicit alignment because if it's unspecified,
GCC cannot optimize access size, and reads to memory-mapped I/O with invalid
access sizes silently fail - honestly you don't want this to happen */
#define PACKED(x) __attribute__((packed, aligned(x)))
#define GPACKED(x) __attribute__((packed, aligned(x)))
#endif /* GINT_DEFS_ATTRIBUTES */

@ -0,0 +1,48 @@
//---
// gint:defs:types - Type definitions
//---
#ifndef GINT_DEFS_TYPES
#define GINT_DEFS_TYPES
#include <gint/defs/attributes.h>
/* For size_t, mainly */
#include <stddef.h>
/* For all fixed-width integer types */
#include <stdint.h>
/* Fixed-width types for bit fields are quite meaningless */
typedef unsigned int uint;
//---
// Structure elements
//----
/* Giving a type to padding bytes is misguiding, let's hide it in a macro */
#define pad_nam2(c) _ ## c
#define pad_name(c) pad_nam2(c)
#define pad(bytes) uint8_t pad_name(__COUNTER__)[bytes]
/* byte_union() - union between an uint8_t 'byte' element and a bit field */
#define byte_union(name, fields) \
union { \
uint8_t byte; \
struct { fields } GPACKED(1); \
} GPACKED(1) name
/* word_union() - union between an uint16_t 'word' element and a bit field */
#define word_union(name, fields) \
union { \
uint16_t word; \
struct { fields } GPACKED(2); \
} GPACKED(2) name
/* lword_union() - union between an uint32_t 'lword' element and a bit field */
#define lword_union(name, fields) \
union { \
uint32_t lword; \
struct { fields } GPACKED(4); \
} GPACKED(4) name
#endif /* GINT_DEFS_TYPES */

@ -0,0 +1,67 @@
//---
// gint:defs:util - Various utility macros
//---
/* min(), max() (without double evaluation) */
#define min(a, b) ({ \
__auto_type _a = (a); \
__auto_type _b = (b); \
_a < _b ? _a : _b; \
})
#define max(a, b) ({ \
__auto_type _a = (a); \
__auto_type _b = (b); \
_a > _b ? _a : _b; \
})
/* sgn() (without double evaluation) */
#define sgn(s) ({ \
__auto_type _s = (s); \
_s < 0 ? -1 : \
_s > 0 ? +1 : \
0; \
})
/* abs() (without double evaluation) */
#define abs(s) ({ \
__auto_type _s = (s); \
_s < 0 ? -s : s; \
})
/* swap() - exchange two variables of the same type */
#define swap(a, b) ({ \
__auto_type _tmp = (a); \
(a) = (b); \
(b) = _tmp; \
})
//---
// Const casts
//---
/* const_cast() - perform const casts
This is intended for initialization purposes only, like "final" in Java.
This macro is the most generic form without any type inference; using
const_cint() or const_cptr() may be more convenient for simple types */
#define const_cast(x, T) (*((T *)(&(x))))
/* const_cptr() - perform const casts on pointers */
#define const_cptr(x) (*((void **)(&(x))))
/* const_cint() - perform const casts on integers
This macro infers the integer type it's using, which may avoid errors when
types change during code maintenance. It only works on primitive types and
their aliases, this is on purpose to avoid integer coercion with tricks such
as typeof(x + 0). */
#define const_cint(x) (*_Generic((x), \
char: (char *) (&(x)), \
unsigned char: (unsigned char *) (&(x)), \
short: (short *) (&(x)), \
unsigned short: (unsigned short *) (&(x)), \
int: (int *) (&(x)), \
unsigned int: (unsigned int *) (&(x)), \
long: (long *) (&(x)), \
unsigned long: (unsigned long *) (&(x)), \
long long: (long long *) (&(x)), \
unsigned long long: (unsigned long long *) (&(x)) \
))

@ -0,0 +1,21 @@
//---
// gint:display-cg - fxcg50 rendering functions
//
// This module covers all 16-bit opaque rendering functions. For
// gamma-related functions, color composition, check out a color library.
//
//---
#ifndef GINT_DISPLAY_CG
#define GINT_DISPLAY_CG
#ifdef FXCG50
/* Screen dimensions on fxcg50 - never mind the borders, gint lets you use the
full surface! */
#define DWIDTH 396
#define DHEIGHT 224
#endif /* FXCG50 */
#endif /* GINT_DISPLAY_CG */

@ -11,16 +11,14 @@
#ifdef FX9860G
/* Screen dimensions on fx9860g */
#define DWIDTH 128
#define DHEIGHT 64
#include <gint/defs/types.h>
/* color_t - colors available for drawing
The following colors are defined by the library:
OPAQUE COLORS (override existing pixels)
white, black - the usual thing
light, dark - additional colors used by the gray engine
light, dark - intermediate colors used with the gray engine
OPERATORS (combine with existing pixels)
none - leaves unchanged
@ -69,10 +67,6 @@ void dclear(color_t color);
This functions applies a color or an operator to a rectangle defined by two
points (x1 y1) and (x2 y2). Both are included in the rectangle.
If GINT_LAX is defined, this function makes the following assumptions:
0 <= x1 < x2 <= 127
0 <= y1 < y2 <= 63
@x1 @y1 @x2 @y2 Bounding rectangle (drawn area).
@color Allowed colors: white, black, none, reverse */
void drect(int x1, int y1, int x2, int y2, color_t color);
@ -83,11 +77,10 @@ void drect(int x1, int y1, int x2, int y2, color_t color);
/* dpixel() - change a pixel's color
If the requested color is an operator, the result will depend on the current
color of the pixel.
If GINT_LAX is defined, this function makes the following assumptions:
0 <= x <= 127
0 <= y <= 63
color of the pixel. Setting single pixels is the slowest method to produce a
graphical result: all other functions for rendering lines, rectangles,
images or text use highly-optimized methods, so check them out first if you
care about performance.
@x @y Coordinates of the pixel to repaint
@color Allowed colors: white, black, none, reverse */
@ -98,16 +91,114 @@ void dpixel(int x, int y, color_t color);
that the affected pixels may not be exactly the same when using dline() and
Bdisp_DrawLineVRAM().
dline() has optimization facilities for horizontal and vertical lines.
dline() has optimization facilities for horizontal and vertical lines, but
it does not detect if your line doesn't fit in the screen. So drawing from
(-1e6,0) to (1e6,63) will work, but will be veeery slow.
If GINT_LAX is defined, this function makes the following assumptions:
0 <= x1 <= x2 <= 127
0 <= y1, y2 <= 63
@x1 @y1 @x2 @y2 End points of theline (both included).
@x1 @y1 @x2 @y2 End points of the line (both included).
@color Allowed colors: white, black, none, reverse */
void dline(int x1, int y1, int x2, int y2, color_t color);
//---
// Image rendering (bopti)
//---
/* image_t - image files encoded for bopti
This format is the result of encoding images for bopti with the fxSDK's
[fxconv] tool. The bopti routines can render it extremely fast, which makes
it preferable over plain bitmaps if the images are never edited. */
typedef struct
{
/* Image can only be rendered with the gray engine */
uint gray :1;
/* Left for future use */
uint :3;
/* Image profile (uniquely identifies a rendering function) */
uint profile :4;
/* Full width, in pixels */
uint width :12;
/* Full height, in pixels */
uint height :12;
/* Raw layer data */
uint8_t data[];
} GPACKED(4) image_t;
//---
// Text rendering (topti)
//---
/* font_t - font data encoded for topti */
typedef struct
{
/* Length of font name (not NUL-terminated) */
uint title :5;
/* Font shape flags */