Compare commits

...

11 Commits
master ... dev

  1. 2
      CMakeLists.txt
  2. 3
      include/gint/bfile.h
  3. 30
      include/gint/display-cg.h
  4. 15
      include/gint/drivers/keydev.h
  5. 19
      include/gint/gint.h
  6. 8
      include/gint/hardware.h
  7. 2
      include/gint/keyboard.h
  8. 4
      include/gint/keycodes.h
  9. 2
      src/dma/dma.c
  10. 2
      src/fs/fugue/fugue.h
  11. 38
      src/fs/fugue/fugue_rename.c
  12. 8
      src/fs/rename.c
  13. 3
      src/kernel/hardware.c
  14. 2
      src/kernel/inth.S
  15. 10
      src/kernel/osmenu.c
  16. 40
      src/kernel/start.c
  17. 3
      src/kernel/syscalls.S
  18. 5
      src/keysc/getkey.c
  19. 48
      src/keysc/iokbd.c
  20. 10
      src/keysc/keydev.c
  21. 12
      src/t6k11/t6k11.c

@ -50,6 +50,7 @@ set(SOURCES_COMMON
src/fs/pwrite.c
src/fs/read.c
src/fs/readdir.c
src/fs/rename.c
src/fs/rewinddir.c
src/fs/rmdir.c
src/fs/seekdir.c
@ -64,6 +65,7 @@ set(SOURCES_COMMON
src/fs/fugue/fugue_open.c
src/fs/fugue/fugue_mkdir.c
src/fs/fugue/fugue_stat.c
src/fs/fugue/fugue_rename.c
src/fs/fugue/fugue_rmdir.c
src/fs/fugue/fugue_unlink.c
src/fs/fugue/util.c

@ -73,6 +73,9 @@ extern "C" {
/* Remove a file or folder (also works if the entry does not exist). */
int BFile_Remove(uint16_t const *path);
/* Rename a file (can move folders; Fugue only). */
int BFile_Rename(uint16_t const *oldpath, uint16_t const *newpath);
#define BFile_File 1
#define BFile_Folder 5

@ -70,31 +70,27 @@ typedef image_t bopti_image_t;
// Video RAM management
//---
/* dsetvram() - Control video RAM address and triple buffering
/* dsetvram(): Control video RAM address and triple buffering
Normal rendering under gint uses double-buffering: there is one image
displayed on the screen and one in memory, in a region called the video RAM
(VRAM). The application draws frames in the VRAM then sends them to the
screen only when they are finished, using dupdate().
On fxcg50, the performance bottleneck is almost always the graphical
rendering (especially in games) because the high amount of data, 173 kB per
frame in full-resolution, makes graphics manipulation computationally
expensive. The transfer also takes about 10 ms in itself.
On fx-CG, sending frames with dupdate() is a common bottleneck because it
takes about 11 ms. Fortunately, while the DMA is sending the frame to the
display, the CPU is available to do work in parallel. This function sets up
triple buffering (ie. a second VRAM) so that the CPU can start working on
the next frame while the DMA is sending the current one.
Since gint transfers data to the screen using the DMA, it is possible to run
the application while the finished frame is being transferred. However,
writing to the VRAM during this period will cause display artifacts since
the VRAM it is still being read by the DMA.
However, experience shows minimal performance improvements, because writing
to main RAM does not parallelize with DMA transfers. Since gint 2.8, this
is no longer the default, and the memory for the extra VRAM is instead
available via malloc().
The solution to this is to use triple-buffering with the display and two
VRAMs that are alternately being written to while the other is being
transferred. The VRAM switching is handled by dupdate() and is activated
whenever two VRAMs are configured.
By default gint uses triple buffering with two VRAMs in the system stack.
VRAMs must be contiguous, 32-aligned, (2*396*224)-byte buffers.
VRAMs must be contiguous, 32-aligned, (2*396*224)-byte buffers with 32 bytes
of extra data on each side (ie. 32 bytes into a 32-aligned buffer of size
177472).
@main Main VRAM area, used alone if [secondary] is NULL
@secondary Additional VRAM area, enables triple buffering if non-NULL */

@ -135,9 +135,9 @@ typedef struct {
is useful for demo/replays that input events without the physical keyboard,
and a couple of corner uses like control over USB.
The keyboard device has built-in event transformations, which modifty the
The keyboard device has built-in event transformations, which modify the
stream of events by adding information, combining modifiers, and removing
undesired events. Because the event transformation reky on the current state
undesired events. Because the event transformation rely on the current state
of the keyboard, they must be run by the driver whenever events are read, so
they are tied to the device.
@ -173,7 +173,7 @@ typedef struct {
/* Candidate key for repeats (or 0 if no key is candidate yet) */
int rep_key;
/* Number of repeats alreay sent */
/* Number of repeats already sent */
int rep_count;
/* Time since key was first pressed (us) */
int rep_time;
@ -181,7 +181,7 @@ typedef struct {
int rep_delay;
/* Latest state of keys we are aware of. At every processing step, the
different between this and the fresh information is queued and this
difference between this and the fresh information is queued and this
is updated. state_now is identical to the real state obtained from
the device unless earlier events failed to be queued, in which case
a difference is maintained so they will be reconsidered later. */
@ -284,8 +284,11 @@ void keydev_set_transform(keydev_t *d, keydev_transform_t tr);
@next_us Delay between subsequent repeats (microseconds) */
void keydev_set_standard_repeats(keydev_t *d, int first_us, int next_us);
/* keydev_read(): Retrieve the next transformed event */
key_event_t keydev_read(keydev_t *d);
/* keydev_read(): Retrieve the next transformed event
If there is no event, returns an event with type KEYEV_NONE, unless
[wait=true], in which case waits for an event to occur or *timeout to
become non-zero (if timeout is not NULL), whichever comes first. */
key_event_t keydev_read(keydev_t *d, bool wait, volatile int *timeout);
#ifdef __cplusplus
}

@ -59,14 +59,23 @@ void gint_world_sync(void);
call to getkey(), but can also be called manually. */
void gint_osmenu(void);
/* gint_osmenu_native(): Like gint_osmenu() without the world switch
This is a replacement for gint_osmenu() which can be used when the current
kernel is already the native OS kernel. */
void gint_osmenu_native(void);
/* gint_setrestart(): Set whether to restart the add-in after exiting
An add-in that reaches the end of its code exits. On the calculator, except
using OS-dependent settings, it cannot be started again unless another
application is launched first.
An add-in that returns from its main() function automatically exits to the
OS' main menu. However, when this happens the OS does not allow the add-in
to be restarted unless another add-in is launched first. (This is because
the OS tries to *resume* the current add-in, which then proceeds to exit
again immediately.)
This setting allows the add-in to restart by calling gint_osmenu() instead
of exiting. This can give a proper illusion of restarting if used correctly.
This function enables a gint trick where after main() returns the add-in
will invoke the main menu with gint_osmenu() rather than exiting. If the
add-in is selected again, gint will jump back to the entry point, creating
the illusion that the add-in exited and was then restarted.
@restart 0 to exit, 1 to restart by using gint_osmenu() */
void gint_setrestart(int restart);

@ -45,6 +45,12 @@ void hw_detect(void);
#define isSH4() (!isSH3())
#endif
#if defined(FX9860G)
#define isSlim() (gint[HWCALC] == HWCALC_FX9860G_SLIM)
#else
#define isSlim() 0
#endif
#ifdef FXCG50
#define isSH3() 0
#define isSH4() 1
@ -105,6 +111,8 @@ void hw_detect(void);
#define HWCALC_FXCG50 5
/* fx-CG 50 emulator, hardcoded in kernel/inth.S */
#define HWCALC_FXCG_MANAGER 6
/* fx-9860G Slim, SH-3-based fx-9860G with hardware differences */
#define HWCALC_FX9860G_SLIM 7
/*
** Keyboard

@ -207,7 +207,7 @@ enum {
/* Enable modifiers keys */
GETKEY_MOD_SHIFT = 0x01,
GETKEY_MOD_ALPHA = 0x02,
/* SHIFT + OPTN toggles backlight (requires GETKEY_MOD_SHIFT) */
/* SHIFT + OPTN (requires GETKEY_MOD_SHIFT) or LIGHT toggles backlight */
GETKEY_BACKLIGHT = 0x04,
/* MENU triggers a task switch and displays the main menu */
GETKEY_MENU = 0x08,

@ -75,6 +75,10 @@ enum {
of the matrix one could use a ghosting effect to boot the calc. */
KEY_ACON = 0x07,
/* Virtual key codes */
KEY_HELP = 0x20, /* fx-9860G Slim: 0x75 */
KEY_LIGHT = 0x10, /* fx-9860G Slim: 0x76 */
/* Key aliases (handle with care =D) */
KEY_X2 = KEY_SQUARE,
KEY_CARET = KEY_POWER,

@ -178,7 +178,7 @@ static void dma_channel_wait(int channel, bool foreign)
if(!ch) return;
/* If interrupts are disabled or we don't own the device, spin-wait by
checking either for TE to be set (Transfere Ended) or DE to be gone
checking either for TE to be set (Transfer Ended) or DE to be gone
(channel disabled).
There are definitely race conditions if the DMA is restarted between

@ -25,6 +25,8 @@ int fugue_open(char const *path, int flags, mode_t mode);
int fugue_unlink(char const *path);
int fugue_rename(char const *oldpath, char const *newpath);
int fugue_mkdir(char const *path, mode_t mode);
int fugue_rmdir(char const *path);

@ -0,0 +1,38 @@
#include <gint/hardware.h>
#include <gint/bfile.h>
#include <gint/fs.h>
#include <errno.h>
#include <sys/stat.h>
#include "util.h"
int fugue_rename(char const *oldpath, char const *newpath)
{
ENOTSUP_IF_NOT_FUGUE(-1);
int rc = -1;
uint16_t *fcpath_1 = NULL;
uint16_t *fcpath_2 = NULL;
fcpath_1 = fs_path_normalize_fc(oldpath);
if(!fcpath_1) {
errno = ENOMEM;
goto end;
}
fcpath_2 = fs_path_normalize_fc(newpath);
if(!fcpath_2) {
errno = ENOMEM;
goto end;
}
rc = BFile_Rename(fcpath_1, fcpath_2);
if(rc < 0) {
errno = bfile_error_to_errno(rc);
rc = -1;
}
else rc = 0;
end:
free(fcpath_1);
free(fcpath_2);
return rc;
}

@ -0,0 +1,8 @@
#include <stdio.h>
#include "fugue/fugue.h"
int rename(char const *oldpath, char const *newpath)
{
/* Standard rename() is the Fugue filesystem only */
return fugue_rename(oldpath, newpath);
}

@ -69,7 +69,8 @@ void hw_detect(void)
gint[HWCALC] = HWCALC_FX9860G_SH4;
if(gint[HWMPU] == HWMPU_SH7337 || gint[HWMPU] == HWMPU_SH7355)
{
gint[HWCALC] = HWCALC_FX9860G_SH3;
gint[HWCALC] = (SH7705_PFC.PEDR & 0x08) ? HWCALC_FX9860G_SH3 :
HWCALC_FX9860G_SLIM;
}
/* Tell Graph 35+E II from OS version (this is accurate unless someone

@ -102,7 +102,7 @@ _gint_inth_7305:
#ifdef FX9860G
/* SH7705-TYPE INTERRUT HANDLER ENTRY - 56 BYTES */
/* SH7705-TYPE INTERRUPT HANDLER ENTRY - 56 BYTES */
_gint_inth_7705:
/* Save caller-saved registers as before */

@ -1,5 +1,6 @@
#include <gint/gint.h>
#include <gint/display.h>
#include <gint/hardware.h>
#include <string.h>
@ -17,13 +18,16 @@ static int __osmenu_id;
static void __osmenu_handler(void)
{
__PutKeyCode(0x04, 0x09, 0);
if(isSlim())
__PutKeyCode(0x07, 0x0A, 0);
else
__PutKeyCode(0x04, 0x09, 0);
__Timer_Stop(__osmenu_id);
__Timer_Deinstall(__osmenu_id);
}
static void __osmenu(void)
void gint_osmenu_native(void)
{
__ClearKeyBuffer();
@ -70,5 +74,5 @@ static void __osmenu(void)
/* gint_osmenu() - switch out of gint and call the calculator's main menu */
void gint_osmenu(void)
{
gint_world_switch(GINT_CALL(__osmenu));
gint_world_switch(GINT_CALL(gint_osmenu_native));
}

@ -94,11 +94,7 @@ static void callarray(void (**f)(void), void (**l)(void))
while(f < l) (*(*f++))();
}
/* start(): Where it all starts
Returns a status code. Invoking main menu is better than returning, see
gint_setrestart() for that. */
GSECTION(".text.entry")
int start(int isappli, int optnum)
static int start2(int isappli, int optnum)
{
/* We are currently in a dynamic userspace mapping of an add-in run
from the storage memory. We are running in privileged mode with one
@ -179,20 +175,14 @@ int start(int isappli, int optnum)
hosted user application, which has its own constructors and
destructors to work with. */
while(1)
{
/* Here, we use exit() to allow the standard library to do
what it wants in exit() after main() finishes executing */
if(!setjmp(gint_exitbuf)) {
callarray(&bctors, &ectors);
exit(main(isappli, optnum));
}
else {
callarray(&bdtors, &edtors);
}
if(!gint_restart) break;
gint_osmenu();
/* Here, we use exit() to allow the standard library to do
what it wants in exit() after main() finishes executing */
if(!setjmp(gint_exitbuf)) {
callarray(&bctors, &ectors);
exit(main(isappli, optnum));
}
else {
callarray(&bdtors, &edtors);
}
/* Before leaving the application, we need to clean everything we
@ -206,6 +196,18 @@ int start(int isappli, int optnum)
return gint_exitcode;
}
GSECTION(".text.entry")
int start(int isappli, int optnum)
{
int rc;
while(1) {
rc = start2(isappli, optnum);
if(!gint_restart) break;
gint_osmenu_native();
}
return rc;
}
/* Standard _Exit, used by the fxlibc exit() to leave control */
void _Exit(int rc)
{

@ -19,6 +19,7 @@
/* Bfile driver */
.global _BFile_Remove
.global _BFile_Rename
.global _BFile_Create
.global _BFile_Open
.global _BFile_Close
@ -131,6 +132,8 @@ ___realloc:
_BFile_Remove:
syscall(0x1db4)
_BFile_Rename:
syscall(0x1db3)
_BFile_Create:
syscall(0x1dae)
_BFile_Open:

@ -35,7 +35,7 @@ key_event_t getkey_opt(int opt, volatile int *timeout)
while(1)
{
e = keydev_read(d);
e = keydev_read(d, true, timeout);
if(e.type == KEYEV_NONE && timeout && *timeout) break;
/* Skip repeat events that are not enabled by options */
@ -51,7 +51,8 @@ key_event_t getkey_opt(int opt, volatile int *timeout)
#ifdef FX9860G
/* Backlight toggle */
if((opt & GETKEY_BACKLIGHT) && e.type == KEYEV_DOWN &&
e.key == KEY_OPTN && e.shift && !e.alpha)
((e.key == KEY_LIGHT) ||
(e.key == KEY_OPTN && e.shift && !e.alpha)))
{
t6k11_backlight(-1);
continue;

@ -4,6 +4,7 @@
#include <gint/defs/types.h>
#include <gint/mpu/pfc.h>
#include <gint/hardware.h>
/* This file is SH7705-only. */
#ifdef FX9860G
@ -111,12 +112,57 @@ uint8_t iokbd_row(int row)
return input;
}
static const uint16_t SLIM_SC[] = {
0x0940, 0x0920, 0x0910, 0x0908, 0x0904, 0x0902,
0x0840, 0x0820, 0x0810, 0x0808,
0x0740, 0x0720, 0x0710, 0x0708, 0x0704, 0x0702,
0x0640, 0x0620, 0x0610, 0x0608, 0x0604, 0x0602,
0x0540, 0x0520, 0x0510, 0x0508, 0x0504, 0x0502,
0x0440, 0x0420, 0x0410, 0x0408, 0x0404, 0x0402,
0x0340, 0x0320, 0x0310, 0x0308, 0x0304, 0x0302,
0x0240, 0x0220, 0x0210, 0x0208, 0x0204, 0x0202,
0x0101,
0x0020, 0x0010, 0x0008, 0x0004, 0x0002
};
#define SCANCODE_COUNT (sizeof(SLIM_SC) / sizeof(uint16_t))
static const uint16_t SLIM_TR[] = {
0x0940, 0x0620, 0x0720, 0x0710, 0x0804, 0x0802,
0x0808, 0x0640, 0x0840, 0x0740,
0x0910, 0x0608, 0x0502, 0x0810, 0x0280, 0x0180,
0x0920, 0x0610, 0x0504, 0x0820, 0x0704, 0x0702,
0x0904, 0x0602, 0x0420, 0x0320, 0x0220, 0x0120,
0x0908, 0x0604, 0x0440, 0x0340, 0x0240, 0x0140,
0x0708, 0x0520, 0x0408, 0x0308, 0x0208, 0x0108,
0x0902, 0x0540, 0x0410, 0x0310, 0x0210, 0x0110,
0x0001,
0x0510, 0x0508, 0x0304, 0x0104, 0x0204
};
/* iokbd_scan() - scan ports A/B/M to generate 12 rows of key data */
void iokbd_scan(uint8_t *scan)
{
/* Scan each row independently; the gain from scanning them altogether
/* Scan each row independently; the gain from scanning them all together
is probably not worth it */
for(int i = 0; i < 12; i++) scan[i] = iokbd_row(i);
/* Translate fx-9860G Slim scancodes to standard scancodes */
if(isSlim())
{
uint8_t slim_scan[12];
for(uint i = 0; i < 10; i++)
{
slim_scan[i] = scan[i];
scan[i] = 0x00;
}
for(uint i = 0; i < SCANCODE_COUNT; ++i)
{
if(slim_scan[SLIM_SC[i] >> 8] & (SLIM_SC[i] & 0xFF))
scan[SLIM_TR[i] >> 8] |= (SLIM_TR[i] & 0xFF);
}
}
}
#endif /* FX9860G */

@ -3,6 +3,7 @@
//---
#include <gint/keyboard.h>
#include <gint/cpu.h>
#include <gint/drivers/keydev.h>
#include <gint/defs/types.h>
#include <gint/defs/util.h>
@ -239,7 +240,7 @@ void keydev_set_standard_repeats(keydev_t *d, int first, int next)
}
/* keydev_read(): Retrieve the next transformed event */
key_event_t keydev_read(keydev_t *d)
key_event_t keydev_read(keydev_t *d, bool wait, volatile int *timeout)
{
#define opt(NAME) (d->tr.enabled & KEYDEV_TR_ ## NAME)
key_event_t e;
@ -248,7 +249,12 @@ key_event_t keydev_read(keydev_t *d)
{
e = keydev_unqueue_event(d);
if(e.type == KEYEV_NONE)
return e;
{
if(!wait || (timeout && *timeout))
return e;
sleep();
continue;
}
int k = e.key;
e.mod = (opt(ALL_MODS) != 0);

@ -168,8 +168,16 @@ void t6k11_backlight(int setting)
TODO: Document the PFC to remove these addresses */
if(isSH3())
{
port = (void *)0xa400012c;
mask = 0x80;
if(isSlim())
{
port = (void *)0xa4000126;
mask = 0x20;
}
else
{
port = (void *)0xa400012c;
mask = 0x80;
}
}
else
{

Loading…
Cancel
Save