From ee511ccde5cfbe5f880996739438334ee2fee83b Mon Sep 17 00:00:00 2001 From: Lailouezzz Date: Sun, 29 Dec 2019 22:28:26 +0100 Subject: [PATCH] First commit : p7utils-v3.0.0 --- AUTHORS.md | 2 + LICENSE.md | 336 +++++ Makefile | 243 ++++ Makefile.msg | 58 + Makefile.vars | 155 +++ README.md | 53 + configure | 190 +++ doc/mcsfile.1.txt | 36 + doc/p7.1.txt | 85 ++ doc/p7os.1.txt | 60 + doc/p7screen.1.txt | 43 + src/mcsfile/args.c | 93 ++ src/mcsfile/main.c | 53 + src/mcsfile/main.h | 27 + src/mcsfile/print.c | 130 ++ src/mcsfile/vars.mk | 4 + src/p7/args.c | 348 ++++++ src/p7/dump.c | 83 ++ src/p7/main.c | 304 +++++ src/p7/main.h | 47 + src/p7/vars.mk | 3 + src/p7os/args.c | 220 ++++ src/p7os/cake.exe/.gitignore | 6 + src/p7os/cake.exe/.gitmodules | 3 + src/p7os/cake.exe/LICENSE.md | 336 +++++ src/p7os/cake.exe/Makefile | 136 ++ src/p7os/cake.exe/Makefile.msg | 63 + src/p7os/cake.exe/Makefile.vars | 81 ++ src/p7os/cake.exe/README.md | 40 + src/p7os/cake.exe/TODO.md | 8 + src/p7os/cake.exe/configure | 97 ++ src/p7os/cake.exe/include/main.h | 10 + src/p7os/cake.exe/libgint/.gitignore | 20 + src/p7os/cake.exe/libgint/Makefile | 210 ++++ src/p7os/cake.exe/libgint/README.md | 72 ++ src/p7os/cake.exe/libgint/TODO | 33 + src/p7os/cake.exe/libgint/configure | 78 ++ src/p7os/cake.exe/libgint/demo/gintdemo.c | 531 ++++++++ src/p7os/cake.exe/libgint/demo/gintdemo.h | 114 ++ src/p7os/cake.exe/libgint/demo/gintdemo.ld | 110 ++ src/p7os/cake.exe/libgint/demo/icon.bmp | Bin 0 -> 1870 bytes .../libgint/demo/resources/bopti_thumbs.bmp | Bin 0 -> 1250 bytes .../libgint/demo/resources/clock_7305.bmp | Bin 0 -> 12410 bytes .../libgint/demo/resources/clock_7705.bmp | Bin 0 -> 12410 bytes .../libgint/demo/resources/clock_chars.bmp | Bin 0 -> 1082 bytes .../libgint/demo/resources/font_modern.bmp | Bin 0 -> 24698 bytes .../libgint/demo/resources/isometric.bmp | Bin 0 -> 4134 bytes .../cake.exe/libgint/demo/resources/items.bmp | Bin 0 -> 99322 bytes .../libgint/demo/resources/opt_bitmap.bmp | Bin 0 -> 3194 bytes .../libgint/demo/resources/opt_gray.bmp | Bin 0 -> 3194 bytes .../libgint/demo/resources/opt_menu.bmp | Bin 0 -> 3194 bytes .../libgint/demo/resources/opt_rtc.bmp | Bin 0 -> 20474 bytes .../libgint/demo/resources/opt_tales.bmp | Bin 0 -> 3194 bytes .../libgint/demo/resources/opt_timer.bmp | Bin 0 -> 3194 bytes .../libgint/demo/resources/rtc_segments.bmp | Bin 0 -> 6962 bytes .../libgint/demo/resources/screen.bmp | Bin 0 -> 32906 bytes .../libgint/demo/resources/sprites.bmp | Bin 0 -> 8850 bytes .../libgint/demo/resources/swords.bmp | Bin 0 -> 5770 bytes .../cake.exe/libgint/demo/resources/zelda.bmp | Bin 0 -> 72922 bytes src/p7os/cake.exe/libgint/demo/test_bopti.c | 221 ++++ src/p7os/cake.exe/libgint/demo/test_gray.c | 102 ++ .../cake.exe/libgint/demo/test_keyboard.c | 82 ++ src/p7os/cake.exe/libgint/demo/test_rtc.c | 262 ++++ src/p7os/cake.exe/libgint/demo/test_tales.c | 158 +++ src/p7os/cake.exe/libgint/demo/test_timer.c | 272 ++++ src/p7os/cake.exe/libgint/doc/bopti.md | 306 +++++ src/p7os/cake.exe/libgint/include/7305.h | 673 ++++++++++ src/p7os/cake.exe/libgint/include/7705.h | 1099 +++++++++++++++++ src/p7os/cake.exe/libgint/include/alloca.h | 23 + src/p7os/cake.exe/libgint/include/clock.h | 128 ++ src/p7os/cake.exe/libgint/include/ctype.h | 35 + src/p7os/cake.exe/libgint/include/display.h | 161 +++ src/p7os/cake.exe/libgint/include/events.h | 84 ++ src/p7os/cake.exe/libgint/include/gint.h | 192 +++ src/p7os/cake.exe/libgint/include/gray.h | 160 +++ .../libgint/include/internals/bopti.h | 160 +++ .../libgint/include/internals/display.h | 56 + .../libgint/include/internals/events.h | 19 + .../cake.exe/libgint/include/internals/gint.h | 30 + .../libgint/include/internals/keyboard.h | 39 + .../cake.exe/libgint/include/internals/mmu.h | 21 + .../cake.exe/libgint/include/internals/rtc.h | 141 +++ .../libgint/include/internals/stdio.h | 32 + .../libgint/include/internals/tales.h | 55 + .../cake.exe/libgint/include/internals/time.h | 16 + .../libgint/include/internals/timer.h | 48 + src/p7os/cake.exe/libgint/include/keyboard.h | 303 +++++ src/p7os/cake.exe/libgint/include/mpu.h | 76 ++ src/p7os/cake.exe/libgint/include/rtc.h | 121 ++ src/p7os/cake.exe/libgint/include/screen.h | 23 + src/p7os/cake.exe/libgint/include/setjmp.h | 35 + src/p7os/cake.exe/libgint/include/stdio.h | 44 + src/p7os/cake.exe/libgint/include/stdlib.h | 149 +++ src/p7os/cake.exe/libgint/include/string.h | 63 + src/p7os/cake.exe/libgint/include/tales.h | 123 ++ src/p7os/cake.exe/libgint/include/time.h | 126 ++ src/p7os/cake.exe/libgint/include/timer.h | 89 ++ .../libgint/src/bopti/bopti_internals.c | 329 +++++ src/p7os/cake.exe/libgint/src/bopti/dimage.c | 57 + .../cake.exe/libgint/src/bopti/dimage_part.c | 65 + src/p7os/cake.exe/libgint/src/bopti/gimage.c | 57 + .../cake.exe/libgint/src/bopti/gimage_part.c | 85 ++ src/p7os/cake.exe/libgint/src/clock/clock.c | 288 +++++ src/p7os/cake.exe/libgint/src/core/crt0.c | 168 +++ src/p7os/cake.exe/libgint/src/core/gint.c | 285 +++++ src/p7os/cake.exe/libgint/src/core/gint_str.c | 37 + src/p7os/cake.exe/libgint/src/core/gint_vbr.s | 66 + src/p7os/cake.exe/libgint/src/core/syscalls.s | 41 + .../libgint/src/display/adjustRectangle.c | 29 + .../cake.exe/libgint/src/display/dclear.c | 12 + .../libgint/src/display/dclear_area.c | 21 + .../libgint/src/display/display_vram.c | 43 + src/p7os/cake.exe/libgint/src/display/dline.c | 116 ++ .../cake.exe/libgint/src/display/dpixel.c | 32 + .../libgint/src/display/dreverse_area.c | 21 + .../cake.exe/libgint/src/display/dupdate.c | 14 + .../libgint/src/display/font_system.bmp | Bin 0 -> 32762 bytes .../cake.exe/libgint/src/display/getMasks.c | 33 + .../cake.exe/libgint/src/events/event_get.c | 38 + .../cake.exe/libgint/src/events/event_push.c | 26 + src/p7os/cake.exe/libgint/src/gray/gclear.c | 14 + .../cake.exe/libgint/src/gray/gclear_area.c | 15 + src/p7os/cake.exe/libgint/src/gray/gline.c | 24 + src/p7os/cake.exe/libgint/src/gray/gpixel.c | 47 + .../cake.exe/libgint/src/gray/gray_engine.c | 157 +++ .../cake.exe/libgint/src/gray/greverse_area.c | 15 + .../libgint/src/keyboard/getPressedKey.c | 24 + .../libgint/src/keyboard/getPressedKeys.c | 54 + .../cake.exe/libgint/src/keyboard/getkey.c | 131 ++ .../libgint/src/keyboard/keyboard_config.c | 20 + .../libgint/src/keyboard/keyboard_interrupt.c | 120 ++ .../libgint/src/keyboard/keyboard_misc.c | 25 + .../libgint/src/keyboard/keyboard_sh7305.c | 142 +++ .../libgint/src/keyboard/keyboard_sh7705.c | 135 ++ .../cake.exe/libgint/src/keyboard/keychar.c | 36 + .../cake.exe/libgint/src/keyboard/keyid.c | 17 + .../cake.exe/libgint/src/keyboard/keytype.c | 17 + .../libgint/src/keyboard/multigetkey.c | 46 + .../cake.exe/libgint/src/mmu/pseudoTLBInit.c | 29 + .../cake.exe/libgint/src/mpu/gint_sh7305.c | 219 ++++ .../cake.exe/libgint/src/mpu/gint_sh7705.c | 190 +++ src/p7os/cake.exe/libgint/src/mpu/mpu.c | 80 ++ .../cake.exe/libgint/src/rtc/rtc_callback.c | 151 +++ .../cake.exe/libgint/src/rtc/rtc_getTime.c | 38 + .../cake.exe/libgint/src/rtc/rtc_interrupt.c | 15 + .../cake.exe/libgint/src/rtc/rtc_setTime.c | 36 + .../libgint/src/screen/screen_display.c | 35 + src/p7os/cake.exe/libgint/src/setjmp/setjmp.s | 79 ++ .../cake.exe/libgint/src/stdio/snprintf.c | 20 + src/p7os/cake.exe/libgint/src/stdio/sprintf.c | 19 + .../cake.exe/libgint/src/stdio/stdio_format.c | 895 ++++++++++++++ .../cake.exe/libgint/src/stdio/vsnprintf.c | 15 + .../cake.exe/libgint/src/stdio/vsprintf.c | 15 + src/p7os/cake.exe/libgint/src/stdlib/calloc.c | 13 + src/p7os/cake.exe/libgint/src/stdlib/free.c | 20 + src/p7os/cake.exe/libgint/src/stdlib/malloc.c | 27 + .../cake.exe/libgint/src/stdlib/realloc.c | 25 + .../cake.exe/libgint/src/stdlib/stdlib_abs.c | 13 + .../cake.exe/libgint/src/stdlib/stdlib_div.c | 29 + .../cake.exe/libgint/src/stdlib/stdlib_rand.c | 14 + src/p7os/cake.exe/libgint/src/string/memcpy.c | 76 ++ src/p7os/cake.exe/libgint/src/string/memset.c | 48 + src/p7os/cake.exe/libgint/src/string/strchr.c | 11 + src/p7os/cake.exe/libgint/src/string/strcpy.c | 11 + src/p7os/cake.exe/libgint/src/string/strlen.c | 12 + .../cake.exe/libgint/src/string/strncpy.c | 20 + .../libgint/src/tales/tales_configuration.c | 15 + .../cake.exe/libgint/src/tales/tales_gray.c | 45 + .../libgint/src/tales/tales_internals.c | 278 +++++ .../cake.exe/libgint/src/tales/tales_print.c | 33 + .../cake.exe/libgint/src/tales/tales_text.c | 20 + src/p7os/cake.exe/libgint/src/time/asctime.c | 57 + src/p7os/cake.exe/libgint/src/time/ctime.c | 13 + src/p7os/cake.exe/libgint/src/time/gmtime.c | 45 + src/p7os/cake.exe/libgint/src/time/mktime.c | 68 + src/p7os/cake.exe/libgint/src/time/time.c | 29 + .../cake.exe/libgint/src/time/time_misc.c | 21 + .../cake.exe/libgint/src/time/time_util.c | 28 + .../cake.exe/libgint/src/timer/timer_get.c | 25 + .../libgint/src/timer/timer_interrupt.c | 28 + .../cake.exe/libgint/src/timer/timer_reload.c | 22 + .../cake.exe/libgint/src/timer/timer_start.c | 35 + .../cake.exe/libgint/src/timer/timer_stop.c | 18 + src/p7os/cake.exe/osupd.ld | 101 ++ src/p7os/cake.exe/src/endblock.c | 26 + src/p7os/cake.exe/src/main.c | 40 + src/p7os/main.c | 188 +++ src/p7os/main.h | 48 + src/p7os/prepare.c | 68 + src/p7os/vars.mk | 4 + src/p7screen/args.c | 135 ++ src/p7screen/main.c | 167 +++ src/p7screen/main.h | 20 + src/p7screen/vars.mk | 3 + 194 files changed, 16885 insertions(+) create mode 100644 AUTHORS.md create mode 100644 LICENSE.md create mode 100755 Makefile create mode 100755 Makefile.msg create mode 100755 Makefile.vars create mode 100644 README.md create mode 100755 configure create mode 100644 doc/mcsfile.1.txt create mode 100644 doc/p7.1.txt create mode 100644 doc/p7os.1.txt create mode 100644 doc/p7screen.1.txt create mode 100644 src/mcsfile/args.c create mode 100644 src/mcsfile/main.c create mode 100644 src/mcsfile/main.h create mode 100644 src/mcsfile/print.c create mode 100755 src/mcsfile/vars.mk create mode 100644 src/p7/args.c create mode 100644 src/p7/dump.c create mode 100644 src/p7/main.c create mode 100644 src/p7/main.h create mode 100755 src/p7/vars.mk create mode 100644 src/p7os/args.c create mode 100644 src/p7os/cake.exe/.gitignore create mode 100644 src/p7os/cake.exe/.gitmodules create mode 100644 src/p7os/cake.exe/LICENSE.md create mode 100755 src/p7os/cake.exe/Makefile create mode 100755 src/p7os/cake.exe/Makefile.msg create mode 100755 src/p7os/cake.exe/Makefile.vars create mode 100644 src/p7os/cake.exe/README.md create mode 100644 src/p7os/cake.exe/TODO.md create mode 100755 src/p7os/cake.exe/configure create mode 100644 src/p7os/cake.exe/include/main.h create mode 100644 src/p7os/cake.exe/libgint/.gitignore create mode 100755 src/p7os/cake.exe/libgint/Makefile create mode 100644 src/p7os/cake.exe/libgint/README.md create mode 100644 src/p7os/cake.exe/libgint/TODO create mode 100755 src/p7os/cake.exe/libgint/configure create mode 100644 src/p7os/cake.exe/libgint/demo/gintdemo.c create mode 100644 src/p7os/cake.exe/libgint/demo/gintdemo.h create mode 100644 src/p7os/cake.exe/libgint/demo/gintdemo.ld create mode 100644 src/p7os/cake.exe/libgint/demo/icon.bmp create mode 100644 src/p7os/cake.exe/libgint/demo/resources/bopti_thumbs.bmp create mode 100644 src/p7os/cake.exe/libgint/demo/resources/clock_7305.bmp create mode 100644 src/p7os/cake.exe/libgint/demo/resources/clock_7705.bmp create mode 100644 src/p7os/cake.exe/libgint/demo/resources/clock_chars.bmp create mode 100644 src/p7os/cake.exe/libgint/demo/resources/font_modern.bmp create mode 100644 src/p7os/cake.exe/libgint/demo/resources/isometric.bmp create mode 100644 src/p7os/cake.exe/libgint/demo/resources/items.bmp create mode 100644 src/p7os/cake.exe/libgint/demo/resources/opt_bitmap.bmp create mode 100644 src/p7os/cake.exe/libgint/demo/resources/opt_gray.bmp create mode 100644 src/p7os/cake.exe/libgint/demo/resources/opt_menu.bmp create mode 100644 src/p7os/cake.exe/libgint/demo/resources/opt_rtc.bmp create mode 100644 src/p7os/cake.exe/libgint/demo/resources/opt_tales.bmp create mode 100644 src/p7os/cake.exe/libgint/demo/resources/opt_timer.bmp create mode 100644 src/p7os/cake.exe/libgint/demo/resources/rtc_segments.bmp create mode 100644 src/p7os/cake.exe/libgint/demo/resources/screen.bmp create mode 100644 src/p7os/cake.exe/libgint/demo/resources/sprites.bmp create mode 100644 src/p7os/cake.exe/libgint/demo/resources/swords.bmp create mode 100644 src/p7os/cake.exe/libgint/demo/resources/zelda.bmp create mode 100644 src/p7os/cake.exe/libgint/demo/test_bopti.c create mode 100644 src/p7os/cake.exe/libgint/demo/test_gray.c create mode 100644 src/p7os/cake.exe/libgint/demo/test_keyboard.c create mode 100644 src/p7os/cake.exe/libgint/demo/test_rtc.c create mode 100644 src/p7os/cake.exe/libgint/demo/test_tales.c create mode 100644 src/p7os/cake.exe/libgint/demo/test_timer.c create mode 100644 src/p7os/cake.exe/libgint/doc/bopti.md create mode 100644 src/p7os/cake.exe/libgint/include/7305.h create mode 100644 src/p7os/cake.exe/libgint/include/7705.h create mode 100644 src/p7os/cake.exe/libgint/include/alloca.h create mode 100644 src/p7os/cake.exe/libgint/include/clock.h create mode 100644 src/p7os/cake.exe/libgint/include/ctype.h create mode 100644 src/p7os/cake.exe/libgint/include/display.h create mode 100644 src/p7os/cake.exe/libgint/include/events.h create mode 100644 src/p7os/cake.exe/libgint/include/gint.h create mode 100644 src/p7os/cake.exe/libgint/include/gray.h create mode 100644 src/p7os/cake.exe/libgint/include/internals/bopti.h create mode 100644 src/p7os/cake.exe/libgint/include/internals/display.h create mode 100644 src/p7os/cake.exe/libgint/include/internals/events.h create mode 100644 src/p7os/cake.exe/libgint/include/internals/gint.h create mode 100644 src/p7os/cake.exe/libgint/include/internals/keyboard.h create mode 100644 src/p7os/cake.exe/libgint/include/internals/mmu.h create mode 100644 src/p7os/cake.exe/libgint/include/internals/rtc.h create mode 100644 src/p7os/cake.exe/libgint/include/internals/stdio.h create mode 100644 src/p7os/cake.exe/libgint/include/internals/tales.h create mode 100644 src/p7os/cake.exe/libgint/include/internals/time.h create mode 100644 src/p7os/cake.exe/libgint/include/internals/timer.h create mode 100644 src/p7os/cake.exe/libgint/include/keyboard.h create mode 100644 src/p7os/cake.exe/libgint/include/mpu.h create mode 100644 src/p7os/cake.exe/libgint/include/rtc.h create mode 100644 src/p7os/cake.exe/libgint/include/screen.h create mode 100644 src/p7os/cake.exe/libgint/include/setjmp.h create mode 100644 src/p7os/cake.exe/libgint/include/stdio.h create mode 100644 src/p7os/cake.exe/libgint/include/stdlib.h create mode 100644 src/p7os/cake.exe/libgint/include/string.h create mode 100644 src/p7os/cake.exe/libgint/include/tales.h create mode 100644 src/p7os/cake.exe/libgint/include/time.h create mode 100644 src/p7os/cake.exe/libgint/include/timer.h create mode 100644 src/p7os/cake.exe/libgint/src/bopti/bopti_internals.c create mode 100644 src/p7os/cake.exe/libgint/src/bopti/dimage.c create mode 100644 src/p7os/cake.exe/libgint/src/bopti/dimage_part.c create mode 100644 src/p7os/cake.exe/libgint/src/bopti/gimage.c create mode 100644 src/p7os/cake.exe/libgint/src/bopti/gimage_part.c create mode 100644 src/p7os/cake.exe/libgint/src/clock/clock.c create mode 100644 src/p7os/cake.exe/libgint/src/core/crt0.c create mode 100644 src/p7os/cake.exe/libgint/src/core/gint.c create mode 100644 src/p7os/cake.exe/libgint/src/core/gint_str.c create mode 100644 src/p7os/cake.exe/libgint/src/core/gint_vbr.s create mode 100644 src/p7os/cake.exe/libgint/src/core/syscalls.s create mode 100644 src/p7os/cake.exe/libgint/src/display/adjustRectangle.c create mode 100644 src/p7os/cake.exe/libgint/src/display/dclear.c create mode 100644 src/p7os/cake.exe/libgint/src/display/dclear_area.c create mode 100644 src/p7os/cake.exe/libgint/src/display/display_vram.c create mode 100644 src/p7os/cake.exe/libgint/src/display/dline.c create mode 100644 src/p7os/cake.exe/libgint/src/display/dpixel.c create mode 100644 src/p7os/cake.exe/libgint/src/display/dreverse_area.c create mode 100644 src/p7os/cake.exe/libgint/src/display/dupdate.c create mode 100644 src/p7os/cake.exe/libgint/src/display/font_system.bmp create mode 100644 src/p7os/cake.exe/libgint/src/display/getMasks.c create mode 100644 src/p7os/cake.exe/libgint/src/events/event_get.c create mode 100644 src/p7os/cake.exe/libgint/src/events/event_push.c create mode 100644 src/p7os/cake.exe/libgint/src/gray/gclear.c create mode 100644 src/p7os/cake.exe/libgint/src/gray/gclear_area.c create mode 100644 src/p7os/cake.exe/libgint/src/gray/gline.c create mode 100644 src/p7os/cake.exe/libgint/src/gray/gpixel.c create mode 100644 src/p7os/cake.exe/libgint/src/gray/gray_engine.c create mode 100644 src/p7os/cake.exe/libgint/src/gray/greverse_area.c create mode 100644 src/p7os/cake.exe/libgint/src/keyboard/getPressedKey.c create mode 100644 src/p7os/cake.exe/libgint/src/keyboard/getPressedKeys.c create mode 100644 src/p7os/cake.exe/libgint/src/keyboard/getkey.c create mode 100644 src/p7os/cake.exe/libgint/src/keyboard/keyboard_config.c create mode 100644 src/p7os/cake.exe/libgint/src/keyboard/keyboard_interrupt.c create mode 100644 src/p7os/cake.exe/libgint/src/keyboard/keyboard_misc.c create mode 100644 src/p7os/cake.exe/libgint/src/keyboard/keyboard_sh7305.c create mode 100644 src/p7os/cake.exe/libgint/src/keyboard/keyboard_sh7705.c create mode 100644 src/p7os/cake.exe/libgint/src/keyboard/keychar.c create mode 100644 src/p7os/cake.exe/libgint/src/keyboard/keyid.c create mode 100644 src/p7os/cake.exe/libgint/src/keyboard/keytype.c create mode 100644 src/p7os/cake.exe/libgint/src/keyboard/multigetkey.c create mode 100644 src/p7os/cake.exe/libgint/src/mmu/pseudoTLBInit.c create mode 100644 src/p7os/cake.exe/libgint/src/mpu/gint_sh7305.c create mode 100644 src/p7os/cake.exe/libgint/src/mpu/gint_sh7705.c create mode 100644 src/p7os/cake.exe/libgint/src/mpu/mpu.c create mode 100644 src/p7os/cake.exe/libgint/src/rtc/rtc_callback.c create mode 100644 src/p7os/cake.exe/libgint/src/rtc/rtc_getTime.c create mode 100644 src/p7os/cake.exe/libgint/src/rtc/rtc_interrupt.c create mode 100644 src/p7os/cake.exe/libgint/src/rtc/rtc_setTime.c create mode 100644 src/p7os/cake.exe/libgint/src/screen/screen_display.c create mode 100644 src/p7os/cake.exe/libgint/src/setjmp/setjmp.s create mode 100644 src/p7os/cake.exe/libgint/src/stdio/snprintf.c create mode 100644 src/p7os/cake.exe/libgint/src/stdio/sprintf.c create mode 100644 src/p7os/cake.exe/libgint/src/stdio/stdio_format.c create mode 100644 src/p7os/cake.exe/libgint/src/stdio/vsnprintf.c create mode 100644 src/p7os/cake.exe/libgint/src/stdio/vsprintf.c create mode 100644 src/p7os/cake.exe/libgint/src/stdlib/calloc.c create mode 100644 src/p7os/cake.exe/libgint/src/stdlib/free.c create mode 100644 src/p7os/cake.exe/libgint/src/stdlib/malloc.c create mode 100644 src/p7os/cake.exe/libgint/src/stdlib/realloc.c create mode 100644 src/p7os/cake.exe/libgint/src/stdlib/stdlib_abs.c create mode 100644 src/p7os/cake.exe/libgint/src/stdlib/stdlib_div.c create mode 100644 src/p7os/cake.exe/libgint/src/stdlib/stdlib_rand.c create mode 100644 src/p7os/cake.exe/libgint/src/string/memcpy.c create mode 100644 src/p7os/cake.exe/libgint/src/string/memset.c create mode 100644 src/p7os/cake.exe/libgint/src/string/strchr.c create mode 100644 src/p7os/cake.exe/libgint/src/string/strcpy.c create mode 100644 src/p7os/cake.exe/libgint/src/string/strlen.c create mode 100644 src/p7os/cake.exe/libgint/src/string/strncpy.c create mode 100644 src/p7os/cake.exe/libgint/src/tales/tales_configuration.c create mode 100644 src/p7os/cake.exe/libgint/src/tales/tales_gray.c create mode 100644 src/p7os/cake.exe/libgint/src/tales/tales_internals.c create mode 100644 src/p7os/cake.exe/libgint/src/tales/tales_print.c create mode 100644 src/p7os/cake.exe/libgint/src/tales/tales_text.c create mode 100644 src/p7os/cake.exe/libgint/src/time/asctime.c create mode 100644 src/p7os/cake.exe/libgint/src/time/ctime.c create mode 100644 src/p7os/cake.exe/libgint/src/time/gmtime.c create mode 100644 src/p7os/cake.exe/libgint/src/time/mktime.c create mode 100644 src/p7os/cake.exe/libgint/src/time/time.c create mode 100644 src/p7os/cake.exe/libgint/src/time/time_misc.c create mode 100644 src/p7os/cake.exe/libgint/src/time/time_util.c create mode 100644 src/p7os/cake.exe/libgint/src/timer/timer_get.c create mode 100644 src/p7os/cake.exe/libgint/src/timer/timer_interrupt.c create mode 100644 src/p7os/cake.exe/libgint/src/timer/timer_reload.c create mode 100644 src/p7os/cake.exe/libgint/src/timer/timer_start.c create mode 100644 src/p7os/cake.exe/libgint/src/timer/timer_stop.c create mode 100644 src/p7os/cake.exe/osupd.ld create mode 100644 src/p7os/cake.exe/src/endblock.c create mode 100644 src/p7os/cake.exe/src/main.c create mode 100644 src/p7os/main.c create mode 100644 src/p7os/main.h create mode 100644 src/p7os/prepare.c create mode 100755 src/p7os/vars.mk create mode 100644 src/p7screen/args.c create mode 100644 src/p7screen/main.c create mode 100644 src/p7screen/main.h create mode 100755 src/p7screen/vars.mk diff --git a/AUTHORS.md b/AUTHORS.md new file mode 100644 index 0000000..62a693d --- /dev/null +++ b/AUTHORS.md @@ -0,0 +1,2 @@ +# p7utils authors +Copyright (C) 2016-2017 Thomas "Cakeisalie5" Touhey <> diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..0daa041 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,336 @@ +GNU General Public License +========================== + +_Version 2, June 1991_ +_Copyright © 1989, 1991 Free Software Foundation, Inc.,_ +_51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA_ + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + +### Preamble + +The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + +When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + +For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + +We protect your rights with two steps: **(1)** copyright the software, and +**(2)** offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + +Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + +Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and +modification follow. + +### TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +**0.** This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The “Program”, below, +refers to any such program or work, and a “work based on the Program” +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term “modification”.) Each licensee is addressed as “you”. + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + +**1.** You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + +**2.** You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + +* **a)** You must cause the modified files to carry prominent notices +stating that you changed the files and the date of any change. +* **b)** You must cause any work that you distribute or publish, that in +whole or in part contains or is derived from the Program or any +part thereof, to be licensed as a whole at no charge to all third +parties under the terms of this License. +* **c)** If the modified program normally reads commands interactively +when run, you must cause it, when started running for such +interactive use in the most ordinary way, to print or display an +announcement including an appropriate copyright notice and a +notice that there is no warranty (or else, saying that you provide +a warranty) and that users may redistribute the program under +these conditions, and telling the user how to view a copy of this +License. (Exception: if the Program itself is interactive but +does not normally print such an announcement, your work based on +the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + +**3.** You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + +* **a)** Accompany it with the complete corresponding machine-readable +source code, which must be distributed under the terms of Sections +1 and 2 above on a medium customarily used for software interchange; or, +* **b)** Accompany it with a written offer, valid for at least three +years, to give any third party, for a charge no more than your +cost of physically performing source distribution, a complete +machine-readable copy of the corresponding source code, to be +distributed under the terms of Sections 1 and 2 above on a medium +customarily used for software interchange; or, +* **c)** Accompany it with the information you received as to the offer +to distribute corresponding source code. (This alternative is +allowed only for noncommercial distribution and only if you +received the program in object code or executable form with such +an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + +**4.** You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + +**5.** You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + +**6.** Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + +**7.** If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + +**8.** If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + +**9.** The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and “any +later version”, you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + +**10.** If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + +### NO WARRANTY + +**11.** BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + +**12.** IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS + +### How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the “copyright” line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w` and `show c` should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w` and `show c`; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a “copyright disclaimer” for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/Makefile b/Makefile new file mode 100755 index 0000000..a66836e --- /dev/null +++ b/Makefile @@ -0,0 +1,243 @@ +#!/usr/bin/make -f +#******************************************************************************# +# Include variables and message subsystem # +#******************************************************************************# +include Makefile.vars Makefile.msg + +# Check if we're a git repository + ISGIT := $(shell test -e .git && echo y) + +#******************************************************************************# +# General targets # +#******************************************************************************# +# Make it all +all: all-bins + +# Mostly clean +mostlyclean: mostlyclean-bins + mclean: mostlyclean + +# Clean it all +clean: clean-bins clean-doc + fclean: clean + +# Clean it entirely +mrproper: clean + $(call rmsg,Removing configuration.) + $(call qcmd,$(RM) Makefile.cfg) + $(call qcmd,$(RM) $(NAME)-*) + +# Remake it all +re: clean all + +# Install it all +install: install-bins + +# Uninstall it all +uninstall: uninstall-bins + +# Reinstall it all +reinstall: uninstall install + +# Make dist +dist: mrproper $(if $(ISGIT),reinit-gitmodules) + $(call bcmd,mkdir,$(NAME)-$(VERSION),\ + $(MD) .dist) + $(call bcmd,cp,* $(NAME)-$(VERSION),\ + cp -R * .dist) + $(call qcmd,\ + mv .dist $(NAME)-$(VERSION)) + $(call bcmd,tarball,$(NAME)-$(VERSION),\ + tar czf $(NAME)-$(VERSION).tar.gz \ + --exclude .git $(NAME)-$(VERSION)) + $(call qcmd,$(RM) -r $(NAME)-$(VERSION)) + +.PHONY: all mostlyclean mclean clean fclean mrproper re +.PHONY: dist install uninstall reinstall +#******************************************************************************# +# Git submodules # +#******************************************************************************# +# Main rule. + reinit-gitmodules: + $(call qcmd,git submodule deinit -- \ + $(shell grep path .gitmodules | sed 's/.*= //')) + $(call qcmd,git submodule update --init --recursive) + +# Initialize one module +ifeq ($(ISGIT),y) +define check-gitmodule +-$(call qcmd,git submodule update --init --quiet $1) +endef +else +define check-gitmodule +@true +endef +endif + +.PHONY: reinit-gitmodules +#******************************************************************************# +# Configuration (version) checking dependencies # +#******************************************************************************# +# Define the dependencies. + CHECKCFG := $(if $(shell test -f Makefile.cfg || echo y),check-config, \ + $(if $(shell [ "$(VERSION)" = "$(CONFIG_VERSION)" ] || echo y), \ + check-config-version)) + +# Define the rules. + check-config: + @printf "\033[1;31mNo configuration file found!\n" + @printf "You should configure before re-running this target.\033[0m\n" + @false + check-config-version: + @printf "\033[1;31mConfiguration version is incorrect!\n" + @printf "You should re-configure before re-running this target.\033[0m\n" + @false + +.PHONY: check-config check-config-version +#******************************************************************************# +# Information getting from the Makefile variables # +#******************************************************************************# +# Get the project name. + getname: + @echo "$(NAME)" + +# Get the project version. + getversion: + @echo "$(VERSION)" + +# Get the project author. + getmaintainer: + @echo "$(MAINTAINER_NAME) <$(MAINTAINER_MAIL)>" + +.PHONY: getname getmaintainer getversion +#******************************************************************************# +# Binaries-specific targets # +#******************************************************************************# +# Make the binaries. + all-bins: $(CHECKCFG) $(DEFAULT_BINARIES:%=all-%) + +# Make a binary object directory. + $(BINARIES:%=$(OBJDIR)/%): + $(call bcmd,mkdir,$@,$(MD) $@) + +# Make an object out of a source file/directory. +define make-binaryobj-rule +ifeq ($(shell test -f $(SRCDIR)/$1/$2.c && echo y),y) +# - Out of a C source file + $(OBJDIR)/$1/$2.o: $(SRCDIR)/$1/$2.c | $(OBJDIR)/$1 + $(call bcmd,cc,$$@,$(CC) -c -o $$@ $$< $(CFLAGS_$1)) +else +# - Out of an update.exe project + $(SRCDIR)/$1/$2.exe/$2.exe.bin:| $(SRCDIR)/$1/$2.exe + $(call check-gitmodule,$(SRCDIR)/$1/$2.exe) + $(if $(shell test -f $(SRCDIR)/$1/$2.exe/configure \ + && test -x $(SRCDIR)/$1/$2.exe/configure && echo y), \ + $(call qcmd,cd $(SRCDIR)/$1/$2.exe && ./configure 1>/dev/null)) + $(call bcmd,make,$2.exe,$(MAKE) -C $(SRCDIR)/$1/$2.exe $2.exe.bin \ + | sed -e 's/^/ /') + + $(OBJDIR)/$1/$2.o: $(SRCDIR)/$1/$2.exe/$2.exe.bin | $(OBJDIR)/$1 + $(call bcmd,ld -r,$$@,cd $(SRCDIR)/$1/$2.exe && \ + $(LDR) -o ../../../$$@ -b binary $2.exe.bin) +endif +endef +$(foreach bin,$(BINARIES),\ +$(foreach obj,$(SRC_$(bin)),\ +$(eval $(call make-binaryobj-rule,$(bin),$(obj))))) + +# Make a binary +define make-binary-rules + $1$(if $(FOR_WINDOWS),.exe): $(SRC_$1:%=$(OBJDIR)/$1/%.o) | $(OBJDIR)/$1 + $(call bcmd,ld,$$@,$(LD) -o $$@ $$^ $(LDFLAGS_$1)) + all-$1 all-$1.exe: $(CHECKCFG) $1$(if $(FOR_WINDOWS),.exe) all-doc-$1 + + clean-$1 clean-$1.exe: + $(call rmsg,Removing $1 and its objects directory.) + $(call qcmd,$(RM) -r $(OBJDIR)/$1) + $(call qcmd,$(RM) $1$(if $(FOR_WINDOWS),.exe)) + re-$1 re-$1.exe: clean-$1 all-$1 +endef +$(foreach bin,$(BINARIES),\ +$(eval $(call make-binary-rules,$(bin)))) + +# Remove object files. + mostlyclean-bins: + $(call rmsg,Removing objects directory.) + $(call qcmd,$(RM) -r $(OBJDIR)) + mclean-bins: mostlyclean-bins + +# Clean and remove binaries. + clean-bins: mostlyclean-bins + $(call rmsg,Removing binaries.) + $(call qcmd,$(RM) $(BINARIES:%=%*)) + +# Remake binaries + re-bins: clean-bins all-bins + +# Install a binary +define make-installbinary-rule + install-$1 install-$1.exe: $(CHECKCFG) \ + all-$1 $(if $(INSTALL_MANPAGES),install-doc-$1) + $(call imsg,Installing $1$(if $(FOR_WINDOWS),.exe).) + $(call qcmd,$(INSTALL) -m 755 -d "$(IBINDIR)") + $(call qcmd,$(INSTALL) -m 755 -t "$(IBINDIR)" $1$(if $(FOR_WINDOWS),.exe)) + + uninstall-$1 uninstall-$1.exe: $(CHECKCFG) uninstall-doc-$1 + $(call rmsg,Uninstalling $1) + $(call qcmd,$(RM) "$(IBINDIR)/$1"{,.exe}) +endef +$(foreach bin,$(BINARIES),\ +$(eval $(call make-installbinary-rule,$(bin)))) + +# Install binaries + install-bins: $(DEFAULT_BINARIES:%=install-%) + +# Uninstall binaries + uninstall-bins: $(BINARIES:%=uninstall-%) + +.PHONY: all-bins mostlyclean-bins mclean-bins clean-bins re-bins +.PHONY: install-bins uninstall-bins +.PHONY: $(foreach b,$(BINARIES),all-$(b) all-$(b).exe \ + clean-$(b) clean-$(b).exe re-$(b) re-$(b).exe \ + install-$(b) install-$(b).exe uninstall-$(b) uninstall-$(b).exe) +#******************************************************************************# +# Documentation-related # +#******************************************************************************# +# Make manpages directories + $(MANDIR)/man1: + $(call bcmd,mkdir,$@,$(MD) $@) + +# Make-A-Manpage +define make-manpage-rule + $(MANDIR)/man1/$1.%: $(DOCDIR)/$1.1.txt | $(MANDIR)/man1 + $(call bcmd,a2x,$$<,$(A2X) -f manpage -D $$| $$< 2>/dev/null) + + all-doc-$1: $(MANDIR)/man1/$1.1 +endef +$(foreach bin,$(BINARIES),\ +$(eval $(call make-manpage-rule,$(bin)))) + +# Remove all manpages + clean-doc: + $(call rmsg,Removing manpages directory.) + $(call qcmd,$(RM) -r $(MANDIR)) + +# Install a manpage. +define make-install-manpage-rule + install-doc-$1: $(MANDIR)/man1/$1.1 + $(call imsg,Installing $1 manpage) + $(call qcmd,$(INSTALL) -m 755 -d "$(IMANDIR)/man1") + $(call qcmd,$(INSTALL) -m 644 -t "$(IMANDIR)/man1" \ + $(MANDIR)/man1/$1.1) + $(call qcmd,$(GZIP) "$(IMANDIR)/man1/$1.1") + + uninstall-doc-$1: + $(call rmsg,Removing $1 manpage) + $(call qcmd,$(RM) "$(IMANDIR)/man1/$1.1*") +endef +$(foreach bin,$(BINARIES), \ +$(eval $(call make-install-manpage-rule,$(bin)))) + +.PHONY: $(foreach bin,$(BINARIES),all-doc-$(bin)) clean-doc +.PHONY: $(foreach bin,$(BINARIES),install-doc-$(bin) uninstall-doc-$(bin)) +# End of file. diff --git a/Makefile.msg b/Makefile.msg new file mode 100755 index 0000000..186d90a --- /dev/null +++ b/Makefile.msg @@ -0,0 +1,58 @@ +#!/usr/bin/make -f +# The Makefile message subsystem. +# For nice logs. 5 dollars per log only. +#******************************************************************************# +# Colors and misc # +#******************************************************************************# +# Used colors ANSI modifiers escape codes + color_green := 32 + color_red := 31 + color_yellow := 33 + +# Newline - comes handy in some situations +define \n + + +endef + +#******************************************************************************# +# General messages # +#******************************************************************************# +# Command message - display basic info about the command, and run it. +define cmd +@$(if $(MAKE_FULL_LOG),,printf "\033[1;""$4""m>\033[0m \033[1m%s\033[0m %s\n" "$1" "$2";) + $(if $(MAKE_FULL_LOG),,@)$3 +endef + +# Quiet command - make it non-quiet if full log is enabled. +define qcmd +$(if $(MAKE_FULL_LOG),,@)$1 +endef + +# Normal message - display it. +define msg +$(if $(MAKE_FULL_LOG),,@printf "\033[1;""$2""m>\033[0m \033[1m%s\033[0m\n" "$1") +endef + +#******************************************************************************# +# Commands # +#******************************************************************************# +# Build command +define bcmd +$(call cmd,$1,$2,$3,$(color_green)) +endef + +#******************************************************************************# +# Messages # +#******************************************************************************# +# Remove message +define rmsg +$(call msg,$1,$(color_red)) +endef + +# Install message +define imsg +$(call msg,$1,$(color_yellow)) +endef + +# End of file diff --git a/Makefile.vars b/Makefile.vars new file mode 100755 index 0000000..6c26965 --- /dev/null +++ b/Makefile.vars @@ -0,0 +1,155 @@ +#!/usr/bin/make -f +#******************************************************************************# +# Include configuration # +#******************************************************************************# +-include Makefile.cfg + +# Correct target + TARGET := $(if $(TARGET),$(TARGET)-) + +#******************************************************************************# +# Project main information # +#******************************************************************************# +# Project name. + NAME := p7utils + +# Author information. + MAINTAINER_NAME := Thomas \"Cakeisalie5\" Touhey + MAINTAINER_MAIL := thomas@touhey.fr + +# Project license. + LICENSE := GPLv2 + +# Project version. + MAJOR := 3 + MINOR := 0 + INDEV := + +# Project version string. + VERSION := $(MAJOR).$(MINOR)$(if $(INDEV),-indev) + +#******************************************************************************# +# Project directories # +#******************************************************************************# +# Sources directory + SRCDIR := ./src + +# Objects directory + OBJDIR := ./obj + +# Manpages sources directory + DOCDIR := ./doc + +# Manpages directory + MANDIR := ./man + +#******************************************************************************# +# Binary utilities # +#******************************************************************************# +# Package configuration + PKGCONFIG := $(TARGET)pkg-config + +# C Compiler + CC := $(TARGET)gcc +# - Check flags (enable warnings) + CWARN := -Wall -Wextra -Wno-unused-macros -Wno-vla +# - Maintainer flags +ifdef MORE_WARNINGS + CWERROR := shadow write-strings redundant-decls format format-nonliteral \ + format-security implicit-function-declaration \ + date-time missing-prototypes return-type pointer-arith + CWARN += $(CWERROR:%=-W%) -Wstack-protector -Wno-unused-parameter +endif +# - More flags (profiling, ...) +#CMOREFLAGS := +# - All C Compiler flags + CFLAGS := $(CWARN) -std=gnu11 -O2 -D NAME="$(NAME)" -D VERSION="$(VERSION)" \ + -D MAINTAINER="$(MAINTAINER_NAME) <$(MAINTAINER_MAIL)>" \ + -D DEFAULT_STORAGE="$(DEFAULT_STORAGE)" \ + -D DEFAULT_ZOOM="$(DEFAULT_ZOOM)" \ + $(CMOREFLAGS) + +# Linker + LD := $(TARGET)gcc +# - Specific linker flags + LDFLAGS_Linux := -Wl,-z,relro +# - Linker flags + LDFLAGS := $(if $(FOR_WINDOWS),,$(LDFLAGS_Linux)) + +# Raw ELF object maker + LDR := $(TARGET)ld -r + +# Maker + MAKE := make --no-print-directory +# Directory maker + MD := mkdir -p +# File remover + RM := rm -f +# Installer + INSTALL := install +# Asciidoc + A2X := a2x +# Gzipper + GZIP := gzip -f + +#******************************************************************************# +# Binaries and sources # +#******************************************************************************# +# Look for binaries + BINARIES := $(notdir $(shell find $(SRCDIR) -mindepth 1 -maxdepth 1 \ + -type d | sort)) + +# Get their libs +define get-binary-libs + LIBS_$1 := $(shell make -f $(SRCDIR)/$1/vars.mk libs 2>/dev/null) + DISABLE_$1 := $(shell make -f $(SRCDIR)/$1/vars.mk disable 2>/dev/null \ + && echo y) +endef +$(foreach bin,$(BINARIES), \ +$(eval $(call get-binary-libs,$(bin)))) + +# Get the default binaries + DEFAULT_BINARIES := $(foreach bin,$(BINARIES), \ + $(if $(DISABLE_$(bin)),,$(bin))) + +# Look for their sources +define get-binary-sources + SRC_$1 := $(basename $(shell find $(SRCDIR)/$1 \ + -maxdepth 1 -mindepth 1 \ + \( -name "*.c" -or -name "*.exe" \) \ + -printf "%P\n" | sort)) + +# - get the flags + CFLAGS_$1 := $(CFLAGS) $(shell $(PKGCONFIG) $(LIBS_$1) --cflags 2>/dev/null) \ + -D BIN="$1$(if $(FOR_WINDOWS),.exe)" + LDFLAGS_$1 := $(LDFLAGS) $(shell $(PKGCONFIG) $(LIBS_$1) --libs 2>/dev/null) +endef +$(foreach bin,$(BINARIES), \ +$(eval $(call get-binary-sources,$(bin)))) + +#******************************************************************************# +# Look for manpages # +#******************************************************************************# +# Get the manpages sections and contents + MAN_SECTIONS := +define check-man + MAN_SECTIONS += $1 + MAN_$1 += $2 +endef +$(foreach doc, $(basename $(shell find $(DOCDIR) \ + -maxdepth 1 -mindepth 1 -printf "%P\n" -type f -or -type l -name "*.*.txt")), \ +$(eval $(call check-man,$(patsubst .%,%,$(suffix $(doc))),$(basename $(doc))))) + +# Remove duplicate sections. + MAN_SECTIONS := $(sort $(MAN_SECTIONS)) + +#******************************************************************************# +# Check for DESTDIR (add as prefix to installation root) # +#******************************************************************************# +define add-dest-dir + $1 = $(DESTDIR)$($1) +endef +$(if $(DESTDIR), $(foreach idir,IBINDIR IMANDIR, \ +$(eval $(call add-dest-dir,$(idir))))) + +# End of file. diff --git a/README.md b/README.md new file mode 100644 index 0000000..80b859f --- /dev/null +++ b/README.md @@ -0,0 +1,53 @@ +# p7utils - Shell utilities to interact with CASIO calculators and files +## Introduction +**p7utils** is a set of command-line utilities that allow you to interact with +your CASIO calculators/files. The name comes from the fact that it originally +was the merge of `p7`, `p7screen` and `p7os` (which had an almost identical +project structure), then the `g1mutils` (shell utilities for +[libg1m](https://github.com/cakeisalie5/libg1m/) merged with this project. + +Available utilities are: + +* `p7` will interact with the storage memories; +* `p7screen` will display the result of the screen streaming; +* `p7os` will allow you to interact with the calculator's OS (backup, flash); +* `mcsfile` will display the content of an MCS archive file. + +## Prerequisites +### Making-only dependencies +| Name | Version | +| -------------------------------------------------- | -------- | +| [gcc](https://gcc.gnu.org/) | >= 4.9 | +| [binutils](https://www.gnu.org/software/binutils/) | >= 2.25 | +| [asciidoc](http://asciidoc.org/) | >= 8.6.9 | +| [gzip](https://www.gnu.org/software/gzip/) | >= 1.6 | + +### Making and runtime dependencies +| Name | Version | +| -------------------------------------------------- | --------- | +| [libp7](https://p7.planet-casio.com/en.html) | >= 3.0 | +| [libg1m](https://github.com/cakeisalie5/libg1m) | >= 0.1 | +| [libsdl](https://libsdl.org/) | == 1.2.15 | + +Notice that dependencies varies if you only want to build some +executables: only `p7screen` will require the SDL, and `mcsfile` +is the only one to require `libg1m`. + +You should check `src//vars.mk` to see what the dependencies of +the particular executable you want are (if you don't want them all; see +the `libs` target). + +## Building +Just `./configure` then `make`. To install, use `make install`. +Make the manpages with `make all-doc` and install them with `make install-doc`. + +Other useful targets : +- `all-[.exe]`: build only a given executable (and its doc); +- `install-[.exe]`: install only a given executable (and its doc, if + `--noinstall-manpages` is not passed to the configure script); +- `uninstall-[.exe]`: uninstall only a given executable (and its doc); +- `clean`, `clean-[.exe]`, `clean-doc`: remove built files; +- `mrproper`: remove all built files, and the configuration; +- `re`: remove all built files, and build all the default executables and docs. + +Notice that the `.exe` suffix is facultative and is valid for all targets. diff --git a/configure b/configure new file mode 100755 index 0000000..c24db40 --- /dev/null +++ b/configure @@ -0,0 +1,190 @@ +#!/bin/sh +cd "$(dirname "$0")" +#******************************************************************************# +# Defaults # +#******************************************************************************# +# Project variables +name="$(make -s getname)" +version="$(make -s getversion)" +maintainer="$(make -s getmaintainer)" + +# Make options +make_full_log= +more_warnings= + +# Build options +target= +windows= +default_zoom=8 +default_storage=fls0 + +# Installation directories +root='' +prefix='${root}/usr' +bindir='${prefix}/bin' +mandir='${prefix}/share/man' + +# Installation options +install_manpages=yes + +#******************************************************************************# +# Help message # +#******************************************************************************# +usage() { +cat </dev/null ]; then + echo "--default-zoom: a number is expected (got \"$zoom\")" >&2 + elif [ $zoom -lt 1 ]; then + echo "--default-zoom: should be 1 or more (got $zoom)" >&2 + elif [ $zoom -gt 16 ]; then + echo "--default-zoom: should be 16 or less (got $zoom)" >&2 + else default_zoom=$zoom; fi ;; +--default-storage=*) + storage="${arg#*=}" + # check if 4 chars long + if [ ! $(echo "$storage" | wc -c ) -eq 5 ]; then + echo "$0: --default-storage: must be 4 characters long" + continue + fi + # then set + default_storage="$storage" ;; +--noinstall-manpages) install_manpages= ;; +--root=*) root="${arg#*=}" ;; +--prefix=*) prefix="${arg#*=}" ;; +--bindir=*) bindir="${arg#*=}" ;; +--mandir=*) mandir="${arg#*=}" ;; +*) echo "$arg: didn't read" ;; +esac; done + +#******************************************************************************# +# Little things # +#******************************************************************************# +# Cross-compilation things +if [ ! $prefix_set ] && [ $target ]; then + prefix="$prefix"/"$target" +fi + +# Check MS-Windows targets +case "$target" in *-mingw32) windows=y ;; esac + +# Evaluate variables +for var in prefix bindir mandir; do + eval $var'='$(eval 'echo $'$var) +done + +# Check if is on Cygwin +[ "$(expr substr "$(uname -s)" 1 10)" = "MINGW32_NT" ] && windows=y + +# If on MS-Windows, do not make the manpages. +[ "$windows" ] && install_manpages= + +#******************************************************************************# +# Create Makefile configuration # +#******************************************************************************# +# Clean before. +make mrproper MAKE_FULL_LOG=y 1>/dev/null 2>/dev/null + +# Do it! +exec 3>&1 1>Makefile.cfg +cat <&3 3>&- +chmod +x Makefile.cfg + +#******************************************************************************# +# Finish # +#******************************************************************************# +echo "Configuration loaded, you can make now." + +# End of file. diff --git a/doc/mcsfile.1.txt b/doc/mcsfile.1.txt new file mode 100644 index 0000000..0a3fe61 --- /dev/null +++ b/doc/mcsfile.1.txt @@ -0,0 +1,36 @@ +MCSFILE(1) +========== +Thomas "Cakeisalie5" Touhey +:Email: thomas@touhey.fr +:man source: p7utils +:man manual: p7utils manual + +NAME +---- +mcsfile - list subfiles in a CASIO MCS archive file + +SYNOPSIS +-------- +[source,bash] +---- +mcsfile [--help] [--version] +---- + +DESCRIPTION +----------- +mcsfile is a simple utility that looks like *file*(1), excepts it lists subfiles +in a CASIO MCS archive file (things with extensions like *g1m* or *g2r*). + +OPTIONS +------- +Options start with one or two dashes. Some of the options require an additional +value next to them. + +*-h, --help*:: + Display command/subcommand help page and quit. +*-v, --version*:: + Display version and quit. + +SEE ALSO +-------- +*libg1m*(3) diff --git a/doc/p7.1.txt b/doc/p7.1.txt new file mode 100644 index 0000000..0ff3ed6 --- /dev/null +++ b/doc/p7.1.txt @@ -0,0 +1,85 @@ +P7(1) +===== +Thomas "Cakeisalie5" Touhey +:Email: thomas@touhey.fr +:man source: p7utils +:man manual: p7utils manual + +NAME +---- +p7 - command-line utility to communicate with casio calculators + +SYNOPSIS +-------- +[source,bash] +---- +p7 [-h|--help] [-v|--version] [ []] +---- + +DESCRIPTION +----------- +p7 is a command-line utility to communicate with machines using casio's +communication protocol 7.00, like (almost only, not gonna lie) CASIO +fx calculators. For now, it only implements file sending/getting functions +on flash memories. + +Available submenus are: + +*send [-f] [-o oncalc.ext] [-d oncalcdir] local.ext*:: + Send a file to the calculator. +*get [-o local.ext] [-d oncalcdir] oncalc.ext*:: + Get a file from calculator. +*copy [-d sourcedir] [-t destdir] source.ext dest.ext*:: + Copies a file into another on the calculator. +*del [-d oncalcdir] oncalc.ext*:: + Delete a file on the calculator. +*ls*:: + List files on the calculator. +*reset*:: + Reset a filesystem on the calculator. +*optimize*:: + Optimize the distant filesystem (defragment). +*info*:: + Dumps information about the calculator. + +OPTIONS +------- +Options start with one or two dashes. Some of the options require an additional +value next to them. + +*-h, --help*:: + Display command/subcommand help page and quit. +*-v, --version*:: + Display version and quit. +*--com *:: + The USB-serial port, if you want to communicate with a calculator connected + using a USB-to-serial cable. (1 to 20) + If this option isn't used, the program will look for a directly connected + USB calculator. +*--storage abc0*:: + The storage device with which to interact. +*--no-term, --no-exit*:: + Do not terminate connection when action is completed. +*--no-start, --no-init*:: + Do not initialize connection -- should only be used when + *--no-term*/*--no-exit* was used last time p7 was called. +*-d DIR, --directory=DIR*:: + The on-calc directory to work in. + Default for this option is device root. +*-t DDIR, --to=DIR*:: + The destination directory (for file copying/moving). + Default for this option is device root. +*-o OUT, --output=OUT*:: + For the *get* subcommand, the local file path to store in the output (or + '-' for stdout). For the *send* subcommand, the distant filename. For the + two subcommands, default is adapted from the input parameter. +*-f, --force*:: + For the *send* subcommand, force overwrite (default is interactive + confirmation from user). +*-#*:: + Displays a nice little loading bar for *send* and *get* subcommands. If + command is *get* and output is stdout, loading bar won't be displayed. + +SEE ALSO +-------- +*libp7*(3) diff --git a/doc/p7os.1.txt b/doc/p7os.1.txt new file mode 100644 index 0000000..9a50ba4 --- /dev/null +++ b/doc/p7os.1.txt @@ -0,0 +1,60 @@ +P7OS(1) +======= +Thomas "Cakeisalie5" Touhey +:Email: thomas@touhey.fr +:man source: p7utils +:man manual: p7utils manual + +NAME +---- +p7os - backup and setup CASIO calculator's software components using protocol 7 + +SYNOPSIS +-------- +[source,bash] +---- +p7os [-h|--help] [-v|--version] [--no-prepare] [--uexe ] + [ []] +---- + +DESCRIPTION +----------- +p7os is a command-line utility to get and upload an OS on CASIO fx calculators, +using its communication protocol 7.00 and OS update mode. + +Available submenus are : + +*prepare-only*:: + Sends the update program, but leave it for other programs to interact + with it. +*get [-o os.bin]*:: + Backup the bootcode, CASIOWIN entry and OS. + +You have to *prepare* before doing any other action. Preparing means sending +a P7 server on the calculator that will be able to execute commands required +by other subcommands. + +OPTIONS +------- +Options start with one or two dashes. Some of the options require an additional +value next to them. + +*-h, --help*:: + Display command/subcommand help page and quit. +*-v, --version*:: + Display version and quit. +*--com *:: + The USB-serial port, if you want to communicate with a calculator connected + using a USB-to-serial cable. (1 to 20) + If this option isn't used, the program will look for a directly connected + USB calculator. +*--no-prepare*:: + Use the current environment, instead of uploading one. +*--uexe *:: + Use a custom update program. +*-o OUT, --output=OUT*:: + When getting something, where to store. + +SEE ALSO +-------- +*libp7*(3) diff --git a/doc/p7screen.1.txt b/doc/p7screen.1.txt new file mode 100644 index 0000000..2d19b39 --- /dev/null +++ b/doc/p7screen.1.txt @@ -0,0 +1,43 @@ +P7SCREEN(1) +=========== +Thomas "Cakeisalie5" Touhey +:Email: thomas@touhey.fr +:man source: p7utils +:man manual: p7utils manual + +NAME +---- +p7screen - display streamed screen from casio fx calculator + +SYNOPSIS +-------- +[source,bash] +---- +p7screen [-h|--help] [-v|--version] +---- + +DESCRIPTION +----------- +p7screen is a command-line utility to display streamed screen from casio fx +calculator, using its communication protocol 7.00 and screenstreaming mode. + +OPTIONS +------- +Options start with one or two dashes. Some of the options require an additional +value next to them. + +*-h, --help*:: + Display help page and quit. +*-v, --version*:: + Display version and quit. +*--com *:: + The USB-serial port, if you want to communicate with a calculator connected + using a USB-to-serial cable. (1 to 20) + If this option isn't used, the program will look for a directly connected + USB calculator. +*-z ZOOM, --zoom=ZOOM*:: + Change the zoom (will change the window size too). + +SEE ALSO +-------- +*libp7*(3) diff --git a/src/mcsfile/args.c b/src/mcsfile/args.c new file mode 100644 index 0000000..567d1c1 --- /dev/null +++ b/src/mcsfile/args.c @@ -0,0 +1,93 @@ +/* ************************************************************************** */ +/* _____ _ */ +/* args.c |_ _|__ _ _| |__ ___ _ _ */ +/* | Project: mcsfile | |/ _ \| | | | '_ \ / _ \ | | | */ +/* | | (_) | |_| | | | | __/ |_| | */ +/* By: thomas |_|\___/ \__,_|_| |_|\___|\__, |.fr */ +/* Last updated: 2016/12/18 01:20:51 |___/ */ +/* */ +/* ************************************************************************** */ +#include "main.h" +#include +#define Q(x) #x +#define QUOTE(x) Q(x) + +/* ************************************************************************** */ +/* Help and version messages */ +/* ************************************************************************** */ +/* Help message */ +static const char *help_message = +"Usage: mcsfile [--version|-v] [--help|-h] \n" +"\n" +"Reads mcs files in a g1m file.\n" +"\n" +"Options are:\n" +" -h, --help Display this help message.\n" +" -v, --version Display the version message.\n" +"\n" +"Report bugs to " QUOTE(MAINTAINER) "."; + +/* Version message */ +static const char *version_message = +"mcsfile - from p7utils v" QUOTE(VERSION) " (licensed under GPLv2)\n" +"Maintained by " QUOTE(MAINTAINER) ".\n" +"\n" +"This is free software; see the source for copying conditions.\n" +"There is NO warranty; not even for MERCHANTABILITY or\n" +"FITNESS FOR A PARTICULAR PURPOSE."; + +/* ************************************************************************** */ +/* Main function */ +/* ************************************************************************** */ +/** + * parse_args: + * Args parsing main function. + * + * @arg ac the arguments count. + * @arg av the arguments values. + * @arg files pointer to the file paths tab to allocate. + * @return if execution should stop. + */ + +int parse_args(int ac, char **av, const char **path) +{ + /* getopt elements */ + const char *optstring = "hv"; + const struct option longopts[] = { + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'v'}, + {} + }; + + /* get options */ + int c; opterr = 0; + int help = 0, version = 0; + while ((c = getopt_long(ac, av, optstring, longopts, NULL)) != -1) + switch (c) { + case 'h': help = 1; break; + case 'v': version = 1; break; + default: switch (optopt) { + default: + fprintf(stderr, "-%c: unknown option.\n", optopt); + } + return (1); + } + + /* check parameters */ + int pc = ac - optind; + char **pv = &av[optind]; + if (pc != 1) help = 1; + else *path = *pv; + + /* display version or help message */ + if (version) { + puts(version_message); + return (1); + } else if (help) { + puts(help_message); + return (1); + } + + /* no error */ + return (0); +} diff --git a/src/mcsfile/main.c b/src/mcsfile/main.c new file mode 100644 index 0000000..6a1af66 --- /dev/null +++ b/src/mcsfile/main.c @@ -0,0 +1,53 @@ +/* ************************************************************************** */ +/* _____ _ */ +/* main.c |_ _|__ _ _| |__ ___ _ _ */ +/* | Project: mcsfile | |/ _ \| | | | '_ \ / _ \ | | | */ +/* | | (_) | |_| | | | | __/ |_| | */ +/* By: thomas |_|\___/ \__,_|_| |_|\___|\__, |.fr */ +/* Last updated: 2016/12/18 01:19:25 |___/ */ +/* */ +/* ************************************************************************** */ +#include "main.h" +#include +#include + +/** + * main: + * Entry point of the program. + * + * @arg ac the arguments count. + * @arg av the arguments values. + * @return the status code (0 if ok). + */ + +int main(int ac, char **av) +{ + /* parse arguments */ + const char *path; + if (parse_args(ac, av, &path)) + return (0); + + /* parse */ + g1m_t *handle; int err; + if ((err = g1m_open(&handle, path, g1m_type_mcs))) switch (err) { + case g1m_error_wrong_type: + fprintf(stderr, "An MCS file was expected (g1m/g1r, g1m/g2r, g3m)\n"); + return (0); + case g1m_error_nostream: + fprintf(stderr, "Could not open file: %s\n", strerror(errno)); + return (0); + case g1m_error_magic: + fprintf(stderr, "Magic error: file might be corrupted\n"); + return (0); + case g1m_error_eof: + fprintf(stderr, "Unexpected end of file\n"); + return (0); + } + + /* read */ + put_files(handle); + + /* no error */ + g1m_free(handle); + return (0); +} diff --git a/src/mcsfile/main.h b/src/mcsfile/main.h new file mode 100644 index 0000000..64fc6eb --- /dev/null +++ b/src/mcsfile/main.h @@ -0,0 +1,27 @@ +/* ************************************************************************** */ +/* _____ _ */ +/* main.h |_ _|__ _ _| |__ ___ _ _ */ +/* | Project: mcsfile | |/ _ \| | | | '_ \ / _ \ | | | */ +/* | | (_) | |_| | | | | __/ |_| | */ +/* By: thomas |_|\___/ \__,_|_| |_|\___|\__, |.fr */ +/* Last updated: 2016/12/18 01:33:41 |___/ */ +/* */ +/* ************************************************************************** */ +#ifndef MAIN_H +# define MAIN_H +# include + +/* Some printf types */ +# ifdef _WIN64 +# define PRIuSIZE "l64u" +# elif _WIN32 +# define PRIuSIZE "u" +# else +# define PRIuSIZE "zu" +# endif + +/* Prototypes */ +int parse_args(int ac, char **av, const char **paths); +void put_files(g1m_t *handle); + +#endif /* MAIN_H */ diff --git a/src/mcsfile/print.c b/src/mcsfile/print.c new file mode 100644 index 0000000..e61eee8 --- /dev/null +++ b/src/mcsfile/print.c @@ -0,0 +1,130 @@ +/* ************************************************************************** */ +/* _____ _ */ +/* line.c |_ _|__ _ _| |__ ___ _ _ */ +/* | Project: mcsfile | |/ _ \| | | | '_ \ / _ \ | | | */ +/* | | (_) | |_| | | | | __/ |_| | */ +/* By: thomas |_|\___/ \__,_|_| |_|\___|\__, |.fr */ +/* Last updated: 2016/12/18 01:43:52 |___/ */ +/* */ +/* ************************************************************************** */ +#include "main.h" +#include +#include + +/* ************************************************************************** */ +/* Sort */ +/* ************************************************************************** */ +/** + * compare: + * Compare two MCS files. + * + * @arg + */ + +static int compare(const void *vpfile1, const void *vpfile2) +{ + g1m_mcsfile_t *file1 = *((g1m_mcsfile_t**)vpfile1); + g1m_mcsfile_t *file2 = *((g1m_mcsfile_t**)vpfile2); + + /* compare dirnames */ + int dirdiff = strcmp(file1->_dirname, file2->_dirname); + if (dirdiff) return (dirdiff > 0); + + /* compare names */ + return (strcmp(file1->name, file2->name) > 0); +} + +/** + * sort_files: + * Sort MCS files. + * + * @arg handle the handle. + */ + +static void sort_files(g1m_t *handle) +{ + qsort(handle->files, (size_t)handle->count, + sizeof(g1m_mcsfile_t*), &compare); +} + +/* ************************************************************************** */ +/* Display */ +/* ************************************************************************** */ +/** + * put_description: + * Put the description (with the newline). + * + * @arg file the MCS file. + */ + +static void put_description(g1m_mcsfile_t *file) +{ + if (!file->type) + printf("unknown content (%" PRIuSIZE" octets)\n", file->content_size); + else if (file->type & g1m_mcstype_program) { + printf("program ("); + if (g1m_has_password(file)) printf("password: '%s')\n", file->password); + else printf("no password)\n"); + } else if (file->type & g1m_mcstype_list) { + printf("list %d (", g1m_get_id_minor(file->id)); + if (g1m_get_id_major(file->id)) + printf("from listfile %d, ", g1m_get_id_major(file->id)); + printf("%d columns)\n", file->columns); + } else if (file->type & g1m_mcstype_mat) + printf("matrix %c (%d columns, %d rows)\n", + 'A' + file->id - 1, file->columns, file->rows); + else if (file->type & g1m_mcstype_vct) + printf("vector %c (%d rows)\n", + 'A' + file->id - 1, file->rows); + else if (file->type & g1m_mcstype_pict) + printf("picture %d (double %dx%d image)\n", + file->id, file->width, file->height); + else if (file->type & g1m_mcstype_capt) + printf("capture %d (%dx%d)\n", + file->id, file->width, file->height); + else if (file->type & g1m_mcstype_spreadsheet) + printf("spreadsheet (%d columns, %d rows)\n", + file->columns, file->rows); + else if (file->type & g1m_mcstype_string) + printf("string %d\n", file->id); + else if (file->type & g1m_mcstype_setup) + printf("setup\n"); + else if (file->type & g1m_mcstype_alphamem) + printf("alpha memory\n"); + else + printf("unmanaged format\n"); +} + +/** + * put_files: + * Put the files. + * + * @arg handle the handle. + */ + +void put_files(g1m_t *handle) +{ + if (!handle->count) { + fprintf(stderr, "Provided file was empty.\n"); + return ; + } + + sort_files(handle); + /* get first part maximum size */ + int max_size = 0; + for (int i = 0; i < handle->count; i++) { + g1m_mcsfile_t *file = handle->files[i]; + int sz = strlen(file->name) + strlen(file->_dirname); + if (sz > max_size) max_size = sz; + } + max_size += 2; + + /* put the lines */ + char buf[max_size + 1]; + for (int i = 0; i < handle->count; i++) if (handle->files[i]) { + g1m_mcsfile_t *file = handle->files[i]; + sprintf(buf, "%s/%s:", file->_dirname, file->name); + printf("%-*s ", max_size, buf); + put_description(handle->files[i]); + } +} diff --git a/src/mcsfile/vars.mk b/src/mcsfile/vars.mk new file mode 100755 index 0000000..b9df833 --- /dev/null +++ b/src/mcsfile/vars.mk @@ -0,0 +1,4 @@ +#!/usr/bin/make -f +disable: +libs: + @echo libg1m diff --git a/src/p7/args.c b/src/p7/args.c new file mode 100644 index 0000000..701fd3d --- /dev/null +++ b/src/p7/args.c @@ -0,0 +1,348 @@ +/* ************************************************************************** */ +/* _____ _ */ +/* p7/args.c |_ _|__ _ _| |__ ___ _ _ */ +/* | Project: p7utils | |/ _ \| | | | '_ \ / _ \ | | | */ +/* | | (_) | |_| | | | | __/ |_| | */ +/* By: thomas |_|\___/ \__,_|_| |_|\___|\__, |.fr */ +/* Last updated: 2017/01/16 23:55:54 |___/ */ +/* */ +/* ************************************************************************** */ +#include "main.h" +#include +#include +#include +#include +#include + +/* ************************************************************************** */ +/* Help and version messages */ +/* ************************************************************************** */ +/* Version message */ +static const char version_message[] = +QUOTE(BIN) " - from " QUOTE(NAME) " v" QUOTE(VERSION) " (licensed under GPLv2)\n" +"Maintained by " QUOTE(MAINTAINER) ".\n" +"\n" +"This is free software; see the source for copying conditions.\n" +"There is NO warranty; not even for MERCHANTABILITY or\n" +"FITNESS FOR A PARTICULAR PURPOSE."; + +/* Main help message */ +static const char help_main[] = +"Usage: " QUOTE(BIN) " [--version|-v] [--help|-h] [--no-init] [--no-exit]\n" +" [--storage ] [--com ]\n" +" [options...]\n" +"\n" +"Subcommands you can use are:\n" +" send Send a file to the calculator.\n" +" get Get a file from the calculator.\n" +" copy Copy a file into another on the calculator.\n" +" del Delete a file on the calculator.\n" +" reset Reset the flash memory.\n" +" optimize Optimize the distant filesystem.\n" +" ls List files on the distant filesystem.\n" +" info Dump info about the calculator.\n" +"\n" +"General options:\n" +" -h, --help Display the help page of the (sub)command and quit.\n" +" -v, --version Display the version message and quit.\n" +" --com The USB-serial port, if you want to communicate with a\n" +" calculator connected using a USB-to-serial cable. (1 to 20)\n" +" If this option isn't used, the program will look for a\n" +" directly connected USB calculator.\n" +" --storage The storage device with which to interact (fls0, crd0).\n" +" Default storage device is '" QUOTE(DEFAULT_STORAGE) "'.\n" +" --no-exit Does not terminate connection when action is completed.\n" +" --no-init Does not initialize connection (should only be used\n" +" when --no-exit was used last time p7 was called).\n" +"\n" +"Type \"" QUOTE(BIN) " --help\" for some help about the subcommand.\n" +"Report bugs to " QUOTE(MAINTAINER) "."; + +/* Parts */ +#define FOOT \ + "\nType \"" QUOTE(BIN) " --help\" for other subcommands and general options." + +/* Sending help message */ +static const char help_send[] = +"Usage: " QUOTE(BIN) " send [-f] [-o ]\n" +" [-d ] [-#] \n" +"Send a file to the calculator.\n" +"\n" +"Options are:\n" +" -f, --force Overwrite without asking\n" +" -o The output filename on the calculator (by default, the same\n" +" as the local file)\n" +" -d The directory on-calc in which the file will be stored (by\n" +" default, the root directory)\n" +" -# Display a nice little loading bar\n" +FOOT; + +/* Getting help message */ +static const char help_get[] = +"Usage: " QUOTE(BIN) " get [-o ]\n" +" [-d ] \n" +"Request a file from the calculator.\n" +"\n" +"Options are:\n" +" -o The output filename (by default, the same as the on-calc file)\n" +" -d The directory on-calc in which to get the file (by default,\n" +" the root directory)\n" +" -# Display a nice little loading bar (if output isn't stdout)\n" +FOOT; + +/* Copying help message */ +static const char help_copy[] = +"Usage: p7 copy [-f] [-d ] \n" +"Copies a file into the other on the calculator.\n" +"\n" +"Options are:\n" +" -d The source directory (by default, the root directory)\n" +" -t The dest. directory (by default, the root directory)\n" +FOOT; + +/* Deleting help message */ +static const char help_del[] = +"Usage: p7 del [-d \n" +"Delete a file on the calculator.\n" +"\n" +"Options are:\n" +" -d The directory on-calc in which to remove the file (by default,\n" +" the root directory)\n" +FOOT; + +/* Listing help message */ +static const char help_ls[] = +"Usage: p7 ls\n" +"List files on the distant filesystem.\n" +FOOT; + +/* Resetting help message */ +static const char help_reset[] = +"Usage: p7 reset\n" +"Reset the distant filesystem.\n" +FOOT; + +/* Optimizing help message */ +static const char help_optimize[] = +"Usage: p7 optimize\n" +"Optimize the distant filesystem.\n" +FOOT; + +/* Dumping help message */ +static const char help_info[] = +"Usage: p7 info\n" +"Dump information about the calculator.\n" +FOOT; + +/* ************************************************************************** */ +/* Main function */ +/* ************************************************************************** */ +/* useful macros */ +#define sub_init(CMD, NARGS) \ + args->menu = mn_##CMD; \ + if (help || aac != 1 + (NARGS)) { \ + puts(help_##CMD); \ + return (0); \ + } + +/** + * parse_args: + * Args parsing main function. + * + * Was my very first experiment with getopt. + * Then I took an arrow in the knee. + * + * @arg ac the arguments count + * @arg av the arguments values + * @arg args the parsed args pointer + * @return if it was successfully parsed + */ + +int parse_args(int ac, char **av, args_t *args) +{ + /* initialize args */ + *args = (args_t){ + .menu = 0, + .nicedisp = 0, + .dirname = NULL, .filename = NULL, + .newdir = NULL, .newname = NULL, + .local = NULL, .force = 0, + .com = 0, + .storage = QUOTE(DEFAULT_STORAGE), + .initflags = P7_ACTIVE | P7_CHECK | P7_TERM}; + + /* define options */ + char short_options[] = "hvfo:d:t:#"; + struct option long_options[] = { + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'v'}, + {"com", required_argument, NULL, 'c'}, + {"storage", required_argument, NULL, 's'}, + {"force", no_argument, NULL, 'f'}, + {"output", required_argument, NULL, 'o'}, + {"directory", required_argument, NULL, 'd'}, + {"to", required_argument, NULL, 't'}, + {"no-init", no_argument, NULL, 'i'}, + {"no-start", no_argument, NULL, 'i'}, + {"no-exit", no_argument, NULL, 'e'}, + {"no-term", no_argument, NULL, 'e'}, + {NULL, 0, NULL, 0} + }; + + /* get all options */ + int c; opterr = 0; + int help = 0; + const char *s_out = NULL, *s_dir = NULL, *s_todir = NULL, *s_com = NULL; + while ((c = getopt_long(ac, av, short_options, long_options, NULL)) != -1) { + switch (c) { + /* help */ + case 'h': help = 1; break; + /* version */ + case 'v': puts(version_message); return (0); break; + /* force */ + case 'f': args->force = 1; break; + /* nice display */ + case '#': args->nicedisp = 1; break; + + /* output file (on calc or local) */ + case 'o': s_out = optarg; break; + /* directory name */ + case 'd': s_dir = optarg; break; + /* destination directory name */ + case 't': s_todir = optarg; break; + + /* com port */ + case 'c': s_com = optarg; break; + /* storage */ + case 's': args->storage = optarg; break; + /* force no initialization */ + case 'i': args->initflags &= ~P7_CHECK; break; + /* force no exit */ + case 'e': args->initflags &= ~P7_TERM; break; + + /* in case of error */ + case '?': + if (optopt == 'o') + log("-o, --output: expected an argument\n"); + else if (optopt == 'd') + log("-d, --directory: expected an argument\n"); + else if (optopt == 't') + log("-t, --to: expected an argument\n"); + else if (optopt == 'c') + log("--com: expected an argument\n"); + else if (optopt == 's') + log("--storage: expected an argument\n"); + else + break; + return (0); + break; + } + } + + /* check com port */ + if (s_com) { + if (!isdigit(s_com[0])) { + log("-c, --com: expected a number\n"); + return (0); + } + args->com = atoi(s_com); + if (args->com < 1 || args->com > 20) { + log("-c, --com: COM port number should be between 1 and 20\n"); + return (0); + } + } + + /* get non-option arguments (subcommand and parameters) */ + int aac = ac - optind; + char **aav = &av[optind]; + + /* get subcommand and things to check */ + char fpmode[2] = " "; + args->localpath = NULL; + /* - all subcommands - */ + if (!aac || !strcmp(aav[0], "help")) { + puts(help_main); + return (0); + } else if (!strcmp(aav[0], "version")) { + puts(version_message); + return (0); + } else if (!strcmp(aav[0], "info")) { + sub_init(info, 0) + } else if (!strcmp(aav[0], "ls")) { + sub_init(ls, 0) + } else if (!strcmp(aav[0], "reset")) { + sub_init(reset, 0) + } else if (!strcmp(aav[0], "optimize")) { + sub_init(optimize, 0) + } else if (!strcmp(aav[0], "send")) { + sub_init(send, 1) + + /* put arguments to check */ + fpmode[0] = 'r'; + args->localpath = aav[1]; + args->dirname = s_dir ? s_dir : NULL; + if (s_out) args->filename = s_out; + else { + char *rs = strrchr(args->localpath, '/'); + args->filename = rs ? rs + 1 : args->localpath; + } + } else if (!strcmp(aav[0], "get")) { + sub_init(get, 1) + + /* put arguments to check */ + fpmode[0] = 'w'; + args->filename = aav[1]; + args->dirname = s_dir ? s_dir : NULL; + args->localpath = s_out ? s_out : args->filename; + } else if (!strcmp(aav[0], "copy")) { + sub_init(copy, 2) + + /* get filename */ + args->filename = aav[1]; + args->dirname = s_dir ? s_dir : NULL; + args->newname = aav[2]; + args->newdir = s_todir ? s_todir : NULL; + } else if (!strcmp(aav[0], "del") || !strcmp(aav[0], "delete")) { + sub_init(del, 1) + + /* get filename */ + args->filename = aav[1]; + args->dirname = s_dir ? s_dir : NULL; + } else { + /* unknown subcommand ! */ + log("Unknown subcommand '%s'.\n", aav[0]); + return (0); + } + + /* check string lengths */ + int noerror = 0; + if (args->filename && strnlen(args->filename, 13) == 13) + log("On-calc filename must have 12 chars or less!\n"); + else if (args->newname && strnlen(args->newname, 13) == 13) + log("Destination filename must have 12 chars or less!\n"); + else if (args->dirname && strnlen(args->dirname, 9) == 9) + log("On-calc directory name must have 8 chars or less!\n"); + else if (args->newdir && strnlen(args->newdir, 9) == 9) + log("Destination directory name must have 8 chars or less!\n"); + else if (strnlen(args->storage, 5) != 4) + log("Storage device (%s) should be 4 chars long!\n", args->storage); + else + noerror = 1; + if (!noerror) return (0); + + /* check local path */ + if (args->localpath) { + if (fpmode[0] == 'w' && !strcmp(args->localpath, "-")) + args->local = stdout; + else if (!(args->local = fopen(args->localpath, fpmode))) { + log("Could not open local file : %s\n", strerror(errno)); + if (fpmode[0] == 'w') + remove(args->localpath); + return (0); + } + } + + /* everything went well */ + return (1); +} diff --git a/src/p7/dump.c b/src/p7/dump.c new file mode 100644 index 0000000..4ba3c00 --- /dev/null +++ b/src/p7/dump.c @@ -0,0 +1,83 @@ +/* ************************************************************************** */ +/* _____ _ */ +/* p7/dump.c |_ _|__ _ _| |__ ___ _ _ */ +/* | Project: p7utils | |/ _ \| | | | '_ \ / _ \ | | | */ +/* | | (_) | |_| | | | | __/ |_| | */ +/* By: thomas |_|\___/ \__,_|_| |_|\___|\__, |.fr */ +/* Last updated: 2017/01/16 23:55:54 |___/ */ +/* */ +/* ************************************************************************** */ +#include "main.h" +#include +#include +#define numformat "%" PRIuP7INT +#define addrformat "0x%08" PRIxP7INT + +/** + * dump: + * Dump calculator information. + * + * @arg handle the libp7 handle + * @return the error code (0 if ok). + */ + +int dump(p7_handle_t *handle) +{ + /* get server info */ + const p7_server_t *info = p7_get_info(handle); + + /* Wiped out things */ + if (info->preprog_rom_wiped) + log("Warning: Preprogrammed ROM information looks wiped out !\n"); + if (info->bootcode_wiped) + log("Warning: Bootcode information looks wiped out !\n"); + if (info->os_wiped) + log("Warning: OS information looks wiped out!\n"); + if (!info->username[0]) + log("Warning: Username is not set.\n"); + + /* main information */ + printf("CPU ID (probably out of date): %s\n", info->cpuid); + printf("Environnement ID: %s\n", info->hwid); + printf("Product ID: %s\n", info->product_id); + + /* Preprogrammed ROM */ + if (!info->preprog_rom_wiped) { + printf("Preprogrammed ROM version: %02u.%02u", + info->preprog_rom_version.major, info->preprog_rom_version.minor); + if (info->preprog_rom_version.rev) + printf(" (%u)", info->preprog_rom_version.rev); + printf("\nPreprogrammed ROM capacity: " numformat "o\n", + info->preprog_rom_capacity); + } + + /* ROM and RAM */ + printf("ROM capacity: " numformat "KiB\n", info->flash_rom_capacity / 1024); + printf("RAM capacity: " numformat "KiB\n", info->ram_capacity / 1024); + + /* Bootcode */ + if (!info->bootcode_wiped) { + printf("Bootcode version: %02u.%02u", + info->bootcode_version.major, info->bootcode_version.minor); + if (info->bootcode_version.rev) + printf(" (%u)", info->bootcode_version.rev); + printf("\nBootcode offset: " addrformat "\n", info->bootcode_offset); + printf("Bootcode size: " numformat "KiB\n", info->bootcode_size / 1024); + } + + /* OS */ + if (!info->os_wiped) { + printf("OS version: %02u.%02u", + info->os_version.major, info->os_version.minor); + if (info->os_version.rev) + printf(" (%u)", info->os_version.rev); + printf("\nOS offset: " addrformat "\n", info->os_offset); + printf("OS size: " numformat "KiB\n", info->os_size / 1024); + } + + /* Miscallenous information */ + if (info->username[0]) + printf("Username: %s\n", info->username); + + return (0); +} diff --git a/src/p7/main.c b/src/p7/main.c new file mode 100644 index 0000000..4d225e5 --- /dev/null +++ b/src/p7/main.c @@ -0,0 +1,304 @@ +/* ************************************************************************** */ +/* _____ _ */ +/* p7/main.c |_ _|__ _ _| |__ ___ _ _ */ +/* | Project: p7utils | |/ _ \| | | | '_ \ / _ \ | | | */ +/* | | (_) | |_| | | | | __/ |_| | */ +/* By: thomas |_|\___/ \__,_|_| |_|\___|\__, |.fr */ +/* Last updated: 2017/01/16 23:55:54 |___/ */ +/* */ +/* ************************************************************************** */ +#include "main.h" +#include +#include + +/* ************************************************************************** */ +/* Error messages */ +/* ************************************************************************** */ +/* Couldn't initialize connexion with the calculator. */ +static const char error_noconnexion[] = +"Could not connect to the calculator.\n" +"- Is it plugged in and in receive mode?\n" +"- Have you tried changing the cable?\n"; + +/* Calculator was disconnected. */ +static const char error_disconnected[] = +"Lost connexion to the calculator!\n" +"Please reconnect the calculator, rerun receive mode and try again.\n"; + +/* Calculator was found but program wasn't allowed to communicate with it. */ +static const char error_noaccess[] = +"Could not get access to the calculator.\n" +"Install the appropriate udev rule, or run as root.\n"; + +/* Command was unsupported. */ +static const char error_unsupported[] = +"The command is unsupported by the calculator.\n" +"- Does the calculator have mass storage?\n" +"- Does its OS allow the use of it?\n" +"- Is it in Receive Mode (and not in OS Update)?\n"; + +/* The device didn't exist. */ +static const char error_unsupported_device[] = +"Device '%s' is not supported by the device.\n"; + +/* The calculator acted in an unplanned way. */ +static const char error_unplanned[] = +"The calculator didn't act as planned.\n" +"Stop receive mode on calculator and start it again before re-running " \ + QUOTE(BIN) ".\n" +"Error was: %s\n"; + +/* Requested file didn't exist. */ +static const char error_noexists[] = +"Requested file didn't exist.\n"; + +/* Sent file cannot be empty. */ +static const char error_empty[] = +"Can't send an empty file!\n"; + +/* Not enough space left on the calculator. */ +static const char error_nospace[] = +"Not enough space on the calculator for the file you're trying to send.\n" +"If you believe there should be, try optimizing (OPT) on the calculator\n" +"(in MEMORY menu) and try again.\n"; + +/* ************************************************************************** */ +/* Auxiliary functions */ +/* ************************************************************************** */ +/** + * sendfile_confirm: + * Confirm file sending. + * + * @return if the file overwriting is confirmed + */ + +static int sendfile_confirm(void) +{ + char line[10]; + + /* Print stuff */ + printf("It looks like the file already exists on the calculator.\n"); + printf("Overwrite ? ([n]/y) "); + + /* Get the line */ + if (!fgets(line, 10, stdin)) + return (0); + + /* Check if should overwrite */ + return (*line == 'y'); +} + +/** + * sendfile_display: + * File sending nice display. + * + * "Initialization" is when id > total (called in main). + * + * @arg id data packet ID + * @arg total total number of data packets + */ + +static int sendfile_display_initialized = 0; +static void sendfile_display(p7ushort_t id, p7ushort_t total) +{ + /* here's the buffer */ + static char buf[50] = + "\r|---------------------------------------| 00.00%"; + static char *bar = &buf[2]; + + /* initialize */ + static int pos; + + /* if is initialize, fill */ + if (id > total) { + pos = 0; + /* indicate that is has been initialized */ + sendfile_display_initialized = 1; + /* put initial buffer */ + fputs(buf, stdout); + /* save cursor position */ + fputs("\x1B[s", stdout); + /* we're done */ + return ; + } + + /* id and total start from 1, let them start from zero */ + id--; total--; + + /* modify buffer */ + /* - # - */ + int current = 38 * id / total; + while (pos <= current) bar[pos++] = '#'; + /* - % - */ + unsigned int percent = 10000 * id / total; + sprintf(&buf[43], "%02u.%02u", percent / 100, percent % 100); + + /* put it */ + fputs(buf, stdout); + /* force cursor position */ + fputs("\x1B""8", stdout); +} + +/** + * print_file_info: + * File listing callback. + * + * @arg cookie (unused) + * @arg dir the directory in which the file is stored (NULL if root) + * @arg name the filename + * @arg size the filesize + */ + +static void print_file_info(void *cookie, const char *dir, const char *name, + p7uint_t size) +{ + (void)cookie; + /* initialize buffer */ + static char buf[45]; + + /* clean buffer */ + memset(buf, ' ', 28); + /* put path in buffer */ + char *b = buf; + if (dir) b += sprintf(b, "%s/", dir); + if (name) b[sprintf(b, "%s", name)] = ' '; + /* put size */ + sprintf(&buf[28], "%10uo", (unsigned)size); + + /* put the string */ + puts(buf); +} + +/* ************************************************************************** */ +/* Main function */ +/* ************************************************************************** */ +/** + * main: + * User entry point of the program. + * + * @arg ac arguments count + * @arg av arguments values + * @return return code (0 if ok) + */ + +int main(int ac, char **av) +{ + /* Parse args */ + args_t args; + if (!parse_args(ac, av, &args)) + return (0); + + /* Initialize libp7 and communication */ + p7_handle_t *handle = NULL; int err; + if (args.com) err = p7_cominit(&handle, args.initflags, args.com); + else err = p7_init(&handle, args.initflags); + if (err) { + /* display error */ + switch (err) { + case p7_error_nocalc: log(error_noconnexion); break; + case p7_error_noaccess: log(error_noaccess); break; + default: log(error_unplanned, p7_strerror(err)); break; + } + + /* closing, removing if necessary */ + if (args.menu == mn_send) + fclose(args.local); + if (args.menu == mn_get && args.local != stdout) { + fclose(args.local); + remove(args.localpath); + } + return (1); + } + + /* Check according to menu */ + switch (args.menu) { + case mn_send: + /* get file size */ + fseek(args.local, 0, SEEK_END); + size_t filesize = (p7uint_t)ftell(args.local); + rewind(args.local); + + /* get capacity */ + p7uint_t capacity; + err = p7_getfreemem(handle, args.storage, &capacity); + if (err) break; + + /* optimize if required */ + if (filesize > (size_t)capacity) { + printf("Not enough space on the device. Let's optimize!\n"); + err = p7_optimize(handle, args.storage); + if (err) break; + } + + /* send the file */ + err = p7_sendfile(handle, args.local, + args.dirname, args.filename, + args.storage, 1, args.force ? NULL : &sendfile_confirm, + args.nicedisp ? &sendfile_display : NULL); + break; + case mn_get: + err = p7_reqfile(handle, args.local, args.dirname, args.filename, + args.storage, args.nicedisp && args.local != stdout + ? &sendfile_display : NULL); + break; + case mn_copy: + err = p7_copy(handle, args.dirname, args.filename, + args.newdir, args.newname, args.storage); + break; + case mn_del: + err = p7_delete(handle, args.dirname, args.filename, + args.storage); + break; + case mn_ls: + err = p7_list(handle, args.storage, &print_file_info, NULL); + break; + case mn_reset: + err = p7_reset(handle, args.storage); + break; + case mn_optimize: + err = p7_optimize(handle, args.storage); + break; + case mn_info: + err = dump(handle); + break; + } + + /* put error */ + if (err && err != p7_error_denied_overwrite) { + if (sendfile_display_initialized) + puts("\b\b\b\b\b\bError !"); + + /* close the file */ + if (args.local) fclose(args.local); + if (args.menu == mn_get && args.local != stdout) + remove(args.localpath); + + /* put the error string */ + switch (err) { + case p7_error_fullmem: log(error_nospace); break; + case p7_error_empty: log(error_empty); break; + case p7_error_notfound: log(error_noexists); break; + case p7_error_nocalc: log(error_disconnected); break; + case p7_error_unsupported: log(error_unsupported); break; + case p7_error_unsupported_device: + log(error_unsupported_device, args.storage); break; + default: log(error_unplanned, p7_strerror(err)); + } + + /* that doesn't mean you shouldn't exit, heh. */ + p7_exit(handle); + + /* return that an error has occured */ + return (1); + } + + if (sendfile_display_initialized) + puts("\b\b\b\b\b\bTransfer complete."); + if (args.local) fclose(args.local); + + /* terminate communication and de-initialize libp7 */ + p7_exit(handle); + + /* Then we're good */ + return (0); +} diff --git a/src/p7/main.h b/src/p7/main.h new file mode 100644 index 0000000..ac7be2b --- /dev/null +++ b/src/p7/main.h @@ -0,0 +1,47 @@ +/* ************************************************************************** */ +/* _____ _ */ +/* p7/main.h |_ _|__ _ _| |__ ___ _ _ */ +/* | Project: p7utils | |/ _ \| | | | '_ \ / _ \ | | | */ +/* | | (_) | |_| | | | | __/ |_| | */ +/* By: thomas |_|\___/ \__,_|_| |_|\___|\__, |.fr */ +/* Last updated: 2017/01/16 23:55:54 |___/ */ +/* */ +/* ************************************************************************** */ +#ifndef MAIN_H +# define MAIN_H +# define Q(x) #x +# define QUOTE(x) Q(x) +# include +# include +# define log(S, ...) fprintf(stderr, S, ##__VA_ARGS__) + +/* Menus */ +typedef enum { + mn_send, mn_get, mn_copy, mn_del, mn_ls, mn_reset, mn_optimize, + mn_info +} menu_t; + +/* Arguments */ +typedef struct { + /* basic things */ + menu_t menu; + int nicedisp; + + /* for file transferring menus */ + const char *dirname, *filename; + const char *newdir, *newname; + FILE *local; const char *localpath; + int force; + + /* other options */ + unsigned int initflags; + int com; const char *storage; +} args_t; + +/* Parsing function */ +int parse_args(int ac, char **av, args_t *args); + +/* Dumping function */ +int dump(p7_handle_t *handle); + +#endif /* MAIN_H */ diff --git a/src/p7/vars.mk b/src/p7/vars.mk new file mode 100755 index 0000000..c22ee31 --- /dev/null +++ b/src/p7/vars.mk @@ -0,0 +1,3 @@ +#!/usr/bin/make -f +libs: + @echo libp7 diff --git a/src/p7os/args.c b/src/p7os/args.c new file mode 100644 index 0000000..9ceb74a --- /dev/null +++ b/src/p7os/args.c @@ -0,0 +1,220 @@ +/* ************************************************************************** */ +/* _____ _ */ +/* p7os/args.c |_ _|__ _ _| |__ ___ _ _ */ +/* | Project: p7utils | |/ _ \| | | | '_ \ / _ \ | | | */ +/* | | (_) | |_| | | | | __/ |_| | */ +/* By: thomas |_|\___/ \__,_|_| |_|\___|\__, |.fr */ +/* Last updated: 2017/01/16 23:55:54 |___/ */ +/* */ +/* ************************************************************************** */ +#include "main.h" +#include +#include +#include +#include +#include + +/* ************************************************************************** */ +/* Help and version messages */ +/* ************************************************************************** */ +/* The version message - that's when the President comes in */ +static const char version_message[] = +QUOTE(BIN) " - from " QUOTE(NAME) " v" QUOTE(VERSION) " (licensed under GPLv2)\n" +"Maintained by " QUOTE(MAINTAINER) ".\n" +"\n" +"This is free software; see the source for copying conditions.\n" +"There is NO warranty; not even for MERCHANTABILITY or\n" +"FITNESS FOR A PARTICULAR PURPOSE."; + +/* Main help message */ +static const char help_main[] = +"Usage: " QUOTE(BIN) " [--version|-v] [--help|-h] [--com ]\n" +" [--no-prepare] [--uexe ]\n" +" [options...]\n" +"\n" +"Subcommands you can use are :\n" +" prepare-only Set-up the update program, but leave it for other programs\n" +" to interact with it.\n" +" get Get the OS image.\n" +"\n" +"General options:\n" +" -h, --help Display the help page of the (sub)command and quit.\n" +" -v, --version Display the version message and quit.\n" +" --com The USB-serial port, if you want to communicate with a\n" +" calculator connected using a USB-to-serial cable. (1 to 20)\n" +" If this option isn't used, the program will look for a\n" +" directly connected USB calculator.\n" +" --no-prepare Use the current environment, instead of uploading one.\n" +" --uexe Use a custom update program.\n" +"\n" +"Type \"" QUOTE(BIN) " --help\" for some help about a subcommand.\n" +"Report bugs to " QUOTE(MAINTAINER) "."; + +/* Subcommands help messages footer */ +#define FOOT \ + "\nType \"" QUOTE(BIN) " --help\" for other subcommands and general options." + +/* Help message for prepare subcommand */ +static const char help_prepare_only[] = +"Usage: " QUOTE(BIN) " prepare-only\n" +"Send the P7 server on the calculator for further operations.\n" +"This must be used before any other p7os operation.\n" +FOOT; + +/* Help message for get subcommand */ +static const char help_get[] = +"Usage: " QUOTE(BIN) " get [-o ]\n" +"Get the calculator OS image.\n" +"You must have \"p7os prepare\"-ed before.\n" +"\n" +"Options are :\n" +" -o Where to store the image (default is \"os.bin\")\n" +FOOT; + +/* ************************************************************************** */ +/* Main function */ +/* ************************************************************************** */ +/* Help macro */ +#define sub_init(CMD, NARGS) { \ + args->menu = mn_##CMD; \ + if (help || pc != (NARGS)) { \ + puts(help_##CMD); \ + return (1); \ + }} + +/** + * parse_args: + * Args parsing main function. + * + * Based on my very first experiment with getopt. + * + * @arg ac the arguments count + * @arg av the arguments values + * @arg args the parsed args pointer + * @return if has been parsed successfully + */ + +int parse_args(int ac, char **av, args_t *args) +{ + /* initialize args */ + *args = (args_t){ + .menu = 0, + .com = 0, .noprepare = 0, + .uexe = NULL, + .local = NULL, .localpath = NULL + }; + + /* define options */ + const char shopts[] = "hvo:#"; + const struct option longopts[] = { + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'v'}, + {"com", required_argument, NULL, 'c'}, + {"no-prepare", no_argument, NULL, 'n'}, + {"uexe", required_argument, NULL, 'u'}, + {"output", required_argument, NULL, 'o'}, + {NULL, 0, NULL, 0} + }; + + /* get all options */ + int c; opterr = 0; + int help = 0, version = 0; + const char *s_out = "os.bin", *s_com = 0, *s_uexe = NULL; + while ((c = getopt_long(ac, av, shopts, longopts, NULL)) != -1) switch (c) { + /* help */ + case 'h': help = 1; break; + /* version */ + case 'v': version = 1; break; + /* com port */ + case 'c': s_com = optarg; break; + /* no prepare */ + case 'n': args->noprepare = 1; break; + /* uexe */ + case 'u': s_uexe = optarg; break; + /* output */ + case 'o': s_out = optarg; break; + + /* error */ + case '?': + if (optopt == 'o') + log("-o, --output: expected an argument\n"); + else if (optopt == 'c') + log("--com: expected an argument\n"); + else if (optopt == 'u') + log("--uexe: expected an argument\n"); + else + break; + return (1); + } + + /* check for version */ + if (version) { + puts(version_message); + return (1); + } + + /* get non-option arguments (subcommand and parameters) */ + int pc = ac - optind; + char **pv = &av[optind]; + char *sub = pc ? pv[0] : NULL; + pc--; pv++; + + /* subcommand. */ + char fpmode[2] = "r"; + if (!sub || !strcmp(sub, "help")) { + puts(help_main); + return (1); + } else if (!strcmp(sub, "version")) { + puts(version_message); + return (1); + } else if (!strcmp(sub, "prepare-only")) { + sub_init(prepare_only, 0) + + if (args->noprepare) { + log("So we should prepare but we should not prepare? Duh!\n"); + return (1); + } + } else if (!strcmp(sub, "get")) { + sub_init(get, 0) + args->localpath = s_out; + fpmode[0] = 'w'; + } else { + log("Unknown subcommand '%s'.\n", sub); + return (1); + } + + /* check com port */ + if (s_com) { + if (!isdigit(s_com[0])) { + log("-c, --com: expected a number\n"); + return (0); + } + args->com = atoi(s_com); + if (args->com < 1 || args->com > 20) { + log("-c, --com: COM port number should be between 1 and 20\n"); + return (0); + } + } + + /* open destination file */ + if (args->localpath) { + args->local = fopen(args->localpath, fpmode); + if (!args->local) { + log("Could not open local file: %s\n", strerror(errno)); + return (1); + } + } + + /* open update.exe file */ + if (s_uexe) { + args->uexe = fopen(s_uexe, "r"); + if (!args->uexe) { + log("Could not open update program: %s\n", strerror(errno)); + if (args->local) fclose(args->local); + return (1); + } + } + + /* everything went well :) */ + return (0); +} diff --git a/src/p7os/cake.exe/.gitignore b/src/p7os/cake.exe/.gitignore new file mode 100644 index 0000000..4fef74c --- /dev/null +++ b/src/p7os/cake.exe/.gitignore @@ -0,0 +1,6 @@ +/Makefile.cfg +/obj +/update.exe.elf +/update.exe.bin +/cake.exe.elf +/cake.exe.bin diff --git a/src/p7os/cake.exe/.gitmodules b/src/p7os/cake.exe/.gitmodules new file mode 100644 index 0000000..2e6b16d --- /dev/null +++ b/src/p7os/cake.exe/.gitmodules @@ -0,0 +1,3 @@ +[submodule "libgint"] + path = libgint + url = http://git.planet-casio.com/lephe/gint.git diff --git a/src/p7os/cake.exe/LICENSE.md b/src/p7os/cake.exe/LICENSE.md new file mode 100644 index 0000000..0daa041 --- /dev/null +++ b/src/p7os/cake.exe/LICENSE.md @@ -0,0 +1,336 @@ +GNU General Public License +========================== + +_Version 2, June 1991_ +_Copyright © 1989, 1991 Free Software Foundation, Inc.,_ +_51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA_ + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + +### Preamble + +The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + +When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + +For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + +We protect your rights with two steps: **(1)** copyright the software, and +**(2)** offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + +Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + +Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and +modification follow. + +### TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +**0.** This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The “Program”, below, +refers to any such program or work, and a “work based on the Program” +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term “modification”.) Each licensee is addressed as “you”. + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + +**1.** You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + +**2.** You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + +* **a)** You must cause the modified files to carry prominent notices +stating that you changed the files and the date of any change. +* **b)** You must cause any work that you distribute or publish, that in +whole or in part contains or is derived from the Program or any +part thereof, to be licensed as a whole at no charge to all third +parties under the terms of this License. +* **c)** If the modified program normally reads commands interactively +when run, you must cause it, when started running for such +interactive use in the most ordinary way, to print or display an +announcement including an appropriate copyright notice and a +notice that there is no warranty (or else, saying that you provide +a warranty) and that users may redistribute the program under +these conditions, and telling the user how to view a copy of this +License. (Exception: if the Program itself is interactive but +does not normally print such an announcement, your work based on +the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + +**3.** You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + +* **a)** Accompany it with the complete corresponding machine-readable +source code, which must be distributed under the terms of Sections +1 and 2 above on a medium customarily used for software interchange; or, +* **b)** Accompany it with a written offer, valid for at least three +years, to give any third party, for a charge no more than your +cost of physically performing source distribution, a complete +machine-readable copy of the corresponding source code, to be +distributed under the terms of Sections 1 and 2 above on a medium +customarily used for software interchange; or, +* **c)** Accompany it with the information you received as to the offer +to distribute corresponding source code. (This alternative is +allowed only for noncommercial distribution and only if you +received the program in object code or executable form with such +an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + +**4.** You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + +**5.** You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + +**6.** Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + +**7.** If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + +**8.** If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + +**9.** The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and “any +later version”, you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + +**10.** If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + +### NO WARRANTY + +**11.** BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + +**12.** IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS + +### How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the “copyright” line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w` and `show c` should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w` and `show c`; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a “copyright disclaimer” for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/src/p7os/cake.exe/Makefile b/src/p7os/cake.exe/Makefile new file mode 100755 index 0000000..0d70b6f --- /dev/null +++ b/src/p7os/cake.exe/Makefile @@ -0,0 +1,136 @@ +#!/usr/bin/make -f +#******************************************************************************# +# Include variables and message subsystem # +#******************************************************************************# +include Makefile.vars Makefile.msg + +#******************************************************************************# +# General targets # +#******************************************************************************# +# Build everything. +all: all-bin + +# Mostly clean everything (remove everything but the end results). +mostlyclean: mostlyclean-bin + mclean: mostlyclean + +# Clean everything. +clean: clean-bin clean-gint + fclean: clean + +# Clean everything with configuration. +mrproper: clean + $(call rmsg,Removing configuration.) + $(call qcmd,$(RM) Makefile.cfg) + distclean: mrproper + +# Remake everything (clean and build). +re: mostlyclean all + +.PHONY: all mostlyclean mclean clean fclean distclean mrproper re +#******************************************************************************# +# Configuration (version) checking dependencies # +#******************************************************************************# +# Define the dependencies. + CHECKCFG := $(if $(shell test -f Makefile.cfg || echo y),check-config, \ + $(if $(shell [ "$(VERSION)" = "$(CONFIG_VERSION)" ] || echo y), \ + check-config-version)) + +# Define the rules. + check-config: + @printf "\033[1;31mNo configuration file found!\n" + @printf "You should configure before re-running this target.\033[0m\n" + @false + check-config-version: + @printf "\033[1;31mConfiguration version is incorrect!\n" + @printf "You should re-configure before re-running this target.\033[0m\n" + @false + +.PHONY: check-config check-config-version +#******************************************************************************# +# Information getting from the Makefile variables # +#******************************************************************************# +# Get the project name. + getname: + @echo $(NAME) + +# Get the project version. + getversion: + @echo $(VERSION) + +# Get the project maintainer. + getmaintainer: + @echo "$(MAINTAINER_NAME) <$(MAINTAINER_MAIL)>" + +.PHONY: getname getmaintainer getversion +#******************************************************************************# +# gint-related targets # +#******************************************************************************# +# Main gint target + all-gint: $(GLIBDIR)/libgint.a + +# Configure gint libraries. + $(GLIBDIR)/gcc.cfg: + -$(call qcmd,test -e .git && ! test -e $(GLIBDIR)/.git && \ + git submodule update --init $(GLIBDIR)) + $(call bmsg,Configuring gint.) + $(call qcmd,cd $(GLIBDIR) && ./configure --no-syscalls) + +# Make gint libraries. + $(GLIBDIR)/libgint.a $(GLIBDIR)/libc.a: $(GLIBDIR)/gcc.cfg + $(call bmsg,Making gint.) + $(call bcmd,make,gint,$(MAKE) $(GLIBDIR) libgint.a libc.a | sed 's/^/ /') + +# Clean gint libraries. + clean-gint: + $(call rmsg,Cleaning gint.) + -$(call qcmd,test -e $(GLIBDIR)/Makefile && \ + $(MAKE) $(GLIBDIR) distclean | sed 's/^/ /') + +.PHONY: all-gint clean-gint +#******************************************************************************# +# Binary-related targets # +#******************************************************************************# +# Make the binary. + all-bin: $(CHECKCFG) $(NAME).bin + +# Make the object directory. + $(OBJDIR): + $(call bcmd,mkdir,$@,$(MD) $@) + +# Make an object file out of an assembly source file. + $(OBJDIR)/%.o: $(SRCDIR)/%.s | $(OBJDIR) + $(call bcmd,as,$@,$(AS) -c -o $@ $<) + +# Make an object file out of a C source file. + $(OBJDIR)/%.o: $(SRCDIR)/%.c | $(OBJDIR) + $(call bcmd,cc,$@,$(CC) -c -o $@ $< $(CFLAGS)) + +# Make the ELF file. + $(NAME).elf: all-gint $(SRC:%=$(OBJDIR)/%.o) + $(call bcmd,ld,$@,$(LD) -o $@ $(SRC:%=$(OBJDIR)/%.o) $(LDFLAGS)) + +# Make the binary file. + $(NAME).bin: $(NAME).elf + $(call bcmd,objcopy,$@,$(OBJCOPY) -R .comment -R .bss -O binary $< $@) + +# Removing the objects directory. + mostlyclean-bin: + $(call rmsg,Removing the objects directory.) + $(call qcmd,$(RM) -r $(OBJDIR)) + $(call rmsg,Removing the ELF file.) + $(call qcmd,$(RM) *.elf) + + mclean-bin: mostlyclean-bin + +# Remove everything that was built. + clean-bin: mostlyclean-bin + $(call rmsg,Removing the final binary.) + $(call qcmd,$(RM) *.bin) + fclean-bin: clean-bin + +# Remake the binary. + re-bin: clean-bin all-bin + +.PHONY: all-bin mostlyclean-bin mclean-bin clean-bin fclean-bin re-bin +# End of file. diff --git a/src/p7os/cake.exe/Makefile.msg b/src/p7os/cake.exe/Makefile.msg new file mode 100755 index 0000000..6502666 --- /dev/null +++ b/src/p7os/cake.exe/Makefile.msg @@ -0,0 +1,63 @@ +#!/usr/bin/make -f +# The Makefile message subsystem. +# For nice logs. 5 dollars per log only. +#******************************************************************************# +# Colors and misc # +#******************************************************************************# +# Used colors ANSI modifiers escape codes + color_green := 32 + color_red := 31 + color_yellow := 33 + +# Newline - comes handy in some situations +define \n + + +endef + +#******************************************************************************# +# General messages # +#******************************************************************************# +# Command message - display basic info about the command, and run it. +define cmd +@$(if $(MAKE_FULL_LOG),,printf "\033[1;""$4""m>\033[0m \033[1m%s\033[0m %s\n" "$1" "$2";) + $(if $(MAKE_FULL_LOG),,@)$3 +endef + +# Quiet command - make it non-quiet if full log is enabled. +define qcmd +$(if $(MAKE_FULL_LOG),,@)$1 +endef + +# Normal message - display it. +define msg +$(if $(MAKE_FULL_LOG),,@printf "\033[1;""$2""m>\033[0m \033[1m%s\033[0m\n" "$1") +endef + +#******************************************************************************# +# Commands # +#******************************************************************************# +# Build command +define bcmd +$(call cmd,$1,$2,$3,$(color_green)) +endef + +#******************************************************************************# +# Messages # +#******************************************************************************# +# Build message +define bmsg +$(call msg,$1,$(color_green)) +endef + +# Remove message +define rmsg +$(call msg,$1,$(color_red)) +endef + +# Install message +define imsg +$(call msg,$1,$(color_yellow)) +endef + +# End of file. diff --git a/src/p7os/cake.exe/Makefile.vars b/src/p7os/cake.exe/Makefile.vars new file mode 100755 index 0000000..4d8c600 --- /dev/null +++ b/src/p7os/cake.exe/Makefile.vars @@ -0,0 +1,81 @@ +#!/usr/bin/make -f +#******************************************************************************# +# Include configuration # +#******************************************************************************# +-include Makefile.cfg + +#******************************************************************************# +# Project main information # +#******************************************************************************# +# Project name. + NAME := cake.exe + +# Maintainer information + MAINTAINER_NAME := Thomas \"Cakeisalie5\" Touhey + MAINTAINER_MAIL := thomas@touhey.fr + +# Project license + LICENSE := GPLv2 + +# Project version + VERSION_MAJOR := 0 + VERSION_MINOR := 1 + INDEV := yes + VERSION := $(VERSION_MAJOR).$(VERSION_MINOR)$(if $(INDEV),-indev) + +#******************************************************************************# +# Project directories # +#******************************************************************************# +# Headers directory - where all the headers are. + INCDIR := ./include + +# Sources directory - where all the source files are. + SRCDIR := ./src + +# Objects directory - where the objects will be put. + OBJDIR := ./obj + +# Gint lib directory + GLIBDIR := ./libgint + +# Gint include directory + GINCDIR := ./libgint/include + +#******************************************************************************# +# Binary utilities # +#******************************************************************************# +# C Compiler + CC := sh3eb-elf-gcc +# - Check flags (for warnings enabling) + CHKFLAGS := -Wall -Wextra +# - More flags (for profiling, ...) +#CMOREFLAGS := +# - All of the C compiler flags + CFLAGS := -m3 -mb -Os -ffreestanding -I $(INCDIR) -I $(GINCDIR) $(CHKFLAGS) \ + -D AUTHOR="$(AUTHOR_NAME)" -D AUTHOR_MAIL="$(AUTHOR_MAIL)" \ + -D LICENSE="$(LICENSE)" -D VERSION="$(VERSION)" \ + $(CMOREFLAGS) + +# Assembler + AS := sh3eb-elf-as +# Linker + LD := sh3eb-elf-gcc +# - Linker flags + LDFLAGS := -nostdlib -T osupd.ld -L $(GLIBDIR) -lgint -lc -lgcc + +# Maker. + MAKE := make --no-print-directory -C +# Object copier + OBJCOPY := sh3eb-elf-objcopy +# Directory maker + MD := mkdir -p +# File remover + RM := rm -f + +#******************************************************************************# +# Look for sources # +#******************************************************************************# +# SOURCES + SRC := $(basename $(notdir $(shell find $(SRCDIR) -name "*.[cs]"))) + +# END OF FILE diff --git a/src/p7os/cake.exe/README.md b/src/p7os/cake.exe/README.md new file mode 100644 index 0000000..f65b1d1 --- /dev/null +++ b/src/p7os/cake.exe/README.md @@ -0,0 +1,40 @@ +# cake.exe - communautary Update.Exe for CASIO calculators +## Introduction +There is a special command in CASIO's Communication Protocol 7.00: the 0x56 +command, considered by the community to be the "upload and run" command. + +CASIO uses it to modify the OS on the calculator: +- The tools uploads an UpdateExe kernel; +- The OS checks the UpdateExe, transfers it to RAM and transfers + full machine control to it; +- The kernel sets up a Protocol 7 server; +- The tool communicates with this server to make operations on the calculator + (mainly on flash memory): backup the OS, flash a new OS, ... + +Simon Lothar made his own for fxRemote, using bootcode functions for displaying +and communicating (USB, Protocol 7). +This project is a community-made update.exe to imitate proprietary CASIO ones +and Simon Lothar's one. + +## Restrictions +In order to be SH3 and SH4 compatible, the size of the kernel musn't be +greater than 64Kio. Also, a full independence from the OS and the bootcode +should be seeked, so that this update.exe can also serve for flash-erasure +operations - which may come in a very very long time. + +Also, the binary should finish with an identification block -- +see `src/endblock.c` for details. + +## Making dependencies +| Name | Version | +| -------------------------------------------------- | ------- | +| [sh3eb-elf-gcc](https://gcc.gnu.org/) | >= 4.9 | +| [binutils](https://www.gnu.org/software/binutils/) | >= 2.25 | + +## Building + +Just `make`. + +Other useful targets: +- `mostlyclean`, `clean`: remove built files. +- `re`: remake. diff --git a/src/p7os/cake.exe/TODO.md b/src/p7os/cake.exe/TODO.md new file mode 100644 index 0000000..fa13bec --- /dev/null +++ b/src/p7os/cake.exe/TODO.md @@ -0,0 +1,8 @@ +# TODO in Update.exe +## As soon as possible +- Integrate gint (with USB implemented) +- Make a P7 server + +## Later +- Find out update.exe-specific commands +- Implement flash commands diff --git a/src/p7os/cake.exe/configure b/src/p7os/cake.exe/configure new file mode 100755 index 0000000..af15630 --- /dev/null +++ b/src/p7os/cake.exe/configure @@ -0,0 +1,97 @@ +#!/bin/sh +cd "$(dirname "$0")" +#******************************************************************************# +# Defaults # +#******************************************************************************# +# Project variables +name="$(make -s getname)" +version="$(make -s getversion)" + +# Maintainer +maintainer="$(make -s getmaintainer)" + +# Make options +make_full_log= + +#******************************************************************************# +# Help message # +#******************************************************************************# +usage() { +cat </dev/null + +# Write +exec 3>&1 1>Makefile.cfg +cat <&3 3>&- +chmod +x Makefile.cfg + +# Finish +echo "Configuration loaded, you can make now." + +# End of file. diff --git a/src/p7os/cake.exe/include/main.h b/src/p7os/cake.exe/include/main.h new file mode 100644 index 0000000..a519344 --- /dev/null +++ b/src/p7os/cake.exe/include/main.h @@ -0,0 +1,10 @@ +/* ************************************************************************** */ +/* _____ _ */ +/* main.h |_ _|__ _ _| |__ ___ _ _ */ +/* | Project: cake.exe | |/ _ \| | | | '_ \ / _ \ | | | */ +/* | | (_) | |_| | | | | __/ |_| | */ +/* By: thomas |_|\___/ \__,_|_| |_|\___|\__, |.fr */ +/* Last updated: 2017/01/16 18:05:44 |___/ */ +/* */ +/* ************************************************************************** */ + diff --git a/src/p7os/cake.exe/libgint/.gitignore b/src/p7os/cake.exe/libgint/.gitignore new file mode 100644 index 0000000..41fea35 --- /dev/null +++ b/src/p7os/cake.exe/libgint/.gitignore @@ -0,0 +1,20 @@ +# Build directory +build/** + +# Sublime Text files +*.sublime-project +*.sublime-workspace + +# Object files. +*.o + +# Some notes. +LIBC + +# Output files +libc.a +libgint.a +gintdemo.g1a + +# Configuration files +gcc.cfg diff --git a/src/p7os/cake.exe/libgint/Makefile b/src/p7os/cake.exe/libgint/Makefile new file mode 100755 index 0000000..e58aff7 --- /dev/null +++ b/src/p7os/cake.exe/libgint/Makefile @@ -0,0 +1,210 @@ +#! /usr/bin/make -f +#--- +# +# gint project Makefile. +# +#--- + + + +#--- +# Project variables. +#--- + +# Modules +modules-gint = core clock keyboard mmu mpu rtc screen timer \ + bopti display gray tales events +modules-libc = setjmp string stdio stdlib time + +# Targets +target-g1a = gintdemo.g1a +target-lib = libgint.a +target-std = libc.a + +# Tools +cc = sh3eb-elf-gcc +as = sh3eb-elf-as +ar = sh3eb-elf-ar +ob = sh3eb-elf-objcopy +wr = g1a-wrapper + +# Flags +cflags = -m3 -mb -nostdlib -I include -ffreestanding -std=c11 -Os \ + -W -Wall -Wextra -pedantic @gcc.cfg + +# Demo application (could be done better) +demo-src = $(notdir $(wildcard demo/*.[cs])) +demo-dep = $(wildcard demo/*.h) +demo-ld = demo/gintdemo.ld +demo-icon = demo/icon.bmp +demo-res = $(notdir $(wildcard demo/resources/*)) +demo-obj = $(patsubst %,build/demo_%.o,$(demo-src) $(demo-res)) +demo-elf = build/gintdemo.elf +demo-bin = build/gintdemo.bin +demo-libs = -L. -lgint -lc -lgcc + +# Specific objects +obj-lib-spec = build/display_font_system.bmp.o +obj-std-spec = + +# Configuration files +config = gcc.cfg + +#--- +# Automatic variables. +#--- + +# Modules are subfolders of src/. +modules = $(modules-gint) $(modules-libc) + +define n +# This is a newline character. + +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\ + mod-$(mod)-asm = $(notdir $(wildcard src/$(mod)/*.s)) $n\ + mod-$(mod)-src = $$(mod-$(mod)-c)$$(mod-$(mod)-asm) $n\ + mod-$(mod)-obj = $$(patsubst %,build/$(mod)_%.o,$$(mod-$(mod)-src)) \ +)) + +# Target-scope variables. +obj-std = $(foreach mod,$(modules-libc),$(mod-$(mod)-obj)) $(obj-std-spec) +obj-lib = $(foreach mod,$(modules-gint),$(mod-$(mod)-obj)) $(obj-lib-spec) + +# Dependencies +hdr-dep = $(wildcard include/*.h include/internals/*.h) + + + +#--- +# Rule templates. +#--- + +#ifndef VERBOSE +#$(note "default full log") +#VERBOSE = +#endif + +# C source file template: +# $1 module name +# $2 filename +# $3 dependencies +define rule-c-source +build/$1_$2.o: src/$1/$2 $3 $(config) + $(if $(VERBOSE),,@ printf '\e[34;1msrc \u00bb\e[0m cc $$<\n') + $(if $(VERBOSE),,@) $(cc) -c $$< -o $$@ $(cflags) -I src/$1 +endef + +# asm source file template: +# $1 module name +# $2 filename +define rule-asm-source +build/$1_$2.o: src/$1/$2 $(config) + $(if $(VERBOSE),,@ printf '\e[34;1msrc \u00bb\e[0m as $$<\n') + $(if $(VERBOSE),,@) $(as) -c $$< -o $$@ +endef + + + +#--- +# Building. +#--- + +# Generic rules + +all: $(config) $(target-std) $(target-lib) $(target-g1a) + @ printf '\e[32;1mmsg \u00bb\e[0m All done!\n' + +build: + $(if $(VERBOSE),,@ printf '\e[35;1mdir \u00bb\e[0m mkdir $@\n') + $(if $(VERBOSE),,@) mkdir -p $@ + +$(obj-std) $(obj-lib) $(demo-obj): | build + +$(target-std): $(config) $(obj-std) + $(if $(VERBOSE),,@ printf '\e[35;1mlib \u00bb\e[0m ar $@\n') + $(if $(VERBOSE),,@) $(ar) rcs $@ $(obj-std) + @ printf '\e[32;1mmsg \u00bb\e[0m Succesfully built libc (' + @ printf $$(stat -c %s $@) + @ printf ' bytes)\n\n' + +$(target-lib): $(config) $(target-std) $(obj-lib) + $(if $(VERBOSE),,@ printf '\e[35;1mlib \u00bb\e[0m ar $@\n') + $(if $(VERBOSE),,@) $(ar) rcs $@ $(obj-lib) + @ printf '\e[32;1mmsg \u00bb\e[0m Succesfully built libgint (' + @ printf $$(stat -c %s $@) + @ printf ' bytes)\n\n' + +$(target-g1a): $(config) $(target-std) $(target-lib) $(demo-obj) + $(if $(VERBOSE),,@ printf '\e[35;1mexe \u00bb\e[0m ld -o $(demo-elf)\n') + $(if $(VERBOSE),,@) $(cc) -o $(demo-elf) $(cflags) -T $(demo-ld) $(demo-obj) $(demo-libs) + $(if $(VERBOSE),,@ printf '\e[35;1mexe \u00bb\e[0m objcopy -o $(demo-bin)\n') + $(if $(VERBOSE),,@) $(ob) -R .comment -R .bss -O binary $(demo-elf) $(demo-bin) + $(if $(VERBOSE),,@ printf '\e[35;1mexe \u00bb\e[0m g1a-wrapper -o $@\n') + $(if $(VERBOSE),,@) $(wr) $(demo-bin) -o $@ -i $(demo-icon) + @ printf '\e[32;1mmsg \u00bb\e[0m Succesfully built demo application (' + @ printf $$(stat -c %s $@) + @ printf ' bytes)\n\n' + +# Automated rules + +$(foreach mod,$(modules), \ + $(foreach source,$(mod-$(mod)-c), $(eval \ + $(call rule-c-source,$(mod),$(source),$(hdr-dep)))) \ + $(foreach source,$(mod-$(mod)-asm), $(eval \ + $(call rule-asm-source,$(mod),$(source)))) \ +) + +# Specific rules + +# This one should not be optimized. It makes __attribute__((interrupt_handler)) +# buggy... maybe. Anyway there's some bug in this file that I can't fix now. +build/core_gint.c.o: src/core/gint.c $(mod-core-dep) $(config) + $(if $(VERBOSE),,@ printf '\e[34;1msrc \u00bb\e[0m cc $<\n') + $(if $(VERBOSE),,@) $(cc) -c $< -o $@ $(cflags) -I src/core -O0 + +build/display_font_system.bmp.o: src/display/font_system.bmp + $(if $(VERBOSE),,@ printf '\e[36;1mres \u00bb\e[0m fxconv $<\n') + $(if $(VERBOSE),,@) fxconv $< -o $@ --font -n gint_font_system + +# Demo application + +build/demo_%.c.o: demo/%.c $(hdr-dep) $(demo-dep) $(config) + $(if $(VERBOSE),,@ printf '\e[34;1msrc \u00bb\e[0m cc $<\n') + $(if $(VERBOSE),,@) $(cc) -c $< -o $@ $(cflags) + +build/demo_font_%.bmp.o: demo/resources/font_%.bmp + $(if $(VERBOSE),,@ printf '\e[36;1mres \u00bb\e[0m fxconv $<\n') + $(if $(VERBOSE),,@) fxconv $< -o $@ --font -n $(patsubst demo/resources/%.bmp,res_%,$<) + +build/demo_%.bmp.o: demo/resources/%.bmp + $(if $(VERBOSE),,@ printf '\e[36;1mres \u00bb\e[0m fxconv $<\n') + $(if $(VERBOSE),,@) fxconv $< -o $@ -n $(patsubst demo/resources/%.bmp,res_%,$<) + + + +#--- +# Cleaning and others. +#--- + +clean: + @ rm -rf build + +mrproper: clean + @ rm -f $(target-g1a) $(target-lib) $(target-std) + @ rm -f $(config) + +distclean: mrproper + +install: + p7 send -f $(target-g1a) + + +.PHONY: all clean mrproper distclean install help diff --git a/src/p7os/cake.exe/libgint/README.md b/src/p7os/cake.exe/libgint/README.md new file mode 100644 index 0000000..f3b5fad --- /dev/null +++ b/src/p7os/cake.exe/libgint/README.md @@ -0,0 +1,72 @@ +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). + +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. + + + +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. + + + +Building and installing +----------------------- + +There are some dependencies: +* The `sh3eb-elf` toolchain somewhere in the PATH +* The 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 : +* `libgint.a`, the gint library +* `libc.a`, a (very) few standard procedures +* `gintdemo.g1a`, a test application + +The common `clean`, `mrproper`, and `distclean` rules will clean the directory. + + + +Source organization +------------------- + +gint is made of *modules*. Each module may have any of the following +components: +* 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, I think. + +The demo application is in the `demo` directory. + +The `doc` folder contains some documentation. diff --git a/src/p7os/cake.exe/libgint/TODO b/src/p7os/cake.exe/libgint/TODO new file mode 100644 index 0000000..70a42f7 --- /dev/null +++ b/src/p7os/cake.exe/libgint/TODO @@ -0,0 +1,33 @@ +Bugs to fix: +- Left-vram overflow when rendering text +- A few key hits ignored after leaving the application (could not reproduce) +- Lost keyboard control at startup (could not reproduce) +- Back-light issues (0xa400012c on SH3, 0xa4050138 on SH4) + +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 +- timer: Add duration and frequency settings +- core: Add VBR handlers debugging information (if possible) +- core: Implement all callbacks and a complete user API + +Modules to implement: +- Serial communication +- Sound playback and synthesizing +- Handle errors within errno + +Things to investigate: +- Packed bit fields alignment +- Registers that may need to be saved within setjmp() +- Registers that may need to be saved and restored by gint +- Possible bug when optimizing __attribute__((interrupt_handler)) + +Configuration: +- ATEXIT_MAX (16) +- RTC_CB_ARRAY_SIZE (5) +- EVENTS_QUEUE_SIZE (64) +- GINT_NO_SYSCALLS (undefined) diff --git a/src/p7os/cake.exe/libgint/configure b/src/p7os/cake.exe/libgint/configure new file mode 100755 index 0000000..4f70807 --- /dev/null +++ b/src/p7os/cake.exe/libgint/configure @@ -0,0 +1,78 @@ +#! /bin/bash + +declare -A conf +conf[ATEXIT_MAX]=16 +conf[RTC_CB_ARRAY_SIZE]=5 +conf[EVENTS_QUEUE_SIZE]=64 +conf[GINT_NO_SYSCALLS]= +fail=false +output="gcc.cfg" + +help() +{ + cat << EOF +Configuration script for the gint library. + +Options that affect the behavior of the library: + --no-syscalls [default: false] + Never use syscalls. Expect some trouble with the malloc() function... + Do not trigger this option unless you know what you are doing. + +Options that customize size limits: + --atexit-max= [default: 16] + Number of exit handlers that can be registered by atexit(). + --rtc-callbacks= [default: 5] + Number of RTC callbacks that can be registered. + --events-queue-size= [default: 64] + Number of events simultaneously stored in the event queue. +EOF + + exit 0 +} + +for arg; do case "$arg" in + -h | --help) help;; + --no-syscalls) conf[GINT_NO_SYSCALLS]=true;; + + --atexit-max=*) + size=${arg#*=} + if [[ $size == +([0-9]) ]]; then + conf[ATEXIT_MAX]=$size + else echo "error: --atexit-max expects an integer value" + fail=true; fi;; + --rtc-callbacks=*) + size=${arg#*=} + if [[ $size == +([0-9]) ]]; then + conf[RTC_CB_ARRAY_SIZE]=$size + else echo "error: --rtc-callbacks expects an integer value" + fail=true; fi;; + --events-queue-size=*) + size=${arg#*=} + if [[ $size == +([0-9]) ]]; then + conf[EVENTS_QUEUE_SIZE]=$size + else echo "error: --events-queue-size expects an integer value" + fail=true; fi;; + + --atexit-max | --rtc-callbacks | --events-queue-size) + echo "error: syntax for $arg is $arg=";; + + *) + echo "error: unrecognized argument '$arg'"; fail=true;; +esac; done + +output_config() +{ + echo "-D ATEXIT_MAX=${conf[ATEXIT_MAX]}" + echo "-D RTC_CB_ARRAY_SIZE=${conf[RTC_CB_ARRAY_SIZE]}" + echo "-D EVENTS_QUEUE_SIZE=${conf[EVENTS_QUEUE_SIZE]}" + if [ "${conf[GINT_NO_SYSCALLS]}" != "" ]; then + echo "-D GINT_NO_SYSCALLS" + fi +} + +if $fail; then + echo "Configuration has not been modified." +else + output_config > $output + echo "Configuration details have been output to file $output." +fi diff --git a/src/p7os/cake.exe/libgint/demo/gintdemo.c b/src/p7os/cake.exe/libgint/demo/gintdemo.c new file mode 100644 index 0000000..7284c35 --- /dev/null +++ b/src/p7os/cake.exe/libgint/demo/gintdemo.c @@ -0,0 +1,531 @@ +#include "gintdemo.h" + +#include +#include +#include +#include +#include + +#include + + + +//--- +// A few procedures for displaying text aligned on a 21*8 grid. +// Not really beautiful... but this will do. +//--- + +void locate(int x, int y, const char *str) +{ + if(x < 1 || x > 21 || y < 1 || y > 8) return; + if(gray_runs()) gtext(x * 6 - 5, y * 8 - 8, str); + else dtext(x * 6 - 5, y * 8 - 8, str); +} + +void print(int x, int y, const char *format, ...) +{ + va_list args; + + va_start(args, format); + __printf(0, format, args); + va_end(args); + + locate(x, y, __stdio_buffer); +} + +/* + printf_test() + Tests formatting functions. + +void printf_test(void) +{ + dclear(); + locate(1, 1, "Formatted printing"); + + print(2, 3, "%%4.2d 5 :\"%4.2d\"", 5); + print(2, 4, "%%-3c '&':\"%-3c\"", '&'); + print(2, 5, "%%#05x 27 :\"%#05x\"", 27); + print(2, 6, "%%1s \"tr\":\"%1s\"", "tr"); + print(2, 7, "%%6p NULL :\"%6p\"", NULL); + + dupdate(); + while(getkey() != KEY_EXIT); +} +*/ + +/* +static const unsigned char screen[1024] = { +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 7, 159, 0, 0, 1, 192, 0, 0, 0, 0, 0, 121, 240, 0, 0, 0, +31, 191, 192, 0, 3, 224, 27, 216, 0, 0, 1, 251, 252, 0, 0, 0, 57, 247, 222, +30, 7, 240, 36, 36, 62, 25, 131, 159, 24, 255, 129, 224, 0, 227, 142, 126, 1, +192, 45, 172, 127, 127, 192, 14, 1, 255, 199, 224, 0, 227, 140, 240, 1, 192, +26, 88, 115, 127, 224, 14, 57, 221, 207, 0, 0, 227, 13, 192, 1, 192, 34, 68, +120, 30, 0, 14, 25, 156, 220, 0, 0, 227, 253, 252, 1, 192, 36, 36, 126, 28, +0, 14, 219, 156, 223, 192, 0, 227, 253, 252, 1, 192, 36, 36, 31, 12, 0, 46, +27, 140, 223, 192, 0, 227, 141, 193, 193, 192, 40, 20, 7, 140, 0, 206, 25, 140, +220, 28, 0, 227, 140, 225, 129, 199, 24, 24, 99, 156, 1, 14, 25, 204, 206, 24, +0, 227, 142, 127, 1, 195, 39, 228, 255, 156, 2, 14, 24, 237, 199, 240, 1, 247, +222, 62, 1, 198, 44, 44, 223, 30, 2, 31, 28, 237, 131, 224, 1, 224, 0, 0, 3, +254, 27, 216, 0, 0, 4, 30, 0, 0, 0, 0, 3, 192, 0, 0, 7, 252, 0, 0, 0, 0, 4, +60, 1, 249, 240, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 4, 0, 97, 240, 56, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 1, 224, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +4, 0, 47, 192, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 32, 255, 128, 63, 128, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 32, 255, 0, 48, 78, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 15, 176, 255, 0, 112, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 8, 56, 255, 0, +96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 8, 60, 255, 0, 224, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 130, 56, 126, 255, 3, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 192, +62, 255, 15, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 14, 191, 255, 192, 0, +0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 6, 129, 255, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, +1, 0, 0, 6, 0, 255, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 7, 128, 63, 192, +0, 0, 96, 1, 224, 1, 0, 0, 0, 2, 0, 0, 7, 0, 31, 192, 0, 0, 95, 1, 11, 68, 88, +0, 0, 4, 0, 0, 7, 128, 31, 192, 0, 1, 192, 129, 204, 85, 100, 0, 0, 8, 0, 0, +15, 128, 63, 224, 0, 0, 95, 1, 8, 85, 68, 0, 1, 144, 0, 0, 31, 128, 143, 224, +64, 0, 96, 1, 232, 41, 68, 0, 2, 96, 0, 31, 255, 129, 7, 248, 96, 0, 0, 0, 0, +0, 0, 0, 4, 0, 0, 96, 254, 129, 7, 254, 96, 0, 0, 0, 0, 0, 0, 0, 4, 0, 1, 128, +254, 131, 135, 255, 224, 0, 0, 1, 192, 64, 16, 0, 8, 0, 7, 0, 254, 131, 255, +63, 224, 0, 0, 1, 38, 113, 208, 0, 8, 0, 13, 0, 222, 147, 254, 31, 224, 0, 0, +1, 41, 74, 80, 0, 8, 0, 25, 0, 222, 67, 254, 31, 160, 0, 0, 1, 41, 74, 80, 0, +12, 0, 49, 0, 222, 19, 254, 62, 48, 0, 0, 1, 198, 113, 208, 0, 2, 0, 32, 128, +222, 195, 255, 252, 56, 0, 0, 0, 0, 0, 0, 0, 2, 0, 124, 64, 220, 151, 135, 248, +127, 0, 0, 0, 0, 0, 0, 0, 2, 0, 66, 32, 221, 223, 7, 240, 255, 0, 0, 0, 0, 0, +0, 0, 2, 0, 129, 23, 93, 159, 15, 241, 131, 0, 0, 0, 0, 0, 0, 0, 4, 0, 128, +136, 217, 95, 3, 226, 9, 0, 0, 1, 240, 0, 0, 0, 4, 0, 128, 72, 89, 95, 129, +228, 18, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0, 72, 73, 127, 128, 224, 36, 0, 0, 0, 0, +0, 0, 0, 28, 1, 0, 76, 129, 127, 192, 96, 8, 0, 0, 0, 0, 0, 0, 0, 16, 1, 0, +231, 203, 124, 96, 64, 0, 0, 0, 0, 0, 0, 0, 0, 16, 1, 1, 28, 123, 240, 12, 64, +1, 0, 0, 0, 0, 0, 0, 0, 16, 1, 2, 28, 143, 128, 15, 192, 7, 0, 0, 0, 0, 0, 0, +0, 16, 1, 4, 17, 143, 24, 15, 192, 14, 0, 0, 0, 0, 0, 0, 0, 28, 1, 4, 1, 135, +24, 31, 192, 24, 0, 0, 0, 0, 0, 0, 0, 18, 1, 62, 1, 135, 248, 63, 224, 192, +0, 0, 0, 0, 0, 0, 0, 35, 1, 195, 1, 135, 128, 254, 126, 1, 0, 0, 0, 0, 0, 0, +0, 35, 193, 131, 195, 135, 255, 248, 112, 1, 0, 0, 0, 0, 0, 0, 0, 67, 241, 131, +14, 207, 255, 192, 224, 3, 0, 0, 0, 0, 0, 0, 3, 67, 15, 143, 56, 255, 7, 1, +224, 7, 0, 0, 0, 0, 0, 0, 28, 130, 7, 255, 112, 204, 7, 131, 224, 31, 0, 0, +0, 0, 0, 0, 32, 134, 30, 29, 120, 156, 7, 255, 224, 127, 0, 0, 0, 0, 0, 63, +197, 206, 60, 56, 192, 248, 15, 255, 248, 255, 0, 0, 0, 0, 0, 120, 5, 227, 248, +56, 195, 248, 127, 191, 254, 63, 0, 0, 0, 0, 7, 254, 255, 193, 255, 15, 193, +255, 15, 31, 252, 31 }; + +void ML_bmp_or_cl(const unsigned char *bmp, int x, int y, int width, int height) +{ + unsigned short line; + char shift, *screen, *p; + int i, j, real_width, begin_x, end_x, begin_y, end_y; + char bool1=1, bool2=1, bool3; + if(!bmp || x<1-width || x>127 || y<1-height || y>63 || height<1 || width<1) return; + p = (char*)&line; + real_width = (width-1>>3<<3)+8; + if(y < 0) begin_y = -y; + else begin_y = 0; + if(y+height > 64) end_y = 64-y; + else end_y = height; + shift = 8-(x&7); + if(x<0) + { + begin_x = -x>>3; + if(shift != 8) bool1 = 0; + } else begin_x = 0; + if(x+real_width > 128) end_x = 15-(x>>3), bool2 = 0; + else end_x = real_width-1>>3; + bool3 = (end_x == real_width-1>>3); + screen = display_getCurrentVRAM()+(y+begin_y<<4)+(x>>3); + + for(i=begin_y ; i>3)+begin_x] << shift; + if(bool1) screen[begin_x] |= *p; + if(shift!=8) screen[begin_x+1] |= *(p+1); + for(j=begin_x+1 ; j>3)+j] << shift; + screen[j] |= *p; + if(shift!=8) screen[j+1] |= *(p+1); + } + } + line = bmp[i*(real_width>>3)+end_x]; + if(bool3) line &= -1< +void debug(void) +{ + extern Image res_screen_start; + struct mod_tmu *timer; + int time1, time2; + int i; + + timer_get(TIMER_USER, &timer, NULL); + + dclear(); + ML_bmp_or_cl(screen, 1, 1, 128, 64); + dupdate(); + getkey(); + + dclear(); + dimage(&res_screen_start, 1, 1); + dupdate(); + getkey(); + + dclear(); + dtext("ML...", 2, 2); + dupdate(); + + timer_start(TIMER_USER, 0x0fffffff, TIMER_Po_4, NULL, 0); + for(i = 0; i < 1000; i++) ML_bmp_or_cl(screen, 1, 1, 128, 64); + time1 = timer->TCNT; + timer_stop(TIMER_USER); + time1 = 0x0fffffff - time1; + + dclear(); + dtext("gint...", 2, 2); + dupdate(); + + timer_start(TIMER_USER, 0x0fffffff, TIMER_Po_4, NULL, 0); + for(i = 0; i < 1000; i++) dimage(&res_screen_start, 1, 1); + time2 = timer->TCNT; + timer_stop(TIMER_USER); + time2 = 0x0fffffff - time2; + + dclear(); + print_hex(time1, 2, 2); + print_hex(time2, 2, 9); + dupdate(); + while(getkey() != KEY_EXIT); +} +*/ + +/* + tlb_debug() + Displays the TLB contents and some information. Only available for + SH7705, because the SH7305's TLB is much more complicated. + +void tlb_debug(void) +{ + // Entry address address (pointer in the address array), entry data + // address (pointer in the data address), and their contents. + unsigned int address, data, a, d; + // Virtual page number and physical page number. + unsigned int vpn, ppn; + // Contents of register MMUCR. + unsigned mmucr; + + int i, r, key = 0; + int way = 0, entry = 0; + int pointer_base; + + const char *protection[] = { "pr", "prw", "ar", "arw" }; + mmucr = *((volatile unsigned int *)gint_reg(Register_MMUCR)); + + dclear(); + locate("MMU register info", 1, 1); + locate("MMUCR.IX = ", 2, 3); + locate(mmucr & 0x02 ? "1" : "0", 13, 3); + dupdate(); + getkey(); + + while(key != KEY_EXIT && way < 4) + { + dclear(); + + print(1, 1, "TLB way=%d %d-%d", way, entry, + entry > 29 ? 31 : entry + 2); + + for(i = 0; i < 3 && entry < 32; i++, entry++) + { + address = 0xf2000000 | (entry << 12) | (way << 8); + data = 0xf3000000 | (entry << 12) | (way << 8); + + a = *((volatile unsigned int *)address); + d = *((volatile unsigned int *)data); + + ppn = (d >> 10) & 0x00007ffff; + // 4-kbyte page + if(d & 0x08) + { + vpn = (a >> 12) | entry; + pointer_base = vpn << 12; + } + // 1-kbyte page + else + { + vpn = (a >> 10) | (entry << 2); + pointer_base = vpn << 10; + } + + r = 2 * i + 3; + print(1, r, "%08x :%08x", pointer_base, ppn << 10); + + r++; + locate((d & 0x08) ? "4k" : "1k", 1, r); + print(5, r, "pr=%s", protection[(d >> 5) & 3]); + locate((d & 0x02) ? "shared" : "exclusive", 13, r); + } + + if(entry == 32) entry = 0, way++; + + dupdate(); + key = getkey(); + } +} +*/ + +/* + main_menu() + Displays the main menu and returns user's choice: 0 for [EXIT], + application numbers otherwise. Sets the ctaegory and application + number. +*/ +void main_menu(int *category, int *app) +{ + //--- + // Quite a few things to declare... + //--- + + extern Image res_opt_menu; + + const char *mpu, *mpu_names[] = { + "Unknown", + "SH7337", + "SH7355", + "SH7305", + "SH7724", + "[error]" + }; + + const char *list_tests[] = { + "Keyboard", + "Gray engine", + "Image rendering", + "Text rendering", + "Real-time clock", + "Clocks and timers", + NULL + }; + const char *list_perfs[] = { + "Image rendering", + "Text rendering", + NULL + }; + const char *list_debug[] = { + "View TLB (SH3 only)", + NULL + }; + const char **list = NULL; + int list_len = 0; + + extern unsigned int bgint, egint; + extern unsigned int romdata; + int gint_size = (char *)&egint - (char *)&bgint; + + + + static int tab = 0, index = 0, scroll = 0; + // Set to 1 when interface has to be redrawn. + int leave = 1; + int i; + + mpu = mpu_names[MPU_CURRENT < 5 ? MPU_CURRENT : 5]; + text_configure(NULL, Color_Black); + + while(1) + { + //--- + // Displaying the current tab. + //--- + + dclear(); + dupdate(); + + switch(tab) + { + case 0: + locate(1, 1, "Demo application"); + print(2, 3, "gint version: %5s", GINT_VERSION_STR); + print(2, 4, "handler size: %5d", gint_size); + print(2, 5, "mpu type: %7s", mpu); + print(2, 6, "romdata: %08x", &romdata); + + list = NULL; + break; + + case 1: + locate(1, 1, "Test list"); + list = list_tests; + break; + + case 2: + locate(1, 1, "Performance"); + list = list_perfs; + break; + + case 3: + locate(1, 1, "Debug"); + list = list_debug; + break; + + default: + print(1, 1, "Tab %d", tab); + break; + } + dimage(0, 56, &res_opt_menu); + + if(list) + { + list_len = 0; + while(list[list_len]) list_len++; + + for(i = scroll; list[i] && i < scroll + 6; i++) + locate(2, i - scroll + 2, list[i]); + + if(scroll > 0) locate(20, 2, "\x0d"); + if(scroll + 6 < list_len) locate(20, 7, "\x0e"); + + dreverse_area(0, 8 * (index - scroll) + 8, 127, + 8 * (index - scroll) + 15); + } + dupdate(); + + //--- + // Waiting for events. + //--- + + do + { + leave = 1; + + switch(getkey()) + { + case KEY_F1: + tab = 0; + index = 0; + break; + case KEY_F2: + tab = 1; + index = 0; + scroll = 0; + break; + case KEY_F3: + tab = 2; + index = 0; + scroll = 0; + break; + case KEY_F4: + tab = 3; + index = 0; + scroll = 0; + break; + + case KEY_UP: + if(list && list_len > 1) + { + if(index) + { + index--; + if(index < scroll) scroll--; + } + else + { + index = list_len - 1; + scroll = list_len - 6; + if(scroll < 0) scroll = 0; + } + } + else leave = 0; + break; + case KEY_DOWN: + if(list && list_len > 1) + { + if(list[index + 1]) + { + index++; + if(index >= scroll + 6) + scroll++; + } + else + { + index = 0; + scroll = 0; + } + } + else leave = 0; + break; + + case KEY_EXE: + if(!tab) break; + if(category) *category = tab; + if(app) *app = index + 1; + return; + + case KEY_MENU: + if(category) *category = 0; + if(app) *app = 0; + return; + + default: + leave = 0; + } + } + while(!leave); + } + + if(category) *category = 0; + if(app) *app = 0; + return; +} + +/* + main() + No need for description. +*/ +int main(void) +{ + int category, app; + + while(1) + { + main_menu(&category, &app); + if(!category) break; + + switch((category << 8) | app) + { + case 0x0101: + test_keyboard(); + break; + case 0x0102: + test_gray(); + break; + case 0x0103: + test_bopti(); + break; + case 0x0104: + test_tales(); + break; + case 0x0105: + test_rtc(); + break; + case 0x0106: + test_timer(); + break; + + case 0x0201: +// perf_bopti(); + break; + case 0x0202: +// perf_tales(); + break; + + case 0x0301: +// if(isSH3()) debug_tlb(); + break; + } + } + + return 0; +} diff --git a/src/p7os/cake.exe/libgint/demo/gintdemo.h b/src/p7os/cake.exe/libgint/demo/gintdemo.h new file mode 100644 index 0000000..1d32bcd --- /dev/null +++ b/src/p7os/cake.exe/libgint/demo/gintdemo.h @@ -0,0 +1,114 @@ +//--- +// +// gint demo application +// +// Displays some tests cases for many features of the library. +// +//--- + +#ifndef _GINTDEMO_H +#define _GINTDEMO_H + +//--- +// Main routines and common functions. +//--- + +/* + main() + No need for description. +*/ +int main(void); + +/* + main_menu() + Displays the main menu and returns user's choice by setting the + category and application. Category is 0 when the user leaves the + application. +*/ +void main_menu(int *category, int *app); + +/* + locate() + Displays text using a system-like monospaced font on a 21*8 grid. +*/ +void locate(int x, int y, const char *str); + +/* + print() + Locates a string using formatted printing. +*/ +void print(int x, int y, const char *format, ...); + + + +//--- +// Test applications. +//--- + +/* + test_keyboard() + Displays a real-time multigetkey() and the keyboard state. +*/ +void test_keyboard(void); + +/* + test_gray() + Lets the user set the gray delays and see the results. +*/ +void test_gray(void); + +/* + test_bopti() + Displays and moves many kinds of bitmaps. +*/ +void test_bopti(void); + +/* + test_tales() + Displays some text using different modes and clipping options. +*/ +void test_tales(void); + +/* + test_rtc() + Just a clock. +*/ +void test_rtc(void); + +/* + test_timer() + Clock timer and timer precision. +*/ +void test_timer(void); + + + +//--- +// Performance applications. +//--- + +/* + perf_bopti() + Compares bopti and MonochromeLib. +*/ +void perf_bopti(void); + +/* + perf_tales() + Compares tales and the system's text rendering functions. +*/ +void perf_tales(void); + + + +//--- +// Debug applications. +//--- + +/* + debug_tlb() + On SH7705, displays the TLB contents. Does nothing on SH7305. +*/ +void debug_tlb(void); + +#endif // _GINTDEMO_H diff --git a/src/p7os/cake.exe/libgint/demo/gintdemo.ld b/src/p7os/cake.exe/libgint/demo/gintdemo.ld new file mode 100644 index 0000000..49062c9 --- /dev/null +++ b/src/p7os/cake.exe/libgint/demo/gintdemo.ld @@ -0,0 +1,110 @@ +/* + This linker script links the object files when generating the ELF + output. Note how symbols romdata, bbss, ebss, bdata and edata are used + in the initialization routine (crt0.c) to initialize the application. + + Two ram areas are specified. The "real ram" is accessed direcly while + the other area is virtualized. It is not possible to execute code in + virtualized ram. +*/ + +OUTPUT_ARCH(sh3) +ENTRY(_start) + +MEMORY +{ + rom : o = 0x00300200, l = 512k + /* 0x0810000 is apparently mapped to 0x8801c0000. */ + ram : o = 0x08100000, l = 8k + realram : o = 0x8800d000, l = 12k +} + +SECTIONS +{ + /* + ROM sections : binary code and read-only data. + */ + + .text : { + /* Initialization code. */ + *(.pretext.entry) + *(.pretext) + + _bctors = . ; + *(.ctors) + _ectors = . ; + _bdtors = . ; + *(.dtors) + _edtors = . ; + + *(.text) + *(.text.*) + } > rom + + .rodata : { + *(.rodata.fxconv); + *(.rodata) + *(.rodata.*) + + _romdata = ALIGN(4) ; + } > rom + + + + /* + RAM sections : bss section and read/write data. + The BSS section is meant to be stripped from the ELF file (to + reduce the binary size) and initialized with zeros in the + initialization routine, therefore its location is undefined. + */ + + .bss : { + _bbss = . ; + *(.bss) + _ebss = . ; + } > ram + + .data : AT(_romdata) ALIGN(4) { + _bdata = . ; + *(.data) + *(.data.*) + _edata = . ; + } > ram + + .cc : AT(_romdata + SIZEOF(.data)) ALIGN(4) { + *(.eh_frame) + *(.jcr) + + _gint_data = _romdata + SIZEOF(.data) + SIZEOF(.cc) ; + } > ram + + + + /* + Real RAM : interrupt, exception and TLB miss handlers. + */ + + .gint : AT(_gint_data) ALIGN(4) { + /* The vbr needs to be 0x100-aligned because of an ld issue. */ + . = ALIGN(0x100) ; + _gint_vbr = . ; + _bgint = . ; + + /* Exception handler. */ + . = _gint_vbr + 0x100 ; + *(.gint.exc.entry) + *(.gint.exc) + + /* TLB miss handler. */ + . = _gint_vbr + 0x400 ; + *(.gint.tlb.entry) + *(.gint.tlb) + + /* Interrupt handler. */ + . = _gint_vbr + 0x600 ; + *(.gint.int.entry) + *(.gint.int) + + _egint = . ; + } > realram +} diff --git a/src/p7os/cake.exe/libgint/demo/icon.bmp b/src/p7os/cake.exe/libgint/demo/icon.bmp new file mode 100644 index 0000000000000000000000000000000000000000..27f0e48206978289bfc171e9aa03a16e1d448acc GIT binary patch literal 1870 zcmchTI}*Y$3`7kD9Ds(3!=#~tf^*Q(aRLs=eS+ehtT&2do6q1GD{E=>Bnxj#6MoE_(`y>Pd7r2hQmnFy}^;r(;QfBoJsgqO8IvqoS3kw3kD^}p;B zz}n!X0X?76RXvBVp0n$>{~!9Qj3cT;dJ*)?!&Ix7#AlVM)y1sn0m>>P89u!-m5(wc z%+~(HFl5Tl6sFu{nL-*jfsGLeAOR_9qG1H4n8$NbGUZkv*xElPSzdj3fFVDQBdJgG zzLi^J?aKQKsy>Q#BBVZ~Vd4{j#(>${pNUj)wrd)4!2%z;MK z!#~}!!1sEwODD~jx>LrgHvsR|WP)<{;yO(Ay57(wx8lV(NK}N7CQCFC&}xtf$Axma z(-xYkXkXudu43-AGC<7d;#Gf2`wQ^lrTQ!eqXz566Zk$@Kb^!VuIVkR>|5iz3ItF= zOyIj}ssZJz+r3dfodkBCa?XU}xyQs&gVLqpT*cgJgCF6l3R6H%oY}2^xh=t%XXneV{V+$*f7>LF@|4F?YW~NPS%*J* z{_CW)a~1xC!X$y7serBsv;%Cuf=T%y?>nzbMlII^5DiOO;D5oq4K;pL?^eLgl$gvI ozm?~p3ww0PUAKPxs<=EU-&NT_OQ0pt5@-pu1X=r7ZTmdz z))xB*UN8IC-S7m2h5N?`zDNwi=Jow^#HYUBhr+K~l|Us>2~+}=KqXKK%qD<;9%k=v z=(4q{|9rAsQZPmBs9P5JzH%~29u38%)^tpI7p3=SoT)dsWh=J5(y?6rOC+klqA;ooK z%UC}5-b$gGB!Ta3@lu9XmUd0n%V)TCp5vSe#Y>NgQj?=w!?_c4)g~X|tYrB=YrG|X zGy(qv0&}5jgg<{g9Um3EZ~?q&;vvjOP}${y0u+!3XKvQN+_r$8eP>O07C*KkS7cy} z3myRE#BsP%O@WZop9`e?Fa43_CYGxfo(1Au;z#25*IZY9An5mrunSV5T?|3Hhx(;Q z2&OOhAaRm70{HI5eV8NqdP5hDIVr|L;zZ1nvd_)Jv>HZ)9cq6ggFZ;;PTl1-N z)j8;F;;b3**+ra=KH1P%ZjaYb&%U=KFr`Gaq7^yy^h%`xD!=LnlRwh*3uqrwHwb72 zTSO&>b_!DoewI9@#c28hZR)Dhr<{mXVqQ=7fYDri7eJz`^QHd&J6D+>t>Bk%sl9Gz heL@QBl3l;rg5hEo_!gP~=n*sH`xxKXT literal 0 HcmV?d00001 diff --git a/src/p7os/cake.exe/libgint/demo/resources/font_modern.bmp b/src/p7os/cake.exe/libgint/demo/resources/font_modern.bmp new file mode 100644 index 0000000000000000000000000000000000000000..0340f76caa3294d8fa52e91b46611365384cad91 GIT binary patch literal 24698 zcmeH~J(d(l5QJB9G3DqudN^1(Ispg3lZVAAxGuy@s6S$}x@vls?wQ%8>b)%@A|rn) z^%}A7KYsc2bUt5nf7Z`e{rsb!Kc4>9t@G*W>92SGIdfg_Km7aOg17$pXEA=CXKr9_ zU~XV;U~XV;U~XV;U~XV;U~XV;U~b?y*noZ=&Q}(?F_gCBFu%DU*W&h-%feURSj3W| znQh47drIaeb`fruvZ2`0qY%d_j!Mi5MZ{SErARM^BWURb-2!qR{1U+zK{1%FiteS5 z53NPPcu+E$7()UKfQ%l5OE2gc5cO1JDi4MNRw-g8CQd`@1rMkz=r)iu%_%x`++BK| z20EYYxMa?|3N~vIqZcyk(Pi6`G&`$IsmVqq%EuhYEfTlaPIHKnE@zk9G5`cT9 zPHD^Od8R%$FgLK{2K2%0SnUO+{Ka2P+-SR4=g|z~{rlB;3iVqo@~+m?8ZZOop_;&$ zVkowv_o6hyVC63NUgL{*s zUj@p{)JtWy#xn4ZMNP^g?%@=g(d3+S>JpoI%21@8_R zp2}Mk%z)J_N7Iv-XJR8NVC-AY7SM4oKnn^=@j($N%3@jh6@aYPgCbyCtI#Vwm!x^OM1Z47sW8FZz}&#EZ{T%(T(4`|E&p}Oi$r~#yRiD#^=cFmFeoLDqIMdO z&D12tSxLcJ*fT z_;n5u9aDO3$+ahMx};cedJ-4geQ6oY6j1=ooJD~e6xz$OUd&^v6bvm^s2450OdsUV znf<8qJD&Z`%%~2L(o$Ejzl~aXL6iXsV3M((eT#F_xq-QXJ8q!&3Ey#~Yg@nSCzRp8 zEyqhBy2#&Hjzbuv3v-IiQH%DZf;mOmQXk-+6CE%pa<9Z$49A3JpZ|jK(6>;En zsNAdR#gp_}f94*F$Ab-`4i$r_PnlU_DyBu0p(xPe7xl@SPG8k+Q>geKfsUslYLHZz zlMj@b?}D}fTQ7tzXX2JpY79z|vH3R9@km4spqi~!EK2to%wG(mn8AQvFH)`oS@x>L zX`UOH8#rPE`AHgc3xL(yI6=;H_WtiLdZuKNf=zpO)_hBtC9oxw0t)pK5DP^&*m7ru z*6--syY*5(R!>W8>i61^wssHB#e*Sp2iWOuN|E$a@Qs0dV`8tukL~HLhvhiM24U0j s-S$d9mERaRt!DWbV2d5H-r`(EdWtUU+yYW`x(%y()|_~5V3!U20JdRy(*OVf literal 0 HcmV?d00001 diff --git a/src/p7os/cake.exe/libgint/demo/resources/isometric.bmp b/src/p7os/cake.exe/libgint/demo/resources/isometric.bmp new file mode 100644 index 0000000000000000000000000000000000000000..5241b601dab9bab756a145bb1902c33287acb879 GIT binary patch literal 4134 zcmd5%J5EGF3>%=N0Ev=@1`e_f6%ALR3Y)uyC&`jxW(2t6qBaw>JFL!&;#YRGYpZO6BUH4GQz?sK+ap#_J)xbXU z3oL1HtX%|W-ujN(S%SCVB3~}%)tl^7O>$K`-;+RmQ^q-?k1}O_*Xwe(v;>D#HKZ z!17Ek?|J7;K83tDI?fYXUCC99cUm>wHJdvRj*oQpKHGO^ac@Rx`pj$*tC<>MJ1ls2 z-!A&jXpQbD%j$h*wunWhEl=R61>U0dkT&$7e+}YUI4dUiq1gan28DUg@^v=iH;lUy z{XWvwJND4UjPe_>T)eC0);()r4nAh_3ydb@q#YVs%{%hh?EyGi%{wFTN$uEsw@gw| z*}ERX$?J+=mt!IkD+^9$W}8qdwBi>Wdl54Nao;l8iH8UE`SILyC#HR;=N3J_ReiW8 WfrjgO6XmSq9zSx=8ek&U^ZNqrBFN|f literal 0 HcmV?d00001 diff --git a/src/p7os/cake.exe/libgint/demo/resources/items.bmp b/src/p7os/cake.exe/libgint/demo/resources/items.bmp new file mode 100644 index 0000000000000000000000000000000000000000..c57f9345638707c12ffc0d6b4cba05269bbbc3db GIT binary patch literal 99322 zcmeI2yOL!+QiXdk!NlQt#=*iNV%`D|j~Igp-iAlS8P?g~+3U|rUAClind&-H#HdoK zbxEbPtNU;G^S}My|NQCKZTy%1_aFM-KWh0`{ruCff6@Hw*MDpOpa1FC@xLRX>CgZA z@Bewmqd)&40sr=Oq}{#T9r&mYeEk~!_Uo4uw86_A><)Zj2hvw?ejiHHjF0+du@AdD zkUHS6;0*LrkaKlI6YqI<;L|$5x5BCU5RR|m3~ygXgnU|i_IW?K1Ah6%=itwR9hRTm zs(toP>p*<@@k2Rce-IJ%X&u_<{p1d$m(TL}I2_WRGq?XMZl=-bGFwi1}7DO%ob4iWEGSuu%1OFtqV+jQZ> zvdCaSVVaL2l70?SM_{E|%s5uSh?>fHdG3FKIcb=J$SRj)Ai|3H7_-}-(Rm#UWj|5{ zs>dHn$CttchRf_^>rem$PNPLsUd2ew00nVL+_GbLFwcAQ$3h zyUi)%WhW3Qm_y>di7a=H4COs3ZuAG9t@i0 zZ15%0TqwxK*nsB-Hd1hY{7-a1GYZB`=~(WQ4usdPhFFneKsCV5 zUZRt!f*()XPQh!wk3;w_u6n)1j*QRYWSKV+a73D(SXE@H<4j94>SLj6iOJh74_p*R zdJYVhQ76XQ6)a}7#7ML9Ek}r&0fPiA1?8h=jJ2gfZE+?ak&2ac0RXVWLYag~bapk1 zB?6r5*zx;%oVek&94W!%cN^0=(+!b-CQxg6y!&bvs+xCH69 zpe@CIVi8Gf7bxgMVQz6Ta$zxOQS3;7qvDQ{WKmO~0Z|zSN%GzW%QI7hpOvIOQnJG2Fcs9U+w)*bomVt=8g1B{gOSb0GalIWD zF0v2?BflfuwX|leL`k-Qp@30~0$oJ7g2h2TS}0aB&McL|DD5ULL?Ow`ivVs3cE++U zPnk=W=?j4!6@(KnC{-zk>U{!GW|Vib#Aqu5KqgpPMvS)zG?!j+%W*%Dh^~km=B|{v zqyXSKFn8|Of*>s}iZaZ`cvk^Q!<30}m126@6;UH40XwN6!qU?9*doz&7Dmb^yp}j> zCJ>9HmaQU7k=YDhH_O{_6|*v*hNoS+7Tpq;L-#s;h=5j{=)iag+KNH{ML=|6S}JCl zEYdO-##V=gZ0RK;tUg!A;Y6B+JXZBT5ve5BrkH_O#|ZB7EEjQu8;NDTk0PFJyZDoX zo)}yPt)_7oJR)KA3Yf{TTjgS*Es(}{C<4P0I1Q^MFXdH|h5-t!I`pe@YNfbRO<0!dv7i9f;3?cO==E?6}0Y!##Jv$O5pDg3dEHMHpfi<_v;q zb}?mzo$n)xm>83X!U59oXN;oA9Su=-zT=l0as89X}mhrnfyLsT)^D$^}pYh4NYLYK%yjKe>QKCM} zkEjToeTk<5}`F@3| z;DsgnnvWp?{alb~QBX_sVRf5eIk39{-f|EzrhC^!whZvnfJo6UODByl12BH+5zwc{ z-S|3UzErF3R+Hvx7r^lfzx;p1k~cC2Y|TDE8ztqmj7EyJ8$00L4vVd_Jk+f4^Z;MY z$9TG%R9!N0%(S*5rewuT8C%mqsm501#*B%rz=Gu^d#lRTEa$K|ck9TQjLYJ^n?5h+O>stnWA7@cCJi`9 zw+H1XZ@dG*TB;ZeD%OA==cH^A(`^)yjtKz!%P1*=S=kheu;uccFIjPGEyhdpF<#-Y zR@d*sQrldrZ_Lf~RvDPsXCb8*B!!5Kf|iO&Vz!ti!ay^zwA60PLU~4F*%3{a(IuAQ z_!PT;fA}gHMFfss)h!#LZ2h==Fs26F_n#k2%{-fzKa@+cc;~#176qi90{}mz(mE*^ z;6Q-ZvjSrUQ&M1n0|BII783 z@CVY*F5Z5QA3w7CL?d~6SnxU)?8YgVNXq6D5tuq*`74Pc5#W4G#;*ZE&G9?HD^dig zdRc!hkcEgCo#C3&X1%Qg=XKqGzRkB~|EQtXK;#eYrxsD0Sp?^kJdGg>!KzS2$ke$U*uTyg2Os_p5%dj$O5C_McS66KnP< z!SZ~VUr*fRn%6>+3lvV2Dx_@9trG$;tAlJQtmQGn{RQ7gJjYk7yCvOn?Z!Cc;7&MO z2$EgL38P(awRDn#VVwZY(yK$!mhisbJ~HmwD<&`F1uu-GJp1)8c*!NPSkfO?l8&i7 zTMiQ770c-On(rez(3o@%03;2b!jvp)I*9uHI9ZoVX=?bfD=snBOk`C7)#Te)GSbJP z8ho^BJ!SGK6(S<*zPn&5fVr&X=^5K8c!6`&jBz~2%{Ywe>9ubPahWk7DMaKfCgM{p zS#GkWpYSZrs_wRuZ)0(m{tK-ZDWd=H+f_g{8PA2aVQJ~Sg2;;bSHzT|`52f#(MPJ* zbc`2E?_xTIF(pbN&Xxgbd5MYmPAr|Zr}Uj!G{#SGPb6JQq5ZqBF4#)Ktx~E2p-ID!BVLlZLm3p z@rm@iA+Yf&ICd_&3Pu)*+c#aV+7sXxsL}q{0QnTOe zc+IX*fyT%I4I6pv7EG+0*)a@optKJ{QkmG07SRd{go*PACDKP?TO8tc8=;P1kO%qI z>hKG9m5}%CuK!f+*{eI;n7qC5rG8A3vHX z8q`C1#7??YWhAR%0JTMy!PNjwbTm7tf|rw$759*LxGeUWME7m{ZfTT=qUeoG5xFZV zOcC*dJ4lR1ipMY4V4usGD59jl59Ps_5|P!|n&?Q%nJRuQiKgabNJBr@ls=PnZ`}D? zX8d|-m*~1!jRhjyL88Dy%7}sqMy?FJ=W&V;C~lRdyvm3$T&mz|GFCNyqN-FYN%5zV zP$XLLo$q&mM)omjmxk+lXKz?UQ3k&cnfhiSdYS5}E~mUu)~s!AxBsvm=V)gU{qT;1>q}vw&w1@@7RI; zef*BMwrhS@2ln^zu1^0jAO2D_d#E+mtjiPe`}=reGiy?7FJg@)|25(QOO&a9P@p$! ztmSjnE@UpJg6)2Wa|$1Zo_$JdFJg_wO}3sbl~?OuvwJgZ{9m%4_#|~kx_b1D@QLz2 zPio;&EKs##a@Z)R01@09oWmJTQp&Bq{oT-6FvP4V67{E-~N zM^>amA`>x=0eG3j(-K$*Z0i(=GW&9?6eSr+-%IVz8o})lwWU{9mF=)xQW?CN_2y4R zr_+%&AA_*$!Ez?bDz562$6^grvaIPK>c=<&VhpA=3z?pnG8!$s^4d*zYrKP!uC1z( z@){-H8SN$_TjWzEmn;LSLFuK8N0p+a0I5PKEj)Q)Qt@Uf=yMl#(Zr(heiu|tvAi-d zHh}!;fBR`~Ks5pV+G7+^!rt^ImV`Ty_qkfE0HjL$E zPf8XAMCCFTD}G6sGMC^-GFDcw^lP+ljwYCne%k7@BDjppdZLI+ECrF+XR#}Bu_yqYm?59$Xg7GS=mniR$tV4|j9$c-6adl}9?E3{ zqvLoial8&6!g2N`5_w>@Dp_f(&obCBXRPe4XdPn%9B4PjmbwhY(nV>^z9X~XUKSuD z-gP8ivH(Ez0a^Bs7VQ$fL#(pw+aekOotj%<=k29HV~}O~NMPC5I3Q0UU#$+m^OssW z*?sT$;X^nX)l!@=k?UB2U|zOj1NwpJdOI3=vn}_k0${)NK`wThAr7)sfQgD#EtzUz zP9iQaf%DZs81hw?cN5pj0CXq;6!$BPEWps6PcDxvqw;IMz(=b4{#^RUBVrz}S=__rqnAXqBvT5KVfXgPzy4c5pB1@^6TRbg ztLAvF!Z>K*AIT$rGrNsfyFF6r=5jk+Q;MgWb6oZH7dZ&Cbu7%u!N6XfzgCq}usoN5 z$1@!2w2&T&$A!1T2X^3mN4K8~$2Wa}`yvVlISZ4?+R0v2-Im=Q`1^KXe;dty-!T+P+; z5T_epG^e0S6eji%orMYyw`Ofs>$PM&)c*IYZV$PWc)iM8-fesWG`nl^$ELvX0cvB= z%Pirc^nJCfkB`qR2A7&k{_-6-rXe%cC8nT%nJKLQ&mw5{Og4{yqkJs#f`W zbwwH?U0#s@fa&yr&kcf??Cf}HWERK~JjLLpS%ZuVW?9aFU7G-x6huUfEGJ8gn29Wm zG`re}d}55g=3_`$Kc6W7Bc;?LUoU;TY#IQ~<5!9@c*e*RQ|7ix(B{KR^1tI)8c4E#2+-W0&yPPGA2L0xx2GuvZ0s`Sm6R z6=|Juu36%C=qKutc9K4?MMvROli(5wnsCS|c7u7%gKDTilW*ZmbYM%k+^vC7lIO z@*{dbo2x$Q#qsFqT)f_qvs)ovZ%H%^7iPgmSf(h@aJ7m{BV`WMZE_5(?*&FI>yNO& zixRy?dT1hc$xF$YXZI;{Y|Gi9rwIR45jRW+Bp$im*bP|9^dF#L47iF3Mp(&C+z!ji zVi7yjVF8X0^AVPeE+4q`!NjVFwdE1d{&*}|PI~AQKCb$+6}Sq{NdHEzH}*su9?m z_L&q~s9Wk^Z)#4uUM~|YEe#ug6rwOFuR}b6_jjiy?j1@hPs?#uw1d^}p_R*Es=~77 zP6jW{$B5_akoH#UfSRXF|9TTeOR@B3HAK`vq=co6VdE4OM1;$nWUEUfr@S6v$w&>c zLbWO-1psE`RD~_sGLOFIW8hq(cIL7J>Yp%!*K0LcT8=!5k~RJ)qR}`@jwZg1HPS;> z<&LdY=w|i<#5Ery_M^|+yJZK|LM3%?nu$wH%FuREG+z1uF>-~2E zgXfB}#IqG%)`P6(V+gLFm!u8obl~2~`8N6rI^t>T`+Kcb_)b=8X4-&biXBw-WAdG>=(`Zp7R|?yfPOB>v?x&)nr5{}s8#efqun-aa z0?QS)PT{<3BN+FJ_(xbSz$K+X05D}Ylwl;wQ<_@1Cj7ZdUe7fELpdz2}BN$Vx zkXQx~cnQo)1t?f2;;XTdx*5kUB!Af0MZqNtFhuJQvM56=(WksHg+Azo#cYLU#R?^2 z9cqZPw#-sqq`{6aSyC|A^gc^4Jt7V8gDi~1l6cgQaXgM==`&CuKg*J@h-OL9`Y|}I?oU+s z$YL4s&x)z%beC$Yz%|3DW~)*vZS`3O8|I9ay+y`L2g+ZvtX2&~M?t&3-YT+8LY!ia zc-;y*h8?vczVx~?zy6NAWZ6haUb-^lEKK7k63ei78OVa90>@a#Wl5aP(7>}Qu}RFz zwD3{wtJU4o#Du(WpVv!aB%vg{lM&MwH>C=5vLCn%U5n#BMY|xUC}t^`BD$)VvLwzk zkB|Mb4;)GrmMoWDipUEhfzPFYQBsyOl%e?;*e;8GCQ+T^;JO^gm#qK^WtJuJ1+Q1L zRFa;#&oWpcc+Ke(u};}ZDaW&D$pERiq%3D#o`SD`wk}J4Ad%MT;JO^gmwf=q-OjSs zyk5%ELG;F%Is0HYbaqDkM3iYYkdCn{7)!k3R*OEBrwq#5-^WzzzJh(94!-W!S2SLG zTyGszWNq=SSbm!dRC0Xm#R+nP6KNh{*$5Tv6f1CNvcc-wg(=wI$7&bh9WA`Kaa@VE z3qN(ekFa=9R=6w`u7%9nM2d`l1EE+s>>5q5`<8gc;fBdIRt3q6~t3X^}4qB|KJZfiQqCQuC zs+La%pEoe~%jw&)^k8+HJX?yKy4=BY@qOSW{Xy1jB|(`GfmgUqmA1jV1MlxZdiGkX zhBHa%IR=XN*d6%s9pHn|G5uu_AD>7FU-GxPAK%@5z~8+C@%uQw3IF-Q#}Q{^fA>T0 z`gaG$I}kq$vG@wkzh@z1$hhi8?hgEz4#f8#z7L&`6#=L{?+$!m2l&=?@H612zYH&T iusiU99pG1j4}N|pA@PB~H1?5q2kss4hd}V_*Z%{C*-D!L literal 0 HcmV?d00001 diff --git a/src/p7os/cake.exe/libgint/demo/resources/opt_bitmap.bmp b/src/p7os/cake.exe/libgint/demo/resources/opt_bitmap.bmp new file mode 100644 index 0000000000000000000000000000000000000000..c776021b3647f47a5038217020d133593164f535 GIT binary patch literal 3194 zcmd6jJ5B>Z5JcBRmP|(C^Ee?Q;T&XSj(l@d@)J+3*$*rOtXtZ4O?6FmjZZJ<$Kh7z z^tXJMeEWR6;h3Jv{OQ04F$|~Y*Y{8S-QS0?@Y+{n!)2y#+h5&Y&ODy}R*pDh1@IVB z96(Jj%}B8_0V6bAuXxgM6Vg;Bhw;cm=!*NJYUMgT8%Cu9K$U%oBcK|S&5ucy47E3} zGqxH)XL3!nZDPo)Y&I&GyC@Hco@#uyJtmSlCvnXTuFQ|av#YL#(OkjY3iZ`w4r8nN zoag`ZKGSS4c6px0k!ep_9RMELf^$e}a#2R|;DwG4-COqn7BVNEvB3?~lb^l)4(4xw oQC(5rBDp#6f2i>)<{@;%OgodiVl8m*+KcLSxCdaWwV*Tn2U6elvj6}9 literal 0 HcmV?d00001 diff --git a/src/p7os/cake.exe/libgint/demo/resources/opt_gray.bmp b/src/p7os/cake.exe/libgint/demo/resources/opt_gray.bmp new file mode 100644 index 0000000000000000000000000000000000000000..87ba1c74bbbde44530370f05775079654dfbacb4 GIT binary patch literal 3194 zcmd6jv2Fq}5JZnukw}*&-$Rp%hVP(DN5u#7PhrHs)5>dGcZZO%bY^z^c36A2KYdNN zb<%#+ch>i*Z!`U9*V6g-)}M`O+Wj8>9(wNYM+X0&TRE`r;+R4mJs~3`xJ_#Q&Y1$=*zd!R>%-KDECgsbtk9K*p@0;5rKua{Mm?Nr3g-Iz9 z|Gh{U`~Jnnnc048HBiEmvkNoX;BKhD`A#rOyTDM7;6_h&W>reeY<(8gRAyGk7E zYDq$i>HBfc7AeL@2uKMMhQB|PEEU{>YdQg6WuY@^Ct^jHORz-=z(u=CkE(s(`{$|V PI7~hVt}<_xFzWrUb>^3l#R{wwyy)l~t#HuB5JKL*dJ z0NUP2dr8iEu^KZO8KP2vrPl_}$b?PZzv}^5)rAEtk0zg2+>T)6O~7I`K|xqD?j<0z z3UVM`Dw$EYbN^*$H-zUPlC)Yf2wYmlj>u7lAj>k7`CdYf3cVHqM(b1ZDBHPzR`MXM zDhW?pNRcZHvT#~aR;zvYg zWqW3%`TX-=zkIqpe`NhFKY!-u$NYTr>4&W0nScKsKNlg(=bwK4{R!Xt`R!`_``oh@ zURT!LuKU;N8*IoS*Hhi15Hv0g5T^&+z;Z`So9d6)k68et#!*&!y&-;k1d1w_(C-?( zaZ^h$Y&HykSBWqWSx0L_8`_4mr(krq2pErsp-Z1N=-dOG#OWw(iqo|t z+Qt+*oWqkTam@loJzX*7=;EebB94K_2;k`YRCD;#jSeTD0`IBe>75RLdI=xkRc;_( z*vWm5e&y?S@1WuCYb0n~8X(S%fg5;@+8zS+uX)pf%>ta#56!9#tgT0f8b+ZsVBMm3 zaci7SDQWXs+seQMjSm|0P;}a(AwcYuh8~Ian7RV&X>eZy2Vk$!FepxTWbG4nLt{%i z(qdx^+Z+)c=N|6qCGnWTk78|$j%+|_k3qnoXBym#?L5QS;ySgYZs0XujE`R;*r0%5Q{#4;#ipUD9;X02 zJ#A%dA?=bYerib#n+@nv!Ja-0+U&n>a2jA_06jwwMcFhs1q{k|ihB*%oDOR9o?+9k z*?2&U;s)zcdm2oM>j0P$SF92P4~4-4464}%K-(OxZN$;FnbofX7?hHTJf;NE^(Z!Q ziu1AP>kmAnzMed?E{r7AJe0L6iVqE;1K6yNClrNs?LoP?9-VqN8@kQT7D-w1PH}K|6S@%tsX>((5K$~r)VYGa@=d+tl)JS+y&IUeqOCi-1hc^_ep3R? z#skK~zC&#Ktf9@Dm}7Jg3TE*D!{5z4ir$nGS5tUe2ahu}Z3DYdGVmVlz3^nc@wd?M<=%(eyZagm8kYu$vjw<;-B^kEi&Q*3Y((D7`;=#1Z>piAz({x2T8+r)hg#ReF(4I1ZAbXuYzfTu@MD0v!A z&zM4Oa4N88^)SMzf0OF8jQj5rU6bj7TpDYz9Hx~GFZ6=>a#eT-!t7>%VyM4-sm7^|Ya}&LOG;ng;W9B)F*t#LIC0^U;0`t)yYl z$6fdJVK5Gm+N>g28!}?*DxgOS=!P*0RWXa`Y8=Df+J3Nwqao8CwRzQ@QbM*1)%Qjk z0`S-=XwQmUAz}}mdvxvBxdL{vknGxkVXR~|4-krh6jV=-Rs%L01f~GPHm20F($K37 z+8Qub>7ZDk4G^6XCDKjM5e%-xG3>2v9{r)+03DvLZ38wGJ+=vKQyIWcbg4m=7!XnH zkq&^F)Lywd*^a2tz-X+*F|=(}Y-<3fgl02$b<`=bQ-abf4R~x2&>&qK7`esmpsNmHw>Xq)^LuLO_d0~Vgb(m4 zH;^yu2ob;)6ab#!sZzPN7E;FjeWG9z}tE;{oSy?|eg_ z=XUIyCKAlkILe?XZlM818X%^jdyJ2fx^WExMwH_}e|zT}JozEeZ*eH7`7Jb@zrFJf cUdSQf@6u7=E=Pm<|HFp!w|Bn5*Et0K0nW?|&j0`b literal 0 HcmV?d00001 diff --git a/src/p7os/cake.exe/libgint/demo/resources/opt_tales.bmp b/src/p7os/cake.exe/libgint/demo/resources/opt_tales.bmp new file mode 100644 index 0000000000000000000000000000000000000000..8f34e47611f921da87495803af7ba6fc505c87c6 GIT binary patch literal 3194 zcmd6ju};H45JU}CBS5mev*tB@ie;4o$T01KIztTv$L}!AK%Z< z)9*Q}e(HYf9&{h3S5+PLU!HtTOw;l0*XKij({$ zPVzn6^S9nhvo^fPMWQk2t((c?h928&3HwQaMsI&pQLrdB*nP9GCV7m0`@K)M32KB0I8OOmEo^x$1QvS literal 0 HcmV?d00001 diff --git a/src/p7os/cake.exe/libgint/demo/resources/opt_timer.bmp b/src/p7os/cake.exe/libgint/demo/resources/opt_timer.bmp new file mode 100644 index 0000000000000000000000000000000000000000..1d7cb9c5bbca8614c0a4c3e9f6933410cbd7e88a GIT binary patch literal 3194 zcmeH_u?oUK5JXQaK|342Crv6Fzr)ThRsLL;3_gYp0mGH+!ChwOb_epf;XYm3vZgqn zvFF&Q*oStDGgjPR&)PCt8^*`$tAG6-*NyMK6@h&LrKd&D8M+f%3r497KOEgAK}nBh zbrM)yh*DxjiGXl&V7nIHDeX>i?EF4tfP*8X$#>2Q*=k5Rq|vYO;-^z`o?E^!Iy87D z5v3d#KKR$b6rzMnx6q?Z+C|y;`|!F@9}#ZzgL%cab7Mz-^cw;{+Wof%zM(DowmGP zZHW11&)|sKC-R!-UIcdgeUSYo{S{u18Z@j7BoE zL*!K)AOb_woHXM!udv?}t&LolH{R55at3*byov)vV2GNNW}M~~_IskWk?ZotoBB=8 zAP(jH_8)22&9|0LX!+MZ z;i-{68yODuzjKC#BH$AzY@D-Yq7Fnr1VkVsr+I~;PP@A^EEECHIAP40YPwonfH}c*Y4E=WLm%0}&7b5y;4CUSX)y?(Pf=MZhyo*f?j)L>-8L2#7#N zPV)*wopyI;SSSLXal*zqTPEs21VlgtGIE+%80xgUJHtW|@Qf2S&e<|i2O=N>B9IZG zUUA65D%YSox)s`<8evXMu6?LEx)pSDPmM4q!MwuqTT!WI-H@Cq?G$MFn9X@@Nq!|a PY@C1jt<8I0?!<;)xdY_V literal 0 HcmV?d00001 diff --git a/src/p7os/cake.exe/libgint/demo/resources/screen.bmp b/src/p7os/cake.exe/libgint/demo/resources/screen.bmp new file mode 100644 index 0000000000000000000000000000000000000000..050825a995dc236695e5926389a04c0d10130388 GIT binary patch literal 32906 zcmeH^yOJYC5Jd+tG5G;Lg;)m*hhM?PSbKkZQ4XBpL`G(HRZFcHNnJ6Tn|U8ukN)z< zx36#S>)Yl3-k2T6=&3!e$ z)8TUlzQPr6UwQ1$KKwJ7=g^O`c%A`$Pwo?3wK_h$ zp0ibFf8L8ceD2|mctC5^XhyUS?WOL#kIwskQRijd8oY6&qs{v5i@I9&R63k}-7LID z=gdEAUA>Lpz_s51-W+wO!3V~o&pG&6B%jgwtc`kdBhNEwabGX)4_c$1(K-)&U|!bt z)T4P>8}-%MM*c_E@?ClN(Vg(*Y-G@8^4UWc%({C#72>P3;I`I`XKThI>AtV)?hf`u zoqt^p9zQ(@-yuF@=QVFXH9Gw(BX1EnvpQeL=b7x+@p(??Cy!nso)MB8d7fE|`>(9d zKg(C|4F~!>6=ywaJQ=gE>z(U7&&tQ$SJud1Y1P|ipFPy8XCi0ZJ7XpH=-zm*m9^#1 zdiOodlgS+Y*7+(QGq+K9)-e=}!?>_QnjXscHyy1vP!$%Ix-vGWt`|+5g9%*=<8RP!5tMX2WH(po+Gf^2cA9Y z1HCezb$eIq)mfdt<2g_0c&NefxF%yBeHA?`&&%3TeVmy^4F*pQu5ip<#n{XH&E~7z z%pB*a!MwNU;TfUxm9Nsx9bM=9#D2Hp_MYAQug>6&$<54ih8i5r!81bgVCM}zw0ke_ znd_=I$C-nJ2d}xuwKG=Fll}CZ1LVHk&AzV23wAzueD^~34IHg4o$Ra+e}%W25p!l{ z;j1vt*UhN>6~`SbEpvEZ9phbYv3TFnEIbuPt~-nUdA_xkI?s94zI*e%@4+{y@@N%? ze{_~kt7cUk=Ru=i#l3lQVC)-pwctT}&6%&}%yOO?wfor_*~gq!%ya0wGi}W$58|g^ zMb5z-<7gH+dqx~uhs;5z--|KFvs~|;Im)qL#;uI?oON%X>+tMZ*Uql;a6S*`8zEZc zTzk$f>LX`!_SnO}nRDCU)iZPUcw)a;)xM*7xmH`3^HPbB3NQy%Fse=($nfbLG9OKA#6q@YJBWoV#@&dsd6HfR*Pnah%f_ z=W|b8@xBW_qxGupyztHh7pv0XLA<#qYYY#|yl0>rD?R74$2zkzM<2Rt{2-bUZ3Vmh z3U6<&M`y7&`_SN{XQ5@Z?mGK&UwPp=j2YGP?5v}ihhrXnc&O3Hna?$zS#;i+Ego;@ z3mpw_M)W|hE#6+&(HaGeq=#=;8rouppQ9K9UKe2;+(gSni;D|-g|nlJP*G;Ih!+G&#akz_PBS=xx8oS z{#kQvPo8PtsP>HPLxb;n?`;pYb!P3wZsr!xe)g@N%UR})5Px{Q7qxZIfyYOl-ukHa z%&vCco{G=hR_}A;^&Wd_<^+1J@bJF=U*KpN7Tl2_-j~X<$HRo13duQ}nvPOTaGwhke89-*x8_|xyd+l?? a**(+uh?F@!0?T(|^x#R3DGW|NkB@zyJBgVi&(3 z#E-6H_dEtYy?=jy|L|nrJ-!*8d7t%=Cdil08HXmAooc=rja{GhkcKDBy!)JK%!9MX z2|qRWJ$n+451QuMWo92#&0Y23(XIAZzWDJ--)Fw7d1kM#uTQ?a!%t0*)r^Ms+uPem z9%uU?eRg=bGCWDg2i@f2+qW-&9?{NO_;cTFz(C;g+J2JDoku^l<}^Do!e-m45eW?p`|%Y#EB$BK&+4Ly`2XP!Z|>&v^} zsXN*`zCBOh8QdG>+5FDfefZ5we^#y2Pp$b~-!mV6aFuOpacFjsW(RltaCZD~Xm*h1 zF3xwAb64NJ;`W|y#j}I0Tk(5O6I^k7Pq*UPLAr2f%^A&{N9QgaUT0kUAk7)qKB&&P zJ*Vqg>+Pp+^V9b^`tVot%>2#d-S_F?%D27yZ&|oJgDDyCf}O!VblEi*-@bkM^N4oN z!k=^JaNEDN&C$c~rmxI6L7AtoJ2Ox9`CEK*rzgI$q@TWc`M;3r{}VaW;=$gfKl5$< z*?ZtQGklG&TzQu%D93Yne8`e{b7XTFz(C;g+ zJ2JDoku^l<}^D?O literal 0 HcmV?d00001 diff --git a/src/p7os/cake.exe/libgint/demo/resources/swords.bmp b/src/p7os/cake.exe/libgint/demo/resources/swords.bmp new file mode 100644 index 0000000000000000000000000000000000000000..8aa6416275a5725e7cf1e5efc4d602c0c54acc27 GIT binary patch literal 5770 zcmds(L5>tL3`GMh*&rdY<}9;e#RjP*7Tkg@Czzx39XJN(Y4Sb(<|jB^Nu?KvXlk4| z@$Ymy4b^-}QRE;YoU* z@iGq21#g0-9OgEk$LgH?%qmCs&F^(#u6x=1E@vVhOl3s=1r5Qd`EJ==!M|}=p=p6* zF`@_S(0Qw4Qcus}9Wxo%-P`CfH8^XwzvLMQ42~0;jDa}3J9sd5^&p;OLX+j=d06VHmbI?fh9}<_ ztm}xybHO>G2eHg!9QGG1?6J9N!VfBKJbxzj%!I-uB&vp)5AEQ@2lp67n%7->j#xNfGV zmU|4{Q(aAMUXz~9<`K_(QawqJGX{MPi#=gs+GFhbK4W1mzU#aCXL{500J)vl_|Np_ zksQ}$tUNvBQ-HD zv%!KE>Om~nWYB-m<6t2c{lp-Lth&y0jC>8#b?~l6G4N{~&+Tg2;e;OcQhPJ`9)po; zsBYkF_gI&B)OIuFG}JwwGz*>rsV`DYHGj4%7tZ?meC8 zjn)?RJ(9E7W9{#*9%JE-cu)MC9eii?J>fby=+D1&SEvia-*4(2S@wndkEn~x_V?>TiGjGtggu{U`GO^pAhF{~Ceo@BjMm|K0KG z=RXAD|D^*#;!Y*P03p;UM|l+nkk+k?L*1uCjUf;^9_2&1hv^MGc_HSCPb^xMOm?w1 zc%ph@JWrw5q@AZ6)00faLz7b)2C1CwZ;&&pdoN(4+a&E|bI^fwW(A|%WpV?_69h&} z`%&Oi2zy769ukwxsX6aHQ1XBj=;kgw0f+v%BLtZQbBM3RbPh8V4Tn>_i`*SBH>ygG z@_GYram5>;e>HnC;~TyiS~|DB=nXVc1vIHZP#)z&xrg8V22U(nmH5&Df8`ta9*#LX znTm%dr^3=9{Q5TtJNbSqIIKGie}y;DGx*ZnhD_i?INaOGcf0|5>TJD5Z~m}9*im<6 z-9-2hKNMGei-zjF3qm)A0(4L)ka?s+R^5;CC~RgA!{DH>$<*fwASbVFu7jWDQC^^*^pM?TCdbbyqH8CQb9hfqFq z9@*Cp`^ZCW0RqX;1;R)PXHaD`pBcK%d1PNZY62ULFHCP~Bv=Qs3MCaEWb=?FHuzjV z%xVyUEK>?#cu+Fovmx~rpRIQNTS@Sf%`OimH3Dqtg-X%ZQ^L}S5y&YrLq3!Ane)iL zcIHixg}pSwWOP@&3WrLsB6db40COJM*G?YOn|puu3EACp7r-HulMyd4lm!x@$^l+D zG={;XgET{#X2}lDtkkY(vL~uuJG6uc0B>*NB>RLc!(pK-D?#8xD2F+Z>}zLt3D`>` ztm%{rjEC!0>q_s7s@IO2`QXB^-_=N*fyzUw;)84+(xeYK*H&2#B9N6z0SpgHCVV!e zzT&ghuKx$#08{vY3OSvpgryN9kW*xad?x8L=eP5!^CFP9KrU1YKsd-Mo-)tQv1h%- zoc|Tx0NZehyh`A+AirXMn@_$$9`NXld0uDoenS1L6{L5%CdjOOIZm5AHv1*Pks;H z^#<#ktt)-DbKgKen00V;t#xN8X@2e-pl3durQ(M>L0s{bPsO+HL$gIvvk-)kCQb?m z|B8n!r^pQXOokbTeTxST+A35}fvi*tKsd-Mo-)tQv1h%-oPXaNggy*$6JR38J|I(p z2_a2nrEK7{fXX@l);9>P5b|gcgc{#L#jj|**7166F_arju=fNW9+fkz&;e2&W?TsZ zA42)e`Mu_{83K4$_CZf&C9ZgyRN2gDX4e5Fue|{}G>@e#yvkx&O<3`Zwvx5c6`cT< z-s(gVS5Du9&rN`aG|%8FzE8rp;H?L6@^viRZw0=hW_0p(EL(u=#_Uym>+a1ptdp-} z*#gK-nAxlN)?Lj3G!DVLZaKq{ShrGQs5y;qJEEJ8W^~Y0n+y6)+=GfoUMT|HI;=)W z*%iEc67+o@U)mrz8oD93)UFBzGy?$0PxHNt@5HwG?%J5Cc2UDdgUbVXdDK7;WQ^yAp`66&n;Os`hRebC2&3#_*9y+d46(4HZ5u|`H z9nR$2Y;5RlIWor~4tJHRcrT|$w@So749t+&@3-@9w$|@{HR67$o0G&61_Jpigy#jAE#Amyb1W9s-IB3}gV37p+1xQcJxy}8c|-b2S#s^UW} zJAxDtro)-M&z3O9N%W1VQWfte)aX`;82X>a_u1626SvPHNkNsW_-qTMj(ds(IEQat za$7a`)YF)5y15+PKr$3KpVwe}K$8Yx#Y?s;kn-z6wMxZnp`k#e0QCw5&fzuf6ojFq zt@w3;l$QeRq2q&yd=a=OaCW2MD!z}0{vAF(hot6x=nPFtq`GR?s&5}`IQx)fMU|@f z-skoSO*rzrgzvMVd54eBA*p#EIzy8ZsluWvxr%Rtd2>w);QTAtJ%4cV0(jtIhWzmP zp|ALCHTTc@&okBRL!RS@6d!=Mr#QPa!dc7|ONv|7Zvoz9XjsjtNmb>_jGa*lz=TI? z`=x5c_-p2tPhdKScJitCAjmQ@;ssPlFyWDE2f_|F4hY2}5NaAmw4eRW|dP zq1Bwl1ywcv(DPmr?O_IX6`d<2Hb4?99t z@n&#`yZ)(!-rmIVu=AW$Ia>|I(&TJTks0!tq~V-Lc6%m85c-TEL@F~*vX46m4-1D` zS7z*t$^qtlu~t>&#*0{10K%cR;w7UX%L1PTbeQwVwr6OccZ@oc8etKHDuyBfgo9zl zyR6bU?|8iyRrMRVrDNFN%KGtc8AC;q@+<%&%`iI=gu)QYZO$WGzkxggXhr**v5Nk{ zUX=|4l){Qb4m_Kd6w9A z^=cQ&fZ%45ssiIBN)hM=Aa*fuCY@QqLlcrHr^EL45tykwq`dj`XK*|$bR`93Sg5R< z3k#@348fdtv9}{eR^`ez;NI>Luos1tLUkackU+8ks_Y@Y5^E9)`t2jAv?m{b6;$o| z6&yTKB4$`V%nr$kRi$S~WeNIMdYBx}c$5qcL!+UaO6KAqlU2oMH!AxZ^yu+_KC*lf zXd;0XLx}}K)loi_Go(p>1LuIN4nwCoDJy}wp4mQK{AKj)(C4Wxa8g|W3PZPD-UY$} z!7YcbbWA0giiakra*M5%=T$8*%sL4?6icJ5fKn9*N)M0Xss(wv)xQhgZSFM8c6)pt z{u`qbIm=B9!I018p-N#d7XhGZ03OdC#oZ&mfp~!IIV63yP%_k4BzPX00MohCo*ZSi zy5&eCqk^_#Jd~ejg;}dmpyDA2hC#`&-||zPGw;G-BDZDAnSeQIAQ4u4P*(or(@o<< zzlR8;Er#elR95^@JR#d|ll&V~&y8GFRs0hJr#BdSH`U;W;o?fepFPIENS;6@b9*RM_k2H<^I+uY}+(LoA;7FvM|9s#26B2q)=G#K{gCo zd&>8~_wZSO8FE)*zx#}jKM&HggaXH24$P1OV!v5_(Hn%JG?$Oe0sEM@XHZrt6$XZ4 zWdjIS?|1`r(9tXcNC~Ss$@P>9-HLeK#G886cEH?WmvJ+Q6$0=Chd?5vK!7G5x@~sL zjMoYaWdA-wa9RxASS28byaWO4>MOU3KkgqYzAda4t@tPAfA)Lu#t|k{S6wQ8Vl_#@ zZS)L{-ux|dk70=m)-fAR+T~tkDn7KPGw+a6*s_RZNx&kJlDpE$=Wy^3p*)>m!NWq3 zUMo%GnN%Ktn1Fa&QGP#MR$Zwp2QY)bb@wtF?XoAq)La0>c#SrKQ;K}}tm!$w`;SA>4 ztPhOJTl39Dr3AxJZb6p$jdcr#hSOc;nnBe+D~C*;&KWPM8dW@N-7RDH2fpGBG(M;E zsf7bzs9O$V94Nc%&#I^1Kux^!B33QIJcOqN@(+a-A7sOjwHLjCCL-XjA{mC|`n-=n zRH}7-Fp&m;*zfMCR_lN^>v~tJ7JxVd=$TTXlwt@nuR;Lg41zxe+iyeXZl9rNsLt74 zhMs<_#L3(`Gb{}J#H32~E#)K-I)LZV$j^abf-p2f7&K&t?NqL8sFgq<`}YxYrg9bk zE)b^9wm!aRE8aE03;vMsmxHO!CWldvWhYYt|5eeZZE@177Rn^<%jT43^M!o!Bj!e>HDW=b4rZMGIp6T zfs5xUC?RmY80Y6Eo@IGshOQ*#O`y=5H;*`4_LMA}xSI-HMlv%)-etlB3cVx9;$>Y$ z+_Vop3rPlnlmZgSR=|DarYrytWj%U)W?l?|ZU7!P+;R_F`^t66Ks%p*AFO z04BLXWL+=}NoHB*gL(ER)7#2`AXhu%V)0Ho9tuPbK`8f77=^+a3~fcazL8E4%brCd zop+M5;SHJdsuFNd#}W{PTgt$PDz+A>DhEvyY&?(DZrD7^iw;V!7;>J_m!zj8P>PKB z#SpUejq=i#fBcSy6q-{oxr2tG-}IEsQ@}jZAl$_i=$0OUINY7?&2FER5J(Ad3=jq3xhoGU(*&%-|3Ts6;j zkMa}co~ztk^9j7yx5|_EiL%nOLyVFkpUI$Pm^;oH*baSiyDc+urKJQR4BfV__b6y& z6@Z*s#;nL7o`fn{^r5WX?rQW6&QmUSrQ<~nO4N?viQ7wLC|jS37^!xo6)i3DPAXIh z9e9&;CSy4V0Hw+a6lRk-qeAxq9-eN6BuAi1m_RoGkIOoD`=pOEhp@^C6dp41F^>31 z3&2As;M{*A80xcwGhRYxzg@YG-GMmQg5Q!7di7QkBPl&0GJvBR*S`ygkrZ}+5{Nt_ zQat721-i}n6EaVP&{H49dwrS5&4XDS?1uB%Vda7lPEr%4S7jUu83r;}^`#-C)^Erg zeP6{>#3R247c?P!=u(%7(yKB?p=yQ2WPN9-^$HaY0ZFB3gK&6yliTM|0Fo&Q6apMQ zaua~Vq;L0k2`l_o)=6Oi9`@|f(x;aQ6DV9VGLZ@=KGJOKK=Y99(fucc5WJHN&EuB! za0PpbFoD7qAJ?dG;v-EjlonukD4e7u=$5OW@RT(BD|HC0_;}xD&LY5Ez03G?mH4Q} z_3y%avoVium2kozoe@??OWva2>&tw#sE?2}o?XF{Swc#o0R0sTtnfiR8Wob^f!6sD zA|*4IW$ZHH09Zxx?HGokT?&2bkesJ{WLIW9S0alN-U2FlozL@-VT*RVL=82IKu$SB zS@U~b!TFJB$V-F?LJ0YbytkIQY>O|v@?JsG#{uT?CXRc4@NGm&N@0Q!vajw8cJ*rH zwH>P`01q?3UPqh-Vq7pJhi)QS;&(Q5TUV~|Y6Jki!iHr)pirs|q@*80YUaGek_qG% z?`6~|0FKmu5qv;l4#K*CMFtR>Aapl|wDS8Zp0o8YhGx$rGu7qye=S!+FXWcIQ5()x zJjQ6PH64I(Pu^w~FEYp!QWzAJy-FVqP1p!+&rX#Ipq+L)a@Ezo^F4$ai-_L z;?suoc|?QM_!Q)n1OPn2%E>Nye6qzO?&wUu_429JTqMRK7H~}_`x=i=w|cM*$?8JB z&7c`8zyXKZNh;{WmMZ)XJ`8&_94;{=k2;^DZ==4_YPjnU`AfdQTfPUcm|R}l|Li|E z2!H6$)qYRa%WvST{F1*1Zx~u{;9eqs3D73Tq`rah3ePRQM0rH;mz>O_otzCO8ec#uI*NB7 zjg!FV@O_EUd@4^Y ztW-)MYp!BA5^g(~#i9qScqll&K;A~Fhus!c=I8LKOCs*mR=n>A4UfnW(yOaBpP@v# zb9fHcZ#3_4^I7o_ab5w9FQ611#XFG3N#Jw%zC>ug7-~j=T&NU)aFAWg_qp0AoDkYFLS1}w3_iKma!=u_msj3eOhpBV;s>^Vs zg5>H*669Mc8e{<&X+riKzMegdGYKcl`F<1GIlJZ+*!Sf(2%F_?!~~^JB#o2)ejnvI z*lTwfP$4(der%$w18JNDK8Jt#dl071q4xNt-au1_g(^PCLa3^*e*;ZgZLr7(8A3S= zWX)9!M>_p?0d2$KI|UNqIehEFR=D%wAW!gKC=4JRJg?ApG@j5C(iM z9jH2k`!rz}6lL|K9v|>EC--{YVA4@6Q|D{sQPx0Dis)KW}jRKKy(S{I}vy z!uZMe!|y?l9-n^z?>})Y?xFDS&2N|fy?51*RDk>byur`^AKZTTf4&DlZ;-zS`eX4& x0sLj`r~PL1z&`%~-hbrS+(Y5to8K<|d+(|rsQ~x=d4r#S7xKRgf9mhT{{uY0TloM0 literal 0 HcmV?d00001 diff --git a/src/p7os/cake.exe/libgint/demo/test_bopti.c b/src/p7os/cake.exe/libgint/demo/test_bopti.c new file mode 100644 index 0000000..7942f39 --- /dev/null +++ b/src/p7os/cake.exe/libgint/demo/test_bopti.c @@ -0,0 +1,221 @@ +#include "gintdemo.h" +#include +#include +#include + +#include + +#include + +/* + test_bopti() + Displays and moves many kinds of bitmaps. Here are the images used: + + Name Size Color Alpha + --------------------------------------------------------- + items.bmp 266 * 124 Gray - + sprites.bmp 66 * 33 Gray - + swords.bmp 88 * 16 Gray Full + --------------------------------------------------------- + zelda.bmp 86 * 280 Mono - + isometric.bmp 37 * 27 Mono Full + Mono Greater + --------------------------------------------------------- +*/ + +static void getwh(Image *img, int *width, int *height) +{ + const unsigned char *data; + + if(!img) + { + *width = 0; + *height = 0; + return; + } + *width = img->width; + *height = img->height; + if(*width && *height) return; + + data = img->data; + *width = (data[0] << 8) | data[1]; + *height = (data[2] << 8) | data[3]; +} + +static void getxy(Image *img, int *x, int *y) +{ + int width, height; + + getwh(img, &width, &height); + *x = 64 - (width >> 1); + *y = 28 - (height >> 1); +} + +static Image *select(Image *current) +{ + extern Image res_bopti_thumbs; + extern Image + res_items, + res_sprites, + res_swords, + res_zelda, + res_isometric; + + struct { + Image *img; + const char *name; + const char *info; + } images[] = { + { &res_items, "Items", "Gray" }, + { &res_sprites, "Sprites", "Gray" }, + { &res_swords, "Swords", "Gray Alpha" }, + { &res_zelda, "Zelda", "Mono" }, + { &res_isometric, "Isometric", "Mono Alpha" }, + { NULL, NULL, NULL } + }; + + Image *thumbs = &res_bopti_thumbs; + int items = 0; + static int row = 0; + int leave = 1, i; + + while(images[items].img) items++; + + gray_start(); + + while(1) + { + gclear(); + locate(1, 1, "Select an image:"); + + for(i = 0; i < items && i < 7; i++) + { + locate(2, 2 + i + (i > row), images[i].name); + gimage_part(100, 8 + 8 * (i + (i > row)), thumbs, 0, + 8 * i, 7, 7); + if(i == row) + { + int width, height; + getwh(images[i].img, &width, &height); + print(2, 2 + i + 1, "%d\x04%d", width, height); + locate(10, 2 + i + 1, images[i].info); + } + } + + greverse_area(0, 8 * row + 8, 128, 8 * row + 23); + gupdate(); + + do + { + leave = 1; + + switch(getkey()) + { + case KEY_UP: + row = (row + items - 1) % items; + break; + case KEY_DOWN: + row = (row + 1) % items; + break; + case KEY_EXE: + return images[row].img; + case KEY_EXIT: + return current; + default: + leave = 0; + break; + } + } + while(!leave); + } + + gray_stop(); +} + +void test_bopti(void) +{ + extern Image res_opt_bitmap; + Image *img = NULL; + + int leave = 1; + int black_bg = 0; + int x = 0, y = 0; + + while(1) + { + if(img && (img->format & Channel_Light)) + { + gray_start(); + gclear(); + + if(black_bg) greverse_area(0, 0, 127, 63); + if(img) gimage(x, y, img); + + gclear_area(0, 55, 127, 63); + gimage(0, 56, &res_opt_bitmap); + gupdate(); + } + else if(img) + { + gray_stop(); + dclear(); + + if(black_bg) dreverse_area(0, 0, 127, 63); + if(img) dimage(x, y, img); + + dclear_area(0, 55, 127, 63); + dimage(0, 56, &res_opt_bitmap); + dupdate(); + } + else + { + gray_stop(); + + dclear(); + locate(3, 3, "No image selected"); + + dimage(0, 56, &res_opt_bitmap); + dupdate(); + } + + do + { + leave = 1; + + switch(getkey()) + { + case KEY_EXIT: + gray_stop(); + return; + + case KEY_F1: + img = select(img); + getxy(img, &x, &y); + break; + case KEY_F5: + black_bg = !black_bg; + break; + + case KEY_UP: + y--; + break; + case KEY_DOWN: + y++; + break; + case KEY_LEFT: + x--; + break; + case KEY_RIGHT: + x++; + break; + + default: + leave = 0; + } + } + while(!leave); + } + + gray_stop(); + return; +} diff --git a/src/p7os/cake.exe/libgint/demo/test_gray.c b/src/p7os/cake.exe/libgint/demo/test_gray.c new file mode 100644 index 0000000..b562f1f --- /dev/null +++ b/src/p7os/cake.exe/libgint/demo/test_gray.c @@ -0,0 +1,102 @@ +#include "gintdemo.h" +#include +#include +#include + +/* + test_gray() + Lets the user set the gray delays and see the results. +*/ + +static void draw(int delay1, int delay2, int selected) +{ + extern Image res_opt_gray; + unsigned int *vl = gray_lightVRAM(); + unsigned int *vd = gray_darkVRAM(); + + gclear(); + locate(1, 1, "Gray engine"); + + for(int i = 0; i < 36; i++) + { + int o = ((i + 12) << 2) + 2; + unsigned light = -((i % 24) < 12); + unsigned dark = -(i < 24); + vl[o] = light >> 8; + vl[o + 1] = light << 8; + vd[o] = dark >> 8; + vd[o + 1] = dark << 8; + } + + locate(3, 3, "light"); + print(4, 4, "%d", delay1); + + locate(3, 5, "dark"); + print(4, 6, "%d", delay2); + + locate(3, selected ? 6 : 4, "\x02"); + + gimage(0, 56, &res_opt_gray); + gupdate(); +} + +void test_gray(void) +{ + int delays[2]; // { light, dark } + int key, changed = 1; + int selected = 0; + + gray_getDelays(delays, delays + 1); + gray_start(); + + while(1) + { + if(changed) + { + gray_setDelays(delays[0], delays[1]); + draw(delays[0], delays[1], selected); + } + changed = 0; + + key = getkey_opt(Getkey_RepeatArrowKeys, 1); + if(key == KEY_EXIT) break; + + changed = 1; + + switch(key) + { + case KEY_F1: + selected = !selected; + break; + case KEY_F2: + delays[0] = 912; + delays[1] = 1343; + break; + case KEY_F3: + delays[0] = 993; + delays[1] = 1609; + break; + case KEY_F4: + delays[0] = 860; + delays[1] = 1298; + break; + case KEY_UP: + delays[selected] += 10; + break; + case KEY_DOWN: + if(delays[selected] >= 110) delays[selected] -= 10; + break; + case KEY_RIGHT: + delays[selected]++; + break; + case KEY_LEFT: + if(delays[selected] >= 101) delays[selected]--; + break; + default: + changed = 0; + break; + } + } + + gray_stop(); +} diff --git a/src/p7os/cake.exe/libgint/demo/test_keyboard.c b/src/p7os/cake.exe/libgint/demo/test_keyboard.c new file mode 100644 index 0000000..ab90268 --- /dev/null +++ b/src/p7os/cake.exe/libgint/demo/test_keyboard.c @@ -0,0 +1,82 @@ +#include "gintdemo.h" +#include +#include +#include + +/* + test_keyboard() + Displays a real-time multigetkey() and the keyboard state. +*/ + +static void draw(volatile unsigned char *state) +{ + int i, j, k, l; + int x, y; + + for(i = 0; i < 10; i++) for(j = 1; j < 8; j++) + { + // Eliminating keys that do not exist. + if(!i && j != 7) continue; + if(i && j == 7) continue; + if(i <= 4 && j == 6) continue; + if(i == 4 && j == 5) continue; + + x = 5 * j + 1; + y = 61 - 5 * i; + // Moving the [AC/ON] key. + if(!i) x = 5 * (5) + 1, y = 61 - 5 * (4); + + // Drawing a filled shape when the key is pressed. + if(state[i] & (128 >> j)) + { + for(k = -2; k <= 2; k++) for(l = -2; l <= 2; l++) + if(abs(k) + abs(l) <= 2) + dpixel(x + k, y + l, Color_Black); + } + // Drawing a square border otherwise. + else + { + for(k = -1; k <= 1; k++) for(l = -1; l <= 1; l++) + if(k || l) dpixel(x + k, y + l, Color_Black); + } + } +} + +void test_keyboard(void) +{ + const char *key_names[] = { + "F1", "F2", "F3", "F4", "F5", "F6", + "SHIFT", "OPTN", "VARS", "MENU", "Left", "Up", + "ALPHA", "x^2", "^", "EXIT", "Down", "Right", + "X,\x1d,T", "log", "ln", "sin", "cos", "tan", + "[frac]", "F\x0f\x09" "D", "(", ")", ",", "\x09", + "7", "8", "9", "DEL", "AC/ON", NULL, + "4", "5", "6", "\x04", "\x05", NULL, + "1", "2", "3", "+", "-", NULL, + "0", ".", "\x08", "(-)", "EXE", NULL + }; + + volatile unsigned char *state = keystate(); + int keys[4] = { 0 }; + int i; + + while(1) + { + dclear(); + locate(1, 1, "Keyboard driver"); + locate(8, 3, "Pressed keys:"); + draw(state); + + if(keys[0] == KEY_NONE) locate(9, 4, ":None"); + else for(i = 0; i < 4 && keys[i] != KEY_NONE; i++) + { + locate( 9, i + 4, ":"); + locate(10, i + 4, key_names[keyid(keys[i])]); + } + + dupdate(); + + multigetkey(keys, 4, 1); + if(keys[0] == KEY_EXIT && keys[1] == KEY_NONE) break; + } +} diff --git a/src/p7os/cake.exe/libgint/demo/test_rtc.c b/src/p7os/cake.exe/libgint/demo/test_rtc.c new file mode 100644 index 0000000..2264f00 --- /dev/null +++ b/src/p7os/cake.exe/libgint/demo/test_rtc.c @@ -0,0 +1,262 @@ +#include "gintdemo.h" +#include +#include +#include + +#include +#include + +/* + test_rtc() + Just a clock. Of course using all this RTCTime conversion and this / 10 + is awfully un-optimized, but it's a test case so it's made to check the + values in the structure are correct. +*/ + +#include +#include + +static void draw(struct RTCTime time) +{ + extern Image res_rtc_segments; + + const char *days[7] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" + }, *months[12] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", + "Oct", "Nov", "Dec" + }; + int x[6] = { 20, 33, 52, 65, 84, 97 }; + int digits[6]; + int i; + + digits[0] = time.hours / 10; + digits[1] = time.hours % 10; + digits[2] = time.minutes / 10; + digits[3] = time.minutes % 10; + digits[4] = time.seconds / 10; + digits[5] = time.seconds % 10; + + // Drawing digits. + for(i = 0; i < 6; i++) dimage_part(x[i], 8, &res_rtc_segments, + 12 * digits[i], 0, 11, 19); + // Drawing ':' between pairs of digits. + for(i = 0; i < 16; i++) dpixel(47 + 32 * (i >= 8) + (i & 1), + 14 + 5 * !!(i & 4) + !!(i & 2), Color_Black); + + // This should print time.year + 1900 but for the sake of this demo we + // have tweaked the field so that it already contains time.year + 1900. + print(4, 6, "%s %s %02d %4d", days[time.week_day], + months[time.month], time.month_day, time.year); +} + +static void callback(void) +{ + extern Image res_opt_rtc; + struct RTCTime time = rtc_getTime(); + time.year += 1900; + + dclear(); + draw(time); + dimage_part(0, 56, &res_opt_rtc, 0, 0, 19, 8); + dupdate(); +} + +static void set_region(struct RTCTime *time, int region, int value) +{ + switch(region) + { + case 0: + time->hours = 10 * value + (time->hours % 10); + break; + case 1: + time->hours = time->hours - (time->hours % 10) + value; + break; + case 2: + time->minutes = 10 * value + (time->minutes % 10); + break; + case 3: + time->minutes = time->minutes - (time->minutes % 10) + value; + break; + case 4: + time->seconds = 10 * value + (time->seconds % 10); + break; + case 5: + time->seconds = time->seconds - (time->seconds % 10) + value; + break; + case 6: + time->week_day = value; + break; + case 7: + time->month = value; + break; + case 8: + time->month_day = 10 * value + (time->month_day % 10); + break; + case 9: + time->month_day = time->month_day - (time->month_day % 10) + + value; + break; + case 10: + time->year = 1000 * value + (time->year % 1000); + break; + case 11: + time->year = time->year - (time->year % 1000) + 100 * value + + (time->year % 100); + break; + case 12: + time->year = time->year - (time->year % 100) + 10 * value + + (time->year % 10); + break; + case 13: + time->year = time->year - (time->year % 10) + value; + break; + } +} + +static void set(void) +{ + extern Image res_opt_rtc; + Image *opt = &res_opt_rtc; + + struct { + int x, y; + int w, h; + } regions[] = { + { 19, 7, 13, 21 }, { 32, 7, 13, 21 }, { 51, 7, 13, 21 }, + { 64, 7, 13, 21 }, { 83, 7, 13, 21 }, { 96, 7, 13, 21 }, + { 18, 39, 19, 9 }, { 42, 39, 19, 9 }, { 66, 39, 7, 9 }, + { 72, 39, 7, 9 }, { 84, 39, 7, 9 }, { 90, 39, 7, 9 }, + { 96, 39, 7, 9 }, { 102, 39, 7, 9 }, + }; + struct RTCTime time = rtc_getTime(); + int region_count = 14; + int n = 0, slide = 0, key, leave; + + time.year += 1900; + + while(1) + { + dclear(); + draw(time); + dreverse_area(regions[n].x, regions[n].y, regions[n].x + + regions[n].w - 1, regions[n].y + regions[n].h - 1); + + if(n == 6) dimage_part(0, 56, opt, 0, 9 * (1 + slide), 128, 8); + if(n == 7) dimage_part(0, 56, opt, 0, 9 * (3 + slide), 128, 8); + else dimage_part(0, 56, opt, 22 + 22 * (n == region_count - 1), + 0, 19, 8); + + dupdate(); + + do + { + leave = 1; + key = getkey(); + if(key == KEY_EXIT) return; + + else if(key == KEY_F1 || key == KEY_EXE) + { + n++; + slide = 0; + if(n == region_count) + { + time.year -= 1900; + rtc_setTime(time); + return; + } + } + + else if(key == KEY_F6) + { + if(n == 6) slide = (slide + 1) % 2; + if(n == 7) slide = (slide + 1) % 3; + } + + else if((key & 0x0f) == 9) // Other F-keys + { + int k = 7 - (key >> 4); // Number of F-key + + if(n == 7) + { + int month = k + 4 * slide - 2; + set_region(&time, n, month); + n++; + slide = 0; + } + + else if(n == 6 && (slide != 1 || k != 5)) + { + int day = k + 4 * slide - 1; + set_region(&time, n, day); + n++; + slide = 0; + } + + else leave = 0; + } + + else if(isdigit(keychar(key))) // Numbers + { + int val = keychar(key) - '0'; + int ok = 1; + + if(n == 0) ok = (val <= 2); + if(n == 1) + { + int max = time.hours >= 20 ? 3 : 9; + ok = (val <= max); + } + if(n == 2 || n == 4) ok = (val <= 5); + if(n == 8) ok = (val <= 3); + if(n == 9) + { + int max = time.month_day >= 30 ? 1 : 9; + ok = (val <= max); + } + + if(ok) + { + set_region(&time, n, val); + n++; + if(n == region_count) + { + time.year -= 1900; + rtc_setTime(time); + return; + } + slide = 0; + } + else leave = 0; + } + + else leave = 0; + } while(!leave); + } + + while(getkey() != KEY_EXIT); +} + +void test_rtc(void) +{ + int key, cb_id; + + cb_id = rtc_cb_add(RTCFreq_1Hz, callback, 0); + callback(); + + while(1) + { + key = getkey(); + + if(key == KEY_EXIT) break; + if(key == KEY_F1) + { + rtc_cb_edit(cb_id, RTCFreq_None, NULL); + set(); + callback(); + rtc_cb_edit(cb_id, RTCFreq_1Hz, callback); + } + } + + rtc_cb_end(cb_id); +} diff --git a/src/p7os/cake.exe/libgint/demo/test_tales.c b/src/p7os/cake.exe/libgint/demo/test_tales.c new file mode 100644 index 0000000..644fc23 --- /dev/null +++ b/src/p7os/cake.exe/libgint/demo/test_tales.c @@ -0,0 +1,158 @@ +#include "gintdemo.h" +#include +#include +#include + +#include + +/* + test_tales() + Displays some text using different modes and clipping options. +*/ + +static Font *select(Font *current) +{ + extern Font res_font_modern; + struct { + Font *font; + const char *name; + } fonts[] = { + { NULL, "gint default" }, + { &res_font_modern, "Modern" }, + }; + int font_number = 2; + + static int row = 0; + int i, leave; + + while(1) + { + text_configure(NULL, Color_Black); + + dclear(); + locate(1, 1, "Select a font:"); + + for(i = 0; i < font_number && i < 6; i++) + { + if(fonts[i].font) + { + int height = fonts[i].font->line_height; + int y = (i + 2) * 8 - 8 + ((7 - height) >> 1); + + text_configure(fonts[i].font, Color_Black); + dtext(7, y, fonts[i].name); + } + else + { + text_configure(NULL, Color_Black); + locate(2, i + 2, fonts[i].name); + } + + } + + dreverse_area(0, 8 * row + 8, 128, 8 * row + 15); + dupdate(); + + do + { + leave = 1; + + switch(getkey()) + { + case KEY_UP: + row = (row + font_number - 1) % font_number; + break; + case KEY_DOWN: + row = (row + 1) % font_number; + break; + case KEY_EXE: + return fonts[row].font; + case KEY_EXIT: + return current; + default: + leave = 0; + break; + } + } + while(!leave); + } +} + +void test_tales(void) +{ + enum Color colors[] = { Color_Black, Color_Dark, Color_Light, + Color_White, Color_Invert }; + extern Image res_opt_tales; + Font *font = NULL; + + int black_bg = 0; + int color = 0; + int i, x, height; + int leave; + + gray_start(); + while(1) + { + gclear(); + if(black_bg) greverse_area(0, 0, 127, 54); + + if(font) + { + text_configure(font, colors[color]); + height = font->line_height + 1; + } + else + { + text_configure(NULL, colors[color]); + height = 8; + } + + for(i = 0; i < 6 && 2 + (i + 1) * height < 56; i++) + { + char str[17]; + for(int j = 0; j < 16; j++) str[j] = 32 + (i << 4) + j; + str[16] = 0; + + gtext(2, 2 + i * height, str); + } + + gimage(0, 56, &res_opt_tales); + + x = 45 + 8 * color; + gline(x, 57, x + 5, 57, Color_Black); + gline(x, 57, x, 62, Color_Black); + gline(x + 5, 57, x + 5, 62, Color_Black); + gline(x, 62, x + 5, 62, Color_Black); + + gupdate(); + + do + { + leave = 1; + + switch(getkey()) + { + case KEY_F1: + gray_stop(); + font = select(font); + gray_start(); + break; + case KEY_F2: + color = (color + 1) % 5; + break; + case KEY_F5: + black_bg = !black_bg; + break; + + case KEY_EXIT: + gray_stop(); + text_configure(NULL, Color_Black); + return; + default: + leave = 0; + break; + } + } + while (!leave); + } +} diff --git a/src/p7os/cake.exe/libgint/demo/test_timer.c b/src/p7os/cake.exe/libgint/demo/test_timer.c new file mode 100644 index 0000000..36ca64d --- /dev/null +++ b/src/p7os/cake.exe/libgint/demo/test_timer.c @@ -0,0 +1,272 @@ +#include "gintdemo.h" +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +static void draw(int new_tab); +static struct ClockConfig conf; + +//--- +// Timer-RTC comparison. +// The precision of the timer is measured by comparing it to the RTC. +//--- + +static volatile int elapsed_timer = -1; +static volatile int elapsed_rtc = -1; +static int cb_id = -1; + +static void timing_rtc(void) +{ + elapsed_rtc++; +} + +static void timing_timer(void) +{ + elapsed_timer++; +} + +static void timing_start(void) +{ + timer_start(TIMER_USER, clock_setting(16, Clock_Hz), TIMER_Po_4, + timing_timer, 0); + rtc_cb_edit(cb_id, RTCFreq_16Hz, timing_rtc); + + elapsed_timer = 0; + elapsed_rtc = 0; +} + + + +//--- +// Drawing. +//--- + +/* + small_text() + Renders small text using a minimalist bitmap-based font. +*/ +static void small_text(int x, int y, const char *text, int alignment) +{ + extern Image res_clock_chars; + Image *chars = &res_clock_chars; + const char *table = "0123456789kMHz*/"; + + if(alignment) x -= 2 * strlen(text) - 1, y -= 2; + int c; + + while(*text) + { + const char *ptr = strchr(table, *text++); + if(!ptr) continue; + c = ptr - table; + + dimage_part(x, y, chars, c << 2, 0, 3, 5); + x += 4; + } +} + +/* + getFreq() + Prints the given frequency in a string on the form: + 332kHz + There are 1, 2 or 3 characters for the value, and 2 or 3 + characters for the unit. The string is compacted. +*/ +void getFreq(char *str, int freq) +{ + if(freq < 1000) sprintf(str, "%dHz", freq); + else if(freq < 1000000) sprintf(str, "%dkHz", (freq + 500) / 1000); + else sprintf(str, "%dMHz", (freq + 500000) / 1000000); +} + +/* + dislay_freq() + Displays a frequency value a unit, in an simple form. +*/ +static void display_freq(int x, int y, int freq) +{ + int ratio, letter, dot, i; + char buffer[10]; + + if(freq <= 0) + { + dtext(x, y, "Unknown"); + return; + } + if(freq < 10000) + { + dprint(x, y, "%5d", freq); + small_text(x + 31, y + 2, "Hz", 0); + return; + } + + if(freq < 10000000) ratio = 1, letter = 'k'; + else ratio = 1000, letter = 'M'; + + dot = 1 + (freq >= 10000 * ratio) + (freq >= 100000 * ratio); + freq += (ratio * (1 + 9 * (dot >= 2) + 90 * (dot >= 3))) / 2; + snprintf(buffer, 6, "%d", freq); + + for(i = 4; i > dot; i--) buffer[i] = buffer[i - 1]; + buffer[dot] = '.'; + + dprint(x, y, buffer); + sprintf(buffer, "%cHz", letter); + small_text(x + 31, y + 2, buffer, 0); +} + +/* + draw() + Draws the test interface. +*/ +static void draw(int tab) +{ + extern Image res_opt_timer; + extern Image res_clock_7705; + extern Image res_clock_7305; + + char buffer[16]; + + dclear(); + dimage(0, 56, &res_opt_timer); + + if(!tab) + { + locate(1, 1, "Clock frequency"); + dtext(7, 20, "B\x1e"); + display_freq(24, 20, conf.Bphi_f); + dtext(7, 28, "I\x1e"); + display_freq(24, 28, conf.Iphi_f); + dtext(7, 36, "P\x1e"); + display_freq(24, 36, conf.Pphi_f); + + if(isSH3()) + { + dimage(64, 0, &res_clock_7705); + + getFreq(buffer, conf.CKIO_f); + small_text(84, 16, buffer, 1); + + sprintf(buffer, "*%d", conf.PLL1); + small_text(84, 34, buffer, 1); + + if(conf.Iphi_div1 == 1) + dline(85, 43, 99, 43, Color_Black); + else + { + sprintf(buffer, "/%d", conf.Iphi_div1); + small_text(89, 41, buffer, 0); + } + if(conf.Pphi_div1 == 1) + dline(85, 50, 99, 50, Color_Black); + else + { + sprintf(buffer, "/%d", conf.Pphi_div1); + small_text(89, 48, buffer, 0); + } + } + else + { + dimage(64, 0, &res_clock_7305); + + getFreq(buffer, conf.RTCCLK_f); + small_text(84, 14, buffer, 1); + + sprintf(buffer, "*%d", conf.FLL); + small_text(84, 25, buffer, 1); + + sprintf(buffer, "*%d", conf.PLL); + small_text(84, 36, buffer, 1); + + sprintf(buffer, "/%d", conf.Bphi_div1); + small_text(89, 43, buffer, 0); + sprintf(buffer, "/%d", conf.Iphi_div1); + small_text(89, 50, buffer, 0); + sprintf(buffer, "/%d", conf.Pphi_div1); + small_text(89, 57, buffer, 0); + } + } + else + { + int timer = elapsed_timer, rtc = elapsed_rtc; // just in case + + locate(1, 1, "Timer/RTC comparison"); + + locate(2, 3, "Timer"); + if(timer >= 0) print(12, 3, "%04x", timer); + else locate(12, 3, "..."); + + locate(2, 4, "RTC"); + if(rtc >= 0) print(12, 4, "%04x", rtc); + else locate(12, 4, "..."); + + // We define the accuracy of the timer as the ratio between the + // two counters. + locate(2, 5, "Accuracy"); + if(rtc > 0 && timer > 0) + { + int ratio; + if(timer <= rtc) ratio = (10000 * timer) / rtc; + else ratio = (10000 * rtc) / timer; + + print(12, 5, "%d.%02d %%", ratio / 100, ratio % 100); + } + else locate(12, 5, "..."); + } + + dupdate(); +} + + + +//--- +// Timer/clock test. +//--- + +/* + test_timer() + Clock timer and timer precision. +*/ +void test_timer(void) +{ + int tab = 0; + + clock_measure(); + clock_measure_end(); + + conf = clock_config(); + + elapsed_timer = -1; + elapsed_rtc = -1; + cb_id = rtc_cb_add(RTCFreq_16Hz, timing_start, 0); + + text_configure(NULL, Color_Black); + + while(1) + { + draw(tab); + + switch(getkey_opt(Getkey_NoOption, 1)) + { + case KEY_EXIT: + timer_stop(TIMER_USER); + rtc_cb_end(cb_id); + return; + + case KEY_F1: + tab = 0; + break; + case KEY_F2: + tab = 1; + break; + } + } +} diff --git a/src/p7os/cake.exe/libgint/doc/bopti.md b/src/p7os/cake.exe/libgint/doc/bopti.md new file mode 100644 index 0000000..b460253 --- /dev/null +++ b/src/p7os/cake.exe/libgint/doc/bopti.md @@ -0,0 +1,306 @@ + +# 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. diff --git a/src/p7os/cake.exe/libgint/include/7305.h b/src/p7os/cake.exe/libgint/include/7305.h new file mode 100644 index 0000000..a34420f --- /dev/null +++ b/src/p7os/cake.exe/libgint/include/7305.h @@ -0,0 +1,673 @@ +#ifndef _7305_H +#define _7305_H 1 + +/* + Double-underscore prefixed structures (e.g. __st_rtc_counter) are used + internally but are not meant to be used in user programs. + + Underscore-prefixed names (e.g. _R64CNT) are used to avoid name + conflicts (e.g. STRUCTURE.RTC would expand to STRUCTURE.((T *)0x...)). +*/ + +#pragma pack(push, 1) +#define gap(n) unsigned: n << 3 + +//--- +// Interrupt controller, part 1. +//--- + +struct _st_intc +{ + union { + unsigned short WORD; + struct { + unsigned const NMIL :1; + unsigned MAI :1; + unsigned :4; + unsigned NMIB :1; + unsigned NMIE :1; + unsigned :2; + unsigned LVLMODE :1; + unsigned :5; + }; + } ICR0; + + char gap1[14]; + + union { + unsigned int LONG; + struct { + unsigned IRQ0 :4; + unsigned IRQ1 :4; + unsigned IRQ2 :4; + unsigned IRQ3 :4; + unsigned IRQ4 :4; + unsigned IRQ5 :4; + unsigned IRQ6 :4; + unsigned IRQ7 :4; + }; + } INTPRI00; + + char gap2[8]; + + union { + unsigned short WORD; + struct { + unsigned IRQ0S :2; + unsigned IRQ1S :2; + unsigned IRQ2S :2; + unsigned IRQ3S :2; + unsigned IRQ4S :2; + unsigned IRQ5S :2; + unsigned IRQ6S :2; + unsigned IRQ7S :2; + }; + } ICR1; + + char gap3[6]; + + union { + unsigned char BYTE; + struct { + unsigned IRQ0 :1; + unsigned IRQ1 :1; + unsigned IRQ2 :1; + unsigned IRQ3 :1; + unsigned IRQ4 :1; + unsigned IRQ5 :1; + unsigned IRQ6 :1; + unsigned IRQ7 :1; + }; + } INTREQ00; + + char gap4[31]; + + union { + unsigned char BYTE; + struct { + unsigned IRQ0 :1; + unsigned IRQ1 :1; + unsigned IRQ2 :1; + unsigned IRQ3 :1; + unsigned IRQ4 :1; + unsigned IRQ5 :1; + unsigned IRQ6 :1; + unsigned IRQ7 :1; + }; + } INTMSK00; + + char gap5[31]; + + union { + unsigned char BYTE; + struct { + unsigned _IRQ0 :1; + unsigned _IRQ1 :1; + unsigned _IRQ2 :1; + unsigned _IRQ3 :1; + unsigned _IRQ4 :1; + unsigned _IRQ5 :1; + unsigned _IRQ6 :1; + unsigned _IRQ7 :1; + }; + } INTMSKCLR00; + + char gap6[91]; + + union { + unsigned short WORD; + struct { + unsigned const NMIL :1; + unsigned :14; + unsigned NMIFL :1; + }; + } NMIFCR; + + char gap7[6029118]; + + union { + unsigned int LONG; + struct { + unsigned HEXA_A5 :8; + unsigned :16; + unsigned UIMASK :4; + unsigned :4; + }; + } USERIMSK; + +} __attribute__((packed)); + + + +//--- +// Interrupt controller, part 2. +//--- + +struct _st_intx +{ + union { + unsigned short WORD; + struct { + unsigned TMU0_0 :4; + unsigned TMU0_1 :4; + unsigned TMU0_2 :4; + unsigned IrDA :4; + }; + } IPRA; + gap(2); + + union { + unsigned short WORD; + struct { + unsigned JPU :4; + unsigned LCDC :4; + unsigned DMAC1A :4; + unsigned BEU2_1 :4; + }; + } IPRB; + gap(2); + + union { + unsigned short WORD; + struct { + unsigned TMU1_0 :4; + unsigned TMU1_1 :4; + unsigned TMU1_2 :4; + unsigned SPU :4; + }; + } IPRC; + gap(2); + + union { + unsigned short WORD; + struct { + unsigned :4; + unsigned MMCIF :4; + unsigned :4; + unsigned ATAPI :4; + }; + } IPRD; + gap(2); + + union { + unsigned short WORD; + struct { + unsigned DMAC0A :4; + unsigned VARIOUS :4; + unsigned SCIFA3 :4; + unsigned VPU5F :4; + }; + } IPRE; + gap(2); + + union { + unsigned short WORD; + struct { + unsigned _KEYSC :4; + unsigned DMAC0B :4; + unsigned USB01 :4; + unsigned CMT :4; + }; + } IPRF; + gap(2); + + union { + unsigned short WORD; + struct { + unsigned SCIF0 :4; + unsigned SCIF1 :4; + unsigned SCIF2 :4; + unsigned VEU3F0 :4; + }; + } IPRG; + gap(2); + + union { + unsigned short WORD; + struct { + unsigned MSIOF0 :4; + unsigned MSIOF1 :4; + unsigned I2C1 :4; + unsigned I2C0 :4; + }; + } IPRH; + gap(2); + + union { + unsigned short WORD; + struct { + unsigned SCIFA4 :4; + unsigned ICB :4; + unsigned TSIF :4; + unsigned _2DG_ICB :4; + }; + } IPRI; + gap(2); + + union { + unsigned short WORD; + struct { + unsigned CEU2_1 :4; + unsigned EtherMAC :4; + unsigned FSI :4; + unsigned SDHI1 :4; + }; + } IPRJ; + gap(2); + + union { + unsigned short WORD; + struct { + unsigned _RTC :4; + unsigned DMAC1B :4; + unsigned ICB :4; + unsigned SDHI0 :4; + }; + } IPRK; + gap(2); + + union { + unsigned short WORD; + struct { + unsigned SCIFA5 :4; + unsigned :4; + unsigned TPU :4; + unsigned _2DDMAC :4; + }; + } IPRL; + char gap1[82]; + + union + { + unsigned char BYTE; + struct { + unsigned :1; + unsigned TUNI2 :1; + unsigned TUNI1 :1; + unsigned TUNI0 :1; + unsigned SDHII3 :1; + unsigned SDHII2 :1; + unsigned SDHII1 :1; + unsigned SDHII0 :1; + }; + } IMR0; + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned VOUI :1; + unsigned VEU1I :1; + unsigned BEU0I :1; + unsigned CEUOI :1; + unsigned DEI3 :1; + unsigned DEI2 :1; + unsigned DEI1 :1; + unsigned DEI0 :1; + }; + } IMR1; + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned :3; + unsigned VPUI :1; + unsigned ATAPI :1; + unsigned EtherMAC :1; + unsigned :1; + unsigned SCIFA0 :1; + }; + } IMR2; + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned DEI3 :1; + unsigned DEI2 :1; + unsigned DEI1 :1; + unsigned DEI0 :1; + unsigned :3; + unsigned IRDAI :1; + }; + } IMR3; + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned :1; + unsigned TUNI2 :1; + unsigned TUNI1 :1; + unsigned TUNI0 :1; + unsigned JPUI :1; + unsigned :2; + unsigned LCDCI :1; + }; + } IMR4; + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned KEYI :1; + unsigned DADERR :1; + unsigned DEI5 :1; + unsigned DEI4 :1; + unsigned VEU0I :1; + unsigned SCIF2 :1; + unsigned SCIF1 :1; + unsigned SCIF0 :1; + }; + } IMR5; + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned :2; + unsigned ICBI :1; + unsigned SCIFA4 :1; + unsigned CEU1I :1; + unsigned :1; + unsigned MSIOFI0 :1; + unsigned MSIOFI1 :1; + }; + } IMR6; + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned DTE0I :1; + unsigned WAITOI :1; + unsigned TACK0I :1; + unsigned AL0I :1; + unsigned DTE1I :1; + unsigned WAIT1I :1; + unsigned TACK1I :1; + unsigned AL1I :1; + }; + } IMR7; + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned SDHII3 :1; + unsigned SDHII2 :1; + unsigned SDHII1 :1; + unsigned SDHII0 :1; + unsigned :2; + unsigned SCFIA5 :1; + unsigned FSI :1; + }; + } IMR8; + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned :3; + unsigned CMTI :1; + unsigned :1; + unsigned USI1 :1; + unsigned USI0 :1; + unsigned :1; + }; + } IMR9; + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned :1; + unsigned DADERR :1; + unsigned DEI5 :1; + unsigned DEI4 :1; + unsigned :1; + unsigned ATI :1; + unsigned PRI :1; + unsigned CUI :1; + }; + } IMR10; + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned BRK :1; + unsigned CEI :1; + unsigned INI :1; + unsigned TRI :1; + unsigned :1; + unsigned TPUI :1; + unsigned LMBI :1; + unsigned TSIFI :1; + }; + } IMR11; + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned :7; + unsigned _2DDMAC :1; + }; + } IMR12; + char gap2[15]; + + union + { + unsigned char BYTE; + struct { + unsigned :1; + unsigned TUNI2 :1; + unsigned TUNI1 :1; + unsigned TUNI0 :1; + unsigned SDHII3 :1; + unsigned SDHII2 :1; + unsigned SDHII1 :1; + unsigned SDHII0 :1; + }; + } _IMCR0; + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned VOUI :1; + unsigned VEU1I :1; + unsigned BEU0I :1; + unsigned CEUOI :1; + unsigned DEI3 :1; + unsigned DEI2 :1; + unsigned DEI1 :1; + unsigned DEI0 :1; + }; + } _IMCR1; + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned :3; + unsigned VPUI :1; + unsigned ATAPI :1; + unsigned EtherMAC :1; + unsigned :1; + unsigned SCIFA0 :1; + }; + } _IMCR2; + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned DEI3 :1; + unsigned DEI2 :1; + unsigned DEI1 :1; + unsigned DEI0 :1; + unsigned :3; + unsigned IRDAI :1; + }; + } _IMCR3; + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned :1; + unsigned TUNI2 :1; + unsigned TUNI1 :1; + unsigned TUNI0 :1; + unsigned JPUI :1; + unsigned :2; + unsigned LCDCI :1; + }; + } _IMCR4; + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned KEYI :1; + unsigned DADERR :1; + unsigned DEI5 :1; + unsigned DEI4 :1; + unsigned VEU0I :1; + unsigned SCIF2 :1; + unsigned SCIF1 :1; + unsigned SCIF0 :1; + }; + } _IMCR5; + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned :2; + unsigned ICBI :1; + unsigned SCIFA4 :1; + unsigned CEU1I :1; + unsigned :1; + unsigned MSIOFI0 :1; + unsigned MSIOFI1 :1; + }; + } _IMCR6; + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned DTE0I :1; + unsigned WAITOI :1; + unsigned TACK0I :1; + unsigned AL0I :1; + unsigned DTE1I :1; + unsigned WAIT1I :1; + unsigned TACK1I :1; + unsigned AL1I :1; + }; + } _IMCR7; + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned SDHII3 :1; + unsigned SDHII2 :1; + unsigned SDHII1 :1; + unsigned SDHII0 :1; + unsigned :2; + unsigned SCFIA5 :1; + unsigned FSI :1; + }; + } _IMCR8; + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned :3; + unsigned CMTI :1; + unsigned :1; + unsigned USI1 :1; + unsigned USI0 :1; + unsigned :1; + }; + } _IMCR9; + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned :1; + unsigned DADERR :1; + unsigned DEI5 :1; + unsigned DEI4 :1; + unsigned :1; + unsigned ATI :1; + unsigned PRI :1; + unsigned CUI :1; + }; + } _IMCR10; + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned BRK :1; + unsigned CEI :1; + unsigned INI :1; + unsigned TRI :1; + unsigned :1; + unsigned TPUI :1; + unsigned LMBI :1; + unsigned TSIFI :1; + }; + } _IMCR11; + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned :7; + unsigned _2DDMAC :1; + }; + } _IMCR12; + +} __attribute__((packed)); + + + +#define INTC (*(volatile struct _st_intc *)0xa4140000) +#define INTX (*(volatile struct _st_intx *)0xa4080000) + +#pragma pack(pop) +#endif // _7305_H diff --git a/src/p7os/cake.exe/libgint/include/7705.h b/src/p7os/cake.exe/libgint/include/7705.h new file mode 100644 index 0000000..3282d34 --- /dev/null +++ b/src/p7os/cake.exe/libgint/include/7705.h @@ -0,0 +1,1099 @@ +#ifndef _7705_H +#define _7705_H 1 + + +// Internal Control Registers definition : + +struct st_cpg { /* struct CPG */ + union { /* FRQCR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short :3; /* */ + unsigned short CKOEN:1; /* CKOEN */ + unsigned short :2; /* */ + unsigned short STC :2; /* STC */ + unsigned short :2; /* */ + unsigned short IFC :2; /* IFC */ + unsigned short :2; /* */ + unsigned short _PFC :2; /* PFC */ + } BIT; /* */ + } FRQCR; /* */ +}; /* */ +struct st_wdt { /* struct WDT */ + union { /* WTCNT */ + unsigned char READ; /* Read Access*/ + unsigned short WRITE; /* Write Access*/ + } WTCNT; /* */ + union { /* WTCSR */ + union { /* Read Access*/ + unsigned char BYTE; /* Byte Access*/ + struct { /* Bit Access*/ + unsigned char TME :1; /* TME */ + unsigned char WTIT:1; /* WT/IT */ + unsigned char RSTS:1; /* RSTS */ + unsigned char WOVF:1; /* WOVF */ + unsigned char IOVF:1; /* IOVF */ + unsigned char CKS :3; /* CKS */ + } BIT; /* */ + } READ; /* */ + unsigned short WRITE; /* Write Access*/ + } WTCSR; /* */ +}; + +struct st_pa { /* struct PA */ + union { /* */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char B7:1; /* Bit 7 */ + unsigned char B6:1; /* Bit 6 */ + unsigned char B5:1; /* Bit 5 */ + unsigned char B4:1; /* Bit 4 */ + unsigned char B3:1; /* Bit 3 */ + unsigned char B2:1; /* Bit 2 */ + unsigned char B1:1; /* Bit 1 */ + unsigned char B0:1; /* Bit 0 */ + } BIT; /* */ + } DR; /* */ +}; /* */ +struct st_pb { /* struct PB */ + union { /* */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char B7:1; /* Bit 7 */ + unsigned char B6:1; /* Bit 6 */ + unsigned char B5:1; /* Bit 5 */ + unsigned char B4:1; /* Bit 4 */ + unsigned char B3:1; /* Bit 3 */ + unsigned char B2:1; /* Bit 2 */ + unsigned char B1:1; /* Bit 1 */ + unsigned char B0:1; /* Bit 0 */ + } BIT; /* */ + } DR; /* */ +}; /* */ +struct st_pc { /* struct PC */ + union { /* */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char B7:1; /* Bit 7 */ + unsigned char B6:1; /* Bit 6 */ + unsigned char B5:1; /* Bit 5 */ + unsigned char B4:1; /* Bit 4 */ + unsigned char B3:1; /* Bit 3 */ + unsigned char B2:1; /* Bit 2 */ + unsigned char B1:1; /* Bit 1 */ + unsigned char B0:1; /* Bit 0 */ + } BIT; /* */ + } DR; /* */ +}; /* */ +struct st_pd { /* struct PD */ + union { /* */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char B7:1; /* Bit 7 */ + unsigned char B6:1; /* Bit 6 */ + unsigned char B5:1; /* Bit 5 */ + unsigned char B4:1; /* Bit 4 */ + unsigned char B3:1; /* Bit 3 */ + unsigned char B2:1; /* Bit 2 */ + unsigned char B1:1; /* Bit 1 */ + unsigned char B0:1; /* Bit 0 */ + } BIT; /* */ + } DR; /* */ +}; /* */ +struct st_pe { /* struct PE */ + union { /* */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char B7:1; /* Bit 7 */ + unsigned char B6:1; /* Bit 6 */ + unsigned char B5:1; /* Bit 5 */ + unsigned char B4:1; /* Bit 4 */ + unsigned char B3:1; /* Bit 3 */ + unsigned char B2:1; /* Bit 2 */ + unsigned char B1:1; /* Bit 1 */ + unsigned char B0:1; /* Bit 0 */ + } BIT; /* */ + } DR; /* */ +}; /* */ +struct st_pf { /* struct PF */ + union { /* */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char B7:1; /* Bit 7 */ + unsigned char B6:1; /* Bit 6 */ + unsigned char B5:1; /* Bit 5 */ + unsigned char B4:1; /* Bit 4 */ + unsigned char B3:1; /* Bit 3 */ + unsigned char B2:1; /* Bit 2 */ + unsigned char B1:1; /* Bit 1 */ + unsigned char B0:1; /* Bit 0 */ + } BIT; /* */ + } DR; /* */ +}; /* */ +struct st_pg { /* struct PG */ + union { /* */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char B7:1; /* Bit 7 */ + unsigned char B6:1; /* Bit 6 */ + unsigned char B5:1; /* Bit 5 */ + unsigned char B4:1; /* Bit 4 */ + unsigned char B3:1; /* Bit 3 */ + unsigned char B2:1; /* Bit 2 */ + unsigned char B1:1; /* Bit 1 */ + unsigned char B0:1; /* Bit 0 */ + } BIT; /* */ + } DR; /* */ +}; /* */ +struct st_ph { /* struct PH */ + union { /* */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :1; /* Bit 7 */ + unsigned char B6:1; /* Bit 6 */ + unsigned char B5:1; /* Bit 5 */ + unsigned char B4:1; /* Bit 4 */ + unsigned char B3:1; /* Bit 3 */ + unsigned char B2:1; /* Bit 2 */ + unsigned char B1:1; /* Bit 1 */ + unsigned char B0:1; /* Bit 0 */ + } BIT; /* */ + } DR; /* */ +}; /* */ +struct st_pj { /* struct PJ */ + union { /* */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char B7:1; /* Bit 7 */ + unsigned char B6:1; /* Bit 6 */ + unsigned char B5:1; /* Bit 5 */ + unsigned char B4:1; /* Bit 4 */ + unsigned char B3:1; /* Bit 3 */ + unsigned char B2:1; /* Bit 2 */ + unsigned char B1:1; /* Bit 1 */ + unsigned char B0:1; /* Bit 0 */ + } BIT; /* */ + } DR; /* */ +}; /* */ +struct st_pk { /* struct PK */ + union { /* */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char B7:1; /* Bit 7 */ + unsigned char B6:1; /* Bit 6 */ + unsigned char B5:1; /* Bit 5 */ + unsigned char B4:1; /* Bit 4 */ + unsigned char B3:1; /* Bit 3 */ + unsigned char B2:1; /* Bit 2 */ + unsigned char B1:1; /* Bit 1 */ + unsigned char B0:1; /* Bit 0 */ + } BIT; /* */ + } DR; /* */ +}; /* */ +struct st_pl { /* struct PL */ + union { /* */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :4; /* Bit 7-4 */ + unsigned char B3:1; /* Bit 3 */ + unsigned char B2:1; /* Bit 2 */ + unsigned char B1:1; /* Bit 1 */ + unsigned char B0:1; /* Bit 0 */ + } BIT; /* */ + } DR; /* */ +}; /* */ +struct st_scp { /* struct SCP */ + union { /* */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :2; /* Bit 7,6 */ + unsigned char B5:1; /* Bit 5 */ + unsigned char B4:1; /* Bit 4 */ + unsigned char B3:1; /* Bit 3 */ + unsigned char B2:1; /* Bit 2 */ + unsigned char B1:1; /* Bit 1 */ + unsigned char B0:1; /* Bit 0 */ + } BIT; /* */ + } DR; /* */ +}; /* */ +struct st_pm { /* struct PM */ + union { /* */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :1; /* Bit 7 */ + unsigned char B6:1; /* Bit 6 */ + unsigned char :1; /* Bit 5 */ + unsigned char B4:1; /* Bit 4 */ + unsigned char B3:1; /* Bit 3 */ + unsigned char B2:1; /* Bit 2 */ + unsigned char B1:1; /* Bit 1 */ + unsigned char B0:1; /* Bit 0 */ + } BIT; /* */ + } DR; /* */ +}; /* */ +struct st_pn { /* struct PN */ + union { /* */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char B7:1; /* Bit 7 */ + unsigned char B6:1; /* Bit 6 */ + unsigned char B5:1; /* Bit 5 */ + unsigned char B4:1; /* Bit 4 */ + unsigned char B3:1; /* Bit 3 */ + unsigned char B2:1; /* Bit 2 */ + unsigned char B1:1; /* Bit 1 */ + unsigned char B0:1; /* Bit 0 */ + } BIT; /* */ + } DR; /* */ +}; /* */ + +struct st_usb { /* struct USB */ + union { /* UCLKCR */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char USSCS:2; /* USSCS */ + unsigned char USBEN:1; /* USBEN */ + } BIT; /* */ + } UCLKCR; /* */ + char wk1[4063223]; /* */ + unsigned char EPDR0i; /* EPDR0i */ + char wk2[3]; /* */ + unsigned char EPDR0o; /* EPDR0o */ + char wk3[3]; /* */ + unsigned char EPDR0s; /* EPDR0s */ + char wk4[3]; /* */ + unsigned char EPDR1; /* EPDR1 */ + char wk5[3]; /* */ + unsigned char EPDR2; /* EPDR2 */ + char wk6[3]; /* */ + unsigned char EPDR3; /* EPDR3 */ + char wk7[3]; /* */ + union { /* IFR0 */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char BRST :1; /* BRST */ + unsigned char EP1FULL :1; /* EP1FULL */ + unsigned char EP2TR :1; /* EP2TR */ + unsigned char EP2EMPTY:1; /* EP2EMPTY */ + unsigned char SETUPTS :1; /* SETUPTS */ + unsigned char EP0oTS :1; /* EP0oTS */ + unsigned char EP0iTR :1; /* EP0iTR */ + unsigned char EP0iTS :1; /* EP0iTS */ + } BIT; /* */ + } IFR0; /* */ + char wk8[3]; /* */ + union { /* IFR1 */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :4; /* */ + unsigned char VBUSMN:1; /* VBUSMN */ + unsigned char EP3TS :1; /* EP3TS */ + unsigned char EP3TR :1; /* EP3TR */ + unsigned char VBUS :1; /* VBUS */ + } BIT; /* */ + } IFR1; /* */ + char wk9[3]; /* */ + union { /* TRG */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :1; /* */ + unsigned char EP3PKTE :1; /* EP3PKTE */ + unsigned char EP1RDFN :1; /* EP1RDFN */ + unsigned char EP2PKTE :1; /* EP2PKTE */ + unsigned char :1; /* */ + unsigned char EP0sRDFN:1; /* EP0sRDFN */ + unsigned char EP0oRDFN:1; /* EP0oRDFN */ + unsigned char EP0iPKTE:1; /* EP0iPKTE */ + } BIT; /* */ + } TRG; /* */ + char wk10[3]; /* */ + union { /* FCLR */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :1; /* */ + unsigned char EP3CLR :1; /* EP3CLR */ + unsigned char EP1CLR :1; /* EP1CLR */ + unsigned char EP2CLR :1; /* EP2CLR */ + unsigned char :2; /* */ + unsigned char EP0oCLR:1; /* EP0oCLR */ + unsigned char EP0iCLR:1; /* EP0iCLR */ + } BIT; /* */ + } FCLR; /* */ + char wk11[3]; /* */ + unsigned char EPSZ0o; /* EPSZ0o */ + char wk12[3]; /* */ + union { /* DASTS */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :2; /* */ + unsigned char EP3DE :1; /* EP3DE */ + unsigned char EP2DE :1; /* EP2DE */ + unsigned char :3; /* */ + unsigned char EP0iDE:1; /* EP0iDE */ + } BIT; /* */ + } DASTS; /* */ + char wk13[3]; /* */ + union { /* EPSTL */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :4; /* */ + unsigned char EP3STL:1; /* EP3STL */ + unsigned char EP2STL:1; /* EP2STL */ + unsigned char EP1STL:1; /* EP1STL */ + unsigned char EP0STL:1; /* EP0STL */ + } BIT; /* */ + } EPSTL; /* */ + char wk14[3]; /* */ + union { /* IER0 */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char BRST :1; /* BRST */ + unsigned char EP1FULL :1; /* EP1FULL */ + unsigned char EP2TR :1; /* EP2TR */ + unsigned char EP2EMPTY:1; /* EP2EMPTY */ + unsigned char SETUPTS :1; /* SETUPTS */ + unsigned char EP0oTS :1; /* EP0oTS */ + unsigned char EP0iTR :1; /* EP0iTR */ + unsigned char EP0iTS :1; /* EP0iTS */ + } BIT; /* */ + } IER0; /* */ + char wk15[3]; /* */ + union { /* IER1 */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :5; /* */ + unsigned char EP3TS:1; /* EP3TS */ + unsigned char EP3TR:1; /* EP3TR */ + unsigned char VBUS :1; /* VBUS */ + } BIT; /* */ + } IER1; /* */ + char wk16[3]; /* */ + unsigned char EPSZ1; /* EPSZ1 */ + char wk17[3]; /* */ + union { /* DMAR */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :6; /* */ + unsigned char EP2DMAE:1; /* EP2DMAE */ + unsigned char EP1DMAE:1; /* EP1DMAE */ + } BIT; /* */ + } DMAR; /* */ + char wk18[3]; /* */ + union { /* ISR0 */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char BRST :1; /* BRST */ + unsigned char EP1FULL :1; /* EP1FULL */ + unsigned char EP2TR :1; /* EP2TR */ + unsigned char EP2EMPTY:1; /* EP2EMPTY */ + unsigned char SETUPTS :1; /* SETUPTS */ + unsigned char EP0oTS :1; /* EP0oTS */ + unsigned char EP0iTR :1; /* EP0iTR */ + unsigned char EP0iTS :1; /* EP0iTS */ + } BIT; /* */ + } ISR0; /* */ + char wk19[3]; /* */ + union { /* ISR1 */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :5; /* */ + unsigned char EP3TS:1; /* EP3TS */ + unsigned char EP3TR:1; /* EP3TR */ + unsigned char VBUS :1; /* VBUS */ + } BIT; /* */ + } ISR1; /* */ + char wk20[23]; /* */ + union { /* XVERCR */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :6; /* */ + unsigned char XVEROFF:1; /* XVEROFF */ + } BIT; /* */ + } XVERCR; /* */ +}; +struct st_intc { /* struct INTC */ + union { /* ICR0 */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short NMIL:1; /* NMIL */ + unsigned short :6; /* */ + unsigned short NMIE:1; /* NMIE */ + } BIT; /* */ + } ICR0; /* */ + union { /* IPRA */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short _TMU0:4; /* TMU0 */ + unsigned short _TMU1:4; /* TMU1 */ + unsigned short _TMU2:4; /* TMU2 */ + unsigned short _RTC :4; /* RTC */ + } BIT; /* */ + } IPRA; /* */ + union { /* IPRB */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short _WDT:4; /* WDT */ + unsigned short _REF:4; /* REF */ + } BIT; /* */ + } IPRB; /* */ + char wk[234]; /* */ + unsigned int TRA; /* TRA */ + unsigned int EXPEVT; /* EXPEVT */ + unsigned int INTEVT; /* INTEVT */ +}; +struct st_intx { /* struct INTX */ + unsigned int INTEVT2; /* INTEVT2 */ + union { /* IRR0 */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char PINT0R:1; /* PINT0R */ + unsigned char PINT1R:1; /* PINT1R */ + unsigned char IRQ5R :1; /* IRQ5R */ + unsigned char IRQ4R :1; /* IRQ4R */ + unsigned char IRQ3R :1; /* IRQ3R */ + unsigned char IRQ2R :1; /* IRQ2R */ + unsigned char IRQ1R :1; /* IRQ1R */ + unsigned char IRQ0R :1; /* IRQ0R */ + } BIT; /* */ + } IRR0; /* */ + char wk1; /* */ + union { /* IRR1 */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char TXI0R:1; /* TXI0R */ + unsigned char :1; /* */ + unsigned char RXI0R:1; /* RXI0R */ + unsigned char ERI0R:1; /* ERI0R */ + unsigned char DEI3R:1; /* DEI3R */ + unsigned char DEI2R:1; /* DEI2R */ + unsigned char DEI1R:1; /* DEI1R */ + unsigned char DEI0R:1; /* DEI0R */ + } BIT; /* */ + } IRR1; /* */ + char wk2; /* */ + union { /* IRR2 */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :3; /* */ + unsigned char ADIR :1; /* ADIR */ + unsigned char TXI2R:1; /* TXI2R */ + unsigned char :1; /* */ + unsigned char RXI2R:1; /* RXI2R */ + unsigned char ERI2R:1; /* ERI2R */ + } BIT; /* */ + } IRR2; /* */ + char wk3[7]; /* */ + union { /* ICR1 */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short MAI :1; /* MAI */ + unsigned short IRQLVL:1; /* IRQLVL */ + unsigned short BLMSK :1; /* BLMSK */ + unsigned short :1; /* */ + unsigned short IRQ5S :2; /* IRQ5S */ + unsigned short IRQ4S :2; /* IRQ4S */ + unsigned short IRQ3S :2; /* IRQ3S */ + unsigned short IRQ2S :2; /* IRQ2S */ + unsigned short IRQ1S :2; /* IRQ1S */ + unsigned short IRQ0S :2; /* IRQ0S */ + } BIT; /* */ + } ICR1; /* */ + union { /* ICR2 */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short PINT15S:1; /* PINT15S */ + unsigned short PINT14S:1; /* PINT14S */ + unsigned short PINT13S:1; /* PINT13S */ + unsigned short PINT12S:1; /* PINT12S */ + unsigned short PINT11S:1; /* PINT11S */ + unsigned short PINT10S:1; /* PINT10S */ + unsigned short PINT9S :1; /* PINT9S */ + unsigned short PINT8S :1; /* PINT8S */ + unsigned short PINT7S :1; /* PINT7S */ + unsigned short PINT6S :1; /* PINT6S */ + unsigned short PINT5S :1; /* PINT5S */ + unsigned short PINT4S :1; /* PINT4S */ + unsigned short PINT3S :1; /* PINT3S */ + unsigned short PINT2S :1; /* PINT2S */ + unsigned short PINT1S :1; /* PINT1S */ + unsigned short PINT0S :1; /* PINT0S */ + } BIT; /* */ + } ICR2; /* */ + union { /* PINTER */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short PINT15E:1; /* PINT15E */ + unsigned short PINT14E:1; /* PINT14E */ + unsigned short PINT13E:1; /* PINT13E */ + unsigned short PINT12E:1; /* PINT12E */ + unsigned short PINT11E:1; /* PINT11E */ + unsigned short PINT10E:1; /* PINT10E */ + unsigned short PINT9E :1; /* PINT9E */ + unsigned short PINT8E :1; /* PINT8E */ + unsigned short PINT7E :1; /* PINT7E */ + unsigned short PINT6E :1; /* PINT6E */ + unsigned short PINT5E :1; /* PINT5E */ + unsigned short PINT4E :1; /* PINT4E */ + unsigned short PINT3E :1; /* PINT3E */ + unsigned short PINT2E :1; /* PINT2E */ + unsigned short PINT1E :1; /* PINT1E */ + unsigned short PINT0E :1; /* PINT0E */ + } BIT; /* */ + } PINTER; /* */ + union { /* IPRC */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short _IRQ3:4; /* IRQ3 */ + unsigned short _IRQ2:4; /* IRQ2 */ + unsigned short _IRQ1:4; /* IRQ1 */ + unsigned short _IRQ0:4; /* IRQ0 */ + } BIT; /* */ + } IPRC; /* */ + union { /* IPRD */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short _PINT0_7 :4; /* PINT0-7 */ + unsigned short _PINT8_15:4; /* PINT8-15 */ + unsigned short _IRQ5 :4; /* IRQ5 */ + unsigned short _IRQ4 :4; /* IRQ4 */ + } BIT; /* */ + } IPRD; /* */ + union { /* IPRE */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short _DMAC :4; /* DMAC */ + unsigned short _SCIF0:4; /* SCIF0 */ + unsigned short _SCIF2:4; /* SCIF2 */ + unsigned short _ADC :4; /* ADC */ + } BIT; /* */ + } IPRE; /* */ + char wk4[524260]; /* */ + union { /* IPRF */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short :8; /* */ + unsigned short _USB:4; /* USB */ + } BIT; /* */ + } IPRF; /* */ + union { /* IPRG */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short _TPU0:4; /* TPU0 */ + unsigned short _TPU1:4; /* TPU1 */ + } BIT; /* */ + } IPRG; /* */ + union { /* IPRH */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short _TPU2:4; /* TPU2 */ + unsigned short _TPU3:4; /* TPU3 */ + } BIT; /* */ + } IPRH; /* */ +}; +struct st_scif { /* struct SCIF */ + union { /* SCSMR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short :5; /* */ + unsigned short SRC :3; /* SRC */ + unsigned short CA :1; /* CA */ + unsigned short CHR :1; /* CHR */ + unsigned short _PE :1; /* PE */ + unsigned short OE :1; /* O/E */ + unsigned short STOP:1; /* STOP */ + unsigned short :1; /* */ + unsigned short CKS :2; /* CKS */ + } BIT; /* */ + } SCSMR; /* */ + char wk1[2]; /* */ + unsigned char SCBRR; /* SCBRR */ + char wk2[3]; /* */ + union { /* SCSCR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short :4; /* */ + unsigned short TSIE:1; /* TSIE */ + unsigned short ERIE:1; /* ERIE */ + unsigned short BRIE:1; /* BRIE */ + unsigned short DRIE:1; /* DRIE */ + unsigned short TIE :1; /* TIE */ + unsigned short RIE :1; /* RIE */ + unsigned short TE :1; /* TE */ + unsigned short RE :1; /* RE */ + unsigned short :2; /* */ + unsigned short CKE :2; /* CKE */ + } BIT; /* */ + } SCSCR; /* */ + char wk3[2]; /* */ + unsigned char SCTDSR; /* SCTDSR */ + char wk4[3]; /* */ + union { /* SCFER */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short :2; /* */ + unsigned short PER:6; /* PER */ + unsigned short :2; /* */ + unsigned short FER:6; /* FER */ + } BIT; /* */ + } SCFER; /* */ + char wk5[2]; /* */ + union { /* SCSSR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short :6; /* */ + unsigned short ORER:1; /* ORER */ + unsigned short TSF :1; /* TSF */ + unsigned short ER :1; /* ER */ + unsigned short TEND:1; /* TEND */ + unsigned short TDFE:1; /* TDFE */ + unsigned short BRK :1; /* BRK */ + unsigned short FER :1; /* FER */ + unsigned short PER :1; /* PER */ + unsigned short RDF :1; /* RDF */ + unsigned short DR :1; /* DR */ + } BIT; /* */ + } SCSSR; /* */ + char wk6[2]; /* */ + union { /* SCFCR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short TSE :1; /* TSE */ + unsigned short TCRST:1; /* TCRST */ + unsigned short :3; /* */ + unsigned short RSTRG:3; /* RSTRG */ + unsigned short RTRG :2; /* RTRG */ + unsigned short TTRG :2; /* TTRG */ + unsigned short MCE :1; /* MCE */ + unsigned short TFRST:1; /* TFRST */ + unsigned short RFRST:1; /* RFRST */ + unsigned short LOOP :1; /* LOOP */ + } BIT; /* */ + } SCFCR; /* */ + char wk7[2]; /* */ + union { /* SCFDR */ + unsigned short WORD; /* Word Access */ + struct { /* Byte Access */ + unsigned short :1; /* */ + unsigned short T:7; /* T */ + unsigned short :1; /* */ + unsigned short R:7; /* R */ + } BIT; /* */ + } SCFDR; /* */ + char wk8[2]; /* */ + unsigned char SCFTDR; /* SCFTDR */ + char wk9[3]; /* */ + unsigned char SCFRDR; /* SCFRDR */ +}; /* */ +union un_stbcr3 { /* union STBCR3 */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char _USB :1; /* USB */ + unsigned char :1; /* */ + unsigned char _CMT :1; /* CMT */ + unsigned char _TPU :1; /* TPU */ + unsigned char _ADC :1; /* ADC */ + unsigned char _IrDA :1; /* IrDA */ + unsigned char _SCIF2:1; /* SCIF2 */ + unsigned char _SCIF0:1; /* SCIF0 */ + } BIT; /* */ +}; /* */ +struct st_pfc { /* struct PFC */ + union { /* PACR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short PA7MD:2; /* PA7MD */ + unsigned short PA6MD:2; /* PA6MD */ + unsigned short PA5MD:2; /* PA5MD */ + unsigned short PA4MD:2; /* PA4MD */ + unsigned short PA3MD:2; /* PA3MD */ + unsigned short PA2MD:2; /* PA2MD */ + unsigned short PA1MD:2; /* PA1MD */ + unsigned short PA0MD:2; /* PA0MD */ + } BIT; /* */ + } PACR; /* */ + union { /* PBCR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short PB7MD:2; /* PB7MD */ + unsigned short PB6MD:2; /* PB6MD */ + unsigned short PB5MD:2; /* PB5MD */ + unsigned short PB4MD:2; /* PB4MD */ + unsigned short PB3MD:2; /* PB3MD */ + unsigned short PB2MD:2; /* PB2MD */ + unsigned short PB1MD:2; /* PB1MD */ + unsigned short PB0MD:2; /* PB0MD */ + } BIT; /* */ + } PBCR; /* */ + union { /* PCCR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short PC7MD:2; /* PC7MD */ + unsigned short PC6MD:2; /* PC6MD */ + unsigned short PC5MD:2; /* PC5MD */ + unsigned short PC4MD:2; /* PC4MD */ + unsigned short PC3MD:2; /* PC3MD */ + unsigned short PC2MD:2; /* PC2MD */ + unsigned short PC1MD:2; /* PC1MD */ + unsigned short PC0MD:2; /* PC0MD */ + } BIT; /* */ + } PCCR; /* */ + union { /* PDCR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short PD7MD:2; /* PD7MD */ + unsigned short PD6MD:2; /* PD6MD */ + unsigned short PD5MD:2; /* PD5MD */ + unsigned short PD4MD:2; /* PD4MD */ + unsigned short PD3MD:2; /* PD3MD */ + unsigned short PD2MD:2; /* PD2MD */ + unsigned short PD1MD:2; /* PD1MD */ + unsigned short PD0MD:2; /* PD0MD */ + } BIT; /* */ + } PDCR; /* */ + union { /* PECR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short PE7MD:2; /* PE7MD */ + unsigned short PE6MD:2; /* PE6MD */ + unsigned short PE5MD:2; /* PE5MD */ + unsigned short PE4MD:2; /* PE4MD */ + unsigned short PE3MD:2; /* PE3MD */ + unsigned short PE2MD:2; /* PE2MD */ + unsigned short PE1MD:2; /* PE1MD */ + unsigned short PE0MD:2; /* PE0MD */ + } BIT; /* */ + } PECR; /* */ + union { /* PFCR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short PF7MD:2; /* PF7MD */ + unsigned short PF6MD:2; /* PF6MD */ + unsigned short PF5MD:2; /* PF5MD */ + unsigned short PF4MD:2; /* PF4MD */ + unsigned short PF3MD:2; /* PF3MD */ + unsigned short PF2MD:2; /* PF2MD */ + unsigned short PF1MD:2; /* PF1MD */ + unsigned short PF0MD:2; /* PF0MD */ + } BIT; /* */ + } PFCR; /* */ + union { /* PGCR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short PG7MD:2; /* PG7MD */ + unsigned short PG6MD:2; /* PG6MD */ + unsigned short PG5MD:2; /* PG5MD */ + unsigned short PG4MD:2; /* PG4MD */ + unsigned short PG3MD:2; /* PG3MD */ + unsigned short PG2MD:2; /* PG2MD */ + unsigned short PG1MD:2; /* PG1MD */ + unsigned short PG0MD:2; /* PG0MD */ + } BIT; /* */ + } PGCR; /* */ + union { /* PHCR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short :2; /* */ + unsigned short PH6MD:2; /* PH6MD */ + unsigned short PH5MD:2; /* PH5MD */ + unsigned short PH4MD:2; /* PH4MD */ + unsigned short PH3MD:2; /* PH3MD */ + unsigned short PH2MD:2; /* PH2MD */ + unsigned short PH1MD:2; /* PH1MD */ + unsigned short PH0MD:2; /* PH0MD */ + } BIT; /* */ + } PHCR; /* */ + union { /* PJCR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short PJ7MD:2; /* PJ7MD */ + unsigned short PJ6MD:2; /* PJ6MD */ + unsigned short PJ5MD:2; /* PJ5MD */ + unsigned short PJ4MD:2; /* PJ4MD */ + unsigned short PJ3MD:2; /* PJ3MD */ + unsigned short PJ2MD:2; /* PJ2MD */ + unsigned short PJ1MD:2; /* PJ1MD */ + unsigned short PJ0MD:2; /* PJ0MD */ + } BIT; /* */ + } PJCR; /* */ + union { /* PKCR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short PK7MD:2; /* PK7MD */ + unsigned short PK6MD:2; /* PK6MD */ + unsigned short PK5MD:2; /* PK5MD */ + unsigned short PK4MD:2; /* PK4MD */ + unsigned short PK3MD:2; /* PK3MD */ + unsigned short PK2MD:2; /* PK2MD */ + unsigned short PK1MD:2; /* PK1MD */ + unsigned short PK0MD:2; /* PK0MD */ + } BIT; /* */ + } PKCR; /* */ + union { /* PLCR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short :8; /* */ + unsigned short PL3MD:2; /* PL3MD */ + unsigned short PL2MD:2; /* PL2MD */ + unsigned short PL1MD:2; /* PL1MD */ + unsigned short PL0MD:2; /* PL0MD */ + } BIT; /* */ + } PLCR; /* */ + union { /* SCPCR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short :4; /* */ + unsigned short SCP5MD:2; /* SCP5MD */ + unsigned short SCP4MD:2; /* SCP4MD */ + unsigned short SCP3MD:2; /* SCP3MD */ + unsigned short SCP2MD:2; /* SCP2MD */ + unsigned short SCP1MD:2; /* SCP1MD */ + unsigned short SCP0MD:2; /* SCP0MD */ + } BIT; /* */ + } SCPCR; /* */ + union { /* PMCR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short :2; /* */ + unsigned short PM6MD:2; /* PM6MD */ + unsigned short :2; /* */ + unsigned short PM4MD:2; /* PM4MD */ + unsigned short PM3MD:2; /* PM3MD */ + unsigned short PM2MD:2; /* PM2MD */ + unsigned short PM1MD:2; /* PM1MD */ + unsigned short PM0MD:2; /* PM0MD */ + } BIT; /* */ + } PMCR; /* */ + union { /* PNCR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short PN7MD:2; /* PN7MD */ + unsigned short PN6MD:2; /* PN6MD */ + unsigned short PN5MD:2; /* PN5MD */ + unsigned short PN4MD:2; /* PN4MD */ + unsigned short PN3MD:2; /* PN3MD */ + unsigned short PN2MD:2; /* PN2MD */ + unsigned short PN1MD:2; /* PN1MD */ + unsigned short PN0MD:2; /* PN0MD */ + } BIT; /* */ + } PNCR; /* */ + char wk1[327724]; /* */ + union { /* PECR2 */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :1; /* */ + unsigned char PE6MD:1; /* PE6MD */ + unsigned char PE5MD:1; /* PE5MD */ + unsigned char PE4MD:1; /* PE4MD */ + } BIT; /* */ + } PECR2; /* */ + char wk2; /* */ + union { /* PFCR2 */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :4; /* */ + unsigned char PF3MD:1; /* PF3MD */ + unsigned char PF2MD:1; /* PF2MD */ + unsigned char PF1MD:1; /* PF1MD */ + unsigned char PF0MD:1; /* PF0MD */ + } BIT; /* */ + } PFCR2; /* */ + char wk3[15]; /* */ + union { /* PNCR2 */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :1; /* */ + unsigned char PN6MD:1; /* PN6MD */ + unsigned char PN5MD:1; /* PN5MD */ + unsigned char PN4MD:1; /* PN4MD */ + unsigned char PN3MD:1; /* PN3MD */ + unsigned char PN2MD:1; /* PN2MD */ + unsigned char PN1MD:1; /* PN1MD */ + unsigned char PN0MD:1; /* PN0MD */ + } BIT; /* */ + } PNCR2; /* */ +}; /* */ + +struct st_mmu { + union { + unsigned int LONG; + struct { + unsigned int :23; + unsigned char SV :1; + unsigned char :2; + unsigned char RC :2; + unsigned char :1; + unsigned char TF :1; + unsigned char IX :1; + unsigned char AT :1; + } BIT; + } MMUCR; + + char wk1[12]; + union { + unsigned int LONG; + struct { + unsigned int VPN :22; + unsigned char :2; + unsigned char ASID :8; + } BIT; + } PTEH; + + union { + unsigned int LONG; + struct { + unsigned char :3; + unsigned int :19; + unsigned char :1; + unsigned char V :1; + unsigned char :1; + unsigned char PR :2; + unsigned char SZ :1; + unsigned char C :1; + unsigned char D :1; + unsigned char SH :1; + unsigned char :1; + } BIT; + } PTEL; + + unsigned int TTB; +}; + + +struct st_ubc { + unsigned int BDRB; + + unsigned int BDMRB; + + union { + unsigned int LONG; + struct { + unsigned short :10; + unsigned int BASMA :1; + unsigned int BASMB :1; + unsigned int :4; + unsigned int SCMFCA :1; + unsigned int SCMFCB :1; + unsigned int SCMFDA :1; + unsigned int SCMFDB :1; + unsigned int PCTE :1; + unsigned int PCBA :1; + unsigned int :2; + unsigned int DBEB :1; + unsigned int PCBB :1; + unsigned int :2; + unsigned int SEQ :1; + unsigned int :2; + unsigned int ETBE :1; + } BIT; + } BRCR; + + unsigned short BETR; + + char wk1[2]; + + unsigned int BARB; + + unsigned int BAMRB; + + union { + unsigned short WORD; + struct { + unsigned short :8; + unsigned short CDB :2; + unsigned short IDB :2; + unsigned short RWB :2; + unsigned short SZB :2; + } BIT; + } BBRB; + + char wk2[2]; + + union { + unsigned int LONG; + struct { + unsigned int SVF :1; + unsigned char :3; + unsigned int BSA :28; + } BIT; + } BRSR; + + unsigned int BARA; + + unsigned int BAMRA; + + union { + unsigned short WORD; + struct { + unsigned short :8; + unsigned short CDA :2; + unsigned short IDA :2; + unsigned short RWA :2; + unsigned short SZA :2; + } BIT; + } BBRA; + + char wk3[2]; + + union { + unsigned int LONG; + struct { + unsigned int DVF :1; + unsigned char :3; + unsigned int BDA :28; + } BIT; + } BRDR; + + char wk4[36]; + + unsigned char BASRA; + + char wk5[3]; + + unsigned char BASRB; +}; + + +union un_stbcr2 { + unsigned char BYTE; + struct { + unsigned char _UDI :1; + unsigned char _UBC :1; + unsigned char _DMAC :1; + unsigned char :1; + unsigned char _TLB :1; + unsigned char _CACHE :1; + unsigned char :2; + } BIT; +}; + + + +#define CPG (*(volatile struct st_cpg *)0xffffff80) +#define WDT (*(volatile struct st_wdt *)0xffffff84) +#define INTC (*(volatile struct st_intc *)0xfffffee0) +#define INTX (*(volatile struct st_intx *)0xa4000000) +#define PA (*(volatile struct st_pa *)0xa4000120) +#define PB (*(volatile struct st_pb *)0xa4000122) +#define PC (*(volatile struct st_pc *)0xa4000124) +#define PD (*(volatile struct st_pd *)0xa4000126) +#define PE (*(volatile struct st_pe *)0xa4000128) +#define PF (*(volatile struct st_pf *)0xa400012a) +#define PG (*(volatile struct st_pg *)0xa400012c) +#define PH (*(volatile struct st_ph *)0xa400012e) +#define PJ (*(volatile struct st_pj *)0xa4000130) +#define PK (*(volatile struct st_pk *)0xa4000132) +#define PL (*(volatile struct st_pl *)0xa4000134) +#define SCP (*(volatile struct st_scp *)0xa4000136) +#define PM (*(volatile struct st_pm *)0xa4000138) +#define PN (*(volatile struct st_pn *)0xa400013a) +#define USB (*(volatile struct st_usb *)0xa40a0008) +#define SCIF0 (*(volatile struct st_scif *)0xa4400000) +#define SCIF2 (*(volatile struct st_scif *)0xa4410000) +#define STBCR3 (*(volatile union un_stbcr3 *)0xa40a0000) +#define PFC (*(volatile struct st_pfc *)0xa4000100) +#define TEA (*(volatile unsigned int *)0xfffffffc) +#define MMU (*(volatile struct st_mmu *)0xffffffe0) +#define UBC (*(volatile struct st_ubc *)0xffffff90) +#define STBCR2 (*(volatile union un_stbcr2 *)0xffffff88) + +#endif // _7705_H diff --git a/src/p7os/cake.exe/libgint/include/alloca.h b/src/p7os/cake.exe/libgint/include/alloca.h new file mode 100644 index 0000000..37c88e7 --- /dev/null +++ b/src/p7os/cake.exe/libgint/include/alloca.h @@ -0,0 +1,23 @@ +//--- +// +// standard library module: alloca +// +// Allows dynamic memory allocation on the stack. Memory is automatically +// freed when the calling function exits. +// +//--- + +#ifndef _ALLOCA_H +#define _ALLOCA_H 1 + +#include + +/* + alloca() + Allocates a memory block on the stack. +*/ +void *alloca(size_t size); + +#define alloca(size) __builtin_alloca(size) + +#endif // _ALLOCA_H diff --git a/src/p7os/cake.exe/libgint/include/clock.h b/src/p7os/cake.exe/libgint/include/clock.h new file mode 100644 index 0000000..58e5c30 --- /dev/null +++ b/src/p7os/cake.exe/libgint/include/clock.h @@ -0,0 +1,128 @@ +//--- +// +// gint core module: clock +// +// Measures the frequency of the MPU clocks. This module assumes that the +// clock mode is 3 on SH7305 (as does FTune). +// +//--- + +#ifndef _CLOCK_H +#define _CLOCK_H + +//--- +// Some type declarations. +//--- + +enum Clock +{ + Clock_CKIO = 0, // SH7705 + Clock_RTCCLK = 1, // SH7305 + Clock_Bphi = 2, + Clock_Iphi = 3, + Clock_Pphi = 4, +}; + +enum ClockUnit +{ + Clock_us = 0, + Clock_ms = 1, + Clock_s = 2, + + Clock_Hz = 10, + Clock_kHz = 11, + Clock_MHz = 12, +}; + +struct ClockConfig +{ + union + { + int PLL1; // SH7705 + int FLL; // SH7305 + }; + union + { + int PLL2; // SH7705 + int PLL; // SH7305 + }; + + int Bphi_div1; + int Iphi_div1; + int Pphi_div1; + + union + { + int CKIO_f; // SH7705 + int RTCCLK_f; // SH7305 + }; + + int Bphi_f; + int Iphi_f; + int Pphi_f; +}; + +//--- +// Public API. +//--- + +/* + clock_frequency() + Returns the approximate frequency, in Hz, of the given clock. The + measurements need to have been done. Returns a negative number on + error. +*/ +int clock_frequency(enum Clock clock); + +/* + clock_setting() + Returns the P_phi / 4 timer setting that will last for the given time. + Several units can be used. Be aware that the result is approximate, and + very high frequencies or very short delays will yield important errors. +*/ +int clock_setting(int duration, enum ClockUnit unit); + +/* + clock_config() + Returns a copy of the clock configuration. +*/ +struct ClockConfig clock_config(void); + +/* + sleep() + Sleeps until an interrupt is accepted. +*/ +void sleep(void); + +/* + sleep_us() + Sleeps for the given number of us using the user timer. The result will + always be slightly less than required. +*/ +void sleep_us(int us_delay); + + + +//--- +// Internal API. +// Referenced for documentation purposes only. Do not use. +//--- + +/* + clock_measure() + Begins the frequency measurements. The measurements will end + automatically. While doing measurements, do not use the RTC interrupt + or the user timer. + Call clock_measure_end() to wait until the measurements are finished. + It is possible to execute code during the measurements, so that less + time is spent. +*/ +void clock_measure(void); + +/* + clock_measure_end() + Waits until the measurements are finished. This may be immediate. +*/ +void clock_measure_end(void); + +#endif // _CLOCK_H diff --git a/src/p7os/cake.exe/libgint/include/ctype.h b/src/p7os/cake.exe/libgint/include/ctype.h new file mode 100644 index 0000000..8c7ee2d --- /dev/null +++ b/src/p7os/cake.exe/libgint/include/ctype.h @@ -0,0 +1,35 @@ +//--- +// +// standard library module: ctype +// +// Some character manipulation. +// +//--- + +#ifndef _CTYPE_H +#define _CTYPE_H 1 + +// Character definition macros. +#define isalnum(c) (isdigit(c) || isalpha(c)) +#define isalpha(c) (islower(c) || isupper(c)) + +#define iscntrl(c) ((c) <= 0x1f || (c) == 0x7f) +#define isdigit(c) ((c) >= '0' && (c) <= '9') +#define isgraph(c) ((c) > ' ' && (c) < 0x7f) +#define islower(c) ((c) >= 'a' && (c) <= 'z') +#define isprint(c) ((c) >= ' ' && (c) < 0x7f) +#define ispunct(c) (((c) >= '!' && (c) <= '/') || \ + ((c) >= ':' && (c) <= '@') || \ + ((c) >= '[' && (c) <= '`') || \ + ((c) >= '{' && (c) <= '~')) +#define isspace(c) (((c) >= '\t' && (c) <= '\r') || (c) == ' ') +#define isupper(c) ((c) >= 'A' && (c) <= 'Z') +#define isxdigit(c) (((c) >= '0' && (c) <= '9') || \ + ((c) >= 'A' && (c) <= 'F') || \ + ((c) >= 'a' && (c) <= 'f')) + +// Character manipulation macros. +#define tolower(c) (isupper(c) ? (c) | 32 : (c)) +#define toupper(c) (islower(c) ? (c) & ~32 : (c)) + +#endif // _CTYPE_H diff --git a/src/p7os/cake.exe/libgint/include/display.h b/src/p7os/cake.exe/libgint/include/display.h new file mode 100644 index 0000000..a7167a4 --- /dev/null +++ b/src/p7os/cake.exe/libgint/include/display.h @@ -0,0 +1,161 @@ +//--- +// +// gint drawing module: display +// +// Handles vram manipulation and drawing for plain monochrome display. +// +//--- + +#ifndef _DISPLAY_H +#define _DISPLAY_H 1 + + +//--- +// Heading declarations. +//--- + +enum Color +{ + Color_White = 0, + Color_Light = 1, + Color_Dark = 2, + Color_Black = 3, + Color_None = 4, + Color_Invert = 5, +}; + +// This header needs enum Color to be defined. +#include + +/* + struct Image + This structure holds information about a bitmap encoded with fxconv. + Data is accessed using longword operations, which *requires* many + sizes to be multiples of 4 (structure alignment, data alignment, layer + size, ...). +*/ +struct Image +{ + unsigned char magic; + unsigned char format; + + unsigned char width; + unsigned char height; + + const unsigned char __attribute__((aligned(4))) data[]; + +} __attribute__((aligned(4))); +// Useful shorthand for user code. +typedef struct Image Image; + + + +// A few other constants. +#define DISPLAY_WIDTH 128 +#define DISPLAY_HEIGHT 64 + + + +//--- +// Generic functions. +//--- + +/* + display_getLocalVRAM() + Returns the local video ram address. This function always return the + same address. + The buffer returned by this function should not be used directly when + running the gray engine. +*/ +void *display_getLocalVRAM(void); + +/* + display_getCurrentVRAM() + Returns the current video ram. This function usually returns the + parameter of the last call to display_useVRAM(), unless the gray engine + is running (in which case the result is undefined). Returns the local + vram address by default. +*/ +void *display_getCurrentVRAM(void); + +/* + display_useVRAM() + Changes the current video ram address. The argument MUST be a 4- + aligned 1024-byte buffer; otherwise any drawing operation will crash + the program. + This function will most likely have no effect when running the gray + engine. +*/ +void display_useVRAM(void *vram); + + + +//--- +// Global drawing functions. +//--- + +/* + dupdate() + Displays the vram on the physical screen. Does nothing when the gray + engine is running. +*/ +void dupdate(void); + +/* + dclear() + Clears the whole video ram. +*/ +void dclear(void); + +/* + dclear_area() + Clears an area of the video ram. Both (x1, y1) and (x2, y2) are + cleared. +*/ +void dclear_area(int x1, int y1, int x2, int y2); + +/* + dreverse_area() + Reverses an area of the vram. (x1, y1) and (x2, y2) are reversed as + well. +*/ +void dreverse_area(int x1, int y1, int x2, int y2); + + + +//--- +// Local drawing functions. +//--- + +/* + dpixel() + Puts a pixel in the vram. +*/ +void dpixel(int x, int y, enum Color color); + +/* + dline() + Draws a line in the vram. Automatically optimizes horizontal and + vertical lines. + + Uses an algorithm written by PierrotLL for MonochromeLib. +*/ +void dline(int x1, int y1, int x2, int y2, enum Color color); + +/* + dimage() + Displays a monochrome image in the vram. Does a real lot of + optimization. +*/ +void dimage(int x, int y, struct Image *image); + +/* + dimage_part() + Draws a portion of an image, defined by its bounding rectangle. + Point (left, top) is included, but (left + width, top + height) is + excluded. +*/ +void dimage_part(int x, int y, struct Image *img, int left, int top, + int width, int height); + +#endif // _DISPLAY_H diff --git a/src/p7os/cake.exe/libgint/include/events.h b/src/p7os/cake.exe/libgint/include/events.h new file mode 100644 index 0000000..01e5277 --- /dev/null +++ b/src/p7os/cake.exe/libgint/include/events.h @@ -0,0 +1,84 @@ +//--- +// +// gint core module: events +// +// Finally some user-friendly API. +// +//--- + +#ifndef _EVENTS_H +#define _EVENTS_H + +//--- +// Type definitions. +//--- + +/* + enum EventType + Something user programs will surely use most often. +*/ +enum EventType +{ + EventType_None = 0, + ET_None = EventType_None, + + EventType_User = 1, + ET_User = EventType_User, + + EventType_KeyPressed = 2, + ET_KeyPress = EventType_KeyPressed, + + EventType_KeyReleased = 3, + ET_KeyRel = EventType_KeyReleased, +}; + +/* + struct Event + Wake up, something's going on. The union member that holds information + about the event is implicitly defined by the type attribute. +*/ +struct Event +{ + enum EventType type; + + union + { + // For ET_User. + void *data; + // For ET_KeyPress and ET_KeyRel. + int key; + }; +}; + + + +//--- +// Event management. +//--- + +/* + event_push() + Queues a user-defined event, allowing it to be retrieved by getevent() + or pollevent() later. Most often you will not need to use this, as + system events are automatically queued. Pushing ET_None events is not + allowed. + Returns non-zero on error. +*/ +int event_push(struct Event event); + +/* + getevent() + Returns the next event. If no one is available, waits for something to + happen. This function uses low-level sleep and should be preferred to + active waiting using loops. +*/ +struct Event getevent(void); + +/* + pollevent() + Returns the next event. If no one is available, returns an event whose + type is ET_None. This function always returns immediately. +*/ +struct Event pollevent(void); + +#endif // _EVENTS_H diff --git a/src/p7os/cake.exe/libgint/include/gint.h b/src/p7os/cake.exe/libgint/include/gint.h new file mode 100644 index 0000000..c49cb5f --- /dev/null +++ b/src/p7os/cake.exe/libgint/include/gint.h @@ -0,0 +1,192 @@ +//--- +// +// gint core module: interrupt handler +// +// Central point of the library. Controls the interrupt handler and +// defines a few functions to configure callbacks for some interrupts. +// +//--- + +#ifndef _GINT_H +#define _GINT_H 1 + +#define GINT_VERSION 0x01000000 +#define GINT_VERSION_STR "01.00" + +//--- +// Interrupt handler control. +//--- + +/* + gint_getVBR() + Returns the current vbr address. +*/ +unsigned int gint_getVBR(void); + +/* + gint_systemVBR() + Returns the vbr address used by the system (saved when execution + starts). +*/ +unsigned int gint_systemVBR(void); + +/* + gint_setDefaultHandler() + In case gint receives an interrupt it doesn't recognize, it can fall + back to a user-provided interrupt handler. Set it to NULL to disable + this feature. + Be aware that the event code passed to the default handler will either + be INTEVT2 (SH7705) or INTEVT (SH7305), but its value for each + interrupt source is completely platform-dependent. Remember to handle + both platforms for increased portability, if possible. +*/ +void gint_setDefaultHandler(void (*default_handler)(int event_code)); + + + +//--- +// Register access. +//--- + +/* + enum Register + Represents common registers. Used as identifiers to retrieve their + values using gint_register(). +*/ +enum Register +{ + Register_EXPEVT, + Register_MMUCR, + Register_TEA, +}; + +/* + gint_register() + Returns the address of a common register. All common registers exist + on both platforms but they may hold different values for the same + information (f.i. EXPEVT may not return the same value for a given + exception on both 7705 and 7305). +*/ +volatile void *gint_reg(enum Register reg); + +/* + gint_strerror() + Returns a string that describe the error set in EXPEVT in case of + general exception of TLB miss exception. This string is platform- + independent. + Some exception codes represent different errors when invoked inside the + general exception handler and the TLB error handler. Parameter 'is_tlb' + should be set to zero for general exception meanings, and anything non- + zero for TLB error meanings. +*/ +const char *gint_strerror(int is_tlb); + + + +//--- +// Internal API. +// Referenced here for documentation purposes only. +// Do NOT call these functions, you'll most probably screw up the whole +// interrupt handling system. +//--- + +/* + gint_setVBR() + Sets the vbr address and calls the configuration function while + interrupts are disabled. +*/ +void gint_setVBR(unsigned int new_vbr_address, void (*setup)(void)); + +/* + gint_callDefaultHandler() + Calls the user-provided default interrupt handler. +*/ +void gint_callDefaultHandler(int event_code); + +/* + gint_init() + Initializes gint. Loads the interrupt handler into the memory and sets + the new vbr address. +*/ +void gint_init(void); + +/* + gint_quit() + Stops gint. Restores the system's configuration and vbr address. +*/ +void gint_quit(void); + +/* + gint_setup() + Configures interrupt priorities and some parameters to allow gint to + take control of the interrupt flow. +*/ +void gint_setup_7705(void); +void gint_setup_7305(void); + +/* + gint_stop() + Un-configures the interrupt flow to give back the interrupt control to + the system. +*/ +void gint_stop_7705(void); +void gint_stop_7305(void); + +/* + gint_reg() + gint_strerror() + See "Register access" section. +*/ +volatile void *gint_reg_7705(enum Register reg); +volatile void *gint_reg_7305(enum Register reg); +const char *gint_strerror_7705(int is_tlb); +const char *gint_strerror_7305(void); + + +//--- +// Exception handling. +//--- + +/* + gint_exc() + Handles exceptions. +*/ +void gint_exc(void) __attribute__((section(".gint.exc.entry"), + interrupt_handler)); +void gint_exc_7705(void) __attribute__((section(".gint.exc"))); +void gint_exc_7305(void) __attribute__((section(".gint.exc"))); + +/* + gint_tlb() + Handles TLB misses. +*/ +void gint_tlb(void) __attribute__((section(".gint.tlb.entry"), + interrupt_handler)); +void gint_tlb_7705(void) __attribute__((section(".gint.tlb"))); +void gint_tlb_7305(void) __attribute__((section(".gint.tlb"))); + +/* + gint_int() + Handles interrupts. +*/ +void gint_int(void) __attribute__((section(".gint.int.entry"), + interrupt_handler)); +void gint_int_7705(void) __attribute__((section(".gint.int"))); +void gint_int_7305(void) __attribute__((section(".gint.int"))); + + + +//--- +// Internal platform-independent definitions. +//--- + +#define GINT_INTP_WDT 4 +#define GINT_INTP_RTC 12 + +#define GINT_INTP_GRAY 15 +#define GINT_INTP_KEY 8 +#define GINT_INTP_TIMER 10 + + + +#endif // _GINT_H diff --git a/src/p7os/cake.exe/libgint/include/gray.h b/src/p7os/cake.exe/libgint/include/gray.h new file mode 100644 index 0000000..e18a20a --- /dev/null +++ b/src/p7os/cake.exe/libgint/include/gray.h @@ -0,0 +1,160 @@ +//--- +// +// gint core/drawing module: gray +// +// Runs the gray engine and handles drawing for the dual-buffer system. +// +//--- + +#ifndef _GRAY_H +#define _GRAY_H 1 + +#include + +//--- +// Engine control. +//--- + +/* + gray_runs() + Returns 1 if the gray engine is running, 0 otherwise. +*/ +int gray_runs(void); + +/* + gray_start() + Starts the gray engine. The control of the screen is transferred to the + gray engine. +*/ +void gray_start(void); + +/* + gray_stop() + Stops the gray engine. The monochrome display system takes control of + the video ram. +*/ +void gray_stop(void); + +/* + gray_lightVRAM() + Returns the module's light gray vram address. +*/ +void *gray_lightVRAM(void); + +/* + gray_darkVRAM() + Returns the module's dark gray vram address. +*/ +void *gray_darkVRAM(void); + +/* + gray_getDelays() + Returns the gray engine delays. Pointers are not set if NULL. +*/ +void gray_getDelays(int *light, int *dark); + +/* + gray_setDelays() + Changes the gray engine delays. Usually you don't need to call this, + because the engine has its default values. + Finding values that give proper grays is quite the hard part of the + gray engine. Usual values are about 1000, with light being between 75 + and 90% of dark. + + Typical values: + + values stability stripes colors + --------------------------------------------------------- + 860, 1298 excellent worst static good + 912, 1343 bad none very good (default) + 993, 1609 medium light fast good + 1325, 1607 bad light fast excellent + --------------------------------------------------------- +*/ +void gray_setDelays(int light, int dark); + + + +//--- +// Global drawing functions. +//--- + +/* + gupdate() + Swaps the vram buffer sets. +*/ +void gupdate(void); + +/* + gclear() + Clears the video ram. +*/ +void gclear(void); + +/* + gclear_area() + Clears an area of the video ram. End points (x1, y1) and (x2, y2) are + included. +*/ +void gclear_area(int x1, int y1, int x2, int y2); + +/* + greverse_area() + Reverses an area of the vram. End points (x1, y1) and (x2, y2) are + included. +*/ +void greverse_area(int x1, int y1, int x2, int y2); + + + +//--- +// Local drawing functions. +//--- + +/* + gpixel() + Puts a pixel in the vram. +*/ +void gpixel(int x, int y, enum Color color); + +/* + gline() + Draws a line in the vram. Automatically optimizes special cases. +*/ +void gline(int x1, int y1, int x2, int y2, enum Color color); + +/* + gimage() + Displays a gray image in the vram. +*/ +void gimage(int x, int y, struct Image *image); + +/* + gimage_part() + Draws a portion of a gray image, defined by its bounding rectangle. + Point (left, top) is included, but (left + width, top + height) is + excluded. +*/ +void gimage_part(int x, int y, struct Image *image, int left, int top, + int width, int height); + + + +//--- +// Internal API. +// Referenced here for documentation purposes only. Do not call. +//-- + +/* + gray_interrupt() + Answers a timer interrupt. Swaps the two buffers. +*/ +void gray_interrupt(void) __attribute__((section(".gint.int"))); + +/* + gray_init() + Initializes the gray engine. +*/ +void gray_init(void) __attribute__((constructor)); + +#endif // _GRAY_H diff --git a/src/p7os/cake.exe/libgint/include/internals/bopti.h b/src/p7os/cake.exe/libgint/include/internals/bopti.h new file mode 100644 index 0000000..7e0009c --- /dev/null +++ b/src/p7os/cake.exe/libgint/include/internals/bopti.h @@ -0,0 +1,160 @@ +//--- +// +// gint drawing module: bopti +// +// bopti does every job related to display images. There is only one +// public function, but there are lots of internal optimizations. +// +// Some bit-manipulation expressions may look written out of nowhere. The +// idea is always the same: get a part of the image in an 'operator', +// which is a 32-bit variable, shift this operator so that its bits +// correspond to the desired position for the bitmap on the screen, and +// edit the video-ram long entry which correspond to this position using +// a 'mask' that indicates which bits of the operator contain information. +// +//--- + +#ifndef _INTERNALS_BOPTI_H +#define _INTERNALS_BOPTI_H 1 + +#include +#include + +/* + enum Channel + Determines the kind of information written into a layer. Every image is + made of one or more channels. +*/ +enum Channel +{ + Channel_FullAlpha = 0x01, + Channel_LightAlpha = 0x02, + Channel_DarkAlpha = 0x04, + + Channel_Mono = 0x08, + Channel_Light = 0x10, + Channel_Dark = 0x20, +}; + +/* + enum Format + Describes the various combination of channels allowed by bopti. +*/ +enum Format +{ + Format_Mono = Channel_Mono, + Format_MonoAlpha = Format_Mono | Channel_FullAlpha, + Format_Gray = Channel_Light | Channel_Dark, + Format_GrayAlpha = Format_Gray | Channel_FullAlpha, + Format_GreaterAlpha = Format_Mono | Channel_LightAlpha | + Channel_DarkAlpha +}; + +/* + struct Structure + Describes an image's structure. +*/ +struct Structure +{ + int width, height; + int layer_size; + + const unsigned char *data; + int columns; + int end_size, end_bytes; +}; + +/* + struct Command + Contains a drawing operation's parameters. +*/ +struct Command +{ + // Channel being drawn. + enum Channel channel; + // Operation used (whether bopti_op_mono() or bopti_op_gray()). + void (*op)(int offset, uint32_t operator, struct Command *command); + // Portion of the bitmap which is drawn. 'top' and 'bottom' refer to + // lines where 'left' and 'right' refer to column ids. + int left, right, top, bottom; + // Position of the bitmap on the screen. + int x, y; + // Rectangle masks. + uint32_t masks[4]; +}; + +// The video ram addresses are set by the public functions and used internally +// by the module. +// Monochrome video ram, light and dark buffers (in this order). +extern int *bopti_vram, *bopti_v1, *bopti_v2; + + + +//--- +// Some bopti routines. +//--- + +/* + bopti_op() + Operates on a vram long. The operator will often not contain 32 bits of + image information. Since neutral bits are not the same for all + operations, a mask is used to indicate which bits should be used for + the operation. This mask is taken for the image's rectangle masks (see + module display for more information on rectangle masks). + Which operation is performed is determined by the channel setting. +*/ +void bopti_op_mono(int offset, uint32_t operator, struct Command *c); +void bopti_op_gray(int offset, uint32_t operator, struct Command *c); + +/* + bopti_grid() -- general form + bopti_grid_a32() -- when x is a multiple of 32 + + Draws the grid at the beginning of a layer's data. The length of this + grid is always a multiple of 32. + The need for bopti_grid_a32() is not only linked to optimization, + because bopti_grid() will perform a 32-bit shift when x is a multiple + of 32, which is undefined behavior. + bopti_grid() calls bopti_grid_32() by default. +*/ +void bopti_grid_a32(const uint32_t *layer, int columns, int height, + struct Command *c); +void bopti_grid(const uint32_t *layer, int columns, int height, + struct Command *c); +/* + bopti_end_get() + Returns an operator for the end of a line, whose width is lower than 32 + (by design: otherwise, it would have been a column). The given pointer + is read and updated so that it points to the next line at the end of + the operation. +*/ +uint32_t bopti_end_get1(const unsigned char **data); +uint32_t bopti_end_get2(const unsigned char **data); + +/* + bopti_rest() -- general form + bopti_rest_nover() -- when the end does not overlap two vram longs + + Draws the end of a layer, which can be considered as a whole layer + whose with is lower than 32. (Actually is it lower or equal to 16; + otherwise it would have been a column and the end would be empty). The + 'size' arguments is in bytes. + Unlike bopti_grid_a32(), bopti_end_nover() is not called automatically + by bopti_end(). +*/ +void bopti_end_nover(const unsigned char *end, int size, struct Command *c); +void bopti_end(const unsigned char *end, int size, struct Command *c); + +/* + bopti() + Draws a layer in the video ram. +*/ +void bopti(const unsigned char *layer, struct Structure *s, struct Command *c); + +/* + getStructure() + Determines the image size and data pointer. +*/ +void getStructure(struct Image *img, struct Structure *structure); + +#endif // _INTERNALS_BOPTI_H diff --git a/src/p7os/cake.exe/libgint/include/internals/display.h b/src/p7os/cake.exe/libgint/include/internals/display.h new file mode 100644 index 0000000..d862f58 --- /dev/null +++ b/src/p7os/cake.exe/libgint/include/internals/display.h @@ -0,0 +1,56 @@ +//--- +// +// gint drawing module: display +// +// Handles vram manipulation and drawing. +// +//--- + +#ifndef _INTERNALS_DISPLAY_H +#define _INTERNALS_DISPLAY_H 1 + +#include + +extern int *vram; + +//--- +// Rectangle masks. +// +// The concept of 'rectangle masks' is used several times in this module. +// It is based on the fact that an operation that affects a rectangle acts +// the same on all its lines. Therefore the behavior of the operation is +// determined by its behavior on a single line, which is represented using +// 'masks' whose bits indicate whether a pixel is affected (1) or not (0). +// +// For example when clearing the screen rectangle (16, 16, 112, 48), the +// masks will represent information '16 to 112 on x-axis', and will hold +// the following values : 0000ffff, ffffffff, ffffffff and ffff0000. These +// masks can then be used by setting vram[offset] &= ~masks[i]. This +// appears to be very flexible : for instance, vram[offset] ^= masks[i] +// will reverse the pixels in the same rectangle. +// +// This technique can also be used in more subtle cases with more complex +// patterns, but within this module it is unlikely to happen. +// +//--- + +/* + adjustRectangle() + Adjusts the given rectangle coordinates to ensure that : + - the rectangle is entirely contained in the screen + - x1 < x2 + - y1 < y2 + which is needed when working with screen rectangles. + Returns non-zero if the rectangle is outside the screen. +*/ +int adjustRectangle(int *x1, int *y1, int *x2, int *y2); + +/* + getMasks() + Computes the rectangle masks needed to affect pixels located between x1 + and x2 (both included). The four masks are stored in the third argument + (seen as an array). +*/ +void getMasks(int x1, int x2, uint32_t *masks); + +#endif // _INTERNALS_DISPLAY_H diff --git a/src/p7os/cake.exe/libgint/include/internals/events.h b/src/p7os/cake.exe/libgint/include/internals/events.h new file mode 100644 index 0000000..976e352 --- /dev/null +++ b/src/p7os/cake.exe/libgint/include/internals/events.h @@ -0,0 +1,19 @@ +#ifndef _INTERNALS_EVENTS_H +#define _INTERNALS_EVENTS_H + +#include + +#ifndef EVENTS_QUEUE_SIZE +#define EVENTS_QUEUE_SIZE 64 +#endif + +/* + This module is just a circular-array queue that pushes and pops events + like any other queue. Trying to add an event when the queue is full + fails, and the operation is ignored. +*/ +extern volatile struct Event event_queue[]; +extern volatile int queue_start; +extern volatile int queue_size; + +#endif // _INTERNALS_EVENT_H diff --git a/src/p7os/cake.exe/libgint/include/internals/gint.h b/src/p7os/cake.exe/libgint/include/internals/gint.h new file mode 100644 index 0000000..4f038d2 --- /dev/null +++ b/src/p7os/cake.exe/libgint/include/internals/gint.h @@ -0,0 +1,30 @@ +#ifndef _INTERNALS_GINT_H +#define _INTERNALS_GINT_H 1 + +//--- +// Exception code strings. +//--- + +extern const char *gint_str[]; + + + +//--- +// Register access. +//--- + +/* + gint_spc() + Returns the saved program counter, which is the last state of execution + saved by interrupt processing. +*/ +unsigned int gint_spc(void); + +/* + gint_ssr() + Returns the saved status register, which is the last configuration + saved by interrupt processing. +*/ +unsigned int gint_ssr(void); + +#endif // _INTERNALS_GINT_H diff --git a/src/p7os/cake.exe/libgint/include/internals/keyboard.h b/src/p7os/cake.exe/libgint/include/internals/keyboard.h new file mode 100644 index 0000000..f982fcf --- /dev/null +++ b/src/p7os/cake.exe/libgint/include/internals/keyboard.h @@ -0,0 +1,39 @@ +#ifndef _INTERNALS_KEYBOARD_H +#define _INTERNALS_KEYBOARD_H + +#include + +// Keyboard variables. +extern volatile unsigned char keyboard_state[10]; +extern volatile int interrupt_flag; + +// Key statistics. +extern int repeat_first, repeat_next; +extern int last_key, last_repeats, last_events; + +// RTC callback id. +extern unsigned cb_id; + +/* + sleep() + Puts the CPU into sleep until an interrupt request is accepted. +*/ +void sleep(void); + +/* + getPressedKey() + Finds a pressed key in the keyboard state and returns it. +*/ +int getPressedKey(volatile unsigned char *keyboard_state); + +/* + getPressedKeys() + Find 'count' pressed keys in the keyboard state and fills the 'keys' + array. Returns the number of keys found. + WARNING: keyboard artifacts make this function read as pressed keys + that aren't (typically, LEFT + DOWN + SHIFT => ALPHA). +*/ +int getPressedKeys(volatile unsigned char *keyboard_state, int *keys, + int count); + +#endif // _INTERNALS_KEYBOARD_H diff --git a/src/p7os/cake.exe/libgint/include/internals/mmu.h b/src/p7os/cake.exe/libgint/include/internals/mmu.h new file mode 100644 index 0000000..23aa121 --- /dev/null +++ b/src/p7os/cake.exe/libgint/include/internals/mmu.h @@ -0,0 +1,21 @@ +//--- +// +// gint core module: mmu +// +// A wise application should avoid tampering with the system's +// configuration of the MMU and the TLB. This module implicitly calls the +// system but does nothing by itself. +// +//--- + +#ifndef _MMU_H +#define _MMU_H 1 + +/* + mmu_pseudoTLBInit() + Tries to have the system load enough data into TLB to allow add-in to + execute. +*/ +void mmu_pseudoTLBInit(void); + +#endif // _MMU_H diff --git a/src/p7os/cake.exe/libgint/include/internals/rtc.h b/src/p7os/cake.exe/libgint/include/internals/rtc.h new file mode 100644 index 0000000..228ce59 --- /dev/null +++ b/src/p7os/cake.exe/libgint/include/internals/rtc.h @@ -0,0 +1,141 @@ +#ifndef _INTERNALS_RTC_H +#define _INTERNALS_RTC_H + +#include +#include + +#ifndef RTC_CB_ARRAY_SIZE +#define RTC_CB_ARRAY_SIZE 5 +#endif + +/* + struct rtc_cb + An RTC callback. +*/ +struct rtc_cb +{ + enum RTCFrequency freq; + int id; + + void (*callback)(void); + int repeats; +}; + +// The callback array. +struct rtc_cb cb_array[RTC_CB_ARRAY_SIZE]; + +/* + struct mod_rtc + This structure describes the arrangement of RTC register in the memory. + Curious thing, on SH7705, registers RYRAR and RCR3 are at a completely + different address than the other ones. This module does not use these + registers, so they were not included in the structure. +*/ +#pragma pack(push, 1) + +struct mod_rtc +{ + unsigned char const R64CNT; + unsigned char _1; + + union { + unsigned char BYTE; + struct { + unsigned :1; + unsigned TENS :3; + unsigned ONES :4; + }; + } RSECCNT; + unsigned char _2; + + union { + unsigned char BYTE; + struct { + unsigned :1; + unsigned TENS :3; + unsigned ONES :4; + }; + } RMINCNT; + unsigned char _3; + + union { + unsigned char BYTE; + struct { + unsigned :2; + unsigned TENS :2; + unsigned ONES :4; + }; + } RHRCNT; + unsigned char _4; + + // 0 = Sunday, 1 = Monday, ..., 6 = Saturday, 7 = prohibited setting. + unsigned char RWKCNT; + unsigned char _5; + + union { + unsigned char BYTE; + struct { + unsigned :2; + unsigned TENS :2; + unsigned ONES :4; + }; + } RDAYCNT; + unsigned char _6; + + union { + unsigned char BYTE; + struct { + unsigned :3; + unsigned TENS :1; + unsigned ONES :4; + }; + } RMONCNT; + unsigned char _7; + + union { + unsigned short WORD; + struct { + unsigned THOUSANDS :4; + unsigned HUNDREDS :4; + unsigned TENS :4; + unsigned ONES :4; + }; + } RYRCNT; + unsigned char _8[12]; + + union { + unsigned char BYTE; + struct { + unsigned CF :1; + unsigned :2; + unsigned CIE :1; + unsigned AIE :1; + unsigned :2; + unsigned AF :1; + }; + } RCR1; + unsigned char _9; + + union { + unsigned char BYTE; + struct { + unsigned PEF :1; + unsigned PES :3; + unsigned :1; + unsigned ADJ :1; + unsigned RESET :1; + unsigned START :1; + }; + } RCR2; +} __attribute__((packed)); + +#pragma pack(pop) + +/* + We don't need to access the registers in a complicated way like the + function of the timer module. Let's make it simple. +*/ +#define RTC_SH7705 ((volatile struct mod_rtc *)0xfffffec0) +#define RTC_SH7305 ((volatile struct mod_rtc *)0xa413fec0) + +#endif // _INTERNALS_RTC_H diff --git a/src/p7os/cake.exe/libgint/include/internals/stdio.h b/src/p7os/cake.exe/libgint/include/internals/stdio.h new file mode 100644 index 0000000..bf68b81 --- /dev/null +++ b/src/p7os/cake.exe/libgint/include/internals/stdio.h @@ -0,0 +1,32 @@ +//--- +// +// standard library module: stdio +// +// Handles most input/output for the program. This module does not +// interact with the file system directly. +// +//--- + +#ifndef _INTERNALS_STDIO_H +#define _INTERNALS_STDIO_H 1 + +#include +#include + +//--- +// Formatted printing. +//--- + +#ifndef __stdio_buffer_size +#define __stdio_buffer_size 256 +#endif + +extern char __stdio_buffer[]; + +/* + __printf() + Formatted printing to the stdio buffer. +*/ +int __printf(size_t size, const char *format, va_list args); + +#endif // _INTERNALS_STDIO_H diff --git a/src/p7os/cake.exe/libgint/include/internals/tales.h b/src/p7os/cake.exe/libgint/include/internals/tales.h new file mode 100644 index 0000000..40342c1 --- /dev/null +++ b/src/p7os/cake.exe/libgint/include/internals/tales.h @@ -0,0 +1,55 @@ +#ifndef _INTERNALS_TALES_H +#define _INTERNALS_TALES_H 1 + +#include +#include + +#define OPERATE_ARGS uint32_t *operators, int height, int x, int y + +extern struct Font *font; +extern enum Color color; + +/* + tales_init() + Configures tales with the default font (which is part of gint). +*/ +void tales_init(void) __attribute__((constructor)); + +/* + getCharacterIndex() + Returns the index of a character in a font data area depending on the + font format and the size of the characters. Returns the index in the + data area, as long array, or -1 when the character does not belong to + the font format set. +*/ +int getCharacterIndex(int c); + +/* + operate() + Operates on the vram using the given operators. The x-coordinate should + be a multiple of 32. There should be `height` operators. +*/ +void operate_mono(OPERATE_ARGS); +void operate_gray(OPERATE_ARGS); + +/* + update() + Updates the operators using the given glyph. The operation will not be + complete if there are not enough bits available in the operator data. + In this case the offset will become negative, which means that the + calling procedure has to call operate() and re-call update(). + `available` represents the number of free bits in the operators (lower + bits). + Returns the number of bits available after the operation. If it's + negative, call operate() and update() again. +*/ +int update(uint32_t *operators, int height, int available, uint32_t *glyph); + +/* + render() + Renders text without any formatting analysis, using the given operation + function. +*/ +void render(int x, int y, const char *str, void (*op)(OPERATE_ARGS)); + +#endif // _INTERNALS_TALES_H diff --git a/src/p7os/cake.exe/libgint/include/internals/time.h b/src/p7os/cake.exe/libgint/include/internals/time.h new file mode 100644 index 0000000..236dcf6 --- /dev/null +++ b/src/p7os/cake.exe/libgint/include/internals/time.h @@ -0,0 +1,16 @@ +#ifndef _INTERNALS_TIME_H +#define _INTERNALS_TIME_H 1 + +/* + isLeap() + Determines whether the given year is a leap year. +*/ +int isLeap(int year); + +/* + daysInMonth() + Returns number of days for the given month (between 0 and 11) and year. +*/ +int daysInMonth(int month, int year); + +#endif // _INTERNALS_TIME_H diff --git a/src/p7os/cake.exe/libgint/include/internals/timer.h b/src/p7os/cake.exe/libgint/include/internals/timer.h new file mode 100644 index 0000000..f15abc1 --- /dev/null +++ b/src/p7os/cake.exe/libgint/include/internals/timer.h @@ -0,0 +1,48 @@ +#ifndef _INTERNALS_TIMER_H +#define _INTERNALS_TIMER_H 1 + +/* + struct Timer + This structure holds information for a running timer. +*/ +struct Timer +{ + void (*callback)(void); + int repeats; +}; + +extern struct Timer timers[3]; + +/* + struct mod_tmu + This structure holds information about the timer unit (peripheral + module) registers. +*/ +struct mod_tmu +{ + unsigned int TCOR; // Timer constant register. + unsigned int TCNT; // Timer counter. + + union + { + unsigned short WORD; + struct + { + unsigned :7; + unsigned UNF :1; // Underflow flag. + unsigned :2; + unsigned UNIE :1; // Underflow interrupt enable. + unsigned CKEG :2; // Clock edge (SH7705 only). + unsigned TPSC :3; // Timer prescaler. + }; + } TCR; // Timer control register. +}; + +/* + timer_get() + Returns the timer and TSTR register addresses. +*/ +void timer_get(int timer, volatile struct mod_tmu **tmu, + volatile unsigned char **tstr); + +#endif // _INTERNALS_TIMER_H diff --git a/src/p7os/cake.exe/libgint/include/keyboard.h b/src/p7os/cake.exe/libgint/include/keyboard.h new file mode 100644 index 0000000..278d0d9 --- /dev/null +++ b/src/p7os/cake.exe/libgint/include/keyboard.h @@ -0,0 +1,303 @@ +//--- +// +// gint core module: keyboard analyzer +// +// Probably the most difficult hardware interaction. There is very few +// documentation on how the system actually analyzes the keyboard. While +// disassembling syscalls reveals the following procedure (which was +// already documented by SimonLothar), there is nothing about the +// detection problems of the multi-getkey system. +// +//--- + +#ifndef _KEYBOARD_H +#define _KEYBOARD_H 1 + +#include + +//--- +// Keycodes and related. +//--- + +// The following codes are gint matrix codes. They are not compatible with the +// system's. + +#define KEY_F1 0x69 +#define KEY_F2 0x59 +#define KEY_F3 0x49 +#define KEY_F4 0x39 +#define KEY_F4 0x39 +#define KEY_F5 0x29 +#define KEY_F6 0x19 + +#define KEY_SHIFT 0x68 +#define KEY_OPTN 0x58 +#define KEY_VARS 0x48 +#define KEY_MENU 0x38 +#define KEY_LEFT 0x28 +#define KEY_UP 0x18 + +#define KEY_ALPHA 0x67 +#define KEY_SQUARE 0x57 +#define KEY_POWER 0x47 +#define KEY_EXIT 0x37 +#define KEY_DOWN 0x27 +#define KEY_RIGHT 0x17 + +#define KEY_XOT 0x66 +#define KEY_LOG 0x56 +#define KEY_LN 0x46 +#define KEY_SIN 0x36 +#define KEY_COS 0x26 +#define KEY_TAN 0x16 + +#define KEY_FRAC 0x65 +#define KEY_FD 0x55 +#define KEY_LEFTP 0x45 +#define KEY_RIGHTP 0x35 +#define KEY_COMMA 0x25 +#define KEY_ARROW 0x15 + +#define KEY_7 0x64 +#define KEY_8 0x54 +#define KEY_9 0x44 +#define KEY_DEL 0x34 +#define KEY_AC_ON 0x24 + +#define KEY_4 0x63 +#define KEY_5 0x53 +#define KEY_6 0x43 +#define KEY_MUL 0x33 +#define KEY_DIV 0x23 + +#define KEY_1 0x62 +#define KEY_2 0x52 +#define KEY_3 0x42 +#define KEY_PLUS 0x32 +#define KEY_MINUS 0x22 + +#define KEY_0 0x61 +#define KEY_DOT 0x51 +#define KEY_EXP 0x41 +#define KEY_NEG 0x31 +#define KEY_EXE 0x21 + +// Key modifiers. +#define MOD_SHIFT 0x80 +#define MOD_ALPHA 0x100 +#define MOD_CLEAR ~(MOD_SHIFT | MOD_ALPHA) + +// Key events. +#define KEY_NONE 0x00 +#define KEY_NOEVENT 0xff + +/* + enum KeyboardFrequency + Possible values for the keyboard frequency. +*/ +enum KeyboardFrequency +{ + KeyboardFreq_500mHz = RTCFreq_500mHz, + KeyboardFreq_1Hz = RTCFreq_1Hz, + KeyboardFreq_2Hz = RTCFreq_2Hz, + KeyboardFreq_4Hz = RTCFreq_4Hz, + KeyboardFreq_16Hz = RTCFreq_16Hz, + KeyboardFreq_64Hz = RTCFreq_64Hz, + KeyboardFreq_256Hz = RTCFreq_256Hz, +}; + + + +//--- +// Keyboard configuration. +//--- + +/* + keyboard_setFrequency() + Sets the keyboard frequency. The default frequency is 16 Hz. Very few + applications will need to change this setting. + At low frequencies, you will miss key hits. At high frequencies, you + may lose execution power. +*/ +void keyboard_setFrequency(enum KeyboardFrequency frequency); + +/* + keyboard_setRepeatRate() + Sets the default repeat rate for key events. The delay before the first + repeat may have a different value (usually longer). The unit for the + argument is the keyboard period. For example at 32 Hz, values of + (20, 4) will imitate the system default. + Set to 0 to disable repetition. If first = 0, no repetition will be + allowed. If first != 0 and next = 0, only one repetition will be + allowed. +*/ +void keyboard_setRepeatRate(int first, int next); + + + +//--- +// Keyboard access. +//--- + +/* + enum GetKeyOpt + Options available for use with getkey_opt(). +*/ +enum GetkeyOpt +{ + Getkey_NoOption = 0x00, + + // Consider [SHIFT] and [ALPHA] as modifiers instead of returning + // KEY_SHIFT and KEY_ALPHA. + Getkey_ShiftModifier = 0x01, + Getkey_AlphaModifier = 0x02, + + // Key repetition. Notice that modifiers will never be repeated. + Getkey_RepeatArrowKeys = 0x10, + Getkey_RepeatCharKeys = 0x20, + Getkey_RepeatCtrlKeys = 0x40, + Getkey_RepeatFuncKeys = 0x80, + // Shorthand for the four previous properties. + Getkey_RepeatAllKeys = 0xf0, +}; + +/* + keylast() + Returns the matrix code of the last pressed key. If repeat_count is + non-NULL, it is set to the number of repetitions. +*/ +int keylast(int *repeat_count); + +/* + keystate() + Returns the address of the keyboard state array. The keyboard state + consists in 10 bytes, in which every key is represented as a bit. + The returned address is the original buffer address. You should avoid + editing the array. It wouldn't influence the behavior of the keyboard + functions, but the buffer data is very volatile. Therefore, data + written to the buffer could be replaced anytime. +*/ +volatile unsigned char *keystate(void); + +/* + getkey() + Blocking function with auto-repeat and SHIFT modifying functionalities. + Reproduces the behavior of the system's GetKey(). Returns the matrix + code with a possible MOD_SHIFT bit. +*/ +int getkey(void); + +/* + getkey_opt() + Enhances getkey() with most general functionalities. An OR-combination + of options may be given as second argument. + If max_cycles is non-zero and positive, getkey_opt() will return + KEY_NOEVENT if no event occurs during max_cycle analysis. + As getkey(), returns the pressed key matrix code, possibly with + modifiers depending on the options. +*/ +int getkey_opt(enum GetkeyOpt options, int max_cycles); + +/* + multigetkey() + + Listens the keyboard for simultaneous key hits. This functions fills + array `keys` with `count` keycodes, adding KEY_NONE at the end if + less than `count` keys are pressed. + If `max_cycles` is non-zero and nothing happens after `max_cycles` + cycles, this function returns an array of KEY_NONE. + + WARNING: + Because of hardware limitations, this function generally yields poor + results. Rectangle and column effects make it read unpressed keys as + pressed (see documentation for more information). The more pressed + keys, the more errors. + + The results are guaranteed to be exact if two keys or less are pressed. + With three keys or more, column effects (on SH4) and rectangle effects + (on both platforms) mess up the results by making this function think + that some keys, which are actually unpressed, are pressed. + + This function is designed to make combinations of one or two arrow keys + with another key as viable as possible. On SH4, this works pretty well + even if combinations like Left + Down + SHIFT trigger ALPHA sometimes. + On SH3, rectangle effects are *always* present, making it impossible to + use Left + Down or Up + Right with any other key in their rows without + having this function return junk. + + Any other combination of keys may quite randomly result in variably + incorrect results. Please do not expect multigetkey() to work as an + ideal multi-key analyzer. +*/ +void multigetkey(int *keys, int count, int max_cycles); + + + +//--- +// Key analysis. +//--- + +enum KeyType +{ + KeyType_Arrow = 1, + KeyType_Character = 2, + KeyType_Control = 4, + KeyType_Function = 8, +}; + +/* + keyid() + Returns a non-matrix key code that can be used for array subscript. + Ignores modifiers. +*/ +int keyid(int key); + +/* + keychar() + Returns the ASCII character associated with a character key; 0 for + other keys. +*/ +int keychar(int key); + +/* + keytype() + Returns a key's type. Ignores modifiers. +*/ +enum KeyType keytype(int key); + + + +//--- +// Internal API. +// Reference here for documentation purposes only. Do not call. +//--- + +/* + keyboard_interrupt() + Notifies the keyboard module that an interrupt request has been issued, + and updates the keyboard state. +*/ +void keyboard_interrupt(void) __attribute__((section(".gint.int"))); + +/* + keyboard_updateState() + Updates the keyboard state. +*/ +void keyboard_updateState_7705(volatile unsigned char *state) + __attribute__((section(".gint.int"))); +void keyboard_updateState_7305(volatile unsigned char *state) + __attribute__((section(".gint.int"))); + +/* + keyboard_init() + Starts the keyboard timer. +*/ +void keyboard_init(void) __attribute__((constructor)); + +/* + keyboard_quit() + Stops the keyboard timer. +*/ +void keyboard_quit(void) __attribute__((destructor)); + +#endif // _KEYBOARD_H diff --git a/src/p7os/cake.exe/libgint/include/mpu.h b/src/p7os/cake.exe/libgint/include/mpu.h new file mode 100644 index 0000000..fd4a498 --- /dev/null +++ b/src/p7os/cake.exe/libgint/include/mpu.h @@ -0,0 +1,76 @@ +//--- +// +// gint core module: mpu +// +// Determines which kind of MPU is running the program. This module +// provides macro tests isSH3(), isSH4(), and the identifier of the MPU, +// which is stored in a global variable MPU_CURRENT. +// +// If you need to do MPU-dependant jobs, prefer the following alternative: +// +// if(isSH3()) +// { +// ... +// } +// else +// { +// ... +// } +// +//--- + +#ifndef _MPU_H +#define _MPU_H 1 + +/* + enum MPU + This type holds information about the calculator's MPU. +*/ +enum MPU +{ + MPU_Unknown = 0, + // fx-9860G SH3. + MPU_SH7337 = 1, + // fx-9860G II SH3. + MPU_SH7355 = 2, + // fx-9860G II SH4. + MPU_SH7305 = 3, + // Just for reference. + MPU_SH7724 = 4 +}; + +// Global MPU variable, accessible for direct tests. Initialized at the +// beginning of execution. +extern enum MPU MPU_CURRENT; + +// Quick SH3 test. It is safer to assume that an unknown model is SH4 because +// SH3-based models are not produced anymore. +#define isSH3() (MPU_CURRENT == MPU_SH7337 || MPU_CURRENT == MPU_SH7355) +#define isSH4() !isSH3() + + + +//--- +// Public API. +//--- + +/* + getMPU() + Determines the MPU type and returns it. MPU_CURRENT is not updated. +*/ +enum MPU getMPU(void); + + + +//--- +// Internal API. +// Referenced here for documentation purposes only. Do not call. +//--- + +/* + mpu_init() + Determines the MPU type and stores the result into MPU_CURRENT. +*/ +void mpu_init(void) __attribute__((constructor)); + +#endif // _MPU_H diff --git a/src/p7os/cake.exe/libgint/include/rtc.h b/src/p7os/cake.exe/libgint/include/rtc.h new file mode 100644 index 0000000..805c91d --- /dev/null +++ b/src/p7os/cake.exe/libgint/include/rtc.h @@ -0,0 +1,121 @@ +//--- +// +// gint core module: rtc +// +// Manages RTC. This module is used behind standard module time. +// +//--- + +#ifndef _RTC_H +#define _RTC_H 1 + +//--- +// Time access. +//--- + +/* + struct RTCTime + Defines a point in time. +*/ +struct RTCTime +{ + int seconds; // Seconds in range 0-59 + int minutes; // Minutes in range 0-59 + int hours; // Hours in range 0-23 + int month_day; // Day of month in range 1-31 + int month; // Month in range 0-11 + int year; // Years (full value) + int week_day; // Day of week in range 0(Sunday)-6(Saturday). +}; + +/* + rtc_getTime() + Reads the current time from the RTC. There is no guarantee that the + week day is correct (use the time API for that). +*/ +struct RTCTime rtc_getTime(void); + +/* + rtc_setTime() + Sets the time in the RTC registers. The week day is set to 0 if greater + than 6. Other fields are not checked. +*/ +void rtc_setTime(struct RTCTime time); + + + +//--- +// Callback API. +//--- + +/* + enum RTCFrequency + Describes the possible frequencies available for the real-time clock + interrupt. +*/ +enum RTCFrequency +{ + RTCFreq_500mHz = 7, + RTCFreq_1Hz = 6, + RTCFreq_2Hz = 5, + RTCFreq_4Hz = 4, + RTCFreq_16Hz = 3, + RTCFreq_64Hz = 2, + RTCFreq_256Hz = 1, + RTCFreq_None = 0, +}; + +/* + rtc_cb_add() + Registers a new callback for the RTC. Returns the callback id on + success (positive integer), or one of the following error codes: + -1 Array is full + -2 Invalid parameter + The number of repeats may be set to 0, in which case the callback is + called indefinitely unless the user calls rtc_cb_end(). +*/ +int rtc_cb_add(enum RTCFrequency freq, void (*function)(void), int repeats); + +/* + rtc_cb_end() + Removes the callback with the given id (as returned by rtc_cb_add()) + from the callback array. +*/ +void rtc_cb_end(int id); + +/* + rtc_cb_edit() + Changes information related to a callback. This function returns 0 on + success, or one of the following error codes: + -1 Callback does not exist + -2 Invalid parameters + This function never removes a callback. Call rtc_cb_end() for this. One + can set the function to NULL or the frequency to RTCFreq_None to + temporarily disable the callback. +*/ +int rtc_cb_edit(int id, enum RTCFrequency new_freq, + void (*new_function)(void)); + + + +//--- +// Internal API. +// Referenced here for documentation purposes only. Do not call. +//--- + +/* + rtc_interrupt() + Handles an RTC interrupt by calling the callback. +*/ +void rtc_interrupt(void) __attribute__((section(".gint.int"))); +void rtc_interrupt_7705(void) __attribute__((section(".gint.int"))); +void rtc_interrupt_7305(void) __attribute__((section(".gint.int"))); + +/* + rtc_cb_interrupt() + Handles an RTC interrupt. Calls the RTC callbacks if necessary, and + updates the repeat counts. +*/ +void rtc_cb_interrupt(void); + +#endif // _RTC_H diff --git a/src/p7os/cake.exe/libgint/include/screen.h b/src/p7os/cake.exe/libgint/include/screen.h new file mode 100644 index 0000000..175e983 --- /dev/null +++ b/src/p7os/cake.exe/libgint/include/screen.h @@ -0,0 +1,23 @@ +//--- +// +// gint display module: screen +// +// Interacts with the physical screen. See other display modules for video +// ram management and drawing. +// +// The screen basically has two input values, which are a register +// selector and the selected register's value. What this module does is +// essentially selecting registers by setting *selector and assigning them +// values by setting *data. +//--- + +#ifndef _SCREEN_H +#define _SCREEN_H 1 + +/* + screen_display() + Displays contents on the full screen. Expects a 1024-byte buffer. +*/ +void screen_display(const void *vram); + +#endif diff --git a/src/p7os/cake.exe/libgint/include/setjmp.h b/src/p7os/cake.exe/libgint/include/setjmp.h new file mode 100644 index 0000000..54dceea --- /dev/null +++ b/src/p7os/cake.exe/libgint/include/setjmp.h @@ -0,0 +1,35 @@ +//--- +// +// gint standard module: setjmp +// +// Long jumps. The register contents are saved in a buffer when setjmp() +// is called and restored at any time when longjmp() performs the jump. +// +//--- + +#ifndef _SETJMP_H +#define _SETJMP_H 1 + +// There are 16 CPU registers that *must* be saved to ensure a basically +// safe jump. +typedef unsigned int jmp_buf[16]; + + + +//--- +// Long jump functions. +//--- + +/* + setjmp() O(1) + Configures a jump by saving data to the given jump buffer. +*/ +int setjmp(jmp_buf env); + +/* + longjmp() O(1) + Performs a long jump. +*/ +void longjmp(jmp_buf env, int value); + +#endif // _SETJMP_H diff --git a/src/p7os/cake.exe/libgint/include/stdio.h b/src/p7os/cake.exe/libgint/include/stdio.h new file mode 100644 index 0000000..f19ecdb --- /dev/null +++ b/src/p7os/cake.exe/libgint/include/stdio.h @@ -0,0 +1,44 @@ +//--- +// +// standard library module: stdio +// +// Handles most input/output for the program. This module does not +// interact with the file system directly. +// +//--- + +#ifndef _STDIO_H +#define _STDIO_H 1 + +#include +#include + +//--- +// Formatted printing. +//--- + +/* + sprintf() + Prints to a string. +*/ +int sprintf(char *str, const char *format, ...); + +/* + snprintf() + Prints to a string with a size limit. +*/ +int snprintf(char *str, size_t size, const char *format, ...); + +/* + vsprintf() + Prints to a string from an argument list. +*/ +int vsprintf(char *str, const char *format, va_list args); + +/* + vsnprintf() + The most generic formatted printing function around there. +*/ +int vsnprintf(char *str, size_t size, const char *format, va_list args); + +#endif // _STDIO_H diff --git a/src/p7os/cake.exe/libgint/include/stdlib.h b/src/p7os/cake.exe/libgint/include/stdlib.h new file mode 100644 index 0000000..5904525 --- /dev/null +++ b/src/p7os/cake.exe/libgint/include/stdlib.h @@ -0,0 +1,149 @@ +//--- +// +// standard library module: stdlib +// +// Provides standard functionalities such as dynamic allocation, +// string/numeric conversion, and abort calls. +// +//--- + +#ifndef _STDLIB_H +#define _STDLIB_H 1 + +//--- +// Common definitions. +//--- + +#include +#include + +// Common exit codes. +#define EXIT_SUCCESS 1 +#define EXIT_FAILURE 0 + +// Number of atexit() registrations guaranteed. +#ifndef ATEXIT_MAX +#define ATEXIT_MAX 16 +#endif + +// Maximum value returned by rand(). +#define RAND_MAX INT_MAX + +// Integer division result. +typedef struct +{ + int quot, rem; +} div_t; +typedef struct +{ + long quot, rem; +} ldiv_t; + + + +//--- +// Program exit functions. +//--- + +/* + abort() + Aborts the program execution without calling the exit handlers. +*/ +void abort(void); + +/* + exit() + Stops the program execution with the given status code, after calling + the exit handlers. +*/ +void exit(int status); + +/* + atexit() + Registers a function to be called at normal program termination. +*/ +int atexit(void (*function)(void)); + + + +//--- +// Dynamic storage allocation. +//--- + +/* + malloc() + Allocates 'size' bytes and returns a pointer to a free memory area. + Returns NULL on error. +*/ +void *malloc(size_t size); + +/* + calloc() + Allocates 'n' elements of size 'size' and wipes the memory area. + Returns NULL on error. +*/ +void *calloc(size_t n, size_t size); + +/* + realloc() + Reallocates a memory block and moves its data. +*/ +void *realloc(void *ptr, size_t size); + +/* + free() + Frees a memory block allocated by malloc(), calloc() or realloc(). +*/ +void free(void *ptr); + + + +//--- +// Random number generation. +//--- + +/* + rand() + Returns a pseudo-random number. +*/ +int rand(void); + +/* + srand() + Changes the seed used by rand(). +*/ +void srand(unsigned int seed); + +//--- +// Integer arithmetic. +//--- + +/* + abs() + Returns the absolute value of an integer. +*/ +int abs(int x); +// Use a macro instead, when possible. +#define abs(x) ((x) < 0 ? -(x) : (x)) + +/* + labs() + Returns the absolute value of a long integer. +*/ +long labs(long x); +// Use a macro instead. +#define labs(x) ((x) < 0 ? -(x) : (x)) + +/* + div() + Computes the integer division of numerator by denominator. +*/ +div_t div(int numerator, int denominator); + +/* + ldiv() + Computes the integer division of two long integers. +*/ +ldiv_t ldiv(long numerator, long denominator); + +#endif // _STDLIB_H diff --git a/src/p7os/cake.exe/libgint/include/string.h b/src/p7os/cake.exe/libgint/include/string.h new file mode 100644 index 0000000..dc0ac1c --- /dev/null +++ b/src/p7os/cake.exe/libgint/include/string.h @@ -0,0 +1,63 @@ +//--- +// +// standard library module: string +// +// String manipulation using NUL-terminated byte arrays, without extended +// characters. +// +//--- + +#ifndef _STRING_H +#define _STRING_H 1 + +#include + +//--- +// Memory manipulation. +//--- + +/* + memcpy() O(byte_number) + Copies a memory area. The two areas must not overlap (if they do, use + memmove()). A smart copy is performed when possible. To enhance + performance, make sure than destination and source are both 4-aligned. +*/ +void *memcpy(void *destination, const void *source, size_t byte_number); + +/* + memset() O(byte_number) + Sets the contents of a memory area. A smart copy is performed. +*/ +void *memset(void *destination, int byte, size_t byte_number); + + + +//--- +// String manipulation. +//--- + +/* + strlen() O(len(str)) + Returns the length of a string. +*/ +size_t strlen(const char *str); + +/* + strcpy() O(len(source)) + Copies a string to another. +*/ +char *strcpy(char *destination, const char *source); + +/* + strchr() O(len(str)) + Searches a character in a string. +*/ +const char *strchr(const char *str, int value); + +/* + strncpy() O(min(len(source), size)) + Copies part of a string to another. +*/ +char *strncpy(char *destination, const char *source, size_t size); + +#endif // _STRING_H diff --git a/src/p7os/cake.exe/libgint/include/tales.h b/src/p7os/cake.exe/libgint/include/tales.h new file mode 100644 index 0000000..e1304c3 --- /dev/null +++ b/src/p7os/cake.exe/libgint/include/tales.h @@ -0,0 +1,123 @@ +//--- +// +// gint drawing module: tales +// +// Text displaying. Does some pretty good optimization, though requires +// dynamic allocation. The stack is used. +// +//--- + +#ifndef _TALES_H +#define _TALES_H 1 + +#include +#include + +//--- +// Types and constants. +//--- + +/* + enum ImageFormat + This type holds information about the characters in the font. Each bit + represents various characters, and the type itself is a combination of + several of those bits. + Bits represent the following characters (lsb right): + -- -- -- non-print | special capitals lower numbers +*/ +enum FontFormat +{ + FontFormat_Unknown = 0x00, + FontFormat_Numeric = 0x01, + FontFormat_LowerCase = 0x02, + FontFormat_UpperCase = 0x04, + FontFormat_Letters = 0x06, + FontFormat_Common = 0x07, + FontFormat_Print = 0x0f, + FontFormat_Ascii = 0x1f, +}; + +/* + struct FontGlyph + Holds a glyph's data. The width is used for spacing, and the raw data + is encoded line after line, from to to bottom, by appending bits + without consideration of the byte boundaries. + This structure is actually never used, because data is read directly + as a longword array (hence the 4-byte alignment). +*/ +struct FontGlyph +{ + unsigned char width; + + const unsigned char data[]; +} __attribute__((aligned(4))); + +/* + struct Font + Holds a font's data. Data is accessed using longword operations, hence + the 4-alignment attributes. The line height is the one given in the + font image header line, which may be used by applications that write + strings on several lines. The data height is the height of the biggest + glyph. Every glyph is encoded on 'data_height' lines, for optimization + considerations. + The index field is used to reduce character access time. + The name field may not be NUL-terminated when the name contains 28 + characters. When the name is shorter, the field is padded with zeros. +*/ +struct Font +{ + unsigned char magic; + + unsigned char format; + unsigned char line_height; + unsigned char data_height; + + // Warning : this field may not be NUL-terminated. + char name[28]; + + uint16_t index[16]; + + __attribute__((aligned(4))) const uint32_t glyphs[]; + +} __attribute__((aligned(4))); +// Useful shorthand for user code. +typedef struct Font Font; + + + +//--- +// Generic functions. +//--- + +/* + text_configure() + Sets the font and color to use for subsequent text operations. Pass + font = NULL to use the default font. +*/ +void text_configure(struct Font *font, enum Color color); + +/* + dtext() + Prints the given string, without any analysis. +*/ +void dtext(int x, int y, const char *str); + +/* + gtext() + Prints the given raw string. +*/ +void gtext(int x, int y, const char *str); + +/* + dprint() + Prints a formatted string. Works the same as printf(). +*/ +void dprint(int x, int y, const char *format, ...); + +/* + gprint() + Prints a formatted string. Works the same as printf(). +*/ +void gprint(int x, int y, const char *format, ...); + +#endif // _TALES_H diff --git a/src/p7os/cake.exe/libgint/include/time.h b/src/p7os/cake.exe/libgint/include/time.h new file mode 100644 index 0000000..107e4fc --- /dev/null +++ b/src/p7os/cake.exe/libgint/include/time.h @@ -0,0 +1,126 @@ +//--- +// +// standard library module: time +// +// Provides time manipulation and representation functions. +// +//--- + +#ifndef _TIME_H +#define _TIME_H 1 + +#include + +//--- +// Some related types. +//--- + +/* + struct tm + Represents a point in time and gives some date information. +*/ +struct tm +{ + int tm_sec; // Seconds in range 0-59 + int tm_min; // Minutes in range 0-59 + int tm_hour; // Hours in range 0-23 + int tm_mday; // Day of month in range 1-31 + int tm_mon; // Month in range 0-11 + int tm_year; // Number of years since 1900 + int tm_wday; // Day of week in range 0(Sunday)-6(Saturday). + int tm_yday; // Day of the year in range 0-365. + int tm_isdst; // This will always be 0. +}; + +/* + clock_t + Only used by clock(). +*/ +typedef signed int clock_t; + +/* + time_t + Number of seconds elapsed since 1970-01-01 00:00:00. +*/ +typedef signed int time_t; + + + +//--- +// Time access. +//--- + +/* + clock() + Should return elapsed CPU time since beginning of program execution. + This is currently not implemented and returns -1. +*/ +clock_t clock(void); + +/* + time() + Returns the current time as calendar time. If you need a broken-down + time, either use the RTC API or gmtime(). However, this function is + already based on mktime() (for hardware reasons) so it would be much + faster to use the RTC API if possible. + If timeptr is not NULL, it is set to the current time, that is, the + value that is returned. +*/ +time_t time(time_t *timeptr); + +/* + difftime() + Returns the number of seconds between the given points. +*/ +double difftime(time_t end, time_t beginning); +// But this macro should do. +#define difftime(end, beginning) ((double)((end) - (beginning))) + + + +//--- +// Time representation. +//--- + +/* + asctime() + Converts broken-down time to string representation on the form + "Wed Jun 30 21:49:08 1993\n". The returned string is statically + allocated and may be overwritten by any subsequent call to a time + function. +*/ +char *asctime(const struct tm *time); + +/* + ctime() + Converts calendar time to string representation on the form + "Wed Jun 30 21:49:08 1993\n". The returned string is statically + allocated and may be overwritten by any subsequent call to a time + function. +*/ +char *ctime(const time_t *timer); + + + +//--- +// Time conversion. +//--- + +/* + mktime() + Converts broken-down time to calendar time. Computes structure fields + tm_wday and tm_yday using the other fields. Member structures outside + their range are normalized (e.g. 40 October becomes 9 November) and + tm_isdst is set. +*/ +time_t mktime(struct tm *time); + +/* + gmtime() + Converts calendar time to broken-down time. The returned pointer is + statically allocated and may be overwritten by any subsequent call to + a time function. +*/ +struct tm *gmtime(const time_t *t); + +#endif // _TIME_H diff --git a/src/p7os/cake.exe/libgint/include/timer.h b/src/p7os/cake.exe/libgint/include/timer.h new file mode 100644 index 0000000..f896c4a --- /dev/null +++ b/src/p7os/cake.exe/libgint/include/timer.h @@ -0,0 +1,89 @@ +//--- +// +// gint core module: timer +// +// Basic timer unit manipulation. Starts and stops timers with variable +// number of repeats, and allows timer reloads without pause. +// +//--- + +#ifndef _TIMER_H +#define _TIMER_H 1 + +#include + +//--- +// Constants. +//--- + +// Timer identifiers. +#define TIMER_0 0 +#define TIMER_TMU0 TIMER_0 +#define TIMER_1 1 +#define TIMER_TMU1 TIMER_1 +#define TIMER_2 2 +#define TIMER_TMU2 TIMER_2 +// Timer function identifiers. +#define TIMER_KEYBOARD TIMER_TMU0 +#define TIMER_GRAY TIMER_TMU1 +#define TIMER_USER TIMER_TMU2 + +// Timer prescalers. +#define TIMER_Po_4 0 +#define TIMER_Po_16 1 +#define TIMER_Po_64 2 +#define TIMER_Po_256 3 +#define TIMER_TCLK 5 + + + +//--- +// Public API. +//--- + +/* + timer_start() + Configures and starts a timer. The timer argument expects a timer name. + You can use TIMER_USER anytime. You may also use TIMER_GRAY if you're + not running the gray engine. + The delay is in clock counts unit. The possible values for the + prescaler are dividers of the peripheral clock frequency Po: + - TIMER_Po_4 + - TIMER_Po_16 + - TIMER_Po_64 + - TIMER_Po_256 + - TIMER_TCLK + The number of repeats may to set to 0. In this case, the timer will not + stop until timer_stop() is explicitly called. +*/ +void timer_start(int timer, int delay, int prescaler, void (*callback)(void), + int repeats); + +/* + timer_stop() + Stops the given timer. This function may be called even if the timer is + not running. +*/ +void timer_stop(int timer); + +/* + timer_reload() + Reloads the given timer with the given constant. Starts the timer if + it was stopped. The new delay uses the same unit as in timer_start(). +*/ +void timer_reload(int timer, int new_delay); + + + +//--- +// Internal API. +// Referenced for documentation purposes only. Do not call. +//--- + +/* + timer_interrupt() + Handles the interrupt for the given timer. +*/ +void timer_interrupt(int timer) __attribute__((section(".gint.int"))); + +#endif // _TIMER_H diff --git a/src/p7os/cake.exe/libgint/src/bopti/bopti_internals.c b/src/p7os/cake.exe/libgint/src/bopti/bopti_internals.c new file mode 100644 index 0000000..b8c08ce --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/bopti/bopti_internals.c @@ -0,0 +1,329 @@ +#include + +// Monochrome video ram, light and dark buffers (in this order). +int *bopti_vram, *bopti_v1, *bopti_v2; + +/* + bopti_op() + Operates on a vram long. The operator will often not contain 32 bits of + image information. Since neutral bits are not the same for all + operations, a mask is used to indicate which bits should be used for + the operation. This mask is taken for the image's rectangle masks (see + module display for more information on rectangle masks). + Which operation is performed is determined by the channel setting. +*/ +void bopti_op_mono(int offset, uint32_t operator, struct Command *c) +{ + operator &= c->masks[offset & 3]; + + switch(c->channel) + { + case Channel_FullAlpha: + bopti_vram[offset] &= ~operator; + break; + + case Channel_Mono: + bopti_vram[offset] |= operator; + break; + + default: + break; + } +} +void bopti_op_gray(int offset, uint32_t operator, struct Command *c) +{ + operator &= c->masks[offset & 3]; + + switch(c->channel) + { + case Channel_FullAlpha: + bopti_v1[offset] &= ~operator; + bopti_v2[offset] &= ~operator; + break; + + case Channel_LightAlpha: + case Channel_DarkAlpha: + break; + + case Channel_Mono: + bopti_v1[offset] |= operator; + bopti_v2[offset] |= operator; + break; + + case Channel_Light: + bopti_v1[offset] |= operator; + break; + + case Channel_Dark: + bopti_v2[offset] |= operator; + break; + } +} + +/* + bopti_grid() -- general form + bopti_grid_a32() -- when x is a multiple of 32 + + Draws the grid at the beginning of a layer's data. The length of this + grid is always a multiple of 32. + The need for bopti_grid_a32() is not only linked to optimization, + because bopti_grid() will perform a 32-bit shift when x is a multiple + of 32, which is undefined behavior. +*/ +void bopti_grid_a32(const uint32_t *layer, int column_count, int height, + struct Command *c) +{ + int vram_column_offset = (c->y << 2) + (c->x >> 5); + int vram_offset = vram_column_offset; + int column, row; + + for(column = 0; column < column_count; column++) + { + for(row = c->top; row < c->bottom; row++) + { + (*c->op)(vram_offset, layer[row], c); + vram_offset += 4; + } + + vram_column_offset++; + vram_offset = vram_column_offset; + layer += height; + } +} +void bopti_grid(const uint32_t *layer, int column_count, int height, + struct Command *c) +{ + if(!column_count) return; + if(!(c->x & 31)) + { + bopti_grid_a32(layer, column_count, height, c); + return; + } + + const uint32_t *p1, *p2; + uint32_t l1, l2, operator; + int right_column, line; + int actual_column_count; + + int vram_column_offset = (c->y << 2) + (c->x >> 5) + (c->x < 0); + int vram_offset = vram_column_offset; + + int shift1 = 32 - (c->x & 31); + int shift2 = (c->x & 31); + + // Initializing two pointers. They will read two adjacent columns at + // the same time (p2 is column ahead of p1). Since the columns are + // written one after another, incrementing them will suffice when + // reaching the end of two columns, to move them to the next ones. + p1 = layer - height; + p2 = layer; + + // We don't want to write the first vram column when x is negative + // because it's outside the screen. + if(c->x < 0) p1 += height, p2 += height; + right_column = (c->x < 0); + // For the same reason, we don't to draw the additional rightmost + // column when it begins after 96. + if(c->x + (column_count << 5) > 128) + actual_column_count = column_count - 1; + else + actual_column_count = column_count; + + // Drawing vram longwords, using pairs of columns. + while(right_column <= actual_column_count) + { + for(line = c->top; line < c->bottom; line++) + { + l1 = (right_column > 0) ? p1[line] : (0); + l2 = (right_column < column_count) ? p2[line] : (0); + + operator = (l1 << shift1) | (l2 >> shift2); + (*c->op)(vram_offset, operator, c); + vram_offset += 4; + } + + p1 += height; + p2 += height; + vram_column_offset++; + vram_offset = vram_column_offset; + right_column++; + } +} + +/* + bopti_end_get() + Returns an operator for the end of a line, whose width is lower than 32 + (by design: otherwise, it would have been a column). The given pointer + is read and updated so that it points to the next line at the end of + the operation. +*/ +uint32_t bopti_end_get1(const unsigned char **data) +{ + uint32_t operator = **data; + *data += 1; + return operator; +} +uint32_t bopti_end_get2(const unsigned char **data) +{ + uint32_t operator = *((uint16_t *)*data); + *data += 2; + return operator; +} + +/* + bopti_rest() -- general form + bopti_rest_nover() -- when the end does not overlap two vram longs + + Draws the end of a layer, which can be considered as a whole layer + whose with is lower than 32. (Actually is it lower or equal to 16; + otherwise it would have been a column and the end would be empty). +*/ +void bopti_end_nover(const unsigned char *end, int size, struct Command *c) +{ + uint32_t (*get)(const unsigned char **data) = + (size == 2) ? bopti_end_get2 : bopti_end_get1; + + // We *have* shift >= 0 because of this function's 'no overlap' + // requirement. + int shift = (32 - (size << 3)) - (c->x & 31); + int vram_offset = (c->y << 2) + (c->x >> 5); + uint32_t operator; + int row; + + // Skipping c->top lines (because get() function only allows sequential + // access). + end += c->top * size; + + for(row = c->top; row < c->bottom; row++) + { + operator = (*get)(&end); + operator <<= shift; + + (*c->op)(vram_offset, operator, c); + vram_offset += 4; + } +} +void bopti_end(const unsigned char *end, int size, struct Command *c) +{ + uint32_t (*get)(const unsigned char **data) = + (size == 2) ? (bopti_end_get2) : (bopti_end_get1); + + int vram_offset = (c->y << 2) + (c->x >> 5); + uint32_t row_data, operator; + int row; + + int shift_base = (32 - (size << 3)); + int shift1 = (c->x & 31) - shift_base; + int shift2 = shift_base + 32 - (c-> x & 31); + + // Skipping c->top lines (because get() function only allows sequential + // access). + end += c->top * size; + + for(row = c->top; row < c->bottom; row++) + { + row_data = (*get)(&end); + + operator = row_data >> shift1; + (*c->op)(vram_offset, operator, c); + + operator = row_data << shift2; + (*c->op)(vram_offset + 1, operator, c); + + vram_offset += 4; + } +} + + + +//--- +// Wrappers and various functions. +//--- + +/* + bopti() + Draws a layer in the video ram. +*/ +void bopti(const unsigned char *layer, struct Structure *s, struct Command *c) +{ + const unsigned char *grid, *end; + int grid_columns, has_end; + + // Skipping columns at the beginning. + grid = layer + ((c->left * s->height) << 2); + + // Updating the command arguments to eliminate some information about + // parts that are not being drawn. + c->x += (c->left << 5); + c->y += c->top; + + // Columns are identified by ids 0 to s->columns - 1, and the end has + // id s->columns. So the end is drawn if this last column is included. + has_end = (c->right == s->columns); + // Computing number of grid columns to draw. + grid_columns = c->right - c->left + 1 - has_end; + + bopti_grid((const uint32_t *)grid, grid_columns, s->height, c); + + if(has_end) + { + end = layer + ((s->columns * s->height) << 2); + c->x += (grid_columns << 5); + + if((c->x & 31) + s->end_size <= 32) + bopti_end_nover(end, s->end_bytes, c); + else + bopti_end(end, s->end_bytes, c); + } +} + +/* + getStructure() + Determines the image size and data pointer. +*/ +void getStructure(struct Image *img, struct Structure *s) +{ + int column_count, end, end_bytes, layer; + + // Large images. + if(!img->width && !img->height) + { + s->width = (img->data[0] << 8) | img->data[1]; + s->height = (img->data[2] << 8) | img->data[3]; + s->data = img->data + 4; + + column_count = (s->width + 31) >> 5; + end = 0; + end_bytes = 0; + } + else + { + s->width = img->width; + s->height = img->height; + s->data = img->data; + + column_count = img->width >> 5; + end = img->width & 31; + end_bytes = + !end ? 0 : + end <= 8 ? 1 : + end <= 16 ? 2 : + 4; + + if(end_bytes == 4) + { + column_count++; + end = 0; + end_bytes = 0; + } + } + + // The layer size must be rounded to a multiple of 4. + layer = s->height * ((column_count << 2) + end_bytes); + if(layer & 3) layer += 4 - (layer & 3); + + s->columns = column_count; + s->end_bytes = end_bytes; + s->end_size = end; + s->layer_size = layer; +} diff --git a/src/p7os/cake.exe/libgint/src/bopti/dimage.c b/src/p7os/cake.exe/libgint/src/bopti/dimage.c new file mode 100644 index 0000000..6b09ae5 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/bopti/dimage.c @@ -0,0 +1,57 @@ +#include +#include + +/* + dimage() + Displays a monochrome image in the video ram. +*/ +void dimage(int x, int y, struct Image *img) +{ + if(!img || img->magic != 0xb7) return; + + struct Structure s; + struct Command command; + int actual_width; + int format = img->format, i = 0; + + if(format != Format_Mono && format != Format_MonoAlpha) return; + getStructure(img, &s); + + //--- + // Adjusting image parameters. + //--- + + if(x + s.width < 0 || x > 127 || y + s.height < 0 || y > 63) return; + + command.top = (y < 0) ? (-y) : (0); + command.bottom = (y + s.height > 64) ? (64 - y) : (s.height); + command.left = ((x < 0) ? (-x) : (0)) >> 5; + actual_width = (x + s.width > 128) ? (128 - x) : (s.width); + command.right = ((actual_width + 31) >> 5) - 1; + + command.op = bopti_op_mono; + + if(x >= 0) getMasks(x, x + actual_width - 1, command.masks); + else getMasks(0, actual_width + x - 1, command.masks); + + bopti_vram = display_getCurrentVRAM(); + + while(format) + { + // Drawing every layer, in order of formats. + if(format & 1) + { + // These members are modified by bopti()! + command.x = x; + command.y = y; + command.channel = (1 << i); + + bopti(s.data, &s, &command); + s.data += s.layer_size; + } + + format >>= 1; + i++; + } + +} diff --git a/src/p7os/cake.exe/libgint/src/bopti/dimage_part.c b/src/p7os/cake.exe/libgint/src/bopti/dimage_part.c new file mode 100644 index 0000000..06ef43b --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/bopti/dimage_part.c @@ -0,0 +1,65 @@ +#include +#include + +/* + dimage_part() + Draws a portion of an image, defined by its bounding rectangle. + Point (left, top) is included, but (left + width, top + height) is + excluded. +*/ +void dimage_part(int x, int y, struct Image *img, int left, int top, + int width, int height) +{ + if(!img || img->magic != 0xb7) return; + + struct Structure s; + struct Command command; + int actual_width; + int format = img->format, i = 0; + + if(format != Format_Mono && format != Format_MonoAlpha) return; + getStructure(img, &s); + + //--- + // Adjusting the bounding rectangle. + //--- + + // This is what happens when the bounding rectangle overflows from the + // image... + if(left < 0) left = 0; + if(top < 0) top = 0; + if(left + width > s.width) width = s.width - left; + if(top + height > s.height) height = s.height - top; + + if(x + left + width <= 0 || x > 127 || y + top + height <= 0 || y > 63) + return; + + command.top = (y < 0) ? (top - y) : top; + command.bottom = top + ((y + height > 64) ? (64 - y) : height); + command.left = ((x < 0) ? (left - x) : left) >> 5; + actual_width = (x + width > 128) ? (128 - x) : width; + command.right = ((left + actual_width + 31) >> 5) - 1; + + command.op = bopti_op_mono; + + if(x >= 0) getMasks(x, x + actual_width - 1, command.masks); + else getMasks(0, actual_width + x - 1, command.masks); + + bopti_vram = display_getCurrentVRAM(); + + while(format) + { + if(format & 1) + { + command.x = x - left; + command.y = y - top; + command.channel = (1 << i); + + bopti(s.data, &s, &command); + s.data += s.layer_size; + } + + format >>= 1; + i++; + } +} diff --git a/src/p7os/cake.exe/libgint/src/bopti/gimage.c b/src/p7os/cake.exe/libgint/src/bopti/gimage.c new file mode 100644 index 0000000..4f8371e --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/bopti/gimage.c @@ -0,0 +1,57 @@ +#include +#include +#include + +/* + gimage() + Displays a gray image in the video ram. +*/ +void gimage(int x, int y, struct Image *img) +{ + if(!img || img->magic != 0xb7) return; + + struct Structure s; + struct Command command; + int actual_width; + int format = img->format, i = 0; + + getStructure(img, &s); + + //--- + // Adjusting image parameters. + //--- + + if(x + s.width <= 0 || x > 127 || y + s.height <= 0 || y > 63) return; + + command.top = (y < 0) ? (-y) : (0); + command.bottom = (y + s.height > 64) ? (64 - y) : (s.height); + command.left = ((x < 0) ? (-x) : (0)) >> 5; + actual_width = (x + s.width > 128) ? (128 - x) : (s.width); + command.right = ((actual_width + 31) >> 5) - 1; + + command.op = bopti_op_gray; + + if(x >= 0) getMasks(x, x + actual_width - 1, command.masks); + else getMasks(0, actual_width + x - 1, command.masks); + + bopti_v1 = gray_lightVRAM(); + bopti_v2 = gray_darkVRAM(); + + while(format) + { + // Drawing every layer, in order of formats. + if(format & 1) + { + // These members are modified by bopti()! + command.x = x; + command.y = y; + command.channel = (1 << i); + + bopti(s.data, &s, &command); + s.data += s.layer_size; + } + + format >>= 1; + i++; + } +} diff --git a/src/p7os/cake.exe/libgint/src/bopti/gimage_part.c b/src/p7os/cake.exe/libgint/src/bopti/gimage_part.c new file mode 100644 index 0000000..744a7c2 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/bopti/gimage_part.c @@ -0,0 +1,85 @@ +#include +#include +#include + +/* +#define min(a, b) ((a) < (b) ? (a) : (b)) +#define max(a, b) ((a) > (b) ? (a) : (b)) + +struct Rect +{ + int top, bottom; + int left, right; +}; +struct Rect intersect(struct Rect r1, struct Rect r2) +{ + struct Rect result; + result.top = max(r1.top, r2.top); + result.bottom = min(r1.bottom, r2.bottom); + result.left = max(r1.left, r2.left); + result.right = min(r1.right, r2.right); +} +*/ + +/* + gimage_part() + Draws a portion of a gray image, defined by its bounding rectangle. + Point (left, top) is included, but (left + width, top + height) is + excluded. +*/ +void gimage_part(int x, int y, struct Image *img, int left, int top, + int width, int height) +{ + if(!img || img->magic != 0xb7) return; + + struct Structure s; + struct Command command; + int actual_width; + int format = img->format, i = 0; + + getStructure(img, &s); + + //--- + // Adjusting the bounding rectangle. + //--- + + // This is what happens when the bounding rectangle overflows from the + // image... + if(left < 0) left = 0; + if(top < 0) top = 0; + if(left + width > s.width) width = s.width - left; + if(top + height > s.height) height = s.height - top; + + if(x + left + width <= 0 || x > 127 || y + top + height <= 0 || y > 63) + return; + + command.top = (y < 0) ? (top - y) : top; + command.bottom = top + ((y + height > 64) ? (64 - y) : height); + command.left = ((x < 0) ? (left - x) : left) >> 5; + actual_width = (x + width > 128) ? (128 - x) : width; + command.right = ((left + actual_width + 31) >> 5) - 1; + + command.op = bopti_op_gray; + + if(x >= 0) getMasks(x, x + actual_width - 1, command.masks); + else getMasks(0, actual_width + x - 1, command.masks); + + bopti_v1 = gray_lightVRAM(); + bopti_v2 = gray_darkVRAM(); + + while(format) + { + if(format & 1) + { + command.x = x - left; + command.y = y - top; + command.channel = (1 << i); + + bopti(s.data, &s, &command); + s.data += s.layer_size; + } + + format >>= 1; + i++; + } +} diff --git a/src/p7os/cake.exe/libgint/src/clock/clock.c b/src/p7os/cake.exe/libgint/src/clock/clock.c new file mode 100644 index 0000000..bc16418 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/clock/clock.c @@ -0,0 +1,288 @@ +#include +#include +#include +#include +#include +#include + +static struct ClockConfig conf = { + .FLL = -1, .PLL = -1, + .Bphi_div1 = -1, .Iphi_div1 = -1, .Pphi_div1 = -1, + .CKIO_f = -1, + .Bphi_f = -1, .Iphi_f = -1, .Pphi_f = -1 +}; + +/* + clock_frequency() + Returns the approximate frequency, in Hz, of the given clock. The + measurements need to have been done. Returns a negative number on + error. +*/ +int clock_frequency(enum Clock clock) +{ + switch(clock) + { + case Clock_CKIO: + return conf.CKIO_f; + case Clock_RTCCLK: + return conf.RTCCLK_f; + case Clock_Bphi: + return conf.Bphi_f; + case Clock_Iphi: + return conf.Iphi_f; + case Clock_Pphi: + return conf.Pphi_f; + + default: + return -2; + } +} + +/* + clock_setting() + Returns the P_phi / 4 timer setting that will last for the given time. + Several units can be used. Be aware that the result is approximate, and + very high frequencies or very short delays will yield important errors. +*/ +int clock_setting(int duration, enum ClockUnit unit) +{ + if(conf.Pphi_f <= 0) return -1; + int f = conf.Pphi_f >> 2; + + switch(unit) + { + case Clock_us: + return (duration * f) / 1000000; + case Clock_ms: + return (duration * f) / 1000; + case Clock_s: + return (duration * f); + + case Clock_Hz: + return f / duration; + case Clock_kHz: + return f / (duration * 1000); + case Clock_MHz: + return f / (duration * 1000000); + + default: + return -1; + } +} + +/* + clock_config() + Returns a copy of the clock configuration. +*/ +struct ClockConfig clock_config(void) +{ + return conf; +} + +/* + sleep() + Sleeps until an interrupt is accepted. +*/ +void sleep(void) +{ + __asm__( + "sleep\n\t" + ); +} + +/* + sleep_us() + Sleeps for the given number of us using the user timer. The result will + always be slightly less than required. +*/ + +static volatile int sleep_us_done = 0; + +static void sleep_us_callback(void) +{ + sleep_us_done = 1; +} + +void sleep_us(int us_delay) +{ + sleep_us_done = 0; + timer_start(TIMER_USER, clock_setting(us_delay, Clock_us), TIMER_Po_4, + sleep_us_callback, 1); + do sleep(); + while(!sleep_us_done); +} + + + +//--- +// Clock frequency measurements -- Public API. +//--- + +// Indicates whether the measurements are finished. +static volatile int clock_measure_done = 0; +// Once again SH7705 and SH7305 need different methods... +static int cb_id_7705 = -1; +static void clock_measure_7705(); +static void clock_compute_7305(); + +/* + clock_measure() + Measures or computes the clock frequencies. +*/ +void clock_measure(void) +{ + // On SH7705 we cannot have the value of CKIO simply, so we measure + // P_phi using a timer/RTC combination, and we deduce CKIO. + if(isSH3()) + { + // We prepare the timer manually, without starting it, so that + // we only have to push the running bit to start it when the + // measurements begin. This might look of little effect but it + // makes the precision jump from ~97% to more than 99%. + volatile struct mod_tmu *tmu; + timer_get(TIMER_USER, &tmu, NULL); + + tmu->TCOR = 0xffffffff; + tmu->TCNT = tmu->TCOR; + tmu->TCR.TPSC = TIMER_Po_4; + + tmu->TCR.UNF = 0; + tmu->TCR.UNIE = 1; + tmu->TCR.CKEG = 0; + + timers[TIMER_USER].callback = NULL; + timers[TIMER_USER].repeats = 0; + + cb_id_7705 = rtc_cb_add(RTCFreq_256Hz, clock_measure_7705, 0); + } + + // On SH7305, assuming clock mode 3, we can compute the clock + // frequencies because we know that RTC_CLK oscillates at 32768 Hz. + else + { + clock_compute_7305(); + clock_measure_done = 1; + } +} + +/* + clock_measure_end() + Waits until the measurements are finished. This may be immediate. +*/ +void clock_measure_end(void) +{ + while(!clock_measure_done) sleep(); +} + +//--- +// Clock frequency measurements -- SH7305. +//--- + +/* + clock_compute_7305() + Computes the clock frequencies according to the CPG parameters. +*/ +static void clock_compute_7305(void) +{ + volatile unsigned int *FRQCRA = (void *)0xa4150000; + volatile unsigned int *PLLCR = (void *)0xa4150024; + volatile unsigned int *FLLFRQ = (void *)0xa4150050; + + // Surely the documentation of SH7724 does not meet the specification + // of SH7305 for the PLL setting, because the register accepts other + // values than the ones specified for SH7724. The relation given by + // Sentaro21 (thanks again!) yields good results. + int pll = (*FRQCRA >> 24) & 0x3f; // Raw setting + pll = pll + 1; // Resulting multiplier + conf.PLL = pll; + + // This one is simpler. The FLL ratio is actually the setting value. + int fll = *FLLFRQ & 0x7ff; // Raw setting = multiplier + if(*FLLFRQ & (1 << 14)) fll >>= 1; // Halve-output flag + conf.FLL = fll; + + // The divider1 ratios are NOT those of SH7724. The relation between + // the values below and the divider ratios is given by Sentaro21 + // (thanks to him!) and satisfies ratio = 1 / (2 ** (setting + 1)). + int div1_bphi = (*FRQCRA >> 8) & 0xf; + int div1_iphi = (*FRQCRA >> 20) & 0xf; + int div1_pphi = (*FRQCRA ) & 0xf; + + conf.Bphi_div1 = 1 << (div1_bphi + 1); + conf.Iphi_div1 = 1 << (div1_iphi + 1); + conf.Pphi_div1 = 1 << (div1_pphi + 1); + + // Computing the frequency of the signal, which is input to divider 1. + int base = 32768; + if(*PLLCR & (1 << 12)) base *= fll; + if(*PLLCR & (1 << 14)) base *= pll; + + conf.RTCCLK_f = 32768; + conf.Bphi_f = base >> (div1_bphi + 1); + conf.Iphi_f = base >> (div1_iphi + 1); + conf.Pphi_f = base >> (div1_pphi + 1); +} + +//--- +// Clock frequency measurements -- SH7705. +//--- + +/* + clock_measure_7705_finalize() + Given the number of P_phi / 4 timer ticks elapsed between two RTC + 256 Hz interrupts, determines the clock configuration. +*/ +static void clock_measure_7705_finalize(int elapsed) +{ + volatile unsigned int *FRQCR = (void *)0xffffff80; + + conf.Pphi_f = elapsed * 4 * 256; + if(conf.Pphi_f <= 0) return; + + conf.PLL1 = ((*FRQCR >> 8) & 0x03) + 1; + conf.PLL2 = -1; + + conf.Bphi_div1 = 0; + conf.Iphi_div1 = ((*FRQCR >> 4) & 0x03) + 1; + conf.Pphi_div1 = ((*FRQCR ) & 0x03) + 1; + + conf.CKIO_f = (conf.Pphi_f * conf.Pphi_div1) / conf.PLL1; + conf.Bphi_f = conf.CKIO_f; + conf.Iphi_f = (conf.CKIO_f * conf.PLL1) / conf.Iphi_div1; +} + +/* + clock_measure_7705_callback() + Starts measurements. Measurements will end automatically. Do not use + RTC interrupt or the user timer will doing measurements. + Call clock_measure_end() when you need to use those, to ensure + measurements are finished. +*/ +static void clock_measure_7705_callback(void) +{ + timer_stop(TIMER_USER); + rtc_cb_end(cb_id_7705); + + volatile struct mod_tmu *tmu; + timer_get(TIMER_USER, &tmu, NULL); + int elapsed = 0xffffffff - tmu->TCNT; + + clock_measure_7705_finalize(elapsed); + clock_measure_done = 1; +} + +/* + clock_measure_7705() + Programs the clock measurements. We need to have the user timer and the + RTC synchronized for this operation, so we wait for an RTC interrupt + and we prepare the timer beforehand to avoid losing processor time in + configuring the registers. +*/ +static void clock_measure_7705(void) +{ + volatile unsigned char *tstr; + timer_get(TIMER_USER, NULL, &tstr); + + *tstr |= (1 << TIMER_USER); + rtc_cb_edit(cb_id_7705, RTCFreq_256Hz, clock_measure_7705_callback); +} diff --git a/src/p7os/cake.exe/libgint/src/core/crt0.c b/src/p7os/cake.exe/libgint/src/core/crt0.c new file mode 100644 index 0000000..d22de28 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/core/crt0.c @@ -0,0 +1,168 @@ +#include +#include +#include + +#include +#include +#include + +int main(void); + +static void init(void); +static void fini(void); + +// Symbols imported from the linker script. +extern unsigned int + romdata, + bbss, ebss, + bdata, edata; + +// This variable should be overwritten before being returned, so the default +// value doesn't matter much. +static int exit_code = EXIT_SUCCESS; +static jmp_buf env; + +// Exit handlers. +void (*atexit_handlers[ATEXIT_MAX])(void); +int atexit_index = 0; + + + +/* + start() + Program entry point. Loads the data section into the memory and invokes + main(). Also prepares the execution environment by initializing all the + modules. +*/ + +int start(void) + __attribute__(( + section(".pretext.entry") + )); + +int start(void) +{ + // Linker symbols. + unsigned int *bss = &bbss; + unsigned int *data = &bdata, *src = &romdata; + int x; + + // Clearing the .bss section. + while(bss < &ebss) *bss++ = 0; + // Copying the .data section. + while(data < &edata) *data++ = *src++; + + mmu_pseudoTLBInit(); + + // Initializing gint. + gint_init(); + + // Measure clock frequencies. + clock_measure(); + clock_measure_end(); + + // Calling global constructors. + init(); + + + + // Saving the execution state there. + x = setjmp(env); + // If the program has just started, executing main(). Otherwise, the + // exit code has already been set by abort() or similar. + if(!x) exit_code = main(); + + + + // Remember to flush and close opened streams. + + // Calling exit handlers. + while(atexit_index > 0) (*atexit_handlers[--atexit_index])(); + + // Un-initializing everything. + fini(); + gint_quit(); + + return exit_code; +} + +/* + init() + Calls the constructors. +*/ +static void init(void) +{ + extern void + (*bctors)(void), + (*ectors)(void); + void (**func)(void) = &bctors; + + while(func < &ectors) + { + (*(*func))(); + func++; + } +} + +/* + fini() + Calls the destructors. +*/ +static void fini(void) +{ + extern void + (*bdtors)(void), + (*edtors)(void); + void (**func)(void) = &bdtors; + + while(func < &edtors) + { + (*(*func))(); + func++; + } +} + + + +/* + abort() + Immediately ends the program without invoking the exit handlers. +*/ +void abort(void) +{ + exit_code = EXIT_FAILURE; + + // Avoiding any exit handler call. + atexit_index = 0; + + longjmp(env, 1); +} + +/* + exit() + Ends the program and returns the given exit code status. Calls exit + handlers before returning. + Usually exit() would ask the operating system to stop the process but + the fx-9860G executes only one program at a time and calls it as a + function. Reaching the program end point is therefore an efficient way + of achieving this goal while minimizing interaction with the operating + system. +*/ +void exit(int status) +{ + exit_code = status; + longjmp(env, 1); +} + +/* + atexit() + Registers a function to be called at normal program termination. +*/ +int atexit(void (*function)(void)) +{ + if(atexit_index >= ATEXIT_MAX) return 1; + + atexit_handlers[atexit_index++] = function; + return 0; +} + diff --git a/src/p7os/cake.exe/libgint/src/core/gint.c b/src/p7os/cake.exe/libgint/src/core/gint.c new file mode 100644 index 0000000..28de9f2 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/core/gint.c @@ -0,0 +1,285 @@ +//--- +// +// gint core module: interrupt handler +// +// Central point of the library. Controls the interrupt handler and +// defines a few functions to configure callbacks for some interrupts. +// +//--- + +#include +#include +#include +#include + +static unsigned int + new_vbr, + sys_vbr; + +static void (*default_handler)(int event_code) = NULL; + + + +//--- +// Local functions. +//--- + +/* + gint_setup() + Configures interrupt priorities and some parameters to allow gint to + take control of the interrupt flow. +*/ +static void gint_setup(void) +{ + if(isSH3()) + gint_setup_7705(); + else + gint_setup_7305(); +} + +/* + gint_stop() + Un-configures the interrupt flow to give back the interrupt control to + the system. +*/ +static void gint_stop(void) +{ + if(isSH3()) + gint_stop_7705(); + else + gint_stop_7305(); +} + + + +//--- +// Public API. +//--- + +/* + gint_systemVBR() + Returns the vbr address used by the system (saved when execution + starts). +*/ +inline unsigned int gint_systemVBR(void) +{ + return sys_vbr; +} + +/* + gint_setDefaultHandler() + In case gint receives an interrupt it doesn't recognize, it can fall + back to a user-provided interrupt handler. Set it to NULL to disable + this feature. + Be aware that the event code passed to the default handler will either + be INTEVT2 (SH7705) or INTEVT (SH7305), but its value for each + interrupt case is completely platform-dependent. Remember to handle + both platforms for increased portability, if possible. +*/ +void gint_setDefaultHandler(void (*new_handler)(int event_code)) +{ + default_handler = new_handler; +} + +/* + gint_init() + Initializes gint. Loads the interrupt handler into the memory and sets + the new vbr address. +*/ +void gint_init(void) +{ + // Linker script symbols -- gint. + extern unsigned int + gint_vbr, + gint_data, + bgint, egint; + + unsigned int *ptr = &bgint; + unsigned int *src = &gint_data; + + // This initialization routine is usually called before any + // constructor. We want to ensure that the MPU type is detected, but + // mpu_init() hasn't been called yet. + mpu_init(); + + // Loading the interrupt handler into the memory. + while(ptr < &egint) *ptr++ = *src++; + + sys_vbr = gint_getVBR(); + new_vbr = (unsigned int)&gint_vbr; + + gint_setVBR(new_vbr, gint_setup); +} + +/* + gint_quit() + Stops gint. Restores the system's configuration and vbr address. +*/ +void gint_quit(void) +{ + gint_setVBR(sys_vbr, gint_stop); +} + + + +//--- +// VBR space. +//--- + +#include +#define print(str, x, y) dtext(6 * (x) - 5, 8 * (y) - 7, str) +#define hexdigit(n) ((n) + '0' + 39 * ((n) > 9)) + +static void hex(unsigned int x, int digits, char *str) +{ + str[0] = '0'; + str[1] = 'x'; + str[digits + 2] = 0; + + while(digits) + { + str[digits + 1] = hexdigit(x & 0xf); + x >>= 4; + digits--; + } +} + +static void reverse(void) +{ + int *vram = display_getCurrentVRAM(); + int i; + for(i = 0; i < 36; i++) vram[i] = ~vram[i]; +} + +/* + gint_exc() + Handles exceptions. +*/ +void gint_exc(void) +{ + volatile unsigned int *expevt = gint_reg(Register_EXPEVT); + volatile unsigned int *tea = gint_reg(Register_TEA); + unsigned int spc; + char str[11]; + + text_configure(NULL, Color_Black); + + __asm__("\tstc spc, %0" : "=r"(spc)); + + dclear(); + print("Exception raised!", 3, 1); + reverse(); + print(gint_strerror(0), 2, 3); + + print("expevt", 2, 4); + hex(*expevt, 3, str); + print(str, 16, 4); + + print("pc", 2, 5); + hex(spc, 8, str); + print(str, 11, 5); + + print("tea", 2, 6); + hex(*tea, 8, str); + print(str, 11, 6); + + print("Please reset.", 2, 7); + dupdate(); + while(1); +} + +/* + gint_tlb() + Handles TLB misses. +*/ +void gint_tlb(void) +{ + volatile unsigned int *expevt = gint_reg(Register_EXPEVT); + volatile unsigned int *tea = gint_reg(Register_TEA); + unsigned int spc; + char str[11]; + + text_configure(NULL, Color_Black); + + __asm__("\tstc spc, %0" : "=r"(spc)); + + dclear(); + print("TLB error!", 6, 1); + reverse(); + print(gint_strerror(1), 2, 3); + + print("expevt", 2, 4); + hex(*expevt, 3, str); + print(str, 16, 4); + + print("pc", 2, 5); + hex(spc, 8, str); + print(str, 11, 5); + + print("tea", 2, 6); + hex(*tea, 8, str); + print(str, 11, 6); + + print("Please reset.", 2, 7); + dupdate(); + while(1); +} + +/* + gint_int() + Handles interrupts. +*/ +void gint_int(void) +{ + if(isSH3()) + gint_int_7705(); + else + gint_int_7305(); +} + + + +//--- +// Internal API. +//--- + +/* + gint_callDefaultHandler() + Calls the user-provided default interrupt handler. +*/ +void gint_callDefaultHandler(int event_code) +{ + if(default_handler) default_handler(event_code); +} + +/* + gint_reg() + Returns the address of a common register. All common registers exist + on both platforms but they may hold different values for the same + information (f.i. EXPEVT may not return the same value for a given + exception on both 7705 and 7305). +*/ +inline volatile void *gint_reg(enum Register reg) +{ + if(isSH3()) + return gint_reg_7705(reg); + else + return gint_reg_7305(reg); +} + +/* + gint_strerror() + Returns a string that describe the error set in EXPEVT. This string is + not platform-dependent. + Some exception codes represent different errors when invoked inside the + general exception handler and the TLB error handler. Parameter 'is_tlb' + should be set to zero for general exception meanings, and anything non- + zero for TLB error meanings. +*/ +const char *gint_strerror(int is_tlb) +{ + if(isSH3()) + return gint_strerror_7705(is_tlb); + else + return gint_strerror_7305(); +} diff --git a/src/p7os/cake.exe/libgint/src/core/gint_str.c b/src/p7os/cake.exe/libgint/src/core/gint_str.c new file mode 100644 index 0000000..c7e9957 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/core/gint_str.c @@ -0,0 +1,37 @@ +#include + +const char *gint_str[] = { + "Unknown", + + // User breaks. + "User break (before)", + "User break (after)", + "User breakpoint", + + // General. + "Inst. address error", + "Data access error", + "Illegal instruction", + "Illegal slot", + "Data address (r)", + "Data address (w)", + + // Instruction TLB. + "Inst. TLB miss", + "Inst. TLB invalid", + "Inst. TLB protect.", + + // Data TLB. + "Data TLB miss", + "Data TLB miss (r)", + "Data TLB miss (w)", + "Data TLB protection", + "Data TLB prot. (r)", + "Data TLB prot. (w)", + "Data TLB invalid", + + // Others. + "Initial page write", + "Trap", + "DMA address error", +}; diff --git a/src/p7os/cake.exe/libgint/src/core/gint_vbr.s b/src/p7os/cake.exe/libgint/src/core/gint_vbr.s new file mode 100644 index 0000000..488be1b --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/core/gint_vbr.s @@ -0,0 +1,66 @@ +/* + gint_vbr + + Some of the work, especially related to setting and un-setting the vbr + address needs to be done in assembler. +*/ + + .global _gint_getVBR + .global _gint_setVBR + + + +/* + gint_getVBR() + Returns the current vbr address. +*/ +_gint_getVBR: + rts + stc vbr, r0 + + + +/* + gint_setVBR() + + This is quite the hard part when modifying the vbr. We need to set + immediately the interrupt priorities of our own handler, or restore + the ones used by the system ; otherwise we may receive interrupts + requests that the new handler doesn't handle, which will cause the + whole program to freeze. + + Therefore, we must set vbr *and* change interrupt priorities while + having disabled all the interrupts in the status register. That's why + this function takes as parameter the priority management function. +*/ +_gint_setVBR: + sts.l pr, @-r15 + + /* Blocking all interrupts. */ + mov.l sr_block, r0 + stc sr, r3 + or r0, r3 + ldc r3, sr + + /* Setting the vbr address. */ + ldc r4, vbr + + /* Calling the priority manager. */ + jsr @r5 + nop + + /* Activating interrupts again. */ + mov.l sr_block, r0 + not r0, r0 + stc sr, r3 + and r0, r3 + ldc r3, sr + + lds.l @r15+, pr + rts + nop + + .align 4 + +sr_block: + .long (1 << 28) diff --git a/src/p7os/cake.exe/libgint/src/core/syscalls.s b/src/p7os/cake.exe/libgint/src/core/syscalls.s new file mode 100644 index 0000000..e4dd817 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/core/syscalls.s @@ -0,0 +1,41 @@ +/* + gint core module: syscalls + + All the system calls used by the library. Somehow "the less, the + better". + We have finally gotten rid of every obscure system-related syscalls! + Looks like an important step towards being completely free-standing :) +*/ + + .global ___malloc + .global ___free + .global ___realloc + + + +___malloc: + mov.l syscall_table, r2 + mov.l 1f, r0 + jmp @r2 + nop +1: .long 0xacd + +___free: + mov.l syscall_table, r2 + mov.l 1f, r0 + jmp @r2 + nop +1: .long 0xacc + +___realloc: + mov.l syscall_table, r2 + mov.l 1f, r0 + jmp @r2 + nop +1: .long 0xe6d + + + .align 4 + +syscall_table: + .long 0x80010070 diff --git a/src/p7os/cake.exe/libgint/src/display/adjustRectangle.c b/src/p7os/cake.exe/libgint/src/display/adjustRectangle.c new file mode 100644 index 0000000..f46f9b2 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/display/adjustRectangle.c @@ -0,0 +1,29 @@ +#include + +/* + adjustRectangle() + Adjusts the given rectangle coordinates to ensure that : + - the rectangle is entirely contained in the screen + - x1 < x2 + - y1 < y2 + which is needed when working with screen rectangles. + Returns non-zero if the rectangle is outside the screen. +*/ +int adjustRectangle(int *x1, int *y1, int *x2, int *y2) +{ + #define swap(a, b) tmp = a, a = b, b = tmp + int tmp; + + if(*x2 < *x1) swap(*x1, *x2); + if(*y2 < *y1) swap(*y1, *y2); + + if(*x1 > 127 || *y1 > 63 || *x2 < 0 || *y2 < 0) return 1; + + if(*x1 < 0) *x1 = 0; + if(*y1 < 0) *y1 = 0; + if(*x2 > 127) *x2 = 127; + if(*y2 > 63) *y2 = 63; + + return 0; + #undef swap +} diff --git a/src/p7os/cake.exe/libgint/src/display/dclear.c b/src/p7os/cake.exe/libgint/src/display/dclear.c new file mode 100644 index 0000000..ed45a6d --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/display/dclear.c @@ -0,0 +1,12 @@ +#include +#include + +/* + dclear() + Clears the whole vram. +*/ +void dclear(void) +{ + int i; + for(i = 0; i < 256; i++) vram[i] = 0; +} diff --git a/src/p7os/cake.exe/libgint/src/display/dclear_area.c b/src/p7os/cake.exe/libgint/src/display/dclear_area.c new file mode 100644 index 0000000..4cb4a70 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/display/dclear_area.c @@ -0,0 +1,21 @@ +#include +#include + +/* + dclear_area() + Clears an area of the vram using rectangle masks. Both (x1, y1) and + (x2, y2) are cleared. +*/ +void dclear_area(int x1, int y1, int x2, int y2) +{ + uint32_t masks[4]; + if(adjustRectangle(&x1, &y1, &x2, &y2)) return; + getMasks(x1, x2, masks); + + int begin = y1 << 2; + int end = (y2 + 1) << 2; + int i; + + for(i = 0; i < 4; i++) masks[i] = ~masks[i]; + for(i = begin; i < end; i++) vram[i] &= masks[i & 3]; +} diff --git a/src/p7os/cake.exe/libgint/src/display/display_vram.c b/src/p7os/cake.exe/libgint/src/display/display_vram.c new file mode 100644 index 0000000..2dc3763 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/display/display_vram.c @@ -0,0 +1,43 @@ +#include + +// Program video ram. It resides in .bss section, therefore it is cleared at +// program initialization and stripped from the executable file. +static int local_vram[256]; +int *vram = local_vram; + +/* + display_getLocalVRAM() + Returns the local video ram address. This function always return the + same address. + The buffer returned by this function should not be used directly when + running the gray engine. +*/ +inline void *display_getLocalVRAM(void) +{ + return (void *)local_vram; +} + +/* + display_getCurrentVRAM() + Returns the current video ram. This function usually returns the + parameter of the last call to display_useVRAM(), unless the gray engine + is running (in which case the result is undefined). Returns the local + vram address by default. +*/ +inline void *display_getCurrentVRAM(void) +{ + return (void *)vram; +} + +/* + display_useVRAM() + Changes the current video ram address. The argument MUST be a 4- + aligned 1024-byte buffer ; otherwise any drawing operation will crash + the program. + This function will most likely have no effect when running the gray + engine. +*/ +inline void display_useVRAM(void *ptr) +{ + vram = (int *)ptr; +} diff --git a/src/p7os/cake.exe/libgint/src/display/dline.c b/src/p7os/cake.exe/libgint/src/display/dline.c new file mode 100644 index 0000000..e6e1422 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/display/dline.c @@ -0,0 +1,116 @@ +#include +#include + +#define sgn(x) ((x) < 0 ? -1 : 1) +#define abs(x) ((x) < 0 ? -(x) : (x)) +#define rnd(x) ((int)((x) + 0.5)) + +/* + dline() + Draws a line on the screen. Automatically optimizes horizontal and + vertical lines. +*/ + +static void dhline(int x1, int x2, int y, enum Color color) +{ + uint32_t masks[4]; + int offset = y << 2; + int i; + + // Swapping x1 and x2 if needed. + if(x1 > x2) x1 ^= x2, x2 ^= x1, x1 ^= x2; + getMasks(x1, x2, masks); + + switch(color) + { + case Color_White: + for(i = 0; i < 4; i++) vram[offset + i] &= ~masks[i]; + break; + + case Color_Black: + for(i = 0; i < 4; i++) vram[offset + i] |= masks[i]; + break; + + case Color_Invert: + for(i = 0; i < 4; i++) vram[offset + i] ^= masks[i]; + break; + + default: + break; + } +} + +static void dvline(int y1, int y2, int x, enum Color color) +{ + int offset = (y1 << 2) + (x >> 5); + int end = (y2 << 2) + (x >> 5); + int mask = 0x80000000 >> (x & 31); + + switch(color) + { + case Color_White: + while(offset <= end) vram[offset] &= ~mask, offset += 4; + break; + + case Color_Black: + while(offset <= end) vram[offset] |= mask, offset += 4; + break; + + case Color_Invert: + while(offset <= end) vram[offset] ^= mask, offset += 4; + break; + + default: + break; + } +} + +void dline(int x1, int y1, int x2, int y2, enum Color color) +{ + if(adjustRectangle(&x1, &y1, &x2, &y2)) return; + + // Possible optimizations. + if(y1 == y2) + { + dhline(x1, x2, y1, color); + return; + } + if(x1 == x2) + { + dvline(y1, y2, x1, color); + return; + } + + int i, x = x1, y = y1, cumul; + int dx = x2 - x1, dy = y2 - y1; + int sx = sgn(dx), sy = sgn(dy); + + dx = abs(dx), dy = abs(dy); + + dpixel(x1, y1, color); + + if(dx >= dy) + { + cumul = dx >> 1; + for(i = 1; i < dx; i++) + { + x += sx; + cumul += dy; + if(cumul > dx) cumul -= dx, y += sy; + dpixel(x, y, color); + } + } + else + { + cumul = dy >> 1; + for(i = 1; i < dy; i++) + { + y += sy; + cumul += dx; + if(cumul > dy) cumul -= dy, x += sx; + dpixel(x, y, color); + } + } + + dpixel(x2, y2, color); +} diff --git a/src/p7os/cake.exe/libgint/src/display/dpixel.c b/src/p7os/cake.exe/libgint/src/display/dpixel.c new file mode 100644 index 0000000..60c3a06 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/display/dpixel.c @@ -0,0 +1,32 @@ +#include +#include + +/* + dpixel() + Puts a pixel in the vram. +*/ +void dpixel(int x, int y, enum Color color) +{ + if((unsigned int)x > 127 || (unsigned int)y > 63) return; + + int offset = (y << 2) + (x >> 5); + int mask = 0x80000000 >> (x & 31); + + switch(color) + { + case Color_White: + vram[offset] &= ~mask; + break; + + case Color_Black: + vram[offset] |= mask; + break; + + case Color_Invert: + vram[offset] ^= mask; + break; + + default: + break; + } +} diff --git a/src/p7os/cake.exe/libgint/src/display/dreverse_area.c b/src/p7os/cake.exe/libgint/src/display/dreverse_area.c new file mode 100644 index 0000000..0288cbe --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/display/dreverse_area.c @@ -0,0 +1,21 @@ +#include +#include + +/* + dreverse_area() + Reverses an area of the vram. This function is a simple application of + the rectangle masks concept. (x1, y1) and (x2, y2) are reversed as + well. +*/ +void dreverse_area(int x1, int y1, int x2, int y2) +{ + uint32_t masks[4]; + if(adjustRectangle(&x1, &y1, &x2, &y2)) return; + getMasks(x1, x2, masks); + + int begin = y1 << 2; + int end = (y2 + 1) << 2; + int i; + + for(i = begin; i < end; i++) vram[i] ^= masks[i & 3]; +} diff --git a/src/p7os/cake.exe/libgint/src/display/dupdate.c b/src/p7os/cake.exe/libgint/src/display/dupdate.c new file mode 100644 index 0000000..6ca42f8 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/display/dupdate.c @@ -0,0 +1,14 @@ +#include +#include +#include +#include + +/* + dupdate() + Displays the vram on the physical screen. +*/ +void dupdate(void) +{ + if(gray_runs()) return; + screen_display((const void *)vram); +} diff --git a/src/p7os/cake.exe/libgint/src/display/font_system.bmp b/src/p7os/cake.exe/libgint/src/display/font_system.bmp new file mode 100644 index 0000000000000000000000000000000000000000..cee82be5f2e0b35e5c6ce8f0ab74fa0799a77ab5 GIT binary patch literal 32762 zcmeH~v2tul5kwbUOdP&v9V{Fo_zOHd9QX=876(#F%~6uoedo^1dyft6?FhB9PGx2H zbnNV|e*V+H|MAoN`n&eO>gS*O`HOyj^V1)+t5*N_zw^&K(Dw5m|NOU`KKuK(W&F>z zt{1po;Cg}U1+EvkUf_CxU)c-je~0oDSD7tq42bjyvXV=iCxl28&(gE(ZZSfL4RG6l zw$c69`!bZY8E65-hLi9V9AS~I11)oQtIU=)2E_D~Qzho50OH({;#qQy2`8C1JQ(Lz zc$OkhNxd`!%c+uuM*=8ej!0WNlTULJG{QMfFwC9g^e3Erl01UhhhR?C;PSZgyDVpx zXhfbO2%n~w5;id3eZci}WZGG8!PUPC;~IyYO>=}dWOArfZDQs>mt@H+HWf51VHUUhk;^RSM~ z!PI4|^1QPKA1Z&$DGyyqX5DIDY)K}ZXT4>`nud#9FL1p;y@0+kN&Ke=JFWO)eg5|s zh)v=c=5f>MbHy!)ozBX!Q&Tvl3udOBCPW!JLE7W)<}S|2)E@WjnLVR+{`8;`d57m< zotq)MR(ewBWjsq4k-Xq;+&0XJ^e>^$I@ojS*e0i!ZPNJB2wD;e(Gt0Ke)H)RVI*}O zhi7tUronodW=IQ>u}e7fi{w@P8P{a${4ZQsZO2C&e%}b{fayBy=w{Sw5CvkUjCpf$ks9j39B%F6@q)yo-r_ED7CC^&^sYPIl^Uge_ z?vR0{%ULC6!jo9%$WF_dttzu+y(4f$McplB@XCZ6`}{q-lYF{gP!+3^MXJcu*s_aF zqWD2c3z6f7x%-q!l3VYHc%GH!UF*PK;}4Y;n@m;GCv+W`B^sf8G-3zqGU?Be)agN6E4D-#1k2K4T4B^mG# z$Pu*OU7y>rbB>EJO!uzfbUR(=_LUWZ&MGnWtpB2V{7wg@R39z+=!l))Z^ zorXCDNl4C4!9xW%Vn#NFiObc8k7CB~Xp zQnN->0%xnb<(z&WZqB}g7|5~nyuT8TOU0(aW$tv#dCb#{MlfpumtgHY@TC(df%Bwz zVnoSvYLbHsl$lZj?eQuzvszVh$>h>3qD0VBWOu2T(5Gk1$s$Ww=i0_TyG00J@(Jq> zS(eUHIa#LOT|l0+rOsRJc*Uj-jhNTV7Eu${pq;zD#gUUd(|N ztL`Ko5ziJSkRvSWblLJsF4M^=76-ehNH})NcE))S;+8`0dLA-3Fk_`zM2T>L)IgjE zg2D6@beTKma^B?_Bs5#&Ri^nspPxG8lqXl7EADFpO(^M3XL`_ceAklG3xkDV5tU2l zv@OXpaOnh|A35o?t;{ODIM+h(E-3@$oZYoP&W^Jn77R{t-sxHSXUG9L??2;Q-qwS= z@#H&adiX3$I3FQ1Yotn&Ulb3;o;OdYN%0*N_u`3EqIZI)zzmW29x(Ht*2{}6(_V3U zwi1?bzLjit)~%L&2|ZXLRaW>_UN3OHz%S|r<`>pqcJEyE7-Eya`2^HoK#bR4Rp!9+ z2W8+KcaEMIfcDBiDQ04BR7oCcA^2{kRohEa9l8QQ0 z&X7r*Gx;Q(I9ofi<3vf=^NKUmE`7bg^#Z?;7pO0_%3Qvr{%py00KdnF%KPXVK4J+E zPM80n`+scJ#j;Gzr_QTRgSrzYNxd{Lp{C9Z`flYs2z*cdOs2GO+Aeb$yMq~3T4yE6 zGPRRW64|^+R_O%DQrza=ey72FlCoh)?pby`4~Y!);4*O9?w(R3S(a9rM9C%v&F8sg zW7gu>KRuP^@m(h76lp#f_ekzCXK8IH&2r}5UHF&;V7yvYI{ACR zgFDx8DsvqS{>YZE^!ka)sgNR7mia2L7r0*FdVw$Y0{)jCd;U96+NH(RJcV0XCP7P} zWk$c_kCq`VGQX;rpLddctJJ*G6ib`maGD`ZCGpf(-StVmc8^nBrTq08$0WN;E$BtK z$~xk!mj0x<`;*oSWQj)9yPe^Tq_Ea_CJ27*l^^!~qksIfhqkaSwV!1YaYGCC;^|49 Ne(7snFYujS;J=W + +/* + getMasks() + Computes the rectangle masks needed to affect pixels located between x1 + and x2 (both included). The four masks are stored in the third argument + (seen as an array). +*/ +void getMasks(int x1, int x2, uint32_t *masks) +{ + // Indexes of the first and last longs that are non-blank. + int l1 = x1 >> 5; + int l2 = x2 >> 5; + int i = 0; + + // Setting the base masks. Those are the final values, except for the + // longs with indexes l1 and l2, that still need to be adjusted. + while(i < l1) masks[i++] = 0x00000000; + while(i <= l2) masks[i++] = 0xffffffff; + while(i < 4) masks[i++] = 0x00000000; + + // Removing the long number information in x1 and x2 (that is, the + // multiples of 32) to keep only the interesting information -- the + // number of null bits to add in l1 and l2. + x1 &= 31; + // Inverting x2 is here the same as computing 32 - x, since 32 is a + // power of 2 (positive bits at the left are removed by the mask). + x2 = ~x2 & 31; + + // Setting the first and last masks. + masks[l1] &= (0xffffffff >> x1); + masks[l2] &= (0xffffffff << x2); +} diff --git a/src/p7os/cake.exe/libgint/src/events/event_get.c b/src/p7os/cake.exe/libgint/src/events/event_get.c new file mode 100644 index 0000000..eceb1ff --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/events/event_get.c @@ -0,0 +1,38 @@ +#include +#include +#include + +/* + pollevent() + Returns the next event. If no one is available, returns an event whose + type is ET_None. This function always returns immediately. +*/ +struct Event pollevent(void) +{ + struct Event event = { + .type = ET_None + }; + if(queue_size <= 0) return event; + + event = event_queue[queue_start]; + + queue_size--; + if(queue_start == EVENTS_QUEUE_SIZE - 1) queue_start = 0; + else queue_start++; + + return event; +} + +/* + getevent() + Returns the next event. If no one is available, waits for something to + happen. This function uses low-level sleep and should be preferred to + active waiting using loops. +*/ +struct Event getevent(void) +{ + struct Event event; + + while((event = pollevent()).type == ET_None) sleep(); + return event; +} diff --git a/src/p7os/cake.exe/libgint/src/events/event_push.c b/src/p7os/cake.exe/libgint/src/events/event_push.c new file mode 100644 index 0000000..3c47d09 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/events/event_push.c @@ -0,0 +1,26 @@ +#include +#include + +volatile struct Event event_queue[EVENTS_QUEUE_SIZE]; +volatile int queue_start = 0; +volatile int queue_size = 0; + +/* + event_push() + Queues a user-defined event, allowing it to be retrieved by getevent() + or pollevent() later. Pushing ET_None events is not allowed. + Returns non-zero on error. +*/ +int event_push(struct Event event) +{ + if(queue_size >= EVENTS_QUEUE_SIZE) return 1; + if(event.type == ET_None) return 2; + + int index = queue_start + queue_size; + if(index >= EVENTS_QUEUE_SIZE) index -= EVENTS_QUEUE_SIZE; + + event_queue[index] = event; + queue_size++; + + return 0; +} diff --git a/src/p7os/cake.exe/libgint/src/gray/gclear.c b/src/p7os/cake.exe/libgint/src/gray/gclear.c new file mode 100644 index 0000000..e3beb21 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/gray/gclear.c @@ -0,0 +1,14 @@ +#include + +/* + gclear() + Clears the video ram. +*/ +void gclear(void) +{ + int *v1 = gray_lightVRAM(); + int *v2 = gray_darkVRAM(); + int i; + + for(i = 0; i < 256; i++) v1[i] = v2[i] = 0; +} diff --git a/src/p7os/cake.exe/libgint/src/gray/gclear_area.c b/src/p7os/cake.exe/libgint/src/gray/gclear_area.c new file mode 100644 index 0000000..42c3f29 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/gray/gclear_area.c @@ -0,0 +1,15 @@ +#include +#include + +/* + gclear_area() + Clears an area of the video ram. End points (x1, y1) and (x2, y2) are + included. +*/ +void gclear_area(int x1, int y1, int x2, int y2) +{ + display_useVRAM(gray_lightVRAM()); + dclear_area(x1, y1, x2, y2); + display_useVRAM(gray_darkVRAM()); + dclear_area(x1, y1, x2, y2); +} diff --git a/src/p7os/cake.exe/libgint/src/gray/gline.c b/src/p7os/cake.exe/libgint/src/gray/gline.c new file mode 100644 index 0000000..9b31480 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/gray/gline.c @@ -0,0 +1,24 @@ +#include +#include + +/* + gline() + Draws a line in the vram. Automatically optimizes special cases. +*/ +void gline(int x1, int y1, int x2, int y2, enum Color color) +{ + enum Color c1, c2; + + if(color == Color_None) return; + else if(color == Color_Invert) c1 = c2 = Color_Invert; + else + { + c1 = 3 * (color & 1); + c2 = 3 * (color >> 1); + } + + display_useVRAM(gray_lightVRAM()); + dline(x1, y1, x2, y2, c1); + display_useVRAM(gray_darkVRAM()); + dline(x1, y1, x2, y2, c2); +} diff --git a/src/p7os/cake.exe/libgint/src/gray/gpixel.c b/src/p7os/cake.exe/libgint/src/gray/gpixel.c new file mode 100644 index 0000000..be44071 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/gray/gpixel.c @@ -0,0 +1,47 @@ +#include + +/* + gpixel() + Puts a pixel in the vram. +*/ +void gpixel(int x, int y, enum Color color) +{ + if((unsigned int)x > 127 || (unsigned int)y > 63) return; + + int offset = (y << 2) + (x >> 5); + int mask = 0x80000000 >> (x & 31); + + int *v1 = gray_lightVRAM(); + int *v2 = gray_lightVRAM(); + + switch(color) + { + case Color_White: + v1[offset] &= ~mask; + v2[offset] &= ~mask; + break; + + case Color_Light: + v1[offset] |= mask; + v2[offset] &= ~mask; + break; + + case Color_Dark: + v1[offset] &= ~mask; + v2[offset] |= mask; + break; + + case Color_Black: + v1[offset] |= mask; + v2[offset] |= mask; + break; + + case Color_Invert: + v1[offset] ^= mask; + v2[offset] ^= mask; + break; + + default: + break; + } +} diff --git a/src/p7os/cake.exe/libgint/src/gray/gray_engine.c b/src/p7os/cake.exe/libgint/src/gray/gray_engine.c new file mode 100644 index 0000000..639c750 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/gray/gray_engine.c @@ -0,0 +1,157 @@ +//--- +// +// gint core/drawing module: gray +// +// Runs the gray engine and handles drawing for the dual-buffer system. +// +//--- + +#include +#include +#include +#include + +static int internal_vrams[3][256]; +static const void *vrams[4]; + +static int current = 0; +static int delays[2]; + +static int runs = 0; + +#define GRAY_PRESCALER TIMER_Po_64 + + + +//--- +// Engine control. +//--- + +/* + gray_start() + Starts the gray engine. The control of the screen is transferred to the + gray engine. +*/ +void gray_start(void) +{ + if(runs) return; + + timer_start(TIMER_GRAY, delays[0], GRAY_PRESCALER, gray_interrupt, 0); + current &= 1; + runs = 1; +} + +/* + gray_stop() + Stops the gray engine. The monochrome display system takes control of + the video ram. +*/ +void gray_stop(void) +{ + if(!runs) return; + + timer_stop(TIMER_GRAY); + runs = 0; + + display_useVRAM(display_getLocalVRAM()); +} + +/* + gray_setDelays() + Changes the gray engine delays. +*/ +void gray_setDelays(int light, int dark) +{ + delays[0] = light; + delays[1] = dark; +} + + + +//--- +// Engine information. +//--- + +/* + gray_runs() + Returns 1 if the gray engine is running, 0 otherwise. +*/ +inline int gray_runs(void) +{ + return runs; +} + +/* + gray_lightVRAM() + Returns the module's gray vram address. +*/ +void *gray_lightVRAM(void) +{ + return (void *)vrams[~current & 2]; +} + +/* + gray_lightVRAM() + Returns the module's dark vram address. +*/ +void *gray_darkVRAM(void) +{ + return (void *)vrams[(~current & 2) | 1]; +} + +/* + gray_getDelays() + Returns the gray engine delays. Pointers are not set if NULL. +*/ +void gray_getDelays(int *light, int *dark) +{ + if(light) *light = delays[0]; + if(dark) *dark = delays[1]; +} + + + +//--- +// Drawing. +//--- + +/* + gupdate() + Swaps the vram buffer sets. +*/ +inline void gupdate(void) +{ + current ^= 2; +} + + + +//--- +// Interrupt control and initialization. +//--- + +/* + gray_interrupt() + Answers a timer interrupt. Swaps the buffers. +*/ +void gray_interrupt(void) +{ + timer_reload(TIMER_GRAY, delays[(~current) & 1]); + screen_display(vrams[current]); + current ^= 1; +} + +/* + gray_init() + Initializes the gray engine. +*/ +void gray_init(void) +{ + vrams[0] = (const void *)display_getLocalVRAM(); + vrams[1] = (const void *)internal_vrams[0]; + vrams[2] = (const void *)internal_vrams[1]; + vrams[3] = (const void *)internal_vrams[2]; + + delays[0] = 912; + delays[1] = 1343; +} diff --git a/src/p7os/cake.exe/libgint/src/gray/greverse_area.c b/src/p7os/cake.exe/libgint/src/gray/greverse_area.c new file mode 100644 index 0000000..7a3fccd --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/gray/greverse_area.c @@ -0,0 +1,15 @@ +#include +#include + +/* + greverse_area() + Reverses an area of the vram. End points (x1, y1) and (x2, y2) are + included. +*/ +void greverse_area(int x1, int y1, int x2, int y2) +{ + display_useVRAM(gray_lightVRAM()); + dreverse_area(x1, y1, x2, y2); + display_useVRAM(gray_darkVRAM()); + dreverse_area(x1, y1, x2, y2); +} diff --git a/src/p7os/cake.exe/libgint/src/keyboard/getPressedKey.c b/src/p7os/cake.exe/libgint/src/keyboard/getPressedKey.c new file mode 100644 index 0000000..ca8ba32 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/keyboard/getPressedKey.c @@ -0,0 +1,24 @@ +#include + +/* + getPressedKey() + Finds a pressed key in the keyboard state and returns it. +*/ +int getPressedKey(volatile unsigned char *keyboard_state) +{ + int row = 1, column = 0; + int state; + if(keyboard_state[0] & 1) return KEY_AC_ON; + + while(row <= 9 && !keyboard_state[row]) row++; + if(row > 9) return KEY_NONE; + + state = keyboard_state[row]; + while(!(state & 1)) + { + state >>= 1; + column++; + } + + return (column << 4) | row; +} diff --git a/src/p7os/cake.exe/libgint/src/keyboard/getPressedKeys.c b/src/p7os/cake.exe/libgint/src/keyboard/getPressedKeys.c new file mode 100644 index 0000000..b6dd739 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/keyboard/getPressedKeys.c @@ -0,0 +1,54 @@ +#include + +/* + getPressedKeys() + Find 'count' pressed keys in the keyboard state and fills the 'keys' + array. Returns the number of actually-pressed keys found. +*/ +int getPressedKeys(volatile unsigned char *keyboard_state, int *keys, + int count) +{ + int row = 1, column; + int found = 0, actually_pressed; + int state; + if(count <= 0) return 0; + + if(keyboard_state[0] & 1) + { + keys[found++] = KEY_AC_ON; + count--; + } + + while(count && row <= 9) + { + while(row <= 9 && !keyboard_state[row]) row++; + if(row > 9) break; + + state = keyboard_state[row]; + column = 0; + + while(count && column < 8) + { + if(state & 1) + { + keys[found++] = (column << 4) | row; + count--; + } + + state >>= 1; + column++; + } + + row++; + } + + actually_pressed = found; + + while(count) + { + keys[found++] = KEY_NONE; + count--; + } + + return actually_pressed; +} diff --git a/src/p7os/cake.exe/libgint/src/keyboard/getkey.c b/src/p7os/cake.exe/libgint/src/keyboard/getkey.c new file mode 100644 index 0000000..a1d2525 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/keyboard/getkey.c @@ -0,0 +1,131 @@ +#include +#include +#include + +/* + getkey() + Blocking function with auto-repeat and SHIFT modifying functionalities. + Roughly reproduces the behavior of the system's GetKey(). +*/ +int getkey(void) +{ + return getkey_opt( + Getkey_ShiftModifier | + Getkey_AlphaModifier | + + Getkey_RepeatArrowKeys, + + 0 + ); +} + +/* + getkey_opt() + Enhances getkey() with more general functionalities. + If max_cycles is non-zero and positive, getkey_opt() will return + KEY_NOEVENT if no event occurs during max_cycle analysis. +*/ +void getkey_opt_wait(int *cycles) +{ + while(!interrupt_flag) sleep(); + interrupt_flag = 0; + + if(*cycles > 0) (*cycles)--; +} +int getkey_opt(enum GetkeyOpt options, int cycles) +{ + struct Event event; + int modifier = 0; + static int event_ref = 0; + + if(cycles <= 0) cycles = -1; + while(cycles != 0) + { + event = pollevent(); + switch(event.type) + { + case ET_None: + if(last_key == KEY_NONE) + { + getkey_opt_wait(&cycles); + continue; + } + + // Handling repetitions. + enum KeyType type = keytype(last_key); + if(!(options & (type << 4))) break; + + if(event_ref <= 0) + { + getkey_opt_wait(&cycles); + event_ref++; + continue; + } + + last_events++; + event_ref--; + + if(last_events >= (last_repeats ? repeat_next : + repeat_first)) + { + last_repeats++; + last_events = 0; + return last_key; + } + break; + + case ET_KeyPress: + ; + int key = event.key; + if(options & Getkey_ShiftModifier && key == KEY_SHIFT) + { + modifier ^= MOD_SHIFT; + continue; + } + if(options & Getkey_AlphaModifier && key == KEY_ALPHA) + { + modifier ^= MOD_ALPHA; + continue; + } + + last_key = key; + last_repeats = 0; + last_events = 0; + event_ref = 0; + return key | modifier; + + case ET_KeyRel: + if(event.key != last_key) break; + last_key = KEY_NONE; + last_repeats = 0; + last_events = 0; + event_ref = 0; + break; + + default: + break; + } + } + + last_key = KEY_NONE; + last_repeats = 0; + last_events = 0; + event_ref = 0; + return KEY_NONE; +} + +/* +int getkey_opt(enum GetkeyOpt options, int max_cycles) +{ + while(max_cycles != 0) + { + // Handling "new key" events. + + // Handling key repetitions. + + } + + // When no key was pressed during the given delay... + return KEY_NOEVENT; +} +*/ diff --git a/src/p7os/cake.exe/libgint/src/keyboard/keyboard_config.c b/src/p7os/cake.exe/libgint/src/keyboard/keyboard_config.c new file mode 100644 index 0000000..e19347f --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/keyboard/keyboard_config.c @@ -0,0 +1,20 @@ +#include +#include +#include +#include + +/* + keyboard_setRepeatRate() + Sets the default repeat rate for key events. The unit for the argument + is the keyboard period. + For example at 32 Hz, values of (20, 4) will imitate the system + default. +*/ +void keyboard_setRepeatRate(int first, int next) +{ + if(first < 0) first = 0; + if(next < 0) next = 0; + + repeat_first = first; + repeat_next = next; +} diff --git a/src/p7os/cake.exe/libgint/src/keyboard/keyboard_interrupt.c b/src/p7os/cake.exe/libgint/src/keyboard/keyboard_interrupt.c new file mode 100644 index 0000000..e98dc51 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/keyboard/keyboard_interrupt.c @@ -0,0 +1,120 @@ +#include +#include +#include +#include +#include +#include + +//--- +// Keyboard variables. +//--- + +// These ones get modified by interrupts. +volatile unsigned char keyboard_state[10] = { 0 }; +volatile int interrupt_flag = 0; + +// Key statistics. +int repeat_first = 10, repeat_next = 2; +int last_key = KEY_NONE, last_repeats = 0, last_events = 0; + +// RTC callback id. +unsigned cb_id; + + + +//--- +// Interrupt management. +//--- + +static void push_press(int keycode) +{ + struct Event event = { + .type = ET_KeyPress, + .key = keycode, + }; + event_push(event); +} + +static void push_release(int keycode) +{ + struct Event event = { + .type = ET_KeyRel, + .key = keycode, + }; + event_push(event); +} + +/* + keyboard_interrupt() + Callback for keyboard update. Allows keyboard analysis functions to + wake only when keyboard interrupts happen. +*/ +void keyboard_interrupt(void) +{ + unsigned char state[10] = { 0 }; + + isSH3() ? keyboard_updateState_7705(state) + : keyboard_updateState_7305(state) + ; + + // Try to minimize number of operations in common cases... this handles + // AC/ON. + if(keyboard_state[0] ^ state[0]) + { + unsigned char pressed = ~keyboard_state[0] & state[0]; + unsigned char released = keyboard_state[0] & ~state[0]; + + if(pressed & 1) push_press(KEY_AC_ON); + if(released & 1) push_release(KEY_AC_ON); + } + keyboard_state[0] = state[0]; + + for(int row = 1; row <= 9; row++) + { + unsigned char pressed = ~keyboard_state[row] & state[row]; + unsigned char released = keyboard_state[row] & ~state[row]; + keyboard_state[row] = state[row]; + + // Fasten this a bit. + if(!pressed && !released) continue; + + for(int column = 0; column < 8; column++) + { + if(pressed & 1) push_press ((column << 4) | row); + if(released & 1) push_release((column << 4) | row); + + pressed >>= 1; + released >>= 1; + } + } + + interrupt_flag = 1; +} + +/* + keyboard_init() + Starts the keyboard timer. +*/ +void keyboard_init(void) +{ + cb_id = rtc_cb_add(RTCFreq_16Hz, keyboard_interrupt, 0); +} + +/* + keyboard_setFrequency() + Sets the keyboard frequency. +*/ +void keyboard_setFrequency(enum KeyboardFrequency frequency) +{ + if(frequency < 1 || frequency > 7) return; + rtc_cb_edit(cb_id, frequency, keyboard_interrupt); +} + +/* + keyboard_quit() + Stops the keyboard timer. +*/ +void keyboard_quit(void) +{ + rtc_cb_end(cb_id); +} diff --git a/src/p7os/cake.exe/libgint/src/keyboard/keyboard_misc.c b/src/p7os/cake.exe/libgint/src/keyboard/keyboard_misc.c new file mode 100644 index 0000000..abdf59c --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/keyboard/keyboard_misc.c @@ -0,0 +1,25 @@ +#include +#include + +/* + keylast() + Returns the matrix code of the last pressed key. If repeat_count is + non-NULL, it is set to the number of repetitions. +*/ +int keylast(int *repeat_count) +{ + if(repeat_count) *repeat_count = last_repeats; + return last_key; +} + + + +/* + keystate() + Returns the address of the keyboard state array. The returned address + is the handler's buffer, therefore it contains volatile data. +*/ +volatile unsigned char *keystate(void) +{ + return keyboard_state; +} diff --git a/src/p7os/cake.exe/libgint/src/keyboard/keyboard_sh7305.c b/src/p7os/cake.exe/libgint/src/keyboard/keyboard_sh7305.c new file mode 100644 index 0000000..ac740b6 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/keyboard/keyboard_sh7305.c @@ -0,0 +1,142 @@ +//--- +// +// gint core module: keyboard analyzer +// +// Probably the most difficult hardware interaction. There is very few +// documentation on how the system actually analyzes the keyboard. While +// disassembling syscalls reveals the following procedure (which was +// already documented by SimonLothar), there is nothing about the +// detection problems of the multi-getkey system. +// +//--- + +#include +#include <7305.h> + +//--- +// Keyboard management. +//--- + +/* + kdelay() + Should sleep during a few milliseconds. Well... + This delay has a great influence on key detection. Here are a few + observations of what happens with common numbers of "nop" (without + overclock). Take care of the effect of overclock! + + Column effects + May have something to do with register HIZCRB not being used here. When + many keys on the same column are pressed, other keys of the same column + may be triggered. + + - Less Bad key detection. + - 8 Very few column effects. Most often, three keys may be pressed + simultaneously. However, [UP] has latencies and is globally not + detected. + - 12 Seems best. Every individual key is detected well. No column + effect observed before four keys. + - 16 Every single key is detected correctly. Pressing two keys on a + same column does not usually create a column effect. Three keys + almost always. + - More Does not improve single key detection, and increase column + effects. At 256 every single key press create a whole column + effect. +*/ +static void kdelay(void) +{ + #define r4(str) str str str str + + __asm__ + ( + "nop\n\t" + ); + + #undef r4 +} + +/* + krow() + Reads a keyboard row. Works like krow() for SH7705. See gint_7705.c for + more details. +*/ +static int krow(int row) +{ + volatile unsigned short *injector1 = (unsigned short *)0xa4050116; + volatile unsigned char *data1 = (unsigned char *)0xa4050136; + + volatile unsigned short *injector2 = (unsigned short *)0xa4050118; + volatile unsigned char *data2 = (unsigned char *)0xa4050138; + + volatile unsigned short *detector = (unsigned short *)0xa405014c; + volatile unsigned char *keys = (unsigned char *)0xa405016c; + + volatile unsigned char *key_register = (unsigned char *)0xa40501c6; +// volatile unsigned short *hizcrb = (unsigned short *)0xa405015a; + + unsigned short smask; + unsigned char cmask; + int result = 0; + + if(row < 0 || row > 9) return 0; + + // Additional configuration for SH7305. + *detector = 0xaaaa; + *key_register = 0xff; + *injector1 = (*injector1 & 0xf000) | 0x0555; + *injector2 = (*injector2 & 0xf000) | 0x0555; + *data1 |= 0x3f; + *data2 |= 0x3f; + kdelay(); + + if(row < 6) + { + smask = 0x0003 << (row * 2); + cmask = ~(1 << row); + + *injector1 = ((*injector1 & 0xf000) | 0x0aaa) ^ smask; + *injector2 = (*injector2 & 0xf000) | 0x0aaa; + kdelay(); + + *data1 = (*data1 & 0xc0) | cmask; + *data2 |= 0x3f; + kdelay(); + } + else + { + smask = 0x0003 << ((row - 6) * 2); + cmask = ~(1 << (row - 6)); + + *injector1 = (*injector1 & 0xf000) | 0x0aaa; + *injector2 = ((*injector2 & 0xf000) | 0x0aaa) ^ smask; + kdelay(); + + *data1 |= 0x3f; + *data2 = (*data2 & 0xc0) | cmask; + kdelay(); + } + + // Reading the keyboard row. + result = ~*keys; + kdelay(); + + // Re-initializing the port configuration and data. + *injector1 = (*injector1 & 0xf000) | 0x0aaa; + *injector2 = (*injector2 & 0xf000) | 0x0aaa; + kdelay(); + *injector1 = (*injector1 & 0xf000) | 0x0555; + *injector2 = (*injector2 & 0xf000) | 0x0555; + kdelay(); + *data1 &= 0xc0; + *data2 &= 0xc0; + + return result; +} + +/* + keyboard_updateState() + Updates the keyboard state. +*/ +void keyboard_updateState_7305(volatile unsigned char *keyboard_state) +{ + for(int i = 0; i < 10; i++) keyboard_state[i] = krow(i); +} diff --git a/src/p7os/cake.exe/libgint/src/keyboard/keyboard_sh7705.c b/src/p7os/cake.exe/libgint/src/keyboard/keyboard_sh7705.c new file mode 100644 index 0000000..1ab1800 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/keyboard/keyboard_sh7705.c @@ -0,0 +1,135 @@ +//--- +// +// gint core module: keyboard analyzer +// +// Probably the most difficult hardware interaction. There is very few +// documentation on how the system actually analyzes the keyboard. While +// disassembling syscalls reveals the following procedure (which was +// already documented by SimonLothar), there is nothing about the +// detection problems of the multi-getkey system. +// +//--- + +#include +#include <7705.h> + +//--- +// Keyboard management. +//--- + +/* + kdelay() + Used to be a low-level sleep using the watchdog, as in the system. This + way seems OK at least, and it doesn't create column effects as for + SH7305. +*/ +static void kdelay(void) +{ + #define r4(str) str str str str + + __asm__ + ( + r4("nop\n\t") + ); + + #undef r4 + + /* Watchdog delay version. + const int delay = 0xf4; + + // Disabling the watchdog timer interrupt and resetting the + // configuration. Setting the delay. + INTC.IPRB.BIT._WDT = 0; + WDT.WTCSR.WRITE = 0xa500; + WDT.WTCNT.WRITE = 0x5a00 | (delay & 0xff); + + // Counting on Po/256. + WDT.WTCSR.WRITE = 0xa505; + // Starting the timer (sets again to Po/256). + WDT.WTCSR.WRITE = 0xa585; + + // Waiting until it overflows (delaying), then clearing the overflow + // flag. + while((WDT.WTCSR.READ.BYTE & 0x08) == 0); + WDT.WTCSR.WRITE = 0xa500 | (WDT.WTCSR.READ.BYTE & 0xf7); + + // Resetting the configuration and the counter. + WDT.WTCSR.WRITE = 0xa500; + WDT.WTCSR.WRITE = 0x5a00; + + // Enabling back the watchdog timer interrupt. + INTC.IPRB.BIT._WDT = GINT_INTP_WDT; + */ +} + +/* + krow() + Reads a keyboard row. +*/ +static int krow(int row) +{ + // '11' on the active row, '00' everywhere else. + unsigned short smask = 0x0003 << ((row % 8) * 2); + // '0' on the active row, '1' everywhere else. + unsigned char cmask = ~(1 << (row % 8)); + // Line results. + int result = 0; + + if(row < 0 || row > 9) return 0; + + // Initial configuration. + PFC.PBCR.WORD = 0xaaaa; + PFC.PMCR.WORD = (PFC.PMCR.WORD & 0xff00) | 0x0055; + kdelay(); + + if(row < 8) + { + // Configuring port B/M as input except for the row to check, + // which has to be an output. This sets '01' (output) on the + // active row, '10' (input) everywhere else. + PFC.PBCR.WORD = 0xaaaa ^ smask; + PFC.PMCR.WORD = (PFC.PMCR.WORD & 0xff00) | 0x00aa; + kdelay(); + + // Every bit set to 1 except the active row bit. + PB.DR.BYTE = cmask; + PM.DR.BYTE = (PM.DR.BYTE & 0xf0) | 0x0f; + kdelay(); + } + else + { + // The same, but deals with port M. + PFC.PBCR.WORD = 0xaaaa; + PFC.PMCR.WORD = ((PFC.PMCR.WORD & 0xff00) | 0x00aa) ^ smask; + kdelay(); + + PB.DR.BYTE = 0xff; + PM.DR.BYTE = (PM.DR.BYTE & 0xf0) | cmask; + kdelay(); + } + + // Reading the keyboard row. + result = ~PA.DR.BYTE; + kdelay(); + + // Re-initializing the port configuration and data. + PFC.PBCR.WORD = 0xaaaa; + PFC.PMCR.WORD = (PFC.PMCR.WORD & 0xff00) | 0x00aa; + kdelay(); + PFC.PBCR.WORD = 0x5555; + PFC.PMCR.WORD = (PFC.PMCR.WORD & 0xff00) | 0x0055; + kdelay(); + PB.DR.BYTE = 0x00; + PM.DR.BYTE &= 0xf0; + + return result; +} + +/* + keyboard_updateState() + Updates the keyboard state. +*/ +void keyboard_updateState_7705(volatile unsigned char *keyboard_state) +{ + for(int i = 0; i < 10; i++) keyboard_state[i] = krow(i); +} diff --git a/src/p7os/cake.exe/libgint/src/keyboard/keychar.c b/src/p7os/cake.exe/libgint/src/keyboard/keychar.c new file mode 100644 index 0000000..bd9e9cc --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/keyboard/keychar.c @@ -0,0 +1,36 @@ +#include + +/* + keychar() + Returns the ASCII character associated with a key, or 0 for control + keys. +*/ +int keychar(int key) +{ + char flat[] = { + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, '2', '^', 0x0, 0x0, 0x0, + 'X', 'L', 'l', 's', 'c', 't', + 0x0, 0x0, '(', ')', ',', '>', + '7', '8', '9', 0x0, 0x0, 0x0, + '4', '5', '6', '*', '/', 0x0, + '1', '2', '3', '+', '-', 0x0, + '0', '.', 'e', '_', 0x0, 0x0 + }; + char alpha[] = { + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 'r', 'o', 0x0, 0x0, 0x0, + 'A', 'B', 'C', 'D', 'E', 'F', + 'G', 'H', 'I', 'J', 'K', 'L', + 'M', 'N', 'O', 0x0, 0x0, 0x0, + 'P', 'Q', 'R', 'S', 'T', 0x0, + 'U', 'V', 'W', 'X', 'Y', 0x0, + 'Z', ' ', '"', 0x0, 0x0, 0x0 + }; + + int id = keyid(key); + + return (key & MOD_ALPHA) ? alpha[id] : flat[id]; +} diff --git a/src/p7os/cake.exe/libgint/src/keyboard/keyid.c b/src/p7os/cake.exe/libgint/src/keyboard/keyid.c new file mode 100644 index 0000000..c4ed014 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/keyboard/keyid.c @@ -0,0 +1,17 @@ +#include + +/* + keyid() + Returns a non-matrix key code that can be used for array subscript. + Ignores modifiers. +*/ +int keyid(int key) +{ + if(key < 0) return -1; + key &= MOD_CLEAR; + + int row = 9 - (key & 0x0f); + int column = 6 - ((key & 0xf0) >> 4); + + return 6 * row + column; +} diff --git a/src/p7os/cake.exe/libgint/src/keyboard/keytype.c b/src/p7os/cake.exe/libgint/src/keyboard/keytype.c new file mode 100644 index 0000000..9e3c0c9 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/keyboard/keytype.c @@ -0,0 +1,17 @@ +#include + +/* + keytype() + Returns a key's type. Ignores modifiers. +*/ +enum KeyType keytype(int key) +{ + key &= MOD_CLEAR; + + if(key == KEY_UP || key == KEY_RIGHT || key == KEY_DOWN || + key == KEY_LEFT) return KeyType_Arrow; + + if((key & 0x0f) == 0x09) return KeyType_Function; + + return keychar(key) ? KeyType_Character : KeyType_Control; +} diff --git a/src/p7os/cake.exe/libgint/src/keyboard/multigetkey.c b/src/p7os/cake.exe/libgint/src/keyboard/multigetkey.c new file mode 100644 index 0000000..dbe8a44 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/keyboard/multigetkey.c @@ -0,0 +1,46 @@ +#include +#include + +/* + multigetkey() + Listens the keyboard for simultaneous key hits. Uses the same options + as getkey_opt(). + multigetkey() fills the 'keys' array with 'count' key codes, adding + KEY_NOKEY if less than 'count' keys are pressed. + Be aware that rectangle and column effects can make multigetkey() read + unpressed keys as pressed (see documentation for more information). + Setting count = 3 is generally safe. + The function returns after 'max_cycles' if no key is pressed. +*/ +void multigetkey(int *keys, int count, int max_cycles) +{ + int number; + + if(!max_cycles) max_cycles = -1; + + while(max_cycles != 0) + { + while(!interrupt_flag) sleep(); + interrupt_flag = 0; + if(max_cycles > 0) max_cycles--; + + number = getPressedKeys(keyboard_state, keys, count); + + // We need to update the last key data, in case multigetkey() + // returns a single key, and getkey() is called a short time + // after. Otherwise getkey() could re-send an event for this + // key. + if(number == 1) + { + last_key = keys[0]; + last_repeats = 0; + last_events = 0; + } + + if(number) return; + } + + // When no key was pressed during the given delay... (no need to fill + // the array, it has already been done by getPressedKeys()). + return; +} diff --git a/src/p7os/cake.exe/libgint/src/mmu/pseudoTLBInit.c b/src/p7os/cake.exe/libgint/src/mmu/pseudoTLBInit.c new file mode 100644 index 0000000..b27d60d --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/mmu/pseudoTLBInit.c @@ -0,0 +1,29 @@ +#include + +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" + +/* + mmu_pseudoTLBInit() + We need the system to fill the TLB for us, so that it knows what + happens to its contents. We don't want to edit the TLB ourselves, so + we'll just read random data from every 4k-page in the rom area to have + the system virtualize it entirely. + The index system for TLB entries ensures this process will work for + 128-k or less add-ins. On SH7705 there is a limit, which is 384-k (it + does probably not exist on SH7305) but there is no guarantee that the + system will not go wild after 128-k. +*/ +void mmu_pseudoTLBInit(void) +{ + extern unsigned int romdata; + unsigned int address = 0x00300000; + unsigned int x; + + while(address <= (unsigned int)&romdata) + { + x = *((volatile unsigned int *)address); + address += 0x1000; + } +} + +#pragma GCC diagnostic pop diff --git a/src/p7os/cake.exe/libgint/src/mpu/gint_sh7305.c b/src/p7os/cake.exe/libgint/src/mpu/gint_sh7305.c new file mode 100644 index 0000000..7327a38 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/mpu/gint_sh7305.c @@ -0,0 +1,219 @@ +//--- +// +// gint core module: sh7305 interrupt handler +// +// Of course all the work related to interrupts is heavily platform- +// dependent. This module handles interrupts and configures the MPU to +// save and restore the system's configuration when execution ends. +// +//--- + +#include +#include +#include +#include +#include <7305.h> +#include + +#include + +//--- +// Interrupt codes. +//--- + +#define IC_RTC_PRI 0xaa0 +#define IC_KEYSC 0xbe0 +#define IC_TMU0_TUNI0 0x400 +#define IC_TMU0_TUNI1 0x420 +#define IC_TMU0_TUNI2 0x440 + + + +//--- +// Exception handling. +//--- + +void gint_int_7305(void) +{ + volatile unsigned int *intevt = (unsigned int *)0xff000028; + unsigned int code = *intevt; + + switch(code) + { + case IC_RTC_PRI: + rtc_interrupt(); + break; + + case IC_TMU0_TUNI0: + timer_interrupt(TIMER_TMU0); + break; + + case IC_TMU0_TUNI1: + timer_interrupt(TIMER_TMU1); + break; + + case IC_TMU0_TUNI2: + timer_interrupt(TIMER_TMU2); + break; + + default: + gint_callDefaultHandler(code); + } +} + +/* + gint_reg() + Returns the address of a common register. All common registers exist + on both platforms but they may hold different values for the same + information (f.i. EXPEVT may not return the same value for a given + exception on both 7705 and 7305). +*/ +volatile void *gint_reg_7305(enum Register reg) +{ + volatile unsigned int *expevt = (unsigned int *)0xff000024; + volatile unsigned int *tea = (unsigned int *)0xff00000c; + volatile unsigned int *mmucr = (unsigned int *)0xff000010; + + switch(reg) + { + case Register_EXPEVT: return expevt; + case Register_TEA: return tea; + case Register_MMUCR: return mmucr; + default: return NULL; + } +} + +/* + gint_strerror() + Returns a string that describe the error set in EXPEVT. This string is + not platform-dependent. +*/ +const char *gint_strerror_7305(void) +{ + volatile unsigned int *expevt = gint_reg_7305(Register_EXPEVT); + + switch(*expevt) + { + case 0x1e0: return gint_str[3]; + case 0x0e0: return gint_str[8]; + case 0x040: return gint_str[14]; + case 0x0a0: return gint_str[17]; + case 0x180: return gint_str[6]; + case 0x1a0: return gint_str[7]; + case 0x100: return gint_str[9]; + case 0x060: return gint_str[15]; + case 0x0c0: return gint_str[18]; + case 0x080: return gint_str[20]; + case 0x160: return gint_str[21]; + } + return gint_str[0]; +} + + + +//--- +// Setup. +//--- + +static unsigned short ipr[12]; +static unsigned char rcr2; +// Saves of the keyboard registers. Could be better. +static unsigned short inj1, inj2, det; +static unsigned char data1, data2, keys, reg; + +static void gint_priority_lock_7305(void) +{ + // Saving the current interrupt priorities. + ipr[0] = INTX.IPRA.WORD; + ipr[1] = INTX.IPRB.WORD; + ipr[2] = INTX.IPRC.WORD; + ipr[3] = INTX.IPRD.WORD; + ipr[4] = INTX.IPRE.WORD; + ipr[5] = INTX.IPRF.WORD; + ipr[6] = INTX.IPRG.WORD; + ipr[7] = INTX.IPRH.WORD; + ipr[8] = INTX.IPRI.WORD; + ipr[9] = INTX.IPRJ.WORD; + ipr[10] = INTX.IPRK.WORD; + ipr[11] = INTX.IPRL.WORD; + + // Disabling everything by default to avoid freezing on non-handled + // interrupts. + INTX.IPRA.WORD = 0x0000; + INTX.IPRB.WORD = 0x0000; + INTX.IPRC.WORD = 0x0000; + INTX.IPRD.WORD = 0x0000; + INTX.IPRE.WORD = 0x0000; + INTX.IPRF.WORD = 0x0000; + INTX.IPRG.WORD = 0x0000; + INTX.IPRH.WORD = 0x0000; + INTX.IPRI.WORD = 0x0000; + INTX.IPRJ.WORD = 0x0000; + INTX.IPRK.WORD = 0x0000; + INTX.IPRL.WORD = 0x0000; + + // Saving keyboard registers. + inj1 = *((volatile unsigned short *)0xa4050116); + data1 = *((volatile unsigned char *)0xa4050136); + inj2 = *((volatile unsigned short *)0xa4050118); + data2 = *((volatile unsigned char *)0xa4050138); + det = *((volatile unsigned short *)0xa405014c); + keys = *((volatile unsigned char *)0xa405016c); + reg = *((volatile unsigned char *)0xa40501c6); + + // Allowing RTC. Keyboard analysis is done regularly using a RTC + // because SH7305's special KEYSC interface does not allow us to clear + // the keyboard interrupt flags. + INTX.IPRK._RTC = GINT_INTP_RTC; + INTX.IPRA.TMU0_0 = GINT_INTP_KEY; + INTX.IPRA.TMU0_1 = GINT_INTP_GRAY; + INTX.IPRA.TMU0_2 = GINT_INTP_TIMER; +} + +static void gint_priority_unlock_7305(void) +{ + // Restoring the interrupt priorities. + INTX.IPRA.WORD = ipr[0]; + INTX.IPRB.WORD = ipr[1]; + INTX.IPRC.WORD = ipr[2]; + INTX.IPRD.WORD = ipr[3]; + INTX.IPRE.WORD = ipr[4]; + INTX.IPRF.WORD = ipr[5]; + INTX.IPRG.WORD = ipr[6]; + INTX.IPRH.WORD = ipr[7]; + INTX.IPRI.WORD = ipr[8]; + INTX.IPRJ.WORD = ipr[9]; + INTX.IPRK.WORD = ipr[10]; + INTX.IPRL.WORD = ipr[11]; + + // Restoring keyboard registers. + *((volatile unsigned short *)0xa4050116) = inj1; + *((volatile unsigned char *)0xa4050136) = data1; + *((volatile unsigned short *)0xa4050118) = inj2; + *((volatile unsigned char *)0xa4050138) = data2; + *((volatile unsigned short *)0xa405014c) = det; + *((volatile unsigned char *)0xa405016c) = keys; + *((volatile unsigned char *)0xa40501c6) = reg; +} + +void gint_setup_7305(void) +{ + volatile struct mod_rtc *RTC = RTC_SH7305; + + gint_priority_lock_7305(); + + // Saving the RTC configuration. + rcr2 = RTC->RCR2.BYTE; + // Disabling RTC interrupts by default. + RTC->RCR2.BYTE = 0x09; +} + +void gint_stop_7305(void) +{ + volatile struct mod_rtc *RTC = RTC_SH7305; + + gint_priority_unlock_7305(); + + // Restoring the RTC configuration. + RTC->RCR2.BYTE = rcr2; +} diff --git a/src/p7os/cake.exe/libgint/src/mpu/gint_sh7705.c b/src/p7os/cake.exe/libgint/src/mpu/gint_sh7705.c new file mode 100644 index 0000000..a1c19aa --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/mpu/gint_sh7705.c @@ -0,0 +1,190 @@ +//--- +// +// gint core module: sh7705 interrupt handler +// +// Of course all the work related to interrupts is heavily platform- +// dependent. This module handles interrupts and configures the MPU to +// save and restore the system's configuration when execution ends. +// +//--- + +#include +#include +#include +#include +#include <7705.h> +#include + +#include + +//--- +// Interrupt codes. +//--- + +#define IC_RTC_PRI 0x4a0 +#define IC_PINT07 0x700 +#define IC_TMU0_TUNI0 0x400 +#define IC_TMU1_TUNI1 0x420 +#define IC_TMU2_TUNI2 0x440 + + + +//--- +// Exception handling. +//--- + +void gint_int_7705(void) +{ + volatile unsigned int *intevt2 = (unsigned int *)0xa4000000; + unsigned int code = *intevt2; + + switch(code) + { + case IC_RTC_PRI: + rtc_interrupt(); + break; + + case IC_TMU0_TUNI0: + timer_interrupt(TIMER_TMU0); + break; + + case IC_TMU1_TUNI1: + timer_interrupt(TIMER_TMU1); + break; + + case IC_TMU2_TUNI2: + timer_interrupt(TIMER_TMU2); + break; + + default: + gint_callDefaultHandler(code); + } +} + +/* + gint_reg() + Returns the address of a common register. All common registers exist + on both platforms but they may hold different values for the same + information (f.i. EXPEVT may not return the same value for a given + exception on both 7705 and 7305). +*/ +volatile void *gint_reg_7705(enum Register reg) +{ + volatile unsigned int *expevt = (unsigned int *)0xffffffd4; + volatile unsigned int *mmucr = (unsigned int *)0xfffffff4; + volatile unsigned int *tea = (unsigned int *)0xfffffffc; + + switch(reg) + { + case Register_EXPEVT: return expevt; + case Register_MMUCR: return mmucr; + case Register_TEA: return tea; + default: return NULL; + } +} + +/* + gint_strerror() + Returns a string that describe the error set in EXPEVT. This string is + not platform-dependent. + Some exception codes represent different errors when invoked inside the + general exception handler and the TLB error handler. Parameter 'is_tlb' + should be set to zero for general exception meanings, and anything non- + zero for TLB error meanings. +*/ +const char *gint_strerror_7705(int is_tlb) +{ + volatile unsigned int *expevt = gint_reg_7705(Register_EXPEVT); + + switch(*expevt) + { + case 0x1e0: return gint_str[3]; + case 0x0e0: return gint_str[4]; + case 0x040: return gint_str[is_tlb ? 10 : 11]; + case 0x0a0: return gint_str[12]; + case 0x180: return gint_str[6]; + case 0x1a0: return gint_str[7]; + case 0x100: return gint_str[5]; + case 0x060: return gint_str[is_tlb ? 13 : 19]; + case 0x0c0: return gint_str[16]; + case 0x080: return gint_str[20]; + case 0x160: return gint_str[21]; + case 0x5c0: return gint_str[22]; + } + return gint_str[0]; +} + + + +//--- +// Setup. +//--- + +static unsigned short iprs[8]; +static unsigned char rcr2; + +static void gint_priority_lock_7705(void) +{ + // Saving the interrupt masks from registers IPRA to IPRH. + iprs[0] = INTC.IPRA.WORD; + iprs[1] = INTC.IPRB.WORD; + iprs[2] = INTX.IPRC.WORD; + iprs[3] = INTX.IPRD.WORD; + iprs[4] = INTX.IPRE.WORD; + iprs[5] = INTX.IPRF.WORD; + iprs[6] = INTX.IPRG.WORD; + iprs[7] = INTX.IPRH.WORD; + + // Disabling everything by default to avoid receiving an interrupt that + // the handler doesn't handle, which would cause the user program to + // freeze. + INTC.IPRA.WORD = 0x0000; + INTC.IPRB.WORD = 0x0000; + INTX.IPRC.WORD = 0x0000; + INTX.IPRD.WORD = 0x0000; + INTX.IPRE.WORD = 0x0000; + INTX.IPRF.WORD = 0x0000; + INTX.IPRG.WORD = 0x0000; + INTX.IPRH.WORD = 0x0000; + + // Allowing RTC, which handles keyboard. + INTC.IPRA.BIT._RTC = GINT_INTP_RTC; + INTC.IPRA.BIT._TMU0 = GINT_INTP_KEY; + INTC.IPRA.BIT._TMU1 = GINT_INTP_GRAY; + INTC.IPRA.BIT._TMU2 = GINT_INTP_TIMER; +} + +static void gint_priority_unlock_7705(void) +{ + // Restoring the saved states. + INTC.IPRA.WORD = iprs[0]; + INTC.IPRB.WORD = iprs[1]; + INTX.IPRC.WORD = iprs[2]; + INTX.IPRD.WORD = iprs[3]; + INTX.IPRE.WORD = iprs[4]; + INTX.IPRF.WORD = iprs[5]; + INTX.IPRG.WORD = iprs[6]; + INTX.IPRH.WORD = iprs[7]; +} + +void gint_setup_7705(void) +{ + volatile struct mod_rtc *RTC = RTC_SH7705; + + gint_priority_lock_7705(); + + // Saving the RTC configuration. + rcr2 = RTC->RCR2.BYTE; + // Disabling RTC interrupts by default. + RTC->RCR2.BYTE = 0x09; +} + +void gint_stop_7705(void) +{ + volatile struct mod_rtc *RTC = RTC_SH7705; + + gint_priority_unlock_7705(); + + // Restoring the RTC configuration. + RTC->RCR2.BYTE = rcr2; +} diff --git a/src/p7os/cake.exe/libgint/src/mpu/mpu.c b/src/p7os/cake.exe/libgint/src/mpu/mpu.c new file mode 100644 index 0000000..f4c7dc6 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/mpu/mpu.c @@ -0,0 +1,80 @@ +//--- +// +// gint core module: mpu +// +// Determines which kind of MPU is running the program. +// +//--- + +#include + +enum MPU MPU_CURRENT; + +/* + getMPU() + + Returns the MPU identifier of the calculator. + Thanks to SimonLothar for this function and related information. + + Processor version register (PVR) and product control register (PRR) + hold information about the MPU version, they but are only accessible on + SH-4-based MPUs. + To detect SH-3-based MPUs, this function uses port L control register + (PLCR), whose bits 8 to 15 cannot be set with SH7337 where bits 8 to 11 + can be set with SH7355. + + Additionally, the CPU core ID register (CPIDR) at 0xff000048 returns 1 + on SH7305. +*/ +enum MPU getMPU(void) +{ + // Processor version register. + volatile unsigned int *pvr = (unsigned int *)0xff000030; + // Product version register. + volatile unsigned int *prr = (unsigned int *)0xff000044; + // Port L control register. + volatile unsigned short *plcr = (unsigned short *)0xa4000114; + // Saved value for PLCR. + unsigned short saved_plcr; + unsigned int tested_plcr; + + + // Looking for SH-3-based MPUs by testing PLCR writing access. + saved_plcr = *plcr; + *plcr = 0xffff; + tested_plcr = *plcr; + *plcr = saved_plcr; + + // Checking whether we are working with an SH7337 or an SH7355. + if(tested_plcr == 0x00ff) return MPU_SH7337; + if(tested_plcr == 0x0fff) return MPU_SH7355; + + // Looking for SH-4-based MPUs by testing the version registers. This + // needs to have the three upper bytes of the processor version + // register match 0x10300b : + if((*pvr & 0xffffff00) != 0x10300b00) return MPU_Unknown; + + // Now that we have an SH-4-based MPU, checking whether it is SH7305 or + // SH7724. + switch(*prr & 0xfffffff0) + { + case 0x00002c00: + return MPU_SH7305; + case 0x00002200: + return MPU_SH7724; + } + + // By default, the MPU is unknown. + return MPU_Unknown; +} + + + +/* + mpu_init() + Determines the MPU type and stores the result into MPU_CURRENT. +*/ +void mpu_init(void) +{ + MPU_CURRENT = getMPU(); +} diff --git a/src/p7os/cake.exe/libgint/src/rtc/rtc_callback.c b/src/p7os/cake.exe/libgint/src/rtc/rtc_callback.c new file mode 100644 index 0000000..3a69a95 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/rtc/rtc_callback.c @@ -0,0 +1,151 @@ +#include +#include +#include + +// Array holding callback informations. +struct rtc_cb cb_array[RTC_CB_ARRAY_SIZE] = { 0 }; +// Callback identifier (unique). +static int unique_id = 1; +// Current RTC interrupt frequency. +static enum RTCFrequency rtc_freq = RTCFreq_None; +// 256-Hz tick count. This counter is stopped when no callback is registered. +static unsigned elapsed256 = 0; + +/* + rtc_cb_update() + After successful registration or deletion of a callback, updates the + RTC interrupt frequency stored in register RCR2. After update, the + interrupt frequency is high enough to handle all callbacks, but nothing + more (so that no time is wasted handling interrupts that occur too + often). +*/ +static void rtc_cb_update(void) +{ + enum RTCFrequency max = RTCFreq_None; + int n; + + for(n = 0; n < RTC_CB_ARRAY_SIZE; n++) if(cb_array[n].id) + { + if(!max || (cb_array[n].freq && cb_array[n].freq < max)) + max = cb_array[n].freq; + } + + if(rtc_freq == max) return; + rtc_freq = max; + + volatile struct mod_rtc *RTC = isSH3() ? RTC_SH7705 : RTC_SH7305; + RTC->RCR2.BYTE = (rtc_freq << 4) | 0x09; +} + +/* + rtc_cb_add() + Registers a new callback for the RTC. Returns the callback id on + success (positive integer), or one of the following error codes: + -1 Array is full + -2 Invalid parameter + The number of repeats may be set to 0, in which case the callback is + called indefinitely unless the user calls rtc_cb_end(). +*/ +int rtc_cb_add(enum RTCFrequency freq, void (*function)(void), int repeats) +{ + int n = 0; + if(freq == RTCFreq_None || !function || repeats < 0) return -2; + + while(n < RTC_CB_ARRAY_SIZE && cb_array[n].id) n++; + if(n >= RTC_CB_ARRAY_SIZE) return -1; + + cb_array[n].freq = freq; + cb_array[n].callback = function; + cb_array[n].repeats = repeats; + cb_array[n].id = unique_id++; + + rtc_cb_update(); + + return cb_array[n].id; +} + +/* + rtc_cb_end() + Removes the callback with the given id (as returned by rtc_cb_add()) + from the callback array. +*/ +void rtc_cb_end(int id) +{ + int n = 0; + + while(n < RTC_CB_ARRAY_SIZE && cb_array[n].id != id) n++; + if(n >= RTC_CB_ARRAY_SIZE) return; + + cb_array[n].id = 0; + cb_array[n].freq = RTCFreq_None; + cb_array[n].callback = NULL; + cb_array[n].repeats = 0; + + rtc_cb_update(); +} + +/* + rtc_cb_edit() + Changes information related to a callback. This function returns 0 on + success, or one of the following error codes: + -1 Callback does not exist + -2 Invalid parameters + This function never removes a callback. Call rtc_cb_end() for this. +*/ +int rtc_cb_edit(int id, enum RTCFrequency new_freq, + void (*new_function)(void)) +{ + if(new_freq < 0 || new_freq > 7) return -2; + int n = 0; + + while(n < RTC_CB_ARRAY_SIZE && cb_array[n].id != id) n++; + if(n >= RTC_CB_ARRAY_SIZE) return -1; + + cb_array[n].freq = new_freq; + cb_array[n].callback = new_function; + rtc_cb_update(); + + return 0; +} + +/* + rtc_cb_interrupt() + Handles an RTC interrupt. Calls the RTC callbacks if necessary, and + updates the repeat counts. +*/ +void rtc_cb_interrupt(void) +{ + int n; + + int scales[] = { + 1, // 256 Hz + 4, // 64 Hz + 16, // 16 Hz + 64, // 4 Hz + 128, // 2 Hz + 256, // 1 Hz + 512, // 0.5 Hz + }; + // Adding to elapsed256 the number of 256-Hz ticks that correspond to + // the current interrupt frequency, and rounding the result to a + // multiple of this tick number. + elapsed256 = (elapsed256 + scales[rtc_freq]) & ~(scales[rtc_freq] - 1); + + for(n = 0; n < RTC_CB_ARRAY_SIZE; n++) + { + struct rtc_cb *cb = &cb_array[n]; + if(!cb->id || !cb->freq) continue; + + // Only execute callback when the number of elapsed 256-Hz + // ticks reach a multiple that correspond to the callback + // frequency. + if(elapsed256 & (scales[cb->freq] - 1)) continue; + + if(cb->callback) (*cb->callback)(); + if(cb->repeats) + { + if(cb->repeats == 1) rtc_cb_end(cb->id); + else cb->repeats--; + } + } +} diff --git a/src/p7os/cake.exe/libgint/src/rtc/rtc_getTime.c b/src/p7os/cake.exe/libgint/src/rtc/rtc_getTime.c new file mode 100644 index 0000000..5e9f653 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/rtc/rtc_getTime.c @@ -0,0 +1,38 @@ +#include +#include +#include + +/* + integer() + Converts a BCD value to an integer. +*/ +static int integer8(int bcd) +{ + return (bcd & 0x0f) + 10 * (bcd >> 4); +} +static int integer16(int bcd) +{ + return (bcd & 0xf) + 10 * ((bcd >> 4) & 0xf) + 100 * ((bcd >> 8) & 0xf) + + 1000 * (bcd >> 12); +} + +/* + rtc_getTime() + Reads the current time from the RTC. There is no guarantee that the + week day is correct (use the time API for that). +*/ +struct RTCTime rtc_getTime(void) +{ + volatile struct mod_rtc *rtc = isSH3() ? RTC_SH7705 : RTC_SH7305; + struct RTCTime time; + + time.seconds = integer8(rtc->RSECCNT.BYTE); + time.minutes = integer8(rtc->RMINCNT.BYTE); + time.hours = integer8(rtc->RHRCNT.BYTE); + time.month_day = integer8(rtc->RDAYCNT.BYTE); + time.month = integer8(rtc->RMONCNT.BYTE); + time.year = integer16(rtc->RYRCNT.WORD); + time.week_day = rtc->RWKCNT; + + return time; +} diff --git a/src/p7os/cake.exe/libgint/src/rtc/rtc_interrupt.c b/src/p7os/cake.exe/libgint/src/rtc/rtc_interrupt.c new file mode 100644 index 0000000..775a220 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/rtc/rtc_interrupt.c @@ -0,0 +1,15 @@ +#include +#include +#include + +/* + rtc_interrupt() + Handles an RTC interrupt by calling the callback. +*/ +void rtc_interrupt(void) +{ + rtc_cb_interrupt(); + + volatile struct mod_rtc *RTC = isSH3() ? RTC_SH7705 : RTC_SH7305; + RTC->RCR2.PEF = 0; +} diff --git a/src/p7os/cake.exe/libgint/src/rtc/rtc_setTime.c b/src/p7os/cake.exe/libgint/src/rtc/rtc_setTime.c new file mode 100644 index 0000000..d343c51 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/rtc/rtc_setTime.c @@ -0,0 +1,36 @@ +#include +#include +#include + +/* + bcd() + Converts an integer to a BCD value. +*/ +static int bcd8(int integer) +{ + integer %= 100; + return ((integer / 10) << 4) | (integer % 10); +} +static int bcd16(int integer) +{ + integer %= 10000; + return (bcd8(integer / 100) << 8) | bcd8(integer % 100); +} + +/* + rtc_setTime() + Sets the time in the RTC registers. The week day is set to 0 if greater + than 6. Other fields are not checked. +*/ +void rtc_setTime(struct RTCTime time) +{ + volatile struct mod_rtc *rtc = isSH3() ? RTC_SH7705 : RTC_SH7305; + + rtc->RSECCNT.BYTE = bcd8(time.seconds); + rtc->RMINCNT.BYTE = bcd8(time.minutes); + rtc->RHRCNT.BYTE = bcd8(time.hours); + rtc->RDAYCNT.BYTE = bcd8(time.month_day); + rtc->RMONCNT.BYTE = bcd8(time.month); + rtc->RYRCNT.WORD = bcd16(time.year); + rtc->RWKCNT = time.week_day < 7 ? time.week_day : 0; +} diff --git a/src/p7os/cake.exe/libgint/src/screen/screen_display.c b/src/p7os/cake.exe/libgint/src/screen/screen_display.c new file mode 100644 index 0000000..c04d7d8 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/screen/screen_display.c @@ -0,0 +1,35 @@ +#include + +/* + screen_display() + + Displays the given vram on the screen. Only bytes can be transferred + through the screen registers, which is unfortunate because most of the + vram-related operations use longword-base operations. +*/ +void screen_display(const void *ptr) +{ + const char *vram = (const char *)ptr; + volatile char *selector = (char *)0xb4000000; + volatile char *data = (char *)0xb4010000; + int line, bytes; + + for(line = 0; line < 64; line++) + { + // Setting the x-address register. + *selector = 4; + *data = line + 0xc0; + + // Setting Y-Up mode. + *selector = 1; + *data = 1; + + // Setting y-address. + *selector = 4; + *data = 0; + + // Selecting data write register 7 and sending a line's bytes. + *selector = 7; + for(bytes = 0; bytes < 16; bytes++) *data = *vram++; + } +} diff --git a/src/p7os/cake.exe/libgint/src/setjmp/setjmp.s b/src/p7os/cake.exe/libgint/src/setjmp/setjmp.s new file mode 100644 index 0000000..3b6f910 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/setjmp/setjmp.s @@ -0,0 +1,79 @@ +/* + standard library module: setjmp + + Long jumps. The register contents are saved in a buffer when setjmp() + is called and restored at any time when longjmp() performs the jump. + + This is based on a trick that uses pr ; the user program is resumed + after the setjmp() call when longjmp() is invoked but this is not + setjmp() that returns. longjmp() restores the pr value that was saved + by setjmp() and performs an rts instruction. + + setjmp() returns 0 when called to set up the jump point and a non-zero + value when invoked through a long jump. If 0 is given as return value + to longjmp(), then 1 is returned. +*/ + + .global _setjmp + .global _longjmp + +_setjmp: + /* Getting some free space. */ + add #64, r4 + + /* Saving general-purpose registers. */ + mov.l r15, @-r4 + mov.l r14, @-r4 + mov.l r13, @-r4 + mov.l r12, @-r4 + mov.l r11, @-r4 + mov.l r10, @-r4 + mov.l r9, @-r4 + mov.l r8, @-r4 + + /* Saving control and system registers. */ + stc.l sr, @-r4 + stc.l ssr, @-r4 + stc.l spc, @-r4 + stc.l gbr, @-r4 + stc.l vbr, @-r4 + sts.l mach, @-r4 + sts.l macl, @-r4 + sts.l pr, @-r4 + + /* This function always return 0. The cases where setjmp() seems to + return non-zero values, when a long jump has just been performed, is + actually handled by longjmp(). */ + rts + mov #0, r0 + + + +_longjmp: + /* Restoring the system and control registers. Restoring pr is actually + what performs the jump -- and makes the user program think that + setjmp() has returned. */ + lds.l @r4+, pr + lds.l @r4+, macl + lds.l @r4+, mach + ldc.l @r4+, vbr + ldc.l @r4+, gbr + ldc.l @r4+, spc + ldc.l @r4+, ssr + ldc.l @r4+, sr + + /* Restoring the general-purpose registers. */ + mov.l @r4+, r8 + mov.l @r4+, r9 + mov.l @r4+, r10 + mov.l @r4+, r11 + mov.l @r4+, r12 + mov.l @r4+, r13 + mov.l @r4+, r14 + mov.l @r4+, r15 + + /* Preventing return value from being 0 (must be at least 1). */ + tst r5, r5 + movt r0 + rts + add r5, r0 diff --git a/src/p7os/cake.exe/libgint/src/stdio/snprintf.c b/src/p7os/cake.exe/libgint/src/stdio/snprintf.c new file mode 100644 index 0000000..6c5eb20 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/stdio/snprintf.c @@ -0,0 +1,20 @@ +#include +#include +#include + +/* + snprintf() + Prints to a string with a size limit. +*/ +int snprintf(char *str, size_t size, const char *format, ...) +{ + va_list args; + va_start(args, format); + + int x = __printf(size, format, args); + memcpy(str, __stdio_buffer, x + 1); + + + va_end(args); + return x; +} diff --git a/src/p7os/cake.exe/libgint/src/stdio/sprintf.c b/src/p7os/cake.exe/libgint/src/stdio/sprintf.c new file mode 100644 index 0000000..f0a018e --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/stdio/sprintf.c @@ -0,0 +1,19 @@ +#include +#include +#include + +/* + sprintf() + Prints to a string. +*/ +int sprintf(char *str, const char *format, ...) +{ + va_list args; + va_start(args, format); + + int x = __printf(0, format, args); + memcpy(str, __stdio_buffer, x + 1); + + va_end(args); + return x; +} diff --git a/src/p7os/cake.exe/libgint/src/stdio/stdio_format.c b/src/p7os/cake.exe/libgint/src/stdio/stdio_format.c new file mode 100644 index 0000000..5a8ecfb --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/stdio/stdio_format.c @@ -0,0 +1,895 @@ +#include +#include + +#include +#include +#include + +/* + Internal buffer. + + Using a buffer *really* simplifies everything. But it also has + disadvantages, such as some memory loss and limited output size. + + So, in case we find a possibility to get rid of this buffer, we will + just have to change function character(), which is for now the only + function that directly accesses the buffer. +*/ +char __stdio_buffer[__stdio_buffer_size]; + + + +/* + Composed types for format definition. + + The Format structure handles everything in a format: data type, value, + alternative forms, alignment and character number, precision... there + are mainly a data type (altered by a size option), a value to print + and a number of characters. + + Other options are handled by The FormatFlags enumeration. See the + description of functions __printf() for further description on option + precedence and influence. +*/ + +enum FormatFlags +{ + // Alternatives forms add '0' and '0x' prefixes in octal and + // hexadecimal bases. (#) + Alternative = 1, + // Under specific conditions, zero-padding may be used instead of + // whitespace-padding. (0) + ZeroPadded = 2, + // Left alignment specifies that additional spaces should be added + // after the value instead of before. (-) + LeftAlign = 4, + // In numeric display, this forces a blank sign to be written before + // positive values. ( ) + BlankSign = 8, + // In numeric display, this forces an explicit sign in all cases. This + // option overrides BlankSign. (+) + ForceSign = 16 +}; + +struct Format +{ + // Format type, one of 'diouxXcs' ('eEfFgGaApnm' still to add). + char type; + // Format size, one of 'l', 'h', 'i' ('i' means 'hh'). + char size; + + // Number of characters printed. + int characters; + // Number of digits after the dot. + int precision; + + // Various flags. + enum FormatFlags flags; + + // Value to output. + union + { + // Signed int with formats %c, %d and %i. + signed int _int; + // Unsigned int with formats %o, %u, %x and %X. + unsigned int _unsigned; + // Double with formats %f, %F, %e, %E, %g and %G. +// double _double; + // String pointer with format %s. + const char *_pointer; + }; +}; + + + +//--- +// Static declarations. +//--- + +// Outputs a character in the buffer. Updates counters. +static void character(int c); +// Outputs n timers the given character. +static void character_n(int c, int n); +// Reads a format from the given string pointer address (must begin with '%'). +static struct Format get_format(const char **pointer); +// Computes the number of spaces and zeros to add to the bare output. +static void get_spacing(struct Format format, int *begin_spaces, int *sign, + int *zeros, int length, int *end_spaces); + +static void format_di (struct Format format); +static void format_u (struct Format format); +static void format_oxX (struct Format format); +// static void format_e (struct Format format); +static void format_c (struct Format format); +static void format_s (struct Format format); +static void format_p (struct Format format); + +#define abs(x) ((x) < 0 ? -(x) : (x)) + +// Number of characters currently written. +static size_t written = 0; +// Total number of function calls (characters theoretically written). +static size_t total = 0; +// Maximum number of characters to output. +static size_t max = 0; + + + +/* + character() + Outputs a character to the buffer. This function centralizes all the + buffer interface, so that if we come to remove it for property reasons, + we would just have to edit this function. + + Static variables written and total are both needed, because the + terminating NUL character may be written after the maximum has been + reached. + In other words, when the function ends, we need to have a variable + counting the current position in the buffer (written), and one other + containing the total number of theoretic characters (total) because + these two values may be different. + + Of course the three variables need to be initialized before using this + function. +*/ +static void character(int c) +{ + // If there is space left in the buffer. + if(written < max - 1) __stdio_buffer[written++] = c; + total++; +} + +/* + character_n() + Outputs n times the same character. Thought to be used to output spaces + or zeros without heavy loops. +*/ +static void character_n(int c, int n) +{ + int i = 0; + while(i++ < n) character(c); +} + +/* + get_format() + Reads the format from the given string pointer and returns a + corresponding Format structure. The string pointer points to is also + modified, so that is points to the first character after the format. + This function expects **pointer == '%'. +*/ +static struct Format get_format(const char **pointer) +{ + const char *convspec = "diouxXeEfFgGaAcspnm"; + struct Format format; + + const char *string = *pointer, *ptr; + int c, i; + + // Moving the string pointer after the '%' character. + string++; + + // Initializing structure. + format.type = 0; + format.size = 0; + format.flags = 0; + // Initializing digit counts. + format.characters = -1; + format.precision = -1; + + // Parsing the format string. Testing each character until a + // conversion specifier is found. + while((c = *string)) + { + // Looking for a conversion specifier. + ptr = strchr(convspec, c); + if(ptr) + { + format.type = *ptr; + break; + } + + // Looking for a left precision string (number of digits before + // the dot), introduced by a non-null digit. + if(c >= '1' && c <= '9') + { + format.characters = 0; + for(i = 0; i < 9 && isdigit(*string); string++) + { + format.characters *= 10; + format.characters += *string - '0'; + } + + // As pointer is now pointing to the next character, + // we want to try tests again from the beginning. + continue; + } + + // Looking for a right precision string (number of digits after + // the dot), introduced by a point. + if(c == '.') + { + string++; + if(!isdigit(*string)) continue; + + format.precision = 0; + for(i = 0; i < 9 && isdigit(*string); string++) + { + format.precision *= 10; + format.precision += *string - '0'; + } + + // As pointer is now pointing on the next character, + // we want to try tests again from the beginning. + continue; + } + + // Handling predefined characters. + switch(*string) + { + // Length modifiers. + case 'h': + format.size = 'h' + (format.size == 'h'); + break; + case 'l': + case 'L': + case 'z': + case 't': + format.size = *string; + break; + + // Flags. + case '#': + format.flags |= Alternative; + break; + case '0': + format.flags |= ZeroPadded; + break; + case '-': + format.flags |= LeftAlign; + break; + case ' ': + format.flags |= BlankSign; + break; + case '+': + format.flags |= ForceSign; + break; + } + + string++; + } + + // If the format hasn't ended, the type attribute is left to zero and + // the main loop will handle failure and break. Nothing has to be done + // here. + + *pointer = string + 1; + return format; +} + +/* + get_spacing() + Computes the arrangement of beginning spaces, sign, zeros, pure value + and ending spaces in formats. + This formatting follows a recurrent model which is centralized in this + function. Note that you can't have `begin_spaces` and `end_spaces` + both non-zero: at least one is null. +*/ +static void get_spacing(struct Format format, int *begin_spaces, int *sign, + int *zeros, int length, int *end_spaces) +{ + // Using a list of types involving a sign. + const char *signed_types = "dieEfFgGaA"; + int spaces; + // Digits represents pure output + zeros (don't mix up with the *real* + // displayed digits). + int digits; + int left = format.flags & LeftAlign; + + // Getting the total number of digits. + switch(format.type) + { + // In integer display, the number of digits output is specified in the + // precision. + case 'd': + case 'i': + case 'u': + digits = format.precision; + if(digits < length) digits = length; + break; + + // Binary display has prefixes such as '0' and '0x'. + case 'o': + case 'x': + case 'X': + digits = format.precision; + if(digits == -1) digits = length; + + if(format.flags & Alternative) + { + int hexa = (format.type == 'x' || format.type == 'X'); + digits += 1 + hexa; + length += 1 + hexa; + } + if(digits < length) digits = length; + break; + + // Other formats do not have additional zeros. + default: + digits = length; + break; + } + + if(sign) + { + if(strchr(signed_types, format.type)) + { + if(format.flags & BlankSign) *sign = ' '; + // Option '+' overrides option ' '. + if(format.flags & ForceSign) *sign = '+'; + // And of course negative sign overrides everything! + if(format.type == 'd' || format.type == 'i') + { + if(format._int < 0) *sign = '-'; + } +// else if(format._double < 0) *sign = '-'; + + } + else *sign = 0; + } + + // Computing the number of spaces. + spaces = format.characters - digits; + // Computing the number of zeros. + *zeros = digits - length; + + // Removing a space when a sign appears. + if(sign && *sign) spaces--; + + // Option '0' translates spaces to zeros, but only if no precision is + // specified; additionally, left alignment overrides zero-padding. + if(!left && format.precision == -1 && format.flags & ZeroPadded) + { + *zeros += spaces; + spaces = 0; + } + + // Setting the correct spaces number to the computed value, depending + // on the left alignment parameter. + *begin_spaces = left ? 0 : spaces; + *end_spaces = left ? spaces : 0; +} + +/* + __printf() + + Basic buffered formatted printing function. Fully-featured, so that + any call to a printf()-family function can be performed by __printf(). + + It always returns the number of characters of the theoretic formatted + output. The real output may be limited in size by the given size + argument when working with nprintf()-family functions, or the internal + buffer itself. + + The Flags structure isn't necessary, but it simplifies a lot format + argument handling (because flag effects depend on format type, which + is unknown when the flags are read). Also, length modifiers 'hh' is + stored as 'i' to simplify structure handling. 'll' is not supported. + Support for format '%lf' (C99) is planned. + + Generic information on options precedence and influence. + - Number of characters and precision represent different lengths + depending on the data type. + - '#' is independent. + - '+' overrides ' '. + - In integer display, '0' replaces spaces to zeros, only if no + precision (decimal digit number) is specified. + - '-' also overrides it, forcing whitespaces to be written at the end. + + Limits of function. + - Internal buffer size (there should be a loop to allow larger data). + - Precision values (format %a.b) are limited to 127. + + Unsupported features. + - ''' (single quote) (thousands grouping) + - 'I' (outputs locale's digits (glibc 2.2)) + - Length modifiers 'll' and 'q' (libc 5 and 4.4 BSD) + - This is not really a feature but incorrect characters in formats are + ignored and don't invalidate the format. +*/ +int __printf(size_t size, const char *string, va_list args) +{ + struct Format format; + + // Avoiding overflow by adjusting the size argument. + if(!size || size > __stdio_buffer_size) size = __stdio_buffer_size; + + // Initializing character() variables. + written = 0; + total = 0; + max = size; + + // Parsing the format string. At each iteration, a literal character, a + // '%%' identifier or a format is parsed. + while(*string) + { + // Literal text. + if(*string != '%') + { + character(*string++); + continue; + } + + // Literal '%'. + if(string[1] == '%') + { + string += 2; + character('%'); + continue; + } + + // Getting the format. + format = get_format(&string); + if(!format.type) break; + + /* Some debugging... + printf( + "Format found :%s%c%c, options %d, and %d.%d " + "digits\n", + format.size ? " " : "", + format.size ? format.size : ' ', + format.type, + format.flags, + format.digits, + format.mantissa + ); */ + + switch(format.type) + { + // Signed integers. + case 'd': + case 'i': + format._int = va_arg(args, signed int); + + // Reducing value depending on format size. + if(format.size == 'h') format._int &= 0x0000ffff; + if(format.size == 'i') format._int &= 0x000000ff; + + format_di(format); + break; + + // Unsigned integers. + case 'u': + format._unsigned = va_arg(args, unsigned int); + format_u(format); + break; + case 'o': + case 'x': + case 'X': + format._unsigned = va_arg(args, unsigned int); + format_oxX(format); + break; + +/* // Exponent notation. + case 'e': + case 'E': + format._double = va_arg(args, double); + format_e(format); + break; +*/ + // Characters. + case 'c': + format._int = va_arg(args, signed int) & 0xff; + format_c(format); + break; + + // Strings. + case 's': + format._pointer = va_arg(args, const char *); + format_s(format); + break; + + // Pointers. + case 'p': + format._unsigned = va_arg(args, unsigned int); + format_p(format); + break; + + // Character counter. + case 'n': + *va_arg(args, int *) = written; + break; + } + } + + // Adding a terminating NUL character. Function character() should have + // left an empty byte for that. + __stdio_buffer[written] = 0; + return total; +} + +/* + format_di() + + Subroutine itoa(). Writes the given signed integer to the internal + buffer, trough function character(). + It is used by conversion specifiers 'd' and 'i'. + Options '#' and '0' have no effect. +*/ +static void format_di(struct Format format) +{ + // In integer display, character number includes pure digits and + // additional zeros and spacing. + // The precision represents the number of digits (pure digits and + // zeros) to print. + // For example: ' 0004', pure digits: 1, digits: 4, characters: 5. + + int sign = 0; + signed int x = format._int; + // Using integers to store the number pure digits and additional spaces + // and zeros. + int bspaces, zeros, digits = 0, espaces; + // Using a multiplier to output digit in the correct order. + int multiplier = 1; + + // Returning if the argument is null with an explicit precision of + // zero, but only if there are no spaces. + if(!x && format.characters == -1 && !format.precision) return; + + + + //--- + // Computations. + //--- + + // Computing the number of digits and the multiplier. + x = abs(format._int); + if(!x) digits = 1; + else while(x) + { + digits++; + x /= 10; + if(x) multiplier *= 10; + } + + // Getting the corresponding spacing. + get_spacing(format, &bspaces, &sign, &zeros, digits, &espaces); + + + + //--- + // Output. + //--- + + character_n(' ', bspaces); + if(sign) character(sign); + character_n('0', zeros); + + x = abs(format._int); + // Writing the pure digits, except if the value is null with an + // explicit precision of zero. + if(x || format.precision) while(multiplier) + { + character((x / multiplier) % 10 + '0'); + multiplier /= 10; + } + + character_n(' ', espaces); +} + +/* + format_u() + Unsigned integers in base 10. Options ' ', '+' and '#' have no effect. +*/ +static void format_u(struct Format format) +{ + int bspaces, zeros, digits = 0, espaces; + int x = format._unsigned; + int multiplier = 1; + + // Computing number of digits. + if(!x) digits = 1; + else while(x) + { + digits++; + x /= 10; + if(x) multiplier *= 10; + } + + get_spacing(format, &bspaces, NULL, &zeros, digits, &espaces); + + //--- + // Output. + //--- + + character_n(' ', bspaces); + character_n('0', zeros); + + x = format._unsigned; + while(multiplier) + { + character('0' + (x / multiplier) % 10); + multiplier /= 10; + } + + character_n(' ', espaces); +} + +/* + format_oxX() + Unsigned integers in base 8 or 16. + Since the argument is unsigned, options ' ' and '+' have no effect. + Option '#' adds prefix '0' in octal or '0x' in hexadecimal. +*/ +static void format_oxX(struct Format format) +{ + // In unsigned display, the digit number specifies the minimal number + // of characters that should be output. If the prefix (alternative + // form) is present, it is part of this count. + // Integer part and decimal part digit numbers behave the same way as + // in signed integer display. + + // Using integers to store the number of digits, zeros and spaces. + int bspaces, zeros, digits = 0, espaces; + unsigned int x = format._unsigned; + int multiplier = 0, shift, mask; + int c, disp; + + + + //--- + // Computations. + //--- + + shift = (format.type == 'o') ? (3) : (4); + mask = (1 << shift) - 1; + disp = (format.type == 'x') ? (39) : (7); + + // Computing number of digits. + if(!x) digits = 1; + else while(x) + { + digits++; + x >>= shift; + if(x) multiplier += shift; + } + + // Getting the spacing distribution. + get_spacing(format, &bspaces, NULL, &zeros, digits, &espaces); + + + + //--- + // Output. + //--- + + character_n(' ', bspaces); + x = format._unsigned; + + // Writing the alternative form prefix. + if(format.flags & Alternative && x) + { + character('0'); + if(format.type != 'o') character(format.type); + } + + character_n('0', zeros); + + // Extracting the digits. + while(multiplier >= 0) + { + c = (x >> multiplier) & mask; + c += '0' + (c > 9) * disp; + + character(c); + multiplier -= shift; + } + + character_n(' ', espaces); +} + +/* + format_e() + Exponent notation. Option '#' has no effect. + +static void format_e(struct Format format) +{ + // In exponent display, the precision is the number of digits after the + // dot. + + // Using an integer to store the number exponent. + int exponent = 0; + // Using a double value for temporary computations, and another to + // store the format parameter. + double tmp = 1, x = format._double; + // Using spacing variables. Default length is for '0.e+00'; + int bspaces, zeros, sign, length = 6, espaces; + // Using an iterator and a multiplier. + int i, mul; + + + + //--- + // Computations. + //--- + + // Computing the exponent. For positive exponents, increasing until + // the temporary value gets greater than x. + if(x > 1) + { + // Looping until we haven't reached a greater exponent. + while(tmp < x) + { + // Incrementing the exponent. + exponent++; + // Multiplying the test value. + tmp *= 10; + } + // Removing an additional incrementation. + exponent--; + } + // For negative exponents, decreasing until it's lower. + else while(tmp > x) + { + // Decrementing the exponent. + exponent--; + // Dividing the test value. + tmp *= 0.1; + } + + // Adding a character if the exponent is greater that 100. + if(exponent >= 100) length++; + // Adding another one if it's greater than 1000. + if(exponent >= 1000) length++; + + // Adjusting the format precision, defaulting to 6. + if(format.precision == -1) format.precision = 6; + // Adding the decimal digits. + length += format.precision; + + // Getting the space repartition. + get_spacing(format, &bspaces, &sign, &zeros, length, &espaces); + + + + //--- + // Output. + //--- + + // Writing the beginning whitespaces. + character_n(' ', bspaces); + // Writing the sign if existing. + if(sign) character(sign); + // Writing the zeros. + character_n('0', zeros); + + // Initializing x. + x = abs(format._double) / tmp; + // Writing the first digit. + character(x + '0'); + character('.'); + + // Writing the decimal digits. + for(i = 0; i < format.precision; i++) + { + // Multiplying x by 10 and getting rid of the previous digit. + x = (x - (int)x) * 10; + // Writing the current digit. + character(x + '0'); + } + + // Writing the exponent letter and its sign. + character(format.type); + character(exponent < 0 ? '-' : '+'); + + // Getting a positive exponent. + exponent = abs(exponent); + + // Using a multiplier for the exponent. + if(exponent >= 1000) mul = 1000; + else if(exponent >= 100) mul = 100; + else mul = 10; + + // Writing the exponent characters. + while(mul) + { + // Writing the next character. + character((exponent / mul) % 10 + '0'); + // Dividing the multiplier. + mul *= 0.1; + } + + // Writing the ending whitespaces if left-aligned. + character_n(' ', espaces); +} +*/ + +/* + format_c() + Character output. Only handles left alignment and spacing. + Options '#', '0', ' ' and '+', as well as mantissa digit number, have + no effect. +*/ +static void format_c(struct Format format) +{ + // In character display, the digit number represents the number of + // characters written, including the argument and additional + // whitespaces. + + int spaces = format.characters - 1; + int left = format.flags & LeftAlign; + + if(!left) character_n(' ', spaces); + character(format._int & 0xff); + if(left) character_n(' ', spaces); +} + +/* + format_s() + String output. Spaces if needed. +*/ +void format_s(struct Format format) +{ + // In string display, the character number specify the minimum size of + // output (padded with whitespaces if needed) and the precision + // specify the maximum number of string characters output. + + int string = format.precision; + int spaces; + + const char *str = format._pointer; + int length, i; + int left = format.flags & LeftAlign; + + // Computing length of string and number of whitespaces. + length = strlen(str); + if(string > length || string == -1) string = length; + spaces = format.characters - string; + + if(!left) character_n(' ', spaces); + for(i = 0; i < string; i++) character(str[i]); + if(left) character_n(' ', spaces); +} + +/* + format_p() + Pointer output. Simple hexadecimal dump. Prints "(nil)" if pointer is + NULL. +*/ +void format_p(struct Format format) +{ + // Pointer display falls back to %#08x in the pointer is non-null, + // "(nil)" otherwise. + + unsigned int x = format._unsigned; + int bspaces, zeros, digits = 0, espaces; + int c, i; + + digits = x ? 10 : 5; + get_spacing(format, &bspaces, NULL, &zeros, digits, &espaces); + + character_n(' ', bspaces); + character_n('0', zeros); + + if(x) + { + character('0'); + character('x'); + for(i = 0; i < 8; i++) + { + c = x >> 28; + c += '0' + 39 * (c > 9); + character(c); + x <<= 4; + } + } + else + { + character('('); + character('n'); + character('i'); + character('l'); + character(')'); + } + + character_n(' ', espaces); +} diff --git a/src/p7os/cake.exe/libgint/src/stdio/vsnprintf.c b/src/p7os/cake.exe/libgint/src/stdio/vsnprintf.c new file mode 100644 index 0000000..0bfafd4 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/stdio/vsnprintf.c @@ -0,0 +1,15 @@ +#include +#include +#include + +/* + vsnprintf() + The most generic formatted printing function around there. +*/ +int vsnprintf(char *str, size_t size, const char *format, va_list args) +{ + int x = __printf(size, format, args); + memcpy(str, __stdio_buffer, x + 1); + + return x; +} diff --git a/src/p7os/cake.exe/libgint/src/stdio/vsprintf.c b/src/p7os/cake.exe/libgint/src/stdio/vsprintf.c new file mode 100644 index 0000000..0571fc0 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/stdio/vsprintf.c @@ -0,0 +1,15 @@ +#include +#include +#include + +/* + vsprintf() + Prints to a string from an argument list. +*/ +int vsprintf(char *str, const char *format, va_list args) +{ + int x = __printf(0, format, args); + memcpy(str, __stdio_buffer, x + 1); + + return x; +} diff --git a/src/p7os/cake.exe/libgint/src/stdlib/calloc.c b/src/p7os/cake.exe/libgint/src/stdlib/calloc.c new file mode 100644 index 0000000..e1b9ac9 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/stdlib/calloc.c @@ -0,0 +1,13 @@ +#include +#include + +/* + calloc() + Allocates 'n' elements of size 'size' and wipes the memory area. + Returns NULL on error. +*/ +void *calloc(size_t n, size_t size) +{ + void *ptr = malloc(n * size); + return ptr ? memset(ptr, 0, n * size) : NULL; +} diff --git a/src/p7os/cake.exe/libgint/src/stdlib/free.c b/src/p7os/cake.exe/libgint/src/stdlib/free.c new file mode 100644 index 0000000..b51d876 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/stdlib/free.c @@ -0,0 +1,20 @@ +#include + +#pragma GCC diagnostic ignored "-Wunused-parameter" + +#ifndef GINT_NO_SYSCALLS +void __free(void *ptr); +#endif + +/* + free() + Frees a memory block allocated by malloc(), calloc() or realloc(). +*/ +void free(void *ptr) +{ + #ifndef GINT_NO_SYSCALLS + __free(ptr); + #endif +} + +#pragma GCC diagnostic pop diff --git a/src/p7os/cake.exe/libgint/src/stdlib/malloc.c b/src/p7os/cake.exe/libgint/src/stdlib/malloc.c new file mode 100644 index 0000000..92366bc --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/stdlib/malloc.c @@ -0,0 +1,27 @@ +#include + +/* + malloc() + Allocates 'size' bytes and returns a pointer to a free memory area. + Returns NULL on error. +*/ + +#ifndef GINT_NO_SYSCALLS + +void *__malloc(size_t size); +void *malloc(size_t size) +{ + return __malloc(size); +} + +#else + +#pragma GCC diagnostic ignored "-Wunused-parameter" +void *malloc(size_t size) +{ + return NULL; +} +#pragma GCC diagnostic pop + +#endif + diff --git a/src/p7os/cake.exe/libgint/src/stdlib/realloc.c b/src/p7os/cake.exe/libgint/src/stdlib/realloc.c new file mode 100644 index 0000000..b98530e --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/stdlib/realloc.c @@ -0,0 +1,25 @@ +#include + +/* + realloc() + Reallocates a memory block and moves its data. +*/ + +#ifndef GINT_NO_SYSCALLS + +void *__realloc(void *ptr, size_t size); +void *realloc(void *ptr, size_t size) +{ + return __realloc(ptr, size); +} + +#else + +#pragma GCC diagnostic ignored "-Wunused-parameter" +void *realloc(void *ptr, size_t size) +{ + return NULL; +} +#pragma GCC diagnostic pop + +#endif diff --git a/src/p7os/cake.exe/libgint/src/stdlib/stdlib_abs.c b/src/p7os/cake.exe/libgint/src/stdlib/stdlib_abs.c new file mode 100644 index 0000000..3e4c4f8 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/stdlib/stdlib_abs.c @@ -0,0 +1,13 @@ +#include +#undef abs +#undef labs + +int abs(int x) +{ + return (x < 0) ? (-x) : x; +} + +long labs(long x) +{ + return (x < 0) ? (-x) : x; +} diff --git a/src/p7os/cake.exe/libgint/src/stdlib/stdlib_div.c b/src/p7os/cake.exe/libgint/src/stdlib/stdlib_div.c new file mode 100644 index 0000000..77f22a1 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/stdlib/stdlib_div.c @@ -0,0 +1,29 @@ +#include + +/* + div() + Computes the integer division of numerator by denominator. +*/ +div_t div(int numerator, int denominator) +{ + div_t result; + + result.quot = numerator / denominator; + result.rem = numerator - result.quot * denominator; + + return result; +} + +/* + ldiv() + Computes the integer division of two long integers. +*/ +ldiv_t ldiv(long numerator, long denominator) +{ + ldiv_t result; + + result.quot = numerator / denominator; + result.rem = numerator - result.quot * denominator; + + return result; +} diff --git a/src/p7os/cake.exe/libgint/src/stdlib/stdlib_rand.c b/src/p7os/cake.exe/libgint/src/stdlib/stdlib_rand.c new file mode 100644 index 0000000..d5c17a6 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/stdlib/stdlib_rand.c @@ -0,0 +1,14 @@ +#include + +static unsigned int seed = 1; + +void srand(unsigned int new_seed) +{ + seed = new_seed; +} + +int rand(void) +{ + seed = seed * 1103515245 + 12345; + return seed & 0x7fffffff; +} diff --git a/src/p7os/cake.exe/libgint/src/string/memcpy.c b/src/p7os/cake.exe/libgint/src/string/memcpy.c new file mode 100644 index 0000000..d78d1f6 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/string/memcpy.c @@ -0,0 +1,76 @@ +#include +#include + +/* + memcpy() + Copies a memory area. A smart copy is performed if possible. +*/ +void *memcpy(void *d, const void *s, size_t n) +{ + uint8_t *dest = (uint8_t *)d; + const uint8_t *src = (const uint8_t *)s; + + // A long-based copy needs the source and destination to be 4-aligned + // at the same time. + if(((intptr_t)dest & 3) == ((intptr_t)src & 3)) + { + // Getting to a long offset. + while((intptr_t)dest & 3) + { + *dest++ = *src++; + n--; + } + + // Copying groups of four bytes. + while(n >= 4) + { + *((uint32_t *)dest) = *((const uint32_t *)src); + + dest += 4, src += 4; + n -= 4; + } + + // Ending the copy. + while(n) + { + *dest++ = *src++; + n--; + } + } + + // Or we could try a word-based copy. + else if(((intptr_t)dest & 1) == ((intptr_t)src & 1)) + { + // Getting to a word offset. + if((intptr_t)dest & 1) + { + *dest++ = *src++; + n--; + } + + // Copying groups of two bytes. + while(n >= 2) + { + *((uint16_t *)dest) = *((const uint16_t *)src); + + dest += 2, src += 2; + n -= 2; + } + + // Ending the copy. + while(n) + { + *dest++ = *src++; + n--; + } + } + + // In some cases we can just perform a raw copy. + else while(n) + { + *dest++ = *src++; + n--; + } + + return d; +} diff --git a/src/p7os/cake.exe/libgint/src/string/memset.c b/src/p7os/cake.exe/libgint/src/string/memset.c new file mode 100644 index 0000000..7236516 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/string/memset.c @@ -0,0 +1,48 @@ +#include +#include + +/* + memset() + Sets the contents of a memory area. A smart copy is performed. +*/ +void *memset(void *d, int byte, size_t byte_number) +{ + uint8_t *dest = (uint8_t *)d; + unsigned short word = (byte << 8) | byte; + unsigned int longword = (word << 16) | word; + + // When the area is small, simply copying using byte operations. The + // minimum length used for long operations must be at least 3. + if(byte_number < 8) + { + while(byte_number) + { + *dest++ = byte; + byte_number--; + } + + return d; + } + + // Reaching a long offset. + while((intptr_t)dest & 3) + { + *dest++ = byte; + byte_number--; + } + // Copying using long operations. + while(byte_number >= 4) + { + *((uint32_t *)dest) = longword; + dest += 4; + byte_number -= 4; + } + // Ending the copy. + while(byte_number) + { + *dest++ = byte; + byte_number--; + } + + return d; +} diff --git a/src/p7os/cake.exe/libgint/src/string/strchr.c b/src/p7os/cake.exe/libgint/src/string/strchr.c new file mode 100644 index 0000000..7954fcf --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/string/strchr.c @@ -0,0 +1,11 @@ +#include + +/* + strchr + Searches a character in a string. +*/ +const char *strchr(const char *str, int value) +{ + while(*str && *str != value) str++; + return *str ? str : NULL; +} diff --git a/src/p7os/cake.exe/libgint/src/string/strcpy.c b/src/p7os/cake.exe/libgint/src/string/strcpy.c new file mode 100644 index 0000000..7659120 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/string/strcpy.c @@ -0,0 +1,11 @@ +#include + +/* + strcpy() + Copies a string to another. +*/ +char *strcpy(char *destination, const char *source) +{ + size_t length = strlen(source); + return memcpy(destination, source, length); +} diff --git a/src/p7os/cake.exe/libgint/src/string/strlen.c b/src/p7os/cake.exe/libgint/src/string/strlen.c new file mode 100644 index 0000000..7b5a9a1 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/string/strlen.c @@ -0,0 +1,12 @@ +#include + +/* + strlen() + Returns the length of a string. +*/ +size_t strlen(const char *str) +{ + int len = 0; + while(str[len]) len++; + return len; +} diff --git a/src/p7os/cake.exe/libgint/src/string/strncpy.c b/src/p7os/cake.exe/libgint/src/string/strncpy.c new file mode 100644 index 0000000..98422fa --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/string/strncpy.c @@ -0,0 +1,20 @@ +#include + +/* + strncpy() + Copies part of a string to another. +*/ +char *strncpy(char *destination, const char *source, size_t size) +{ + size_t length = strlen(source); + + if(length >= size) + { + return memcpy(destination, source, size); + } + else + { + memset(destination + length, 0, size - length); + return memcpy(destination, source, length); + } +} diff --git a/src/p7os/cake.exe/libgint/src/tales/tales_configuration.c b/src/p7os/cake.exe/libgint/src/tales/tales_configuration.c new file mode 100644 index 0000000..8b00345 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/tales/tales_configuration.c @@ -0,0 +1,15 @@ +#include +#include + +/* + text_configure() + Sets the font and mode to use for the following print operations. +*/ +void text_configure(struct Font *next_font, enum Color next_color) +{ + extern Font gint_font_system; + if(next_font) font = next_font; + else font = &gint_font_system; + + color = next_color; +} diff --git a/src/p7os/cake.exe/libgint/src/tales/tales_gray.c b/src/p7os/cake.exe/libgint/src/tales/tales_gray.c new file mode 100644 index 0000000..4b9b02a --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/tales/tales_gray.c @@ -0,0 +1,45 @@ +#include +#include +#include + +void operate_gray(OPERATE_ARGS) +{ + int *vl = gray_lightVRAM(); + int *vd = gray_darkVRAM(); + int vram_offset = (x >> 5) + (y << 2); + uint32_t op; + int i; + + for(i = 0; i < height; i++) + { + op = operators[i]; + + switch(color) + { + case Color_White: + vl[vram_offset] &= ~op; + vd[vram_offset] &= ~op; + break; + case Color_Light: + vl[vram_offset] |= op; + vd[vram_offset] &= ~op; + break; + case Color_Dark: + vl[vram_offset] &= ~op; + vd[vram_offset] |= op; + break; + case Color_Black: + vl[vram_offset] |= op; + vd[vram_offset] |= op; + break; + case Color_Invert: + vl[vram_offset] ^= op; + vd[vram_offset] ^= op; + break; + default: + break; + } + + vram_offset += 4; + } +} diff --git a/src/p7os/cake.exe/libgint/src/tales/tales_internals.c b/src/p7os/cake.exe/libgint/src/tales/tales_internals.c new file mode 100644 index 0000000..dbef3dd --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/tales/tales_internals.c @@ -0,0 +1,278 @@ +#include +#include +#include +#include +#include + +struct Font *font; +enum Color color; + +/* + tales_init() + Configures tales with the default font (which is part of gint). +*/ +void tales_init(void) +{ + text_configure(NULL, Color_Black); +} + +/* + getCharacterIndex() + Returns the index of a character in a font data area depending on the + font format and the size of the characters. Returns the index in the + data area, as long array, or -1 when the character does not belong to + the font format set. +*/ +int getCharacterIndex(int c) +{ + const char *data = (const char *)&font->glyphs; + int index, current; + int offset; + int width, bits; + + c &= 0x7f; + + + + // Getting the character index in the glyph array. + + if(font->format == FontFormat_Ascii) index = c; + else if(font->format == FontFormat_Print) index = c - 32; + + else switch(font->format) + { + case FontFormat_Numeric: + if(!isdigit(c)) return -1; + index = c - '0'; + break; + case FontFormat_LowerCase: + if(!islower(c)) return -1; + index = c - 'a'; + break; + case FontFormat_UpperCase: + if(!isupper(c)) return -1; + index = c - 'A'; + break; + case FontFormat_Letters: + if(!isalpha(c)) return -1; + index = c - 'A' - ('a' - 'z') * (c >= 'a'); + break; + case FontFormat_Common: + if(!isalnum(c)) return -1; + index = c - '0' - ('A' - '9') * (c >= 'A') - + ('a' - 'z') * (c >= 'a'); + break; + case FontFormat_Unknown: + default: + return -1; + } + + + + // Reaching the character offset. + + current = index & ~7; + offset = font->index[current >> 3]; + + while(current < index) + { + width = data[offset << 2]; + bits = font->data_height * width + 8; + + offset += (bits + 31) >> 5; + current++; + } + + return offset; +} + +/* + operate() + Operates on the vram using the given operators. The x-coordinate should + be a multiple of 32. There should be `height` operators. +*/ +void operate_mono(OPERATE_ARGS) +{ + int *vram = display_getCurrentVRAM(); + int vram_offset = (x >> 5) + (y << 2); + uint32_t op; + int i; + + for(i = 0; i < height; i++) + { + op = operators[i]; + + switch(color) + { + case Color_White: + vram[vram_offset] &= ~op; + break; + case Color_Black: + vram[vram_offset] |= op; + break; + case Color_Invert: + vram[vram_offset] ^= op; + break; + default: + break; + } + + vram_offset += 4; + } +} + +/* + update() + Updates the operators using the given glyph. The operation will not be + complete if there are not enough bits available in the operator data. + In this case the offset will become negative, which means that the + calling procedure has to call operate() and re-call update(). + `available` represents the number of free bits in the operators (lower + bits). + Returns the number of bits available after the operation. If it's + negative, call operate() and update() again. +*/ +int update(uint32_t *operators, int height, int available, + uint32_t *glyph) +{ + // Glyph width. + int width = glyph[0] >> 24; + int i; + + // The glyph mask extracts 'width' bits at the left. The partial mask + // is used when there are less than 'width' bits available in the + // current data longword. + uint32_t glyph_mask = 0xffffffff << (32 - width); + uint32_t partial_mask; + + int shift; + uint32_t line; + + // Current data longword, next data array index, and number of bits + // still available in 'data'. + uint32_t data = glyph[0] << 8; + int data_index = 1; + int bits_available = 24; + + for(i = 0; i < height; i++) + { + shift = 32 - available; + + // Getting the next 'width' bits. In some cases these bits will + // intersect two different longs. + line = data & glyph_mask; + line = (shift >= 0) ? (line >> shift) : (line << -shift); + operators[i] |= line; + + data <<= width; + bits_available -= width; + + // Continue until they do. + if(bits_available >= 0) continue; + + // Computing a special mask that extracts just the number of + // bits missing, and loading a new data longword. + partial_mask = 0xffffffff << (32 + bits_available); + data = glyph[data_index++]; + shift += width + bits_available; + + if(shift <= 31) + { + line = data & partial_mask; + line = (shift >= 0) ? (line >> shift) : + (line << -shift); + operators[i] |= line; + } + + data <<= -bits_available; + bits_available += 32; + } + + return available - width; +} + +/* + render() + Renders text without any formatting analysis, using the given operation + function. +*/ +void render(int x, int y, const char *str, void (*op)(OPERATE_ARGS)) +{ + // Operator data, and number of available bits in the operators (which + // is the same for all operators, since they are treated equally). + uint32_t *operators; + int available; + + // Raw glyph data, each glyph being represented by one or several + // longwords, and an index in this array. + uint32_t *data = (uint32_t *)font->glyphs; + int index; + + // Height of each glyph. This value is constant because the storage + // format requires it: it allows greater optimization. + int height; + + int i; + + + + if(!font) return; + + // Allocating data. There will be one operator for each line. + height = font->data_height; + if(x > 127 || y > 63 || y <= -height) return; + if(y + height > 64) height = 64 - y; + + operators = alloca(height * sizeof(uint32_t)); + for(i = 0; i < height; i++) operators[i] = 0; + if(!operators) return; + + // Computing the initial operator offset to have 32-aligned operators. + // This allows to write directly video ram longs instead of having to + // shift operators, and do all the vram operation twice. + available = 32 - (x & 31); + x &= ~31; + + // Displaying character after another. + while(*str) + { + index = getCharacterIndex(*str++); + if(index < 0) continue; + + // Updating the operators. + available = update(operators, height, available, data + index); + + // Continue until operators are full (this includes an + // additional bit to add a space between each character). + if(available > 1) + { + available--; + continue; + } + + // When operators are full, updating the video ram and + // preparing the operators for another row. + + (*op)(operators, height, x, y); + x += 32; + if(x > 96) break; + + memset(operators, 0, height << 2); + if(available >= 0) + { + available = 31 + available; + continue; + } + + // Finishing update, in case it has been only partially done, + // because there was not enough bits available to fit all the + // information. Also adding a space, assuming that characters + // aren't more than 30 bits wide. + available += 32 + (data[index] >> 24); + available = update(operators, height, available, data + index); + available--; + } + + // Final operation. + if(x <= 96 && available < 32) (*op)(operators, height, x, y); +} diff --git a/src/p7os/cake.exe/libgint/src/tales/tales_print.c b/src/p7os/cake.exe/libgint/src/tales/tales_print.c new file mode 100644 index 0000000..be3d107 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/tales/tales_print.c @@ -0,0 +1,33 @@ +#include +#include +#include + +/* + dprint() + Prints a formatted string. Works the same as printf(). +*/ +void dprint(int x, int y, const char *format, ...) +{ + va_list args; + + va_start(args, format); + __printf(0, format, args); + va_end(args); + + dtext(x, y, __stdio_buffer); +} + +/* + gprint() + Prints a formatted string. Works the same as printf(). +*/ +void gprint(int x, int y, const char *format, ...) +{ + va_list args; + + va_start(args, format); + __printf(0, format, args); + va_end(args); + + gtext(x, y, __stdio_buffer); +} diff --git a/src/p7os/cake.exe/libgint/src/tales/tales_text.c b/src/p7os/cake.exe/libgint/src/tales/tales_text.c new file mode 100644 index 0000000..3729f7d --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/tales/tales_text.c @@ -0,0 +1,20 @@ +#include +#include + +/* + dtext() + Prints the given string, without any analysis. +*/ +void dtext(int x, int y, const char *str) +{ + render(x, y, str, operate_mono); +} + +/* + gtext() + Prints the given raw string. +*/ +void gtext(int x, int y, const char *str) +{ + render(x, y, str, operate_gray); +} diff --git a/src/p7os/cake.exe/libgint/src/time/asctime.c b/src/p7os/cake.exe/libgint/src/time/asctime.c new file mode 100644 index 0000000..ed3d0a3 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/time/asctime.c @@ -0,0 +1,57 @@ +#include + +static char str[26]; + +/* + asctime() + Converts broken-down time to string representation on the form + "Wed Jun 30 21:49:08 1993\n". The returned string is statically + allocated and may be overwritten by any subsequent call to a time + function. +*/ +char *asctime(const struct tm *time) +{ + const char *days[] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" + }, *months[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", + "Sep", "Oct", "Nov", "Dec" + }; + int year = time->tm_year + 1900; + + str[0] = days[time->tm_wday][0]; + str[1] = days[time->tm_wday][1]; + str[2] = days[time->tm_wday][2]; + str[3] = ' '; + + str[4] = months[time->tm_mon][0]; + str[5] = months[time->tm_mon][1]; + str[6] = months[time->tm_mon][2]; + str[7] = ' '; + + str[8] = '0' + (time->tm_mday / 10); + str[9] = '0' + (time->tm_mday % 10); + str[10] = ' '; + + str[11] = '0' + (time->tm_hour / 10); + str[12] = '0' + (time->tm_hour % 10); + str[13] = ':'; + str[14] = '0' + (time->tm_min / 10); + str[15] = '0' + (time->tm_min % 10); + str[16] = ':'; + str[17] = '0' + (time->tm_sec / 10); + str[18] = '0' + (time->tm_sec % 10); + str[19] = ' '; + + str[20] = '0' + (year / 1000); + year %= 1000; + str[21] = '0' + (year / 100); + year %= 100; + str[22] = '0' + (year / 10); + str[23] = '0' + (year % 10); + + str[24] = '\n'; + str[25] = 0; + + return str; +} diff --git a/src/p7os/cake.exe/libgint/src/time/ctime.c b/src/p7os/cake.exe/libgint/src/time/ctime.c new file mode 100644 index 0000000..f3768e0 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/time/ctime.c @@ -0,0 +1,13 @@ +#include + +/* + ctime() + Converts calendar time to string representation on the form + "Wed Jun 30 21:49:08 1993\n". The returned string is statically + allocated and may be overwritten by any subsequent call to a time + function. +*/ +char *ctime(const time_t *timer) +{ + return asctime(gmtime(timer)); +} diff --git a/src/p7os/cake.exe/libgint/src/time/gmtime.c b/src/p7os/cake.exe/libgint/src/time/gmtime.c new file mode 100644 index 0000000..4d84587 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/time/gmtime.c @@ -0,0 +1,45 @@ +#include +#include +#include + +static struct tm tm; + +/* + gmtime() + Converts calendar time to broken-down time. The returned pointer is + statically allocated and may be overwritten by any subsequent call to + a time function. +*/ +struct tm *gmtime(const time_t *timeptr) +{ + time_t t = *timeptr; + div_t d; + int sec; + + tm.tm_year = 1970; + tm.tm_mon = 0; + + sec = daysInMonth(tm.tm_mon, tm.tm_year) * 24 * 3600; + while(t >= sec) + { + t -= sec; + if(++tm.tm_mon == 12) + { + tm.tm_year++; + tm.tm_mon = 0; + } + sec = daysInMonth(tm.tm_mon, tm.tm_year) * 24 * 3600; + } + tm.tm_year -= 1900; + + d = div(sec, 24 * 3600); + tm.tm_mday = d.quot; + d = div(d.rem, 3600); + tm.tm_hour = d.quot; + d = div(d.rem, 60); + tm.tm_min = d.quot; + tm.tm_sec = d.rem; + + mktime(&tm); + return &tm; +} diff --git a/src/p7os/cake.exe/libgint/src/time/mktime.c b/src/p7os/cake.exe/libgint/src/time/mktime.c new file mode 100644 index 0000000..928cf6f --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/time/mktime.c @@ -0,0 +1,68 @@ +#include +#include + +/* + mktime() + Converts broken-down time to calendar time. Computes structure fields + tm_wday and tm_yday using the other fields. Member structures outside + their range are normalized (e.g. 40 October becomes 9 November) and + tm_isdst is set. +*/ +time_t mktime(struct tm *time) +{ + int leaps, yr; + int days, i; + + // Normalizing time. + time->tm_min += (time->tm_sec / 60); + time->tm_hour += (time->tm_min / 60); + time->tm_mday += (time->tm_hour / 24); + time->tm_sec %= 60; + time->tm_min %= 60; + time->tm_hour %= 24; + + // Normalizing date. + days = daysInMonth(time->tm_mon, time->tm_year + 1900); + while(time->tm_mday >= days) + { + time->tm_mday -= days; + if(++time->tm_mon == 12) + { + time->tm_mon = 0; + time->tm_year++; + } + days = daysInMonth(time->tm_mon, time->tm_year + 1900); + } + + // Setting the year day. + days = 0; + for(i = 0; i < time->tm_mon; i++) + days += daysInMonth(i, time->tm_year + 1900); + time->tm_yday = days + time->tm_mday; + + // Setting the week day. The calendar is periodic over 400 years and + // 1601-01-01 was a Monday. + + // Years completely elapsed since last 400n + 1 year (1601-2001-etc). + yr = (time->tm_year + 1900 - 1) % 400; + // Leap years in these yr years. + leaps = (yr / 4) - (yr >= 100) - (yr >= 200) - (yr >= 300); + // Days completely elapsed since last 400n + 1 year, 01-01. + days = 365 * yr + leaps + time->tm_yday; + // Current day of week (1 means Monday 1601-01-01). + time->tm_wday = (1 + days) % 7; + + // This RTC does not seem to have any DST feature. + time->tm_isdst = 0; + + if(time->tm_year + 1900 < 1970) return (time_t)-1; + + // 134774 is the number of days between 1601-01-01 and 1970-01-01. Thus + // days become the number of days elapsed since 1970-01-01. + days -= 134774; + // days may become negative, so add the calendar period. + if(days < 0) days += 146097; + + return (time_t)((24 * 3600) * days + 3600 * time->tm_hour + + 60 * time->tm_min + time->tm_sec); +} diff --git a/src/p7os/cake.exe/libgint/src/time/time.c b/src/p7os/cake.exe/libgint/src/time/time.c new file mode 100644 index 0000000..16189d4 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/time/time.c @@ -0,0 +1,29 @@ +#include +#include + +/* + time() + Returns the current time as calendar time. If you need a broken-down + time, either use the RTC API or gmtime(). However, this function is + already based on mktime() (for hardware reasons) so it would be much + faster to use the RTC API if possible. + If timeptr is not NULL, it is set to the current time, that is, the + value that is returned. +*/ +time_t time(time_t *timeptr) +{ + struct RTCTime rtc = rtc_getTime(); + struct tm tm; + time_t calendar; + + tm.tm_sec = rtc.seconds; + tm.tm_min = rtc.minutes; + tm.tm_hour = rtc.hours; + tm.tm_mday = rtc.month_day; + tm.tm_mon = rtc.month; + tm.tm_year = rtc.year - 1900; + + calendar = mktime(&tm); + if(timeptr) *timeptr = calendar; + return calendar; +} diff --git a/src/p7os/cake.exe/libgint/src/time/time_misc.c b/src/p7os/cake.exe/libgint/src/time/time_misc.c new file mode 100644 index 0000000..88e01fc --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/time/time_misc.c @@ -0,0 +1,21 @@ +#include +#undef difftime + +/* + clock() + Should return elapsed CPU time since beginning of program execution. + This is currently not implemented and returns -1. +*/ +clock_t clock(void) +{ + return (clock_t)-1; +} + +/* + difftime() + Returns the number of seconds between the given points. +*/ +double difftime(time_t end, time_t beginning) +{ + return (double)(end - beginning); +} diff --git a/src/p7os/cake.exe/libgint/src/time/time_util.c b/src/p7os/cake.exe/libgint/src/time/time_util.c new file mode 100644 index 0000000..11c7048 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/time/time_util.c @@ -0,0 +1,28 @@ +#include + +/* + isLeap() + Determines whether the given year is a leap year. +*/ +int isLeap(int year) +{ + int leap = !(year & 3); // Take multiples of 4 + if(!(year % 100)) leap = 0; // Remove multiples of 100 + if(!(year % 400)) leap = 1; // Take multiples of 400 + + return leap; +} + +/* + daysInMonth() + Returns number of days for the given month (between 0 and 11) and year. +*/ +int daysInMonth(int month, int year) +{ + int days[12] = { + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 + }; + + if(month != 1) return days[month]; + return days[month] + isLeap(year); +} diff --git a/src/p7os/cake.exe/libgint/src/timer/timer_get.c b/src/p7os/cake.exe/libgint/src/timer/timer_get.c new file mode 100644 index 0000000..9174164 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/timer/timer_get.c @@ -0,0 +1,25 @@ +#include +#include + +/* + timer_get() + Returns the timer and TSTR register addresses. +*/ +void timer_get(int timer, volatile struct mod_tmu **tmu, + volatile unsigned char **tstr) +{ + // Using SH7705 information for SH-3-based MPUs. + if(isSH3()) + { + if(tstr) *tstr = (volatile unsigned char *)0xfffffe92; + if(tmu) *tmu = (volatile struct mod_tmu *) + (0xfffffe94 + 12 * timer); + } + // Assuming SH7305 by default. + else + { + if(tstr) *tstr = (volatile unsigned char *)0xa4490004; + if(tmu) *tmu = (volatile struct mod_tmu *) + (0xa4490008 + 12 * timer); + } +} diff --git a/src/p7os/cake.exe/libgint/src/timer/timer_interrupt.c b/src/p7os/cake.exe/libgint/src/timer/timer_interrupt.c new file mode 100644 index 0000000..7dd91e4 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/timer/timer_interrupt.c @@ -0,0 +1,28 @@ +#include +#include + +#include + +struct Timer timers[3] = { { NULL, 0 }, { NULL, 0 }, { NULL, 0 } }; + +/* + timer_interrupt() + Handles the interrupt for the given timer. +*/ +void timer_interrupt(int timer) +{ + volatile struct mod_tmu *tmu; + timer_get(timer, &tmu, NULL); + + // Resetting the interrupt flag. + tmu->TCR.UNF = 0; + + // Calling the callback function. + if(timers[timer].callback) timers[timer].callback(); + + // Reducing the number of repetitions left, if not infinite. + if(!timers[timer].repeats) return; + // And stopping it if necessary. + if(timers[timer].repeats == 1) timer_stop(timer); + else timers[timer].repeats--; +} diff --git a/src/p7os/cake.exe/libgint/src/timer/timer_reload.c b/src/p7os/cake.exe/libgint/src/timer/timer_reload.c new file mode 100644 index 0000000..8cc047e --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/timer/timer_reload.c @@ -0,0 +1,22 @@ +#include +#include + +/* + timer_reload() + Reloads the given timer with the given constant. Starts the timer if + it was stopped. +*/ +void timer_reload(int timer, int new_delay) +{ + volatile struct mod_tmu *tmu; + volatile unsigned char *tstr; + int byte = (1 << timer); + timer_get(timer, &tmu, &tstr); + + // Setting the constant and the delay. + tmu->TCOR = new_delay; + tmu->TCNT = new_delay; + + // Starting the timer. + *tstr |= byte; +} diff --git a/src/p7os/cake.exe/libgint/src/timer/timer_start.c b/src/p7os/cake.exe/libgint/src/timer/timer_start.c new file mode 100644 index 0000000..6b7aa1e --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/timer/timer_start.c @@ -0,0 +1,35 @@ +#include +#include + +/* + timer_start() + Configures and starts a timer. +*/ +void timer_start(int timer, int delay, int prescaler, void (*callback)(void), + int repeats) +{ + volatile struct mod_tmu *tmu; + volatile unsigned char *tstr; + int byte = (1 << timer); + + timer_get(timer, &tmu, &tstr); + + // Loading the counter, the constant and the prescaler/ + tmu->TCOR = delay; + tmu->TCNT = delay; + tmu->TCR.TPSC = prescaler; + + // Resetting underflow flag and enabling interruptions. + tmu->TCR.UNF = 0; + tmu->TCR.UNIE = 1; + + // Counting on rising edge (ignored on SH7305). + tmu->TCR.CKEG = 0; + + // Loading the structure information. + timers[timer].callback = callback; + timers[timer].repeats = repeats; + + // Starting the timer. + *tstr |= byte; +} diff --git a/src/p7os/cake.exe/libgint/src/timer/timer_stop.c b/src/p7os/cake.exe/libgint/src/timer/timer_stop.c new file mode 100644 index 0000000..083c4a4 --- /dev/null +++ b/src/p7os/cake.exe/libgint/src/timer/timer_stop.c @@ -0,0 +1,18 @@ +#include +#include + +#include + +/* + timer_stop() + Stops the given timer. This function may be called even if the timer is + not running. +*/ +void timer_stop(int timer) +{ + volatile unsigned char *tstr; + int byte = (1 << timer); + + timer_get(timer, NULL, &tstr); + *tstr &= ~byte; +} diff --git a/src/p7os/cake.exe/osupd.ld b/src/p7os/cake.exe/osupd.ld new file mode 100644 index 0000000..6743064 --- /dev/null +++ b/src/p7os/cake.exe/osupd.ld @@ -0,0 +1,101 @@ +/* + This linker script links the object files when generating the ELF output. + `romdata`, `[be]bss`, `[be]data` symbols are used in the runtime + initialization routine (crt0.c) to initialize the application. + + Two RAM areas are specified. The "real ram" is accessed directly while the + other area is virtualized. It is not possible to execute code in + virtualized ram -- for an add-in, I don't know if this is also the case + for the UpdateExe, so I'll just take one part of the RAM. + + An end block is located at the end of the binary - it's in the `end` + section. +*/ + +OUTPUT_ARCH(sh3) +ENTRY(_start) + +MEMORY +{ + /* http://bible.planet-casio.com/simlo/chm/v20/CommunicationsProtocol.htm */ + rom : o = 0x88030000, l = 64k + ram : o = 0x08024000, l = 40k + realram : o = 0x0802e000, l = 8k +} + +SECTIONS +{ + /* ROM sections : binary code and read-only data */ + .text : { + *(.pretext.entry) + *(.pretext) + + _bctors = . ; + *(.ctors) + _ectors = . ; + _bdtors = . ; + *(.dtors) + _edtors = . ; + + *(.text) + *(.text.*) + } > rom + + .rodata : { + *(.rodata.fxconv) + *(.rodata) + *(.rodata.*) + + _romdata = ALIGN(4) ; + } > rom + + /* RAM sections : bss and rw data */ + .bss : { + _bbss = . ; + *(.bss) + _ebss = . ; + } > ram + + .data : AT(_romdata) ALIGN(4) { + _bdata = . ; + *(.data) + *(.data.*) + _edata = . ; + } > ram + + .cc : AT(_romdata + SIZEOF(.data)) ALIGN(4) { + *(.eh_frame) + *(.jcr) + + _gint_data = _romdata + SIZEOF(.data) + SIZEOF(.cc) ; + } > ram + + /* Real RAM: interrupt, exception and TLB miss handlers */ + .gint : AT(_gint_data) { + /* The vbr needs to be 0x100-aligned because of an ld issue. */ + . = ALIGN(0x100) ; + _gint_vbr = . ; + _bgint = . ; + + /* Exception handler. */ + . = _gint_vbr + 0x100 ; + *(.gint.exc.entry) + *(.gint.exc) + + /* TLB miss handler. */ + . = _gint_vbr + 0x400 ; + *(.gint.tlb.entry) + *(.gint.tlb) + + /* Interrupt handler. */ + . = _gint_vbr + 0x600 ; + *(.gint.int.entry) + *(.gint.int) + + _egint = . ; + } > realram + + .end : AT(_gint_data + SIZEOF(.gint)) { + *(.end) + } > rom +} diff --git a/src/p7os/cake.exe/src/endblock.c b/src/p7os/cake.exe/src/endblock.c new file mode 100644 index 0000000..8233702 --- /dev/null +++ b/src/p7os/cake.exe/src/endblock.c @@ -0,0 +1,26 @@ +/* ************************************************************************** */ +/* _____ _ */ +/* endblock.c |_ _|__ _ _| |__ ___ _ _ */ +/* | Project: cake.exe | |/ _ \| | | | '_ \ / _ \ | | | */ +/* | | (_) | |_| | | | | __/ |_| | */ +/* By: thomas |_|\___/ \__,_|_| |_|\___|\__, |.fr */ +/* Last updated: 2017/01/16 18:05:41 |___/ */ +/* */ +/* ************************************************************************** */ +/** + * endblock: + * End block. + * + * "CASIO COMPUTER CO., LTD." and "CESG502" separated with a transmission + * escaper, where all characters occupy two bytes. + * This block is required to check if the uploaded binary is valid. + * + * Simon Lothar's documentation says the byte after the escape character + * is 0x03, this is not a mistake (if you was wondering). + */ + +extern char endblock[] __attribute__((section(".end"))); +char endblock[] = +"C\0A\0S\0I\0O\0 \0C\0O\0M\0P\0U\0T\0E\0R\0 \0C\0O\0.\0,\0 \0L\0T\0D\0.\0" +"\x10\3" +"C\0E\0S\0G\0""5\0""0\0""2"; diff --git a/src/p7os/cake.exe/src/main.c b/src/p7os/cake.exe/src/main.c new file mode 100644 index 0000000..cfe0647 --- /dev/null +++ b/src/p7os/cake.exe/src/main.c @@ -0,0 +1,40 @@ +/* ************************************************************************** */ +/* _____ _ */ +/* main.c |_ _|__ _ _| |__ ___ _ _ */ +/* | Project: cake.exe | |/ _ \| | | | '_ \ / _ \ | | | */ +/* | | (_) | |_| | | | | __/ |_| | */ +/* By: thomas |_|\___/ \__,_|_| |_|\___|\__, |.fr */ +/* Last updated: 2017/01/16 18:05:41 |___/ */ +/* */ +/* ************************************************************************** */ + +#include +#include +#include +#include + +/* reboot like an update.exe - that means re-running the bootcode */ +static void (*reboot)(void) = (void*)0xa0000000; + +/** + * main: + * User-friendly entry point of the program. + */ + +int main(void) +{ + /* first display */ + dclear(); + dtext(1, 1, "CAKE.EXE"); + dupdate(); + + /* wait for user to press on EXIT */ + while (1) { + int key = getkey(); + if (key == KEY_EXIT) + break; + } + + /* we're done */ + (*reboot)(); +} diff --git a/src/p7os/main.c b/src/p7os/main.c new file mode 100644 index 0000000..31c743a --- /dev/null +++ b/src/p7os/main.c @@ -0,0 +1,188 @@ +/* ************************************************************************** */ +/* _____ _ */ +/* p7os/main.c |_ _|__ _ _| |__ ___ _ _ */ +/* | Project: p7utils | |/ _ \| | | | '_ \ / _ \ | | | */ +/* | | (_) | |_| | | | | __/ |_| | */ +/* By: thomas |_|\___/ \__,_|_| |_|\___|\__, |.fr */ +/* Last updated: 2017/01/16 23:55:54 |___/ */ +/* */ +/* ************************************************************************** */ +#include "main.h" +#include + +/* ************************************************************************** */ +/* Error messages */ +/* ************************************************************************** */ +/* Couldn't initialize connexion to calculator. */ +static const char error_noconnexion[] = +"Could not connect to the calculator.\n" +"- Is it plugged in and in Receive mode/OS Update?\n" +"- Have you tried changing the cable ?\n"; + +/* Calculator was found but program wasn't allowed to communicate with it. */ +static const char error_noaccess[] = +"Could not get access to the calculator.\n" +"Install the appropriate udev rule, or run as root.\n"; + +/* The calculator acted in a weird way. */ +static const char error_unplanned[] = +"The calculator didn't act as planned: %s.\n" +"Stop receive mode on calculator and start it again before re-running " \ + QUOTE(BIN) ".\n"; + +/* Unsupported operation -> OS Update, not receive mode! */ +static const char error_unsupported[] = +"Required operation was unsupported by the calculator.\n" +"If you did not prepare, perhaps you should prepare?\n"; + +/* ************************************************************************** */ +/* Auxiliary functions */ +/* ************************************************************************** */ +/** + * osdisp: + * Nice little loading bar. + * + * Taken from `src/p7/main.c`. + * "Initialization" is when id > total (called in main). + * + * @arg id data packet ID. + * @arg total total number of packets. + */ + +static int osdisp_init = 0; +static void osdisp(p7ushort_t id, p7ushort_t total) +{ + /* here's the buffer */ + static char buf[50] = + "\r|---------------------------------------| 00.00%"; + static char *bar = &buf[2]; + + /* initialize */ + static int pos; + + /* if is initialize, fill */ + if (id > total) { + pos = 0; + /* indicate that is has been initialized */ + osdisp_init = 1; + /* put initial buffer */ + fputs(buf, stdout); + /* save cursor position */ + fputs("\x1B[s", stdout); + /* we're done */ + return ; + } + + /* id and total start from 1, let them start from zero */ + id--; total--; + + /* modify buffer */ + /* - # - */ + int current = 38 * id / total; + while (pos <= current) bar[pos++] = '#'; + /* - % - */ + unsigned int percent = 10000 * id / total; + sprintf(&buf[43], "%02u.%02u", percent / 100, percent % 100); + + /* put it */ + fputs(buf, stdout); + /* force cursor position */ + fputs("\x1B""8", stdout); +} + +/* ************************************************************************** */ +/* Main function */ +/* ************************************************************************** */ +/** + * main: + * User entry point of the program. + * + * @arg ac arguments count + * @arg av arguments values + * @return return code (0 if OK) + */ + +#define initflags (P7_ACTIVE | P7_CHECK | P7_TERM) +int main(int ac, char **av) +{ + /* parse args */ + args_t args; + if (parse_args(ac, av, &args)) + return (0); + + /* Initialize libp7 and communication */ + p7_handle_t *handle = NULL; int err; + if (args.com) err = p7_cominit(&handle, initflags, args.com); + else err = p7_init(&handle, initflags); + if (err) goto fail; + + /* prepare */ + if (!args.noprepare) { + /* make the preparation thing */ + printf("Uploading the Update.Exe.\n"); + if ((err = prepare_ops(handle, args.uexe, osdisp))) + goto fail; + if (osdisp_init) { + osdisp_init = 0; + puts("\b\b\b\b\b\bTransfer complete."); + } + handle = NULL; + + /* was only about preparing? */ + if (args.menu == mn_prepare_only) + return (0); + + /* sleep a little, in case */ + printf("Waiting for the Update.Exe to be setup...\n"); + sleep(1); + + /* re-open the handle */ + if (args.com) err = p7_cominit(&handle, initflags, args.com); + else err = p7_init(&handle, initflags); + if (err) { + p7_exit(handle); + goto fail; + } + } + + /* check according to menu */ + switch (args.menu) { + /* backup the thing menu */ + case mn_get: + /* get the os */ + printf("Gathering the OS...\n"); + err = p7_backup_romfile(handle, args.local, osdisp); + if (err) goto fail; + fclose(args.local); + break; + } + + /* exit libp7 */ + p7_exit(handle); + + /* then we're good */ + return (0); + +fail: + /* interrupt loading bar */ + if (osdisp_init) + puts("\b\b\b\b\b\bError !"); + + /* displaying error */ + if (err > 0) switch (err) { + case p7_error_nocalc: log(error_noconnexion); break; + case p7_error_noaccess: log(error_noaccess); break; + case p7_error_unsupported: log(error_unsupported); break; + default: log(error_unplanned, p7_strerror(err)); + } + + /* closing the handle */ + p7_exit(handle); + + /* closing the file, removing if necessary */ + if (args.localpath) { + fclose(args.local); + remove(args.localpath); + } + return (1); +} diff --git a/src/p7os/main.h b/src/p7os/main.h new file mode 100644 index 0000000..733ab86 --- /dev/null +++ b/src/p7os/main.h @@ -0,0 +1,48 @@ +/* ************************************************************************** */ +/* _____ _ */ +/* p7os/main.h |_ _|__ _ _| |__ ___ _ _ */ +/* | Project: p7utils | |/ _ \| | | | '_ \ / _ \ | | | */ +/* | | (_) | |_| | | | | __/ |_| | */ +/* By: thomas |_|\___/ \__,_|_| |_|\___|\__, |.fr */ +/* Last updated: 2017/01/16 23:55:55 |___/ */ +/* */ +/* ************************************************************************** */ +#ifndef MAIN_H +# define MAIN_H +# include +# include +# define Q(x) #x +# define QUOTE(x) Q(x) +# define log(S, ...) fprintf(stderr, S, ##__VA_ARGS__) + +/* ************************************************************************** */ +/* CLI options */ +/* ************************************************************************** */ +/* Menu */ +# define mn_prepare_only 1 +# define mn_get 2 + +/* Arguments */ +typedef struct { + /* basic things */ + int menu; + + /* communication and tweaks */ + int com, noprepare; + FILE *uexe; + + /* others */ + FILE *local; const char *localpath; +} args_t; + +/* Parsing function */ +int parse_args(int ac, char **av, args_t *args); + +/* ************************************************************************** */ +/* Actual things */ +/* ************************************************************************** */ +/* Main functions */ +int prepare_ops(p7_handle_t *handle, FILE *uexe, void (*disp)()); +int get_os(p7_handle_t *handle, FILE *dest); + +#endif /* MAIN_H */ diff --git a/src/p7os/prepare.c b/src/p7os/prepare.c new file mode 100644 index 0000000..4523e01 --- /dev/null +++ b/src/p7os/prepare.c @@ -0,0 +1,68 @@ +/* ************************************************************************** */ +/* _____ _ */ +/* p7os/prepare.c |_ _|__ _ _| |__ ___ _ _ */ +/* | Project: p7utils | |/ _ \| | | | '_ \ / _ \ | | | */ +/* | | (_) | |_| | | | | __/ |_| | */ +/* By: thomas |_|\___/ \__,_|_| |_|\___|\__, |.fr */ +/* Last updated: 2017/01/16 23:56:41 |___/ */ +/* */ +/* ************************************************************************** */ +#include "main.h" + +/* ************************************************************************** */ +/* Error messages */ +/* ************************************************************************** */ +/* Unable to open the embedded thingy */ +static const char error_fmemopen[] = +"Unable to open the embedded update.exe.\n"; + +/* ************************************************************************** */ +/* Embedded update.exe */ +/* ************************************************************************** */ +#define cake_exe_str (_binary_cake_exe_bin_start) +#define cake_exe_end (_binary_cake_exe_bin_end) +extern char _binary_cake_exe_bin_start[]; +extern char _binary_cake_exe_bin_end[]; + +/* ************************************************************************** */ +/* Main function */ +/* ************************************************************************** */ +/** + * prepare_ops: + * Prepare the operation, by uploading the update.exe. + * + * @arg handle the libp7 handle. + * @arg uexe the update.exe to use (NULL if use the embedded one). + * @return the error (-1 if not a libp7 error, 0 if ok) + */ + +int prepare_ops(p7_handle_t *handle, FILE *uexe, void (*disp)()) +{ + int err; size_t usize; + + /* prepare the update.exe */ + if (uexe) { + /* calculate the size */ + fseek(uexe, 0, SEEK_END); + usize = ftell(uexe); + fseek(uexe, 0, SEEK_SET); + } else { + /* take the default uexe */ + usize = (size_t)&cake_exe_end - (size_t)&cake_exe_str; + uexe = fmemopen(cake_exe_str, usize, "r"); + if (!uexe) { + fprintf(stderr, error_fmemopen); + return (-1); + } + } + + /* send the thing */ + if ((err = p7_sendexe_file(handle, uexe, 0x88030000, 0x88030000, disp))) { + fclose(uexe); + return (err); + } + + /* no error! */ + fclose(uexe); + return (0); +} diff --git a/src/p7os/vars.mk b/src/p7os/vars.mk new file mode 100755 index 0000000..3cc5551 --- /dev/null +++ b/src/p7os/vars.mk @@ -0,0 +1,4 @@ +#!/usr/bin/make -f +disable: +libs: + @echo libp7 diff --git a/src/p7screen/args.c b/src/p7screen/args.c new file mode 100644 index 0000000..2f6a55a --- /dev/null +++ b/src/p7screen/args.c @@ -0,0 +1,135 @@ +/* ************************************************************************** */ +/* _____ _ */ +/* p7screen/args.c |_ _|__ _ _| |__ ___ _ _ */ +/* | Project: p7utils | |/ _ \| | | | '_ \ / _ \ | | | */ +/* | | (_) | |_| | | | | __/ |_| | */ +/* By: thomas |_|\___/ \__,_|_| |_|\___|\__, |.fr */ +/* Last updated: 2017/01/16 23:55:55 |___/ */ +/* */ +/* ************************************************************************** */ +#include "main.h" +#include +#include +#include + +/* ************************************************************************** */ +/* Help and version messages */ +/* ************************************************************************** */ +/* Version message */ +static const char version_message[] = +QUOTE(BIN) " - from " QUOTE(NAME) " v" QUOTE(VERSION) " (licensed under GPLv2)\n" +"Maintained by " QUOTE(MAINTAINER) ".\n" +"\n" +"This is free software; see the source for copying conditions.\n" +"There is NO warranty; not even for MERCHANTABILITY or\n" +"FITNESS FOR A PARTICULAR PURPOSE."; + +/* Help message */ +static const char help_main[] = +"Usage: " QUOTE(BIN) " [--help|-h] [--version|-v]\n" +" [--com ]\n" +"\n" +"Displays the streamed screen from a CASIO fx calculator.\n" +"\n" +"Options are:\n" +" -h, --help Display this help page\n" +" -v, --version Displays the version\n" +" --com The USB-serial port, if you want to communicate with a\n" +" calculator connected using a USB-to-serial cable. (1 to 20)\n" +" If this option isn't used, the program will look for a\n" +" directly connected USB calculator.\n" +" -z ZOOM Change the zoom (1 to 16)\n" +" By default, the zoom will be " QUOTE(DEFAULT_ZOOM) ".\n" +"\n" +"Report bugs to " QUOTE(MAINTAINER) "."; + +/* ************************************************************************** */ +/* Main function */ +/* ************************************************************************** */ +/** + * parse_args: + * Args parsing main function. + * + * Inspired of the edits of my first experiment with getopt. + * Interesting, huh? + * + * @arg ac the arguments count + * @arg av the arguments values + * @arg device pointer to the device + * @arg zoom pointer the zoom + * @arg args the parsed args pointer + * @return 0 if ok, other if not. + */ + +int parse_args(int ac, char **av, int *com, int *zoom) +{ + /* initialize args */ + *com = 0; + *zoom = DEFAULT_ZOOM; + + /* define options */ + const char short_options[] = "hvz:"; + const struct option long_options[] = { + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'v'}, + {"com", required_argument, NULL, 'c'}, + {"zoom", required_argument, NULL, 'z'}, + {NULL, 0, NULL, 0} + }; + + /* get all options */ + int c; opterr = 0; + int help = 0, version = 0; + const char *s_com = NULL; + while ((c = getopt_long(ac, av, short_options, long_options, NULL)) != -1) { + switch (c) { + /* help */ + case 'h': help = 1; break; + /* version */ + case 'v': version = 1; break; + /* com port */ + case 'c': s_com = optarg; break; + /* zoom */ + case 'z': + *zoom = atoi(optarg); + if (*zoom <= 0 || *zoom > 16) { + log("-z, --zoom: should be between 1 and 16"); + return (1); + } + break; + + /* error (ignore) */ + case '?': + if (optopt == 'z') + log("-z, --zoom: expected an argument\n"); + else if (optopt == 'c') + log("--com: expected an argument\n"); + else + break; + return (1); + } + } + + /* check com port */ + if (s_com) { + if (!isdigit(s_com[0])) { + log("-c, --com: expected a number\n"); + return (0); + } + *com = atoi(s_com); + if (*com < 1 || *com > 20) { + log("-c, --com: COM port number should be between 1 and 20\n"); + return (0); + } + } + + /* check if there is any parameter */ + if (ac - optind) + help = 1; + + /* print help or version if required, and return */ + if (version) puts(version_message); + else if (help) puts(help_main); + else return (0); + return (1); +} diff --git a/src/p7screen/main.c b/src/p7screen/main.c new file mode 100644 index 0000000..e89a17c --- /dev/null +++ b/src/p7screen/main.c @@ -0,0 +1,167 @@ +/* ************************************************************************** */ +/* _____ _ */ +/* p7screen/main.c |_ _|__ _ _| |__ ___ _ _ */ +/* | Project: p7utils | |/ _ \| | | | '_ \ / _ \ | | | */ +/* | | (_) | |_| | | | | __/ |_| | */ +/* By: thomas |_|\___/ \__,_|_| |_|\___|\__, |.fr */ +/* Last updated: 2017/01/16 23:55:55 |___/ */ +/* */ +/* ************************************************************************** */ +#include "main.h" +#include +#include +#include + +/* ************************************************************************** */ +/* Error messages */ +/* ************************************************************************** */ +/* Couldn't initialize connexion to calculator. */ +static const char error_noconnexion[] = +"Could not connect to the calculator.\n" +"- Is it plugged in and in PROJ mode?\n" +"- Have you tried unplugging, plugging and selecting Projector on pop-up?\n" +"- Have you tried changing the cable?\n"; + +/* Calculator was found but program wasn't allowed to communicate with it. */ +static const char error_noaccess[] = +"Could not get access to the calculator.\n" +"Install the appropriate udev rule, or run as root.\n"; + +/* The calculator acted in a weird way. */ +static const char error_unplanned[] = +"The calculator didn't act as planned.\n" +"Stop receive mode on calculator and start it again before re-running " \ + QUOTE(BIN) ".\n" +"Error was: %s\n"; + +/* ************************************************************************** */ +/* Globals */ +/* ************************************************************************** */ +/* The z00m (omG) */ +static int zoom; + +/* ************************************************************************** */ +/* Auxiliary functions */ +/* ************************************************************************** */ +/** + * display_callback: + * The main callback for screen streaming. + * + * @arg w the width of the received image + * @arg h the height of the received image + * @arg pixels the image data + * @return if reception should continue + */ + +static int display_callback(int w, int h, uint32_t **pixels) +{ + /* create screen if there isn't one */ + static SDL_Surface *screen = NULL; + static int saved_w = 0, saved_h = 0; + if (!screen || saved_w != w || saved_h != h) { + /* create the window */ + if (!(screen = SDL_SetVideoMode(w * zoom, h * zoom, 32, + SDL_SWSURFACE | SDL_DOUBLEBUF))) { + log("Couldn't set video mode: %s\n", SDL_GetError()); + return (0); + } + SDL_WM_SetCaption("P7screen", NULL); + + /* save data and display message */ + saved_w = w; saved_h = h; + puts("Turn off your calculator (SHIFT+AC) when you have finished."); + } + + /* edit screen */ + /* - lock it - */ + SDL_LockSurface(screen); + /* - copy - */ + uint32_t *px = (uint32_t*)screen->pixels; + int linesize = w * zoom; + for (int y = 0; y < h; y++) { + uint32_t *refline = px; + for (int x = 0; x < w; x++) { + uint32_t pixel = pixels[y][x]; + for (int zx = 0; zx < zoom; zx++) + *px++ = pixel; + } + for (int zy = 1; zy < zoom; zy++) { + memcpy(px, refline, linesize * sizeof(uint32_t)); + px += linesize; + } + } + /* - unlock it - */ + SDL_UnlockSurface(screen); + + /* update screen */ + SDL_Flip(screen); + + /* check if user has pressed escape or cross */ + SDL_Event event; + SDL_PollEvent(&event); + if ((event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE) + || event.type == SDL_QUIT) + return (0); + + /* continue! */ + return (1); +} + +/* ************************************************************************** */ +/* Main function */ +/* ************************************************************************** */ +/** + * main: + * Entry point of the program. + * + * @arg ac arguments count + * @arg av arguments values + * @return if it worked (0 if OK) + */ + +int main(int ac, char **av) +{ + /* parse args */ + int com; + if (parse_args(ac, av, &com, &zoom)) + return (0); + + /* Initialize libp7 */ + p7_handle_t *handle = NULL; int err; + if (com) err = p7_cominit(&handle, 0, com); + else err = p7_init(&handle, 0); + if (err) { + /* display error */ + switch (err) { + case p7_error_nocalc: log(error_noconnexion); break; + case p7_error_noaccess: log(error_noaccess); break; + default: log(error_unplanned, p7_strerror(err)); break; + } + + /* return */ + return (1); + } + + /* Initialize SDL */ + if (SDL_Init(SDL_INIT_VIDEO)) { + log("Failed to initialize SDL: %s\n", SDL_GetError()); + return (3); + } + atexit(SDL_Quit); + + /* receive screen */ + if ((err = p7_getscreen(handle, &display_callback)) + && err != p7_error_nocalc) { + switch (err) { + case p7_error_timeout: log(error_noconnexion); break; + default: log(error_unplanned, p7_strerror(err)); break; + } + return (1); + } + + /* close */ + p7_exit(handle); + + /* everything went well */ + return (0); +} diff --git a/src/p7screen/main.h b/src/p7screen/main.h new file mode 100644 index 0000000..0fe964a --- /dev/null +++ b/src/p7screen/main.h @@ -0,0 +1,20 @@ +/* ************************************************************************** */ +/* _____ _ */ +/* p7screen/main.h |_ _|__ _ _| |__ ___ _ _ */ +/* | Project: p7utils | |/ _ \| | | | '_ \ / _ \ | | | */ +/* | | (_) | |_| | | | | __/ |_| | */ +/* By: thomas |_|\___/ \__,_|_| |_|\___|\__, |.fr */ +/* Last updated: 2017/01/16 23:55:55 |___/ */ +/* */ +/* ************************************************************************** */ +#ifndef MAIN_H +# define MAIN_H +# include +# define Q(x) #x +# define QUOTE(x) Q(x) +# define log(S, ...) fprintf(stderr, S, ##__VA_ARGS__) + +/* all functions */ +int parse_args(int ac, char **av, int *com, int *zoom); + +#endif /* MAIN_H */ diff --git a/src/p7screen/vars.mk b/src/p7screen/vars.mk new file mode 100755 index 0000000..c09f426 --- /dev/null +++ b/src/p7screen/vars.mk @@ -0,0 +1,3 @@ +#!/usr/bin/make -f +libs: + @echo libp7 sdl