From f6133c26fc876ce81626c2639fb06dea28c6cc10 Mon Sep 17 00:00:00 2001 From: lephe Date: Wed, 5 Jul 2017 21:38:12 +0200 Subject: [PATCH] Startup logs instead of diagnostics, created .gint_bss, updated demo. --- Makefile | 41 +---- TODO | 14 +- configure | 24 ++- debug/addin.ld | 31 ---- debug/crt0.s | 172 ------------------ debug/gintdbg.c | 178 ------------------- debug/icon.bmp | Bin 1870 -> 0 bytes debug/include/dispbios.h | 97 ----------- debug/include/endian.h | 31 ---- debug/include/filebios.h | 116 ------------- debug/include/fxlib.h | 100 ----------- debug/include/keybios.h | 158 ----------------- debug/include/timer.h | 31 ---- debug/libfx.a | Bin 410910 -> 0 bytes debug/vsprintf.c | 160 ----------------- demo/gintdemo.c | 19 +- demo/gintdemo.ld | 71 ++++---- demo/resources/font_modern.bmp | Bin 24698 -> 24698 bytes demo/resources/opt_gray.bmp | Bin 3194 -> 3194 bytes demo/test_gray.c | 21 ++- demo/test_keyboard.c | 56 ++++-- include/events.h | 8 +- include/internals/gint.h | 100 +---------- include/internals/init.h | 37 ++++ include/internals/keyboard.h | 7 + include/internals/syscalls.h | 26 +++ include/internals/tales.h | 7 - include/internals/timer.h | 12 +- include/mpu.h | 6 +- src/core/crt0.c | 253 --------------------------- src/core/init_quit.c | 24 ++- src/core/mpu.c | 3 +- src/core/syscalls.s | 24 ++- src/display/display_vram.c | 11 +- src/gray/gray_engine.c | 42 +++-- src/init/crt0.c | 306 +++++++++++++++++++++++++++++++++ src/init/util.c | 90 ++++++++++ src/keyboard/getkey.c | 4 + src/keyboard/keyboard_core.c | 39 ----- src/keyboard/multigetkey.c | 54 ------ src/stdlib/free.c | 5 +- src/stdlib/malloc.c | 2 +- src/stdlib/realloc.c | 2 +- src/tales/tales_internals.c | 15 +- version | 2 +- 45 files changed, 689 insertions(+), 1710 deletions(-) delete mode 100644 debug/addin.ld delete mode 100644 debug/crt0.s delete mode 100644 debug/gintdbg.c delete mode 100644 debug/icon.bmp delete mode 100644 debug/include/dispbios.h delete mode 100644 debug/include/endian.h delete mode 100644 debug/include/filebios.h delete mode 100644 debug/include/fxlib.h delete mode 100644 debug/include/keybios.h delete mode 100644 debug/include/timer.h delete mode 100644 debug/libfx.a delete mode 100644 debug/vsprintf.c create mode 100644 include/internals/init.h create mode 100644 include/internals/syscalls.h delete mode 100644 src/core/crt0.c create mode 100644 src/init/crt0.c create mode 100644 src/init/util.c delete mode 100644 src/keyboard/multigetkey.c diff --git a/Makefile b/Makefile index 83a3ee9..5924ace 100755 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ include Makefile.cfg #--- # Modules -modules-gint = bopti clock core display events gray keyboard mmu rtc \ +modules-gint = bopti clock core display events gray init keyboard mmu rtc \ screen tales timer modules-libc = ctype setjmp stdio stdlib string time @@ -19,7 +19,6 @@ modules-libc = ctype setjmp stdio stdlib string time target-lib = libgint.a target-std = libc.a target-g1a = gintdemo.g1a -target-dbg = gintdbg.g1a # Tools cc = sh3eb-elf-gcc @@ -44,17 +43,6 @@ demo-ldflags = $(demo-cflags) -T demo/gintdemo.ld -L. -lgint -lc -lgcc demo-cflags = -m3 -mb -nostdlib -I include -ffreestanding -std=c11 -Os \ -Wall -Wextra -# Debugger application (displays past diagnostics without running gint) -debug-src = $(notdir $(wildcard debug/*.[cs])) -debug-dep = $(wildcard debug/*.h) -debug-icon = debug/icon.bmp -debug-obj = $(debug-src:%=build/debug_%.o) -debug-elf = build/gintdbg.elf -debug-bin = build/gintdbg.bin -debug-ldflags = $(debug-cflags) -T debug/addin.ld -L debug -lfx -lgcc -debug-cflags = -m3 -mb -nostdlib -ffreestanding -I debug/include -I \ - include -std=c11 -Os -Wall -Wextra - # Specific objects obj-lib-spec = build/display_font_system.bmp.o obj-std-spec = @@ -159,7 +147,7 @@ debug-ldflags += -Wl,--defsym,_GINT_VERSION=$(version_symbol) all-lib: $(config) $(target-std) $(target-lib) -all: $(config) $(target-std) $(target-lib) $(target-g1a) $(target-dbg) +all: $(config) $(target-std) $(target-lib) $(target-g1a) build: $(if $(VERBOSE),,@ printf '\e[35;1mdir \u00bb\e[0m mkdir $@\n') @@ -196,17 +184,6 @@ $(target-g1a): $(config) $(target-std) $(target-lib) $(demo-obj) @ printf $$(stat -c %s $@) @ printf ' bytes)\n\n' -$(target-dbg): $(config) $(debug-obj) - $(if $(VERBOSE),,@ printf '\e[35;1mexe \u00bb\e[0m ld -o $(debug-elf)\n') - $(if $(VERBOSE),,@) $(cc) -o $(debug-elf) $(debug-obj) $(debug-ldflags) - $(if $(VERBOSE),,@ printf '\e[35;1mexe \u00bb\e[0m objcopy -o $(debug-bin)\n') - $(if $(VERBOSE),,@) $(ob) -R .comment -R .bss -O binary $(debug-elf) $(debug-bin) - $(if $(VERBOSE),,@ printf '\e[35;1mexe \u00bb\e[0m g1a-wrapper -o $@\n') - $(if $(VERBOSE),,@) $(wr) $(debug-bin) -o $@ -i $(debug-icon) - @ printf '\e[32;1mmsg \u00bb\e[0m Succesfully built debug application (' - @ printf $$(stat -c %s $@) - @ printf ' bytes)\n\n' - # Automated rules $(foreach mod,$(modules), \ @@ -244,16 +221,6 @@ 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_%,$<) -# Debug application - -build/debug_%.s.o: debug/%.s $(config) - $(if $(VERBOSE),,@ printf '\e[34;1msrc \u00bb\e[0m as $<\n') - $(if $(VERBOSE),,@) $(as) -c $< -o $@ - -build/debug_%.c.o: debug/%.c $(hdr-dep) $(debug-dep) $(config) - $(if $(VERBOSE),,@ printf '\e[34;1msrc \u00bb\e[0m cc $<\n') - $(if $(VERBOSE),,@) $(cc) -c $< -o $@ $(debug-cflags) - #--- @@ -282,9 +249,7 @@ endif install-demo: all p7 send -f $(target-g1a) -install-debug: all - p7 send -f $(target-dbg) .PHONY: all-lib all help .PHONY: clean mrproper distclean -.PHONY: install install-demo install-debug +.PHONY: install install-demo diff --git a/TODO b/TODO index dca8224..7a2c0ff 100644 --- a/TODO +++ b/TODO @@ -1,10 +1,11 @@ Bugs to fix: -- A few key hits ignored after leaving the application (could not reproduce) -- Lost keyboard control at startup (could not reproduce) - Alignment of ALL .data / .rodata files is required to ensure converted data is properly aligned +- Unpreditcable crap happens when more than 10 keys are pressed simultaneously +- Ensure heap data is freed when a task-switch results in leaving the app Things to do before 1.0: +- init: Move qdiv10() somewhere else - bopti: Test partial transparency - demo: Try 284x124 at (-60, -28) (all disadvantages) - project: Check size of *all* library structures @@ -33,8 +34,15 @@ Things to do later: - usb: Implement a driver Things to investigate: -- Packed bit fields alignment - Registers that may need to be saved within setjmp() - Optimizing core/gint.c leads to raising of an illegal slot exception when running the interrupt handler, although it ends on rte; lds.l @r15+, mach, which is totally not an illegal slot. + +Possibly useful modules: +- DMAC +- SCIF, SCIFA +- TPU +- USB +- CMT on SH7305, WDT on SH7705 +- ACD (SH7705 only) diff --git a/configure b/configure index 5ff00f3..83c842f 100755 --- a/configure +++ b/configure @@ -7,9 +7,10 @@ declare -A conf # Behavior -conf[GINT_DIAGNOSTICS]= +conf[GINT_STARTUP_LOG]= conf[GINT_NO_SYSCALLS]= conf[GINT_EXTENDED_LIBC]= +conf[GINT_STATIC_GRAY]= # Size limits conf[ATEXIT_MAX]=16 @@ -37,15 +38,18 @@ help() Configuration script for the gint library. Options that affect the behavior of the library: - $Cr--diagnostics $Cg[default:$Cp false$Cg]$C0 - Use gint in debug mode, where the library outputs some diagnostics in - memory or briefly on screen to diagnose incompatibilites or crashes. + $Cr--startup-log $Cg[default:$Cp false$Cg]$C0 + Enable a on-screen log at startup if a key is kept pressed while launching + the add-in, allowing easy debug and crash diagnoses. $Cr--no-syscalls $Cg[default:$Cp false$Cg]$C0 - Never use syscalls. Expect some trouble with the malloc() function... do + Never use syscalls. Expect trouble with malloc() and the gray engine. Do not trigger this switch unless you know what you are doing. $Cr--extended-libc $Cg[default:$Cp false$Cg]$C0 Enable specific C99 headers/features that are normally not required by calculator programs. This may allow porting programs from other platforms. + $Cr--static-gray-engine $Cg[default:$Cp false$Cg]$C0 + Place the gray engine vram in static ram instead of using the heap. Always + use this option when using both the gray engine and --no-syscalls. Options that customize size limits: $Cr--atexit-max$C0=$Cy$Cg [default:$Cp 16$Cg]$C0 @@ -66,9 +70,10 @@ EOF fail=false for arg; do case "$arg" in -h | --help) help;; - --diagnostics) conf[GINT_DIAGNOSTICS]=true;; - --no-syscalls) conf[GINT_NO_SYSCALLS]=true;; - --extended-libc) conf[GINT_EXTENDED_LIBC]=true;; + --startup-log) conf[GINT_STARTUP_LOG]=true;; + --no-syscalls) conf[GINT_NO_SYSCALLS]=true;; + --extended-libc) conf[GINT_EXTENDED_LIBC]=true;; + --static-gray-engine) conf[GINT_STATIC_GRAY]=true;; --atexit-max=*) size=${arg#*=} @@ -103,9 +108,10 @@ esac; done output_config_gcc() { - [ "${conf[GINT_DIAGNOSTICS]}" != "" ] && echo "-D GINT_DIAGNOSTICS" + [ "${conf[GINT_STARTUP_LOG]}" != "" ] && echo "-D GINT_STARTUP_LOG" [ "${conf[GINT_NO_SYSCALLS]}" != "" ] && echo "-D GINT_NO_SYSCALLS" [ "${conf[GINT_EXTENDED_LIBC]}" != "" ] && echo "-D GINT_EXTENDED_LIBC" + [ "${conf[GINT_STATIC_GRAY]}" != "" ] && echo "-D GINT_STATIC_GRAY" echo "-D ATEXIT_MAX=${conf[ATEXIT_MAX]}" echo "-D TIMER_SLOTS=${conf[TIMER_SLOTS]}" diff --git a/debug/addin.ld b/debug/addin.ld deleted file mode 100644 index b712b1d..0000000 --- a/debug/addin.ld +++ /dev/null @@ -1,31 +0,0 @@ -OUTPUT_ARCH(sh3) -ENTRY(initialize) -MEMORY -{ - rom : o = 0x00300200, l = 512k - ram : o = 0x08100000, l = 64k /* pretty safe guess */ -} -SECTIONS -{ - .text : { - *(.pretext) /* init stuff */ - *(.text) - } > rom - .rodata : { - *(.rodata) - *(.rodata.str1.4) - _romdata = . ; /* symbol for initialization data */ - } > rom - .bss : { - _bbss = . ; - _bssdatasize = . ; - LONG(0); /* bssdatasize */ - *(.bss) *(COMMON); - _ebss = . ; - } > ram - .data : AT(_romdata) { - _bdata = . ; - *(.data); - _edata = . ; - } > ram -} diff --git a/debug/crt0.s b/debug/crt0.s deleted file mode 100644 index 93000cf..0000000 --- a/debug/crt0.s +++ /dev/null @@ -1,172 +0,0 @@ - .section .pretext - .global initialize -initialize: - sts.l pr, @-r15 - - ! set up TLB - mov.l Hmem_SetMMU, r3 - mov.l address_one, r4 ! 0x8102000 - mov.l address_two, r5 ! 0x8801E000 - jsr @r3 ! _Hmem_SetMMU - mov #108, r6 - - ! clear the BSS - mov.l bbss, r4 ! start - mov.l ebss, r5 ! end - bra L_check_bss - mov #0, r6 -L_zero_bss: - mov.l r6, @r4 ! zero and advance - add #4, r4 -L_check_bss: - cmp/hs r5, r4 - bf L_zero_bss - - ! Copy the .data - mov.l bdata, r4 ! dest - mov.l edata, r5 ! dest limit - mov.l romdata, r6 ! source - bra L_check_data - nop -L_copy_data: - mov.l @r6+, r3 - mov.l r3, @r4 - add #4, r4 -L_check_data: - cmp/hs r5, r4 - bf L_copy_data - - mov.l bbss, r4 - mov.l edata, r5 - sub r4, r5 ! size of .bss and .data sections - add #4, r5 - mov.l bssdatasize, r4 - mov.l r5, @r4 - - mov.l GLibAddinAplExecutionCheck, r2 - mov #0, r4 - mov #1, r5 - jsr @r2 ! _GLibAddinAplExecutionCheck(0,1,1); - mov r5, r6 - - mov.l CallbackAtQuitMainFunction, r3 - mov.l exit_handler, r4 - jsr @r3 ! _CallbackAtQuitMainFunction(&exit_handler) - nop - mov.l main, r3 - jmp @r3 ! _main() - lds.l @r15+, pr - -_exit_handler: - mov.l r14, @-r15 - mov.l r13, @-r15 - mov.l r12, @-r15 - sts.l pr, @-r15 - - mov.l Bdel_cychdr, r14 - jsr @r14 ! _Bdel_cychdr - mov #6, r4 - jsr @r14 ! _Bdel_cychdr - mov #7, r4 - jsr @r14 ! _Bdel_cychdr - mov #8, r4 - jsr @r14 ! _Bdel_cychdr - mov #9, r4 - jsr @r14 ! _Bdel_cychdr - mov #10, r4 - - mov.l BfileFLS_CloseFile, r12 - mov #4, r14 - mov #0, r13 -L_close_files: - jsr @r12 ! _BfileFLS_CloseFile - mov r13, r4 - add #1, r13 - cmp/ge r14, r13 - bf L_close_files - - mov.l flsFindClose, r12 - mov #0, r13 -L_close_finds: - jsr @r12 ! _flsFindClose - mov r13, r4 - add #1, r13 - cmp/ge r14, r13 - bf L_close_finds - - lds.l @r15+, pr - mov.l @r15+, r12 - mov.l @r15+, r13 - mov.l Bkey_Set_RepeatTime_Default, r2 - jmp @r2 ! _Bkey_Set_RepeatTime_Default - mov.l @r15+, r14 - -.align 4 -address_two: .long 0x8801E000 -address_one: .long 0x8102000 -Hmem_SetMMU: .long _Hmem_SetMMU -GLibAddinAplExecutionCheck: .long _GLibAddinAplExecutionCheck -CallbackAtQuitMainFunction: .long _CallbackAtQuitMainFunction -Bdel_cychdr: .long _Bdel_cychdr -BfileFLS_CloseFile: .long _BfileFLS_CloseFile -flsFindClose: .long _flsFindClose -Bkey_Set_RepeatTime_Default: .long _Bkey_Set_RepeatTime_Default -bbss: .long _bbss -ebss: .long _ebss -edata: .long _edata -bdata: .long _bdata -romdata: .long _romdata -bssdatasize: .long _bssdatasize - -exit_handler: .long _exit_handler -main: .long _main - -_Hmem_SetMMU: - mov.l sc_addr, r2 - mov.l 1f, r0 - jmp @r2 - nop -1: .long 0x3FA - -_Bdel_cychdr: - mov.l sc_addr, r2 - mov.l 1f, r0 - jmp @r2 - nop -1: .long 0x119 - -_BfileFLS_CloseFile: - mov.l sc_addr, r2 - mov.l 1f, r0 - jmp @r2 - nop -1: .long 0x1E7 - -_Bkey_Set_RepeatTime_Default: - mov.l sc_addr, r2 - mov.l 1f, r0 - jmp @r2 - nop -1: .long 0x244 - -_CallbackAtQuitMainFunction: - mov.l sc_addr, r2 - mov.l 1f, r0 - jmp @r2 - nop -1: .long 0x494 - -_flsFindClose: - mov.l sc_addr, r2 - mov.l 1f, r0 - jmp @r2 - nop -1: .long 0x218 - -_GLibAddinAplExecutionCheck: - mov.l sc_addr, r2 - mov #0x13, r0 - jmp @r2 - nop -sc_addr: .long 0x80010070 -.end diff --git a/debug/gintdbg.c b/debug/gintdbg.c deleted file mode 100644 index 61c70af..0000000 --- a/debug/gintdbg.c +++ /dev/null @@ -1,178 +0,0 @@ -//--- -// -// gintdbg -// -// A simple debugger for gint applications, providing diagnoses to -// determine what went bad. -// -//--- - -// Just for structure definitions, gint does not run here. -#define GINT_DIAGNOSTICS -#include -#include - -#include -#include -#include - -// Some functions from other files... -int vsprintf(char *buffer, const char *format, va_list args); -int sprintf(char *buffer, const char *format, ...); - -//--- -// Some util... -//--- - -static int print_row = 1; - -void print(int col, const char *format, ...) -{ - int row = print_row; - print_row++; - if(row < 1 || row > 8) return; - - char buffer[256]; - va_list args; - va_start(args, format); - vsprintf(buffer, format, args); - va_end(args); - - locate(col, row); - Print((unsigned char *)buffer); -} - -void newline(void) -{ - print_row++; -} - -void nothing_found(void) -{ - unsigned int key; - - Bdisp_AllClr_VRAM(); - PopUpWin(6); - print_row = 2; - print(3, "Apparently there"); - print(3, "is no diagnostic."); - print(3, ""); - print(3, "Show anyway?"); - print(3, " Yes:[F1]"); - print(3, " No :[MENU]"); - - do GetKey(&key); - while(key != KEY_CTRL_F1); -} - -void show_diagnostics(void) -{ - volatile gint_diagnostics_t *dg = gint_diagnostics(); - - const char *stages[] = { - "Startup", "Sections", "MMU", "Gint", "Clock", "Constructors", - "Running", "Leaving", "Destructors", "Terminated", - }; - const char *mpus[] = { - "Unknown", "SH7337", "SH7355", "SH7305", "SH7724", - }; - - print(1, "Gint debugger (%d)", dg->counter); - newline(); - - print(1, "General information"); - print(2, "Magic 0x%02x", dg->magic); - print(2, "Stage %s", dg->stage <= 9 ? stages[dg->stage] : "-"); - if(dg->stage >= stage_gint) - { - print(2, "MPU %s", dg->mpu <= 4 ? mpus[dg->mpu] : "-"); - } - print(2, "Version %08x", dg->version); - newline(); - - print(1, "Memory map"); - print(2, "%08x romdata", dg->romdata); - print(2, "%08x vbr", dg->vbr_address); - print(2, "%08x:%05x text", dg->section_text.address, - dg->section_text.length); - print(2, "%08x:%05x data", dg->section_data.address, - dg->section_data.length); - print(2, "%08x:%05x bss", dg->section_bss.address, - dg->section_bss.length); - - print(2, "%08x:%05x gint", dg->section_gint.address, - dg->section_gint.length); - newline(); - - print(1, "Exception records"); - size_t len = sizeof dg->except_vect; - char line[19]; - for(size_t i = 0; i < len; i += 6) - { - for(size_t n = 0; n < 6 && i + n < len; n++) - { - size_t index = (dg->excepts + i + n) % len; - sprintf(line + 3 * n, " %02x", dg->except_vect[index]); - } - - print(1, "%s", line); - } - print(2, "SPC %08x", dg->spc); - print(2, "SSR %08x", dg->ssr); - print(2, "EXPEVT %08x", dg->expevt); - print(2, "TEA %08x", dg->tea); - newline(); - - if(dg->stage >= stage_clock) - { - print(1, "Clock frequencies"); - print(2, "Bus clock %d MHz", dg->Bphi_f); - print(2, "Peripheral %d MHz", dg->Pphi_f); - print(2, "Processor %d MHz", dg->Iphi_f); - newline(); - } -} - -/* - main() - Let's do this! -*/ -int main(void) -{ - volatile gint_diagnostics_t *dg = gint_diagnostics(); - unsigned int key; - - if(dg->magic != GINT_DIAGNOSTICS_MAGIC - || dg->stage > 9 - || dg->mpu > 4 - ) nothing_found(); - - int total_height = -1; - int y = 0; - - while(1) - { - Bdisp_AllClr_VRAM(); - print_row = 1 - y; - - show_diagnostics(); - if(total_height < 0) total_height = print_row - 1; - - // Drawing a scrollbar. - if(total_height > 8) - { - int base = (64 * y) / total_height; - int height = (64 * 8) / total_height; - Bdisp_DrawLineVRAM(127, base, 127, base + height); - } - Bdisp_PutDisp_DD(); - - do GetKey(&key); - while(key != KEY_CTRL_UP && key != KEY_CTRL_DOWN); - - if(key == KEY_CTRL_UP && y > 0) y--; - else if(key == KEY_CTRL_DOWN && y + 8 < total_height) y++; - } - - return 1; -} diff --git a/debug/icon.bmp b/debug/icon.bmp deleted file mode 100644 index 6240f6142013afb0b62eb2e7a8d0c96b8cdb2702..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1870 zcmb_bu@S;R3^Nok01Xwxq@jX>Iq2w^fC1SjI4@qWIG-mR`0kA?%d+8)?sVQ-io55l zzk|P>zm@Ghn>{yX4=09~qdQ)1887`@2Vvj$f%#wQ-oMApIl-7JjX?CnBofwin2LIJz^Ta(a3l_XCO0G1FlJD> 8)) -#define UtlSwapDword(l) (unsigned long)((((l) & 0x000000ff) << 24) | (((l) & 0x0000ff00) << 8) | (((l) & 0xff000000) >> 24) | (((l) & 0x00ff0000) >> 8)) -#define UtlSwapInteger(i) UtlSwapDword(i) -#define UtlSwapPointer(p) (void*)((((unsigned long)(p) & 0x000000ff) << 24) | (((unsigned long)(p) & 0x0000ff00) << 8) | (((unsigned long)(p) & 0xff000000) >> 24) | (((unsigned long)(p) & 0x00ff0000) >> 8)) - - -#endif - -#ifdef __cplusplus -} -#endif diff --git a/debug/include/filebios.h b/debug/include/filebios.h deleted file mode 100644 index 276d9ce..0000000 --- a/debug/include/filebios.h +++ /dev/null @@ -1,116 +0,0 @@ -/*****************************************************************/ -/* */ -/* CASIO fx-9860G SDK Library */ -/* */ -/* File name : filebios.h */ -/* */ -/* Copyright (c) 2006 CASIO COMPUTER CO., LTD. */ -/* */ -/*****************************************************************/ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef __FILEBIOS_H__ -#define __FILEBIOS_H__ - - -// Defines - -#define FONTCHARACTER unsigned short - -#define _OPENMODE_READ 0x01 -#define _OPENMODE_READ_SHARE 0x80 -#define _OPENMODE_WRITE 0x02 -#define _OPENMODE_READWRITE 0x03 -#define _OPENMODE_READWRITE_SHARE 0x83 - -#define _CREATEMODE_BINARY 1 -#define _CREATEMODE_DIRECTORY 5 - -enum DEVICE_TYPE{ - DEVICE_MAIN_MEMORY, - DEVICE_STORAGE, - DEVICE_SD_CARD, // only fx-9860G SD model -}; - - -// File system standard error code -#define IML_FILEERR_NOERROR 0 -#define IML_FILEERR_ENTRYNOTFOUND -1 -#define IML_FILEERR_ILLEGALPARAM -2 -#define IML_FILEERR_ILLEGALPATH -3 -#define IML_FILEERR_DEVICEFULL -4 -#define IML_FILEERR_ILLEGALDEVICE -5 -#define IML_FILEERR_ILLEGALFILESYS -6 -#define IML_FILEERR_ILLEGALSYSTEM -7 -#define IML_FILEERR_ACCESSDENYED -8 -#define IML_FILEERR_ALREADYLOCKED -9 -#define IML_FILEERR_ILLEGALTASKID -10 -#define IML_FILEERR_PERMISSIONERROR -11 -#define IML_FILEERR_ENTRYFULL -12 -#define IML_FILEERR_ALREADYEXISTENTRY -13 -#define IML_FILEERR_READONLYFILE -14 -#define IML_FILEERR_ILLEGALFILTER -15 -#define IML_FILEERR_ENUMRATEEND -16 -#define IML_FILEERR_DEVICECHANGED -17 -//#define IML_FILEERR_NOTRECORDFILE -18 // Not used -#define IML_FILEERR_ILLEGALSEEKPOS -19 -#define IML_FILEERR_ILLEGALBLOCKFILE -20 -//#define IML_FILEERR_DEVICENOTEXIST -21 // Not used -//#define IML_FILEERR_ENDOFFILE -22 // Not used -#define IML_FILEERR_NOTMOUNTDEVICE -23 -#define IML_FILEERR_NOTUNMOUNTDEVICE -24 -#define IML_FILEERR_CANNOTLOCKSYSTEM -25 -#define IML_FILEERR_RECORDNOTFOUND -26 -//#define IML_FILEERR_NOTDUALRECORDFILE -27 // Not used -#define IML_FILEERR_NOTALARMSUPPORT -28 -#define IML_FILEERR_CANNOTADDALARM -29 -#define IML_FILEERR_FILEFINDUSED -30 -#define IML_FILEERR_DEVICEERROR -31 -#define IML_FILEERR_SYSTEMNOTLOCKED -32 -#define IML_FILEERR_DEVICENOTFOUND -33 -#define IML_FILEERR_FILETYPEMISMATCH -34 -#define IML_FILEERR_NOTEMPTY -35 -#define IML_FILEERR_BROKENSYSTEMDATA -36 -#define IML_FILEERR_MEDIANOTREADY -37 -#define IML_FILEERR_TOOMANYALARMITEM -38 -#define IML_FILEERR_SAMEALARMEXIST -39 -#define IML_FILEERR_ACCESSSWAPAREA -40 -#define IML_FILEERR_MULTIMEDIACARD -41 -#define IML_FILEERR_COPYPROTECTION -42 -#define IML_FILEERR_ILLEGALFILEDATA -43 - -// FILE_INFO.type -#define DT_DIRECTORY 0x0000 // Directory -#define DT_FILE 0x0001 // File -#define DT_ADDIN_APP 0x0002 // Add-In application -#define DT_EACT 0x0003 // eActivity -#define DT_LANGUAGE 0x0004 // Language -#define DT_BITMAP 0x0005 // Bitmap -#define DT_MAINMEM 0x0006 // Main Memory data -#define DT_TEMP 0x0007 // Temporary data -#define DT_DOT 0x0008 // . (Current directory) -#define DT_DOTDOT 0x0009 // .. (Parent directory) -#define DT_VOLUME 0x000A // Volume label - - -// Structs - -typedef struct tag_FILE_INFO -{ - unsigned short id; - unsigned short type; - unsigned long fsize; // File size - unsigned long dsize; // Data size - unsigned int property; // The file has not been completed, except when property is 0. - unsigned long address; -} FILE_INFO; - - -#endif - -#ifdef __cplusplus -} -#endif diff --git a/debug/include/fxlib.h b/debug/include/fxlib.h deleted file mode 100644 index dc4534a..0000000 --- a/debug/include/fxlib.h +++ /dev/null @@ -1,100 +0,0 @@ -/*****************************************************************/ -/* */ -/* CASIO fx-9860G SDK Library */ -/* */ -/* File name : fxlib.h */ -/* */ -/* Copyright (c) 2006 CASIO COMPUTER CO., LTD. */ -/* */ -/*****************************************************************/ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef __FXLIB_H__ -#define __FXLIB_H__ - -#include "dispbios.h" -#include "filebios.h" -#include "keybios.h" - - -// Prototypes - -void Bdisp_AllClr_DD(void); -void Bdisp_AllClr_VRAM(void); -void Bdisp_AllClr_DDVRAM(void); -void Bdisp_AreaClr_DD(const DISPBOX *pArea); -void Bdisp_AreaClr_VRAM(const DISPBOX *pArea); -void Bdisp_AreaClr_DDVRAM(const DISPBOX *pArea); -void Bdisp_AreaReverseVRAM(int x1, int y1, int x2, int y2); -void Bdisp_GetDisp_DD(unsigned char *pData); -void Bdisp_GetDisp_VRAM(unsigned char *pData); -void Bdisp_PutDisp_DD(void); -void Bdisp_PutDispArea_DD(const DISPBOX *PutDispArea); -void Bdisp_SetPoint_DD(int x, int y, unsigned char point); -void Bdisp_SetPoint_VRAM(int x, int y, unsigned char point); -void Bdisp_SetPoint_DDVRAM(int x, int y, unsigned char point); -int Bdisp_GetPoint_VRAM(int x, int y); -void Bdisp_WriteGraph_DD(const DISPGRAPH *WriteGraph); -void Bdisp_WriteGraph_VRAM(const DISPGRAPH *WriteGraph); -void Bdisp_WriteGraph_DDVRAM(const DISPGRAPH *WriteGraph); -void Bdisp_ReadArea_DD(const DISPBOX *ReadArea, unsigned char *ReadData); -void Bdisp_ReadArea_VRAM(const DISPBOX *ReadArea, unsigned char *ReadData); -void Bdisp_DrawLineVRAM(int x1, int y1, int x2, int y2); -void Bdisp_ClearLineVRAM(int x1, int y1, int x2, int y2); - -void locate(int x, int y); -void Print(const unsigned char *str); -void PrintRev(const unsigned char *str); -void PrintC(const unsigned char *c); -void PrintRevC(const unsigned char *str); -void PrintLine(const unsigned char *str, int max); -void PrintRLine(const unsigned char *str, int max); -void PrintXY(int x, int y, const unsigned char *str, int type); -int PrintMini(int x, int y, const unsigned char *str, int type); -void SaveDisp(unsigned char num); -void RestoreDisp(unsigned char num); -void PopUpWin(int n); - -int Bfile_OpenFile(const FONTCHARACTER *filename, int mode); -int Bfile_OpenMainMemory(const unsigned char *name); -int Bfile_ReadFile(int HANDLE, void *buf, int size, int readpos); -int Bfile_WriteFile(int HANDLE, const void *buf, int size); -int Bfile_SeekFile(int HANDLE, int pos); -int Bfile_CloseFile(int HANDLE); -int Bfile_GetMediaFree(enum DEVICE_TYPE devicetype, int *freebytes); -int Bfile_GetFileSize(int HANDLE); -int Bfile_CreateFile(const FONTCHARACTER *filename, int size); -int Bfile_CreateDirectory(const FONTCHARACTER *pathname); -int Bfile_CreateMainMemory(const unsigned char *name); -int Bfile_RenameMainMemory(const unsigned char *oldname, const unsigned char *newname); -int Bfile_DeleteFile(const FONTCHARACTER *filename); -int Bfile_DeleteDirectory(const FONTCHARACTER *pathname); -int Bfile_DeleteMainMemory(const unsigned char *name); -int Bfile_FindFirst(const FONTCHARACTER *pathname, int *FindHandle, FONTCHARACTER *foundfile, FILE_INFO *fileinfo); -int Bfile_FindNext(int FindHandle, FONTCHARACTER *foundfile, FILE_INFO *fileinfo); -int Bfile_FindClose(int FindHandle); - -void Bkey_Set_RepeatTime(long FirstCount, long NextCount); -void Bkey_Get_RepeatTime(long *FirstCount, long *NextCount); -void Bkey_Set_RepeatTime_Default(void); -int GetKeyWait(int sel, int time, int menu, unsigned int *keycode); -int IsKeyDown(int keycode); -int IsKeyUp(int keycode); -int GetKey(unsigned int *keycode); - -int SetTimer(int ID, int elapse, void (*hander)(void)); -int KillTimer(int ID); -void Sleep(int millisecond); - -void SetQuitHandler(void (*callback)(void)); -int INIT_ADDIN_APPLICATION(int isAppli, unsigned short OptionNum); - - -#endif - -#ifdef __cplusplus -} -#endif diff --git a/debug/include/keybios.h b/debug/include/keybios.h deleted file mode 100644 index 848fa5f..0000000 --- a/debug/include/keybios.h +++ /dev/null @@ -1,158 +0,0 @@ -/*****************************************************************/ -/* */ -/* CASIO fx-9860G SDK Library */ -/* */ -/* File name : keybios.h */ -/* */ -/* Copyright (c) 2006 CASIO COMPUTER CO., LTD. */ -/* */ -/*****************************************************************/ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef __KEYBIOS_H__ -#define __KEYBIOS_H__ - - -// Defines - -// Character codes -#define KEY_CHAR_0 0x30 -#define KEY_CHAR_1 0x31 -#define KEY_CHAR_2 0x32 -#define KEY_CHAR_3 0x33 -#define KEY_CHAR_4 0x34 -#define KEY_CHAR_5 0x35 -#define KEY_CHAR_6 0x36 -#define KEY_CHAR_7 0x37 -#define KEY_CHAR_8 0x38 -#define KEY_CHAR_9 0x39 -#define KEY_CHAR_DP 0x2e -#define KEY_CHAR_EXP 0x0f -#define KEY_CHAR_PMINUS 0x87 -#define KEY_CHAR_PLUS 0x89 -#define KEY_CHAR_MINUS 0x99 -#define KEY_CHAR_MULT 0xa9 -#define KEY_CHAR_DIV 0xb9 -#define KEY_CHAR_FRAC 0xbb -#define KEY_CHAR_LPAR 0x28 -#define KEY_CHAR_RPAR 0x29 -#define KEY_CHAR_COMMA 0x2c -#define KEY_CHAR_STORE 0x0e -#define KEY_CHAR_LOG 0x95 -#define KEY_CHAR_LN 0x85 -#define KEY_CHAR_SIN 0x81 -#define KEY_CHAR_COS 0x82 -#define KEY_CHAR_TAN 0x83 -#define KEY_CHAR_SQUARE 0x8b -#define KEY_CHAR_POW 0xa8 -#define KEY_CHAR_IMGNRY 0x7f50 -#define KEY_CHAR_LIST 0x7f51 -#define KEY_CHAR_MAT 0x7f40 -#define KEY_CHAR_EQUAL 0x3d -#define KEY_CHAR_PI 0xd0 -#define KEY_CHAR_ANS 0xc0 -#define KEY_CHAR_LBRCKT 0x5b -#define KEY_CHAR_RBRCKT 0x5d -#define KEY_CHAR_LBRACE 0x7b -#define KEY_CHAR_RBRACE 0x7d -#define KEY_CHAR_CR 0x0d -#define KEY_CHAR_CUBEROOT 0x96 -#define KEY_CHAR_RECIP 0x9b -#define KEY_CHAR_ANGLE 0x7f54 -#define KEY_CHAR_EXPN10 0xb5 -#define KEY_CHAR_EXPN 0xa5 -#define KEY_CHAR_ASIN 0x91 -#define KEY_CHAR_ACOS 0x92 -#define KEY_CHAR_ATAN 0x93 -#define KEY_CHAR_ROOT 0x86 -#define KEY_CHAR_POWROOT 0xb8 -#define KEY_CHAR_SPACE 0x20 -#define KEY_CHAR_DQUATE 0x22 -#define KEY_CHAR_VALR 0xcd -#define KEY_CHAR_THETA 0xce -#define KEY_CHAR_A 0x41 -#define KEY_CHAR_B 0x42 -#define KEY_CHAR_C 0x43 -#define KEY_CHAR_D 0x44 -#define KEY_CHAR_E 0x45 -#define KEY_CHAR_F 0x46 -#define KEY_CHAR_G 0x47 -#define KEY_CHAR_H 0x48 -#define KEY_CHAR_I 0x49 -#define KEY_CHAR_J 0x4a -#define KEY_CHAR_K 0x4b -#define KEY_CHAR_L 0x4c -#define KEY_CHAR_M 0x4d -#define KEY_CHAR_N 0x4e -#define KEY_CHAR_O 0x4f -#define KEY_CHAR_P 0x50 -#define KEY_CHAR_Q 0x51 -#define KEY_CHAR_R 0x52 -#define KEY_CHAR_S 0x53 -#define KEY_CHAR_T 0x54 -#define KEY_CHAR_U 0x55 -#define KEY_CHAR_V 0x56 -#define KEY_CHAR_W 0x57 -#define KEY_CHAR_X 0x58 -#define KEY_CHAR_Y 0x59 -#define KEY_CHAR_Z 0x5a - - -// Control codes -#define KEY_CTRL_NOP 0 -#define KEY_CTRL_EXE 30004 -#define KEY_CTRL_DEL 30025 -#define KEY_CTRL_AC 30015 -#define KEY_CTRL_FD 30046 -#define KEY_CTRL_XTT 30001 -#define KEY_CTRL_EXIT 30002 -#define KEY_CTRL_SHIFT 30006 -#define KEY_CTRL_ALPHA 30007 -#define KEY_CTRL_OPTN 30008 -#define KEY_CTRL_VARS 30016 -#define KEY_CTRL_UP 30018 -#define KEY_CTRL_DOWN 30023 -#define KEY_CTRL_LEFT 30020 -#define KEY_CTRL_RIGHT 30021 -#define KEY_CTRL_F1 30009 -#define KEY_CTRL_F2 30010 -#define KEY_CTRL_F3 30011 -#define KEY_CTRL_F4 30012 -#define KEY_CTRL_F5 30013 -#define KEY_CTRL_F6 30014 -#define KEY_CTRL_CATALOG 30100 -#define KEY_CTRL_CAPTURE 30055 -#define KEY_CTRL_CLIP 30050 -#define KEY_CTRL_PASTE 30036 -#define KEY_CTRL_INS 30033 -#define KEY_CTRL_MIXEDFRAC 30054 -#define KEY_CTRL_FRACCNVRT 30026 -#define KEY_CTRL_QUIT 30029 -#define KEY_CTRL_PRGM 30028 -#define KEY_CTRL_SETUP 30037 -#define KEY_CTRL_PAGEUP 30052 -#define KEY_CTRL_PAGEDOWN 30053 -#define KEY_CTRL_MENU 30003 -#define KEY_CTRL_RESERVE1 30060 -#define KEY_CTRL_RESERVE2 30061 -#define KEY_CTRL_RESERVE3 30062 - - -// in Bkey_GetKeyWait function -#define KEYWAIT_HALTON_TIMEROFF 0 -#define KEYWAIT_HALTOFF_TIMEROFF 1 -#define KEYWAIT_HALTON_TIMERON 2 - -#define KEYREP_NOEVENT 0 -#define KEYREP_KEYEVENT 1 -#define KEYREP_TIMEREVENT 2 - - -#endif - -#ifdef __cplusplus -} -#endif diff --git a/debug/include/timer.h b/debug/include/timer.h deleted file mode 100644 index 286f665..0000000 --- a/debug/include/timer.h +++ /dev/null @@ -1,31 +0,0 @@ -/*****************************************************************/ -/* */ -/* CASIO fx-9860G SDK Library */ -/* */ -/* File name : timer.h */ -/* */ -/* Copyright (c) 2006 CASIO COMPUTER CO., LTD. */ -/* */ -/*****************************************************************/ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef __TIMER_H__ -#define __TIMER_H__ - - -// Defines - -#define ID_USER_TIMER1 1 -#define ID_USER_TIMER2 2 -#define ID_USER_TIMER3 3 -#define ID_USER_TIMER4 4 -#define ID_USER_TIMER5 5 - -#endif - -#ifdef __cplusplus -} -#endif diff --git a/debug/libfx.a b/debug/libfx.a deleted file mode 100644 index 5ef92aaf7eaf3afca041f8f64511d0caf86c42e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 410910 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 z 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 s0r9OE?c!NrzMIs{8f91wQ* -#include - -void vsprintf_int(char **buffer_ptr, int n) -{ - char *buffer = *buffer_ptr; - if(!n) - { - *buffer++ = '0'; - *buffer_ptr = buffer; - return; - } - if(n < 0) - { - *buffer++ = '-'; - n = -n; - } - - int digits = 0, x = n, copy; - while(x) digits++, x /= 10; - copy = digits; - - while(digits) - { - buffer[--digits] = n % 10 + '0'; - n /= 10; - } - - *buffer_ptr = buffer + copy; -} - -void vsprintf_hexa(char **buffer_ptr, uint32_t val, int digits, int zero) -{ - char *buffer = *buffer_ptr; - if(!val) - { - while(digits-- > 1) *buffer++ = (zero) ? '0' : ' '; - *buffer++ = '0'; - *buffer_ptr = buffer; - return; - } - - if(digits <= 0) - { - uint32_t x = val; - while(x) digits++, x >>= 4; - } - int copy = digits; - - while(val && digits) - { - buffer[--digits] = (val & 15) + '0' + 39 * ((val & 15) > 9); - val >>= 4; - } - while(digits) - { - buffer[--digits] = (zero) ? '0': ' '; - } - - *buffer_ptr = buffer + copy; -} - -void vsprintf_ptr(char **buffer_ptr, void *ptr) -{ - vsprintf_hexa(buffer_ptr, (uint32_t)ptr, 8, 1); -} - -void vsprintf_char(char **buffer_ptr, int c) -{ - char *buffer = *buffer_ptr; - *buffer++ = c; - *buffer_ptr = buffer; -} - -void vsprintf_str(char **buffer_ptr, const char *str) -{ - char *buffer = *buffer_ptr; - while(*str) *buffer++ = *str++; - *buffer_ptr = buffer; -} - -int vsprintf(char *buffer, const char *format, va_list args) -{ - char *save = buffer; - int zero, count; - - while(*format) - { - if(*format != '%') - { - *buffer++ = *format++; - continue; - } - if(!*++format) break; - - zero = 0; - count = 0; - - if(*format == '0') zero = 1, format++; - while(*format >= '0' && *format <= '9') - { - count *= 10; - count += (*format++ - '0'); - } - if(!*format) break; - - switch(*format) - { - case 'd': - vsprintf_int(&buffer, va_arg(args, int)); - break; - case 'x': - vsprintf_hexa(&buffer, va_arg(args, uint32_t), count, - zero); - break; - case 'p': - vsprintf_ptr(&buffer, va_arg(args, void *)); - break; - case 'c': - vsprintf_char(&buffer, va_arg(args, int)); - break; - case 's': - vsprintf_str(&buffer, va_arg(args, const char *)); - break; - default: - *buffer++ = *format; - break; - } - - format++; - } - - *buffer = 0; - return buffer - save; -} - -int sprintf(char *buffer, const char *format, ...) -{ - va_list args; - va_start(args, format); - int x = vsprintf(buffer, format, args); - va_end(args); - - return x; -} diff --git a/demo/gintdemo.c b/demo/gintdemo.c index cfc653d..4655bf6 100644 --- a/demo/gintdemo.c +++ b/demo/gintdemo.c @@ -277,8 +277,7 @@ void tlb_debug(void) } */ -#include -#include +#include /* main_menu() @@ -435,14 +434,11 @@ void main_menu(int *category, int *app) index = 0; scroll = 0; break; - case KEY_F5: - gint_switch(); - break; - case KEY_F6:; +/* case KEY_F6:; void screen(void); screen(); break; - +*/ case KEY_UP: if(list && list_len > 1) { @@ -484,11 +480,6 @@ void main_menu(int *category, int *app) if(app) *app = index + 1; return; -/* case KEY_MENU: - if(category) *category = 0; - if(app) *app = 0; - return; -*/ default: leave = 0; } @@ -533,7 +524,7 @@ int main(void) return 0; } -void crash(void) +static void crash(void) { __asm__( "mov #0, r0 \n\t" @@ -542,7 +533,7 @@ void crash(void) ); } -void screen(void) +static void screen(void) { enum { File = 1, Folder = 5 }; enum { Read = 0x01, Write = 0x02, ReadWrite = Read | Write }; diff --git a/demo/gintdemo.ld b/demo/gintdemo.ld index 7a7d11e..5df3f76 100644 --- a/demo/gintdemo.ld +++ b/demo/gintdemo.ld @@ -13,36 +13,32 @@ ENTRY(_start) MEMORY { + /* System-managed mappings map this area into the add-in data */ rom : o = 0x00300200, l = 512k - /* 0x0810000 is apparently mapped to 0x8801c0000. */ + /* 0x0810000 is apparently mapped to 0x8801c0000 */ ram : o = 0x08100000, l = 8k + /* RAM section from P1 area, no MMU involved */ realram : o = 0x8800d000, l = 12k } SECTIONS { - /* - ROM sections : binary code and read-only data. - */ + /* ROM sections: binary code and read-only data */ .text : { - _btext = . ; - /* Initialization code. */ *(.pretext.entry) *(.pretext) - _bctors = . ; + _bctors = ABSOLUTE(.); *(.ctors) - _ectors = . ; - _bdtors = . ; + _ectors = ABSOLUTE(.); + _bdtors = ABSOLUTE(.); *(.dtors) - _edtors = . ; + _edtors = ABSOLUTE(.); *(.text) *(.text.*) - - _etext = . ; } > rom .rodata : { @@ -55,26 +51,23 @@ SECTIONS _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. - */ + /* RAM sections: bss section and read/write data + The .bss section is to be stripped from the ELF file and wiped at + startup, hence its location is undefined */ .bss : { - _bbss = . ; + _bbss = ABSOLUTE(.); + _sbss = ABSOLUTE(SIZEOF(.bss)); + *(.bss) - _ebss = . ; } > ram .data : AT(_romdata) ALIGN(4) { - _bdata = . ; + _bdata = ABSOLUTE(.); + _sdata = ABSOLUTE(SIZEOF(.data)); + *(.data) *(.data.*) - _edata = . ; } > ram .cc : AT(_romdata + SIZEOF(.data)) ALIGN(4) { @@ -82,33 +75,39 @@ SECTIONS *(.jcr) . = ALIGN(4); - _gint_data = _romdata + SIZEOF(.data) + SIZEOF(.cc) ; } > ram + /* Real RAM sections: interrupt handlers and some *uninitialized* gint + data */ - - /* - Real RAM : interrupt, exception and TLB miss handlers. - */ + _gint_data = _romdata + SIZEOF(.data) + SIZEOF(.cc) ; .gint : AT(_gint_data) ALIGN(4) { - /* The vbr needs to be 0x100-aligned because of an ld issue. */ + /* The vbr needs to be 0x100-aligned because of an ld issue */ . = ALIGN(0x100) ; - _gint_vbr = . ; - _bgint = . ; - /* Exception handler. */ + _gint_vbr = . ; + _bgint = ABSOLUTE(.) ; + + /* Exception handler */ . = _gint_vbr + 0x100 ; *(.gint.exc) - /* TLB miss handler. */ + /* TLB miss handler */ . = _gint_vbr + 0x400 ; *(.gint.tlb) - /* Interrupt handler. */ + /* Interrupt handler */ . = _gint_vbr + 0x600 ; *(.gint.int) - _egint = . ; + . = ALIGN(4); + _egint = ABSOLUTE(.) ; + } > realram + + .gint_bss : AT(_gint_data + SIZEOF(.gint)) ALIGN(4) { + _bgbss = ABSOLUTE(.) ; + *(.gint.bss) + _egbss = ABSOLUTE(.) ; } > realram } diff --git a/demo/resources/font_modern.bmp b/demo/resources/font_modern.bmp index 0340f76caa3294d8fa52e91b46611365384cad91..1286f301f05bad4f17e1def00e15eb2592050cba 100644 GIT binary patch delta 126 zcmex$fbrJ>#to_h6DM4qoDd*1d4eg=#0Iv>a)Mox=LfS*5)|5eKrn-G@&i|)$p@5$ zCKs5CPIk}}n!Esr6GVXgpk$yn(a8elijxgQN`dM)Cm+y}2I-wVL0Nq=wrEJ6-?)6E6M$ delta 143 zcmex$fbrJ>#to_hlQ;NrPBxI`nf$^1z~qDgp~(|Wc_ucnO_mevn!JIZZE}JL&*X#{ zw#^3wGZ-g3xEV~IAIvtn0Vn~aCy7e~<%K2}1SJEticS_VSDb7hQVLcw!B=SV0c9Qt eTUmWFw41@#KO3=}8o^7aTI0qfwRvd8e#Ey30)5y*~ksy>jDbCm)kAIG@r^o5~ zPO|U%KJ^{+-A&K3ddfdN_;X;IjxTQ?Klr!*`%e7&+v|ekNbff0_w0WtoY%fS%%X_4 zGan$=n8>V4m!yGHL_t3Xg{d{@*}^G=lBE~=CS+CTxHWd|`Ohe<1MC8jPR?JpAWJ*Q zq+CLL)}`E4N$xsUfQgGpZvi>g61yV`JGsB7N}Dqqm&ub%N}yo7*YLMtcl)^6vGCIs zri8d_opLZaU7742?q9~XTV}>(a;ivqapD8lA||+;D%@M;X3i=g0J&5T=0R#ZqW+%e79)rskkrDaJ6KC8t_qlTq0G{!FqIaEG!HakjRyX(gMr;LaQ? ckTsAkQV_cGhWBTfMWF1ssMh3NDQtEB3%4y6QUCw| 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}<_xFzWrU> 8; - vl[o + 1] = light << 8; - vd[o] = dark >> 8; - vd[o + 1] = dark << 8; + int offset = (i << 2) + 3; + vl[offset] = -(!(i & 16)); + vd[offset] = -(i < 32); } - locate(3, 3, "light"); - print(4, 4, "%d", delay1); + text_configure(&res_font_modern, color_black); + gtext(13, 17, "light"); + gtext(13, 31, "dark"); - locate(3, 5, "dark"); + text_configure(NULL, color_black); + print(4, 4, "%d", delay1); print(4, 6, "%d", delay2); locate(3, selected ? 6 : 4, "\x02"); diff --git a/demo/test_keyboard.c b/demo/test_keyboard.c index 02ea379..59f0471 100644 --- a/demo/test_keyboard.c +++ b/demo/test_keyboard.c @@ -4,9 +4,8 @@ #include #include -static int draw_keyboard(volatile uint8_t *state) +static void draw_keyboard(volatile uint8_t *state) { - int pressed_keys = 0; int i, j, k, l; int x, y; @@ -30,7 +29,6 @@ static int draw_keyboard(volatile uint8_t *state) // Drawing a filled shape when the key is pressed. if(state[i] & (0x80 >> j)) { - pressed_keys++; 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); @@ -51,8 +49,6 @@ static int draw_keyboard(volatile uint8_t *state) // An horizontal line to separate parts of the keyboard. dline(5, 28, 32, 28, color_black); - - return pressed_keys; } typedef struct { @@ -66,7 +62,7 @@ typedef struct { int pressed; } history_t; -static int pressed_keys = -1; +static int pressed_keys = 0; static int releases = 0; static void history_push(history_t *h, event_t event) @@ -120,19 +116,25 @@ static void draw_events(history_t *h) }; int y = 3; + int y_limit = 8 - (h->pressed > h->size); - print(8, 2, "%d %d %d", pressed_keys, h->pressed, releases); + extern font_t res_font_modern; + text_configure(&res_font_modern, color_black); + dtext(49, 12, "Key"); + dtext(89, 12, "Rep."); + // dprint(49, 7, "%d %d %d", h->pressed, pressed_keys, releases); + text_configure(NULL, color_black); + dline(45, 18, 120, 18, color_black); - for(int i = 0; i < h->size; i++) + for(int i = 0; i < h->size && y < y_limit; i++) if(h->data[i].key) { - if(!h->data[i].key) continue; - print(8, y, "%s", key_names[key_id(h->data[i].key)]); + dtext(49, y * 8 - 4, key_names[key_id(h->data[i].key)]); if(h->data[i].repeats > 1) - print(18, y, "%d", h->data[i].repeats); + dprint(89, y * 8 - 4, "%d", h->data[i].repeats); y++; } - if(h->pressed > h->size) print(8, 8, "(more)"); + if(h->pressed > h->size) dtext(49, 52, "(more)"); } /* @@ -149,15 +151,37 @@ void test_keyboard_events(void) }; event_t event; + // There may be keys pressed when this test starts. We need to detect + // which and create a valid history for them. + volatile const uint8_t *buffer = keyboard_stateBuffer(); + + // For the purpose of this function we don't need to calculate the + // other fields. + event_t push_event = { + .type = event_key_press, + .key.code = KEY_AC_ON, + }; + + // Finding all the pressed keys and pushing them in the history. + if(buffer[0] & 1) history_push(&history, push_event); + for(int row = 1; row <= 9; row++) for(int col = 0; col < 8; col++) + { + // Eliminate non-existing keys. + if(col > 6 || col <= (row <= 4)) continue; + + if(buffer[row] & (1 << col)) + { + push_event.key.code = (col << 4) | row; + history_push(&history, push_event); + } + } + while(1) { dclear(); locate(1, 1, "Keyboard and events"); - // There may be more than zero keys pressed when this test - // starts. We need to detect this count automatically. - int x = draw_keyboard(keyboard_stateBuffer()); - if(pressed_keys < 0) pressed_keys = x; + draw_keyboard(keyboard_stateBuffer()); draw_events(&history); dupdate(); diff --git a/include/events.h b/include/events.h index a30729a..b4bce55 100644 --- a/include/events.h +++ b/include/events.h @@ -49,14 +49,14 @@ typedef struct { // This is the key code as defined in (a matrix code), and // probably what you need. - uint32_t code; + uint16_t code; // This is a "compact id" which can be used for array subscript. There // are only a few holes in the "compact id" numbering. - uint32_t id; + uint16_t id; // Character associated with the event key. int character; -} key_event_t; +} __attribute__((packed, aligned(4))) key_event_t; /* event_t @@ -77,7 +77,7 @@ typedef struct timer_t *timer; }; -} event_t; +} __attribute__((packed, aligned(4))) event_t; diff --git a/include/internals/gint.h b/include/internals/gint.h index fd51e06..6e7ed83 100644 --- a/include/internals/gint.h +++ b/include/internals/gint.h @@ -2,6 +2,7 @@ #define _INTERNALS_GINT_H #include +#include #include //--- @@ -45,7 +46,7 @@ void gint_setvbr(uint32_t vbr, void (*setup)(void)); Initializes gint. Loads the interrupt handler into the memory and sets the new vbr address. */ -void gint_init(void); +void gint_init(mpu_t mpu); /* gint_quit() @@ -135,101 +136,4 @@ void gint_restore_and_unlock_7305(environment_7305_t *env); volatile void *gint_reg_7705(gint_register_t reg); volatile void *gint_reg_7305(gint_register_t reg); - - -//--- -// Diagnostics -// When diagnostics are enabled, gint saves runtime information to a -// buffer in RAM, which by chance is held if the application crashes (I -// don't really know why). This allows deeper debugging. -//--- - -#ifdef GINT_DIAGNOSTICS - -#include - -// Determining whether the SaveDisp() buffer actually contains gint diagnostics -// is performed by checking a magic number (1/256 chance of failure) and the -// validity of all fields in the diagnostic information. Formally, a picture -// taken by SaveDisp() could fool the checks but this is *very* unlikely and -// the diagnostics should only be read just after gint crashes or stops anyway. -#define GINT_DIAGNOSTICS_MAGIC 0xb7 - -typedef enum -{ - stage_startup = 0, - stage_sections = 1, - stage_mmu = 2, - stage_gint = 3, - stage_clock = 4, - stage_ctors = 5, - stage_running = 6, - stage_leaving = 7, - stage_dtors = 8, - stage_terminated = 9, - -} gint_stage_t; - -typedef struct -{ - uint32_t address; - uint32_t length; - -} gint_memsection_t; - -typedef struct -{ - // Magic number to check whether there is a diagnostic. - uint8_t magic :8; - // Unique counter that is incremented at each execution, allowing to - // distinguish diagnostics output at different times if the application - // crashes repeatedly. - uint8_t counter :8; - // How many work of initialization had been successfully done before - // the application crashed. - gint_stage_t stage :8; - // What kind of MPU the library detected (undefined if the - // initialization stage does not reach stage_gint). - mpu_t mpu :8; - - // Frequency of the main clocks, in MHz. - uint8_t Bphi_f :8; - uint8_t Iphi_f :8; - uint8_t Pphi_f :8; - - // What kind of exceptions occurred last. - uint8_t excepts :8; - uint8_t except_vect[12]; - // Last values held by registers SPC, SSR, EXPEVT / INTEVT2 / INTEVT, - // and TEA. - uint32_t spc; - uint32_t ssr; - uint32_t expevt; - uint32_t tea; - - // Gint version number, on the form 0xMMmmbbbb, where MM is the major - // version, mm the minor version and bbbb the build number. - uint32_t version; - // Location of the VBR at the time of execution. - uint32_t vbr_address; - - // Memory map. - uint32_t romdata; - gint_memsection_t section_text; - gint_memsection_t section_data; - gint_memsection_t section_bss; - gint_memsection_t section_gint; - -} gint_diagnostics_t; - -// This is somewhere inside the buffers of SaveDisp(), 3 bytes inside the first -// buffer to be exact (that's to be 4-aligned). -// This buffer is 1024-byte long so the logs must fit in 1021 bytes to be safe. -// It looks like that this RAM area is generally not cleared when the -// calculator reboots after a crash, even though it does not seem to work with -// manual resets. Maybe it can provide useful information in some cases. -#define gint_diagnostics() ((volatile gint_diagnostics_t *)0x88004d90) - -#endif // GINT_DIAGNOSTICS - #endif // _INTERNALS_GINT_H diff --git a/include/internals/init.h b/include/internals/init.h new file mode 100644 index 0000000..66b3b29 --- /dev/null +++ b/include/internals/init.h @@ -0,0 +1,37 @@ +//--- +// gint core module: init +// Program initialization and display manipulation for the startup logs. +//--- + +#ifndef _INTERNALS_INIT_H +#define _INTERNALS_INIT_H + +#include + +struct qdiv +{ + uint32_t q, r; +}; + +/* qdiv10() -- quickly divide by 10 */ +struct qdiv qdiv10(uint32_t n); + +/* init_version() -- get a version string */ +const char *init_version(void); + +/* init_stage() -- change the current init stage */ +void init_stage(const char *name); + +/* init_halt() -- halt the program */ +void init_halt(void); + +/* print() -- print text on a 21*8 grid */ +#define print(x, y, str) dtext((x) * 6 - 5, (y) * 8 - 8, (str)) + +/* print_dec() -- print a number in base 10 */ +void print_dec(int x, int y, int n, int digits); + +/* print_hex() -- print a number in base 16 */ +void print_hex(int x, int y, uint32_t n, int digits); + +#endif // _INTERNALS_INIT_H diff --git a/include/internals/keyboard.h b/include/internals/keyboard.h index 2ed7f9e..01d24eb 100644 --- a/include/internals/keyboard.h +++ b/include/internals/keyboard.h @@ -39,4 +39,11 @@ int getPressedKeys(volatile uint8_t *keyboard_state, int *keys, int count); void keyboard_updateState_7705(volatile uint8_t *state); void keyboard_updateState_7305(volatile uint8_t *state); +/* + keyboard_interrupt() + Answers an interrupt event by updating the keyboard state and + generating the associated keyboard events. +*/ +void keyboard_interrupt(void); + #endif // _INTERNALS_KEYBOARD_H diff --git a/include/internals/syscalls.h b/include/internals/syscalls.h new file mode 100644 index 0000000..ae05b78 --- /dev/null +++ b/include/internals/syscalls.h @@ -0,0 +1,26 @@ +//--- +// gint core module: syscalls +// Some of the functionality still requires interacting with the system. +//--- + +#ifndef _INTERNALS_SYSCALLS_H +#define _INTERNALS_SYSCALLS_H + +#include + +/* malloc() -- allocate data in heap */ +void *__malloc(size_t size); + +/* free() -- free data allocated by malloc(), calloc() or realloc() */ +void __free(void *ptr); + +/* realloc() -- reallocate a chunk of memory */ +void *__realloc(void *chunk, size_t new_size); + +/* get_os_version() -- write the OS version in format MM.mm.pppp to a string */ +void __get_os_version(char *str); + +/* system_menu() -- go back to menu, assuming the system has the control */ +void __system_menu(const void *vram); + +#endif // _INTERNALS_SYSCALLS_H diff --git a/include/internals/tales.h b/include/internals/tales.h index a599d4c..455246d 100644 --- a/include/internals/tales.h +++ b/include/internals/tales.h @@ -10,13 +10,6 @@ extern font_t *font; extern color_t operator; -/* - tales_init() - Configures tales with the default font (which is part of gint). -*/ -__attribute__((constructor)) -void tales_init(void); - /* getCharacterIndex() Returns the index of a character in a font data area depending on the diff --git a/include/internals/timer.h b/include/internals/timer.h index c169a6e..8e4feec 100644 --- a/include/internals/timer.h +++ b/include/internals/timer.h @@ -11,11 +11,9 @@ */ typedef struct timer_t { - // Current delay, how much time elapsed since last interrupt occurred, - // and how many repeats are left. - int ms_delay; - int ms_elapsed; - int repeats_left; + // Current delay, how much time elapsed since last interrupt occurred. + uint32_t ms_delay; + uint32_t ms_elapsed; // Is the virtual slot free? Is the virtual timer active? uint8_t used :1; @@ -25,12 +23,14 @@ typedef struct timer_t uint8_t vsupport :1; // How many events do I have received but not executed? uint8_t events :4; + // How many repeats are left. + uint32_t repeats_left :24; // Callback function (NULL for event-firing timers) and its argument. void *callback; void *argument; -} timer_t; +} __attribute__((packed, aligned(4))) timer_t; // Hardware timers. extern timer_t htimers[3]; diff --git a/include/mpu.h b/include/mpu.h index d62919c..8b7219d 100644 --- a/include/mpu.h +++ b/include/mpu.h @@ -12,8 +12,8 @@ // care of assuming unknown MPUs are SH4, which is the more reasonable // option. // -// In a general way, it is advised to always use the following -// alternative (which gint does): +// It is advised to always use the following alternative (which gint +// does): // // if(isSH3()) // { @@ -54,7 +54,7 @@ extern const mpu_t 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() +#define isSH4() (!isSH3()) diff --git a/src/core/crt0.c b/src/core/crt0.c deleted file mode 100644 index 618af26..0000000 --- a/src/core/crt0.c +++ /dev/null @@ -1,253 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -int main(void); - -static void init(void); -static void fini(void); - -// Symbols provided by the linker script. -extern uint32_t - etext, btext, // Location of .text section - bdata, edata, // Location of .data section - bbss, ebss, // Location of .bss section - bgint, egint, // Location of interrupt handler and gint data - gint_vbr, // VBR address - romdata; // ROM address of .data section contents - -// 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. -*/ -__attribute__((section(".pretext.entry"))) int start(void) -{ - #ifdef GINT_DIAGNOSTICS - - // OK, so fill as much information as possible so that in case anything - // goes wrong we can try to analyze what's been going on. - volatile gint_diagnostics_t *dg = gint_diagnostics(); - - // All that follows is "safe" information that can be saved immediately - // because it will never change anyway. - // Basic environment description. - dg->magic = GINT_DIAGNOSTICS_MAGIC; - dg->counter = dg->counter + 1; - dg->mpu = mpu_unknown; - dg->version = (uint32_t)&GINT_VERSION; - dg->stage = stage_startup; - - // Exception records: what kind of exceptions / TLB faults / interrupts - // occurred last to get some trace in case of crash. - dg->excepts = 0; - for(size_t i = 0; i < sizeof dg->except_vect; i++) - dg->except_vect[i] = 0; - dg->spc = 0x00000000; - dg->ssr = 0x00000000; - dg->expevt = 0x00000000; - dg->tea = 0x00000000; - - // Memory map: provides information about alignment and the relative - // size and position of each section, as well as read-only / read-write - // types of addresses. - dg->section_text.address = (uint32_t)&btext; - dg->section_text.length = (uint32_t)&etext - (uint32_t)&btext; - dg->section_data.address = (uint32_t)&bdata; - dg->section_data.length = (uint32_t)&edata - (uint32_t)&bdata; - dg->section_bss.address = (uint32_t)&bbss; - dg->section_bss.length = (uint32_t)&ebss - (uint32_t)&bbss; - dg->romdata = (uint32_t)&romdata; - - // Basic information about the running library. - dg->vbr_address = (uint32_t)&gint_vbr; - dg->section_gint.address = (uint32_t)&bgint; - dg->section_gint.length = (uint32_t)&egint - (uint32_t)&bgint; - #endif - - // Clearing the .bss section. - uint32_t *bss = &bbss; - while(bss < &ebss) *bss++ = 0; - - // Copying the .data section. - uint32_t *data = &bdata, *src = &romdata; - while(data < &edata) *data++ = *src++; - - #ifdef GINT_DIAGNOSTICS - dg->stage = stage_sections; - #endif - - // Trying to get the system to fill the TLB without editing it - // directly, so that it does not go on rampage when finding out. - mmu_pseudoTLBInit(); - - #ifdef GINT_DIAGNOSTICS - // At this point it would be wise to include a copy of the TLB, but - // it's already a huge array. Maybe later... - /* TODO Debug TLB? */ - dg->stage = stage_mmu; - #endif - - // Initializing gint, which does several things: - // - Detect the MPU and platform - // - Initialize register addresses in a platform-independent way - // - Save the current environment information in a large buffer - // - Set up the interrupt handler and configure everything gint needs - gint_init(); - - #ifdef GINT_DIAGNOSTICS - dg->mpu = MPU_CURRENT; - dg->stage = stage_gint; - #endif - - // Measuring clock frequencies. - clock_measure(); - clock_measure_end(); - - #ifdef GINT_DIAGNOSTICS - clock_config_t clock = clock_config(); - dg->Bphi_f = clock.Bphi_f / 1000000; - dg->Iphi_f = clock.Iphi_f / 1000000; - dg->Pphi_f = clock.Pphi_f / 1000000; - dg->stage = stage_clock; - #endif - - // Calling global constructors. - init(); - - #ifdef GINT_DIAGNOSTICS - dg->stage = stage_ctors; - dg->stage = stage_running; - #endif - - // Saving the execution state there. - int 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(); - - - - #ifdef GINT_DIAGNOSTICS - dg->stage = stage_leaving; - #endif - - /* TODO Flush and close opened streams. */ - - // Calling exit handlers and destructors. - while(atexit_index > 0) (*atexit_handlers[--atexit_index])(); - fini(); - - #ifdef GINT_DIAGNOSTICS - dg->stage = stage_dtors; - #endif - - // Un-initializing gint. - gint_quit(); - - #ifdef GINT_DIAGNOSTICS - dg->stage = stage_terminated; - #endif - - 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/core/init_quit.c b/src/core/init_quit.c index 6103f41..4d92d5c 100644 --- a/src/core/init_quit.c +++ b/src/core/init_quit.c @@ -21,11 +21,11 @@ static void setup(void) isSH3() ? gint_lock_and_setup_7705() : gint_lock_and_setup_7305(); } -void gint_init(void) +void gint_init(mpu_t mpu) { - // Detecting the MPU type. I don't like const-casting but this is still + // Setting the MPU type. I don't like const-casting but this is still // better than allowing the user to change the variable by mistake. - *((mpu_t *)&MPU_CURRENT) = getMPU(); + *((mpu_t *)&MPU_CURRENT) = mpu; // Loading the register addresses of the current platform. mod_init(); @@ -89,23 +89,29 @@ void gint_quit(void) #include #include +/* + __system_menu() + Updates the system's vram and triggers the calculator's main menu. +*/ +void __system_menu(void *vram); + +// Stores gint's configuration while the user visits the main menu. +static environment_t switch_env; + /* gint_switch() Temporarily returns to the system's main menu. */ -static environment_t switch_env; -static void switch_(void) +static void restore(void) { isSH3() ? gint_restore_and_unlock_7705(&switch_env.env_7705) : gint_restore_and_unlock_7305(&switch_env.env_7305); } void gint_switch(void) { - // Save the current environment in a special buffer, so that we can - // restore it if we ever come back to gint. isSH3() ? gint_save_7705(&switch_env.env_7705) : gint_save_7305(&switch_env.env_7305); - // Give the control back to the system. + gint_setvbr(gint.system_vbr, stop); // When returning to the add-in from the menu, the system displays the @@ -120,5 +126,5 @@ void gint_switch(void) __system_menu(vram); // If the user came back, restore the gint working environment. - gint_setvbr(gint.gint_vbr, switch_); + gint_setvbr(gint.gint_vbr, restore); } diff --git a/src/core/mpu.c b/src/core/mpu.c index 889e5a7..73d0a46 100644 --- a/src/core/mpu.c +++ b/src/core/mpu.c @@ -9,7 +9,8 @@ #include #include -const mpu_t MPU_CURRENT; +/* Located in gint's uninitialized bss section */ +__attribute__((section(".gint.bss"))) const mpu_t MPU_CURRENT; /* getMPU() diff --git a/src/core/syscalls.s b/src/core/syscalls.s index 960c2de..ad7f984 100644 --- a/src/core/syscalls.s +++ b/src/core/syscalls.s @@ -1,14 +1,25 @@ /* 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! + System calls (and the like) used by the library. The library should + rely the least possible on the system, but sometimes using the syscalls + is nothing of a nuisance. + + For instance, using the malloc()-family syscalls is a bit annoying + because it "locks" many functionalities. On the other hand, getting the + SaveDisp() buffer addresses to store data here is not a problem since + such data can very easily be relocated to static RAM. */ + /* Dynamic allocation */ .global ___malloc .global ___free .global ___realloc + + /* OS version */ + .global ___get_os_version + + /* Return to menu */ .global ___system_menu @@ -34,6 +45,13 @@ ___realloc: nop 1: .long 0xe6d +___get_os_version: + mov.l syscall_table, r2 + mov.l 1f, r0 + jmp @r2 + nop +1: .long 0x02ee + /* __system_menu() Brings one back to the system menu by putting KEY_MENU in the system's diff --git a/src/display/display_vram.c b/src/display/display_vram.c index 34ab168..c0c48ed 100644 --- a/src/display/display_vram.c +++ b/src/display/display_vram.c @@ -1,9 +1,8 @@ #include -// Program video ram. It resides in BSS section, therefore it is cleared at -// program initialization and stripped from the executable file. -static uint32_t local_vram[256]; -uint32_t *vram = local_vram; +/* Add-in monochrome vram in gint's uninitialized bss section */ +__attribute__((section(".gint.bss"))) static uint32_t vram_local[256]; +__attribute__((section(".gint.bss"))) uint32_t *vram; /* display_getLocalVRAM() @@ -16,7 +15,7 @@ uint32_t *vram = local_vram; */ inline uint32_t *display_getLocalVRAM(void) { - return local_vram; + return vram_local; } /* @@ -43,6 +42,6 @@ inline uint32_t *display_getCurrentVRAM(void) */ inline void display_useVRAM(uint32_t *ptr) { - if((intptr_t)ptr & 3) return; + if((uintptr_t)ptr & 3) return; vram = ptr; } diff --git a/src/gray/gray_engine.c b/src/gray/gray_engine.c index 8e9d207..666b725 100644 --- a/src/gray/gray_engine.c +++ b/src/gray/gray_engine.c @@ -10,9 +10,12 @@ #include #include #include +#include // Additional video rams used by the gray engine. -static uint32_t internal_vrams[3][256]; +#ifdef GINT_STATIC_GRAY +static uint32_t internals_vrams[3][256]; +#endif static uint32_t *vrams[4]; // Current vram set (0 or 1), delays of the light and dark frames respectively. @@ -31,10 +34,7 @@ static timer_t *gray_timer = NULL; // Interrupt control and initialization. //--- -/* - gray_interrupt() - Answers a timer interrupt. Swaps the buffers. -*/ +/* gray_interrupt() -- switch buffers and update the screen */ void gray_interrupt(void) { htimer_reload(timer_gray, delays[(~current) & 1]); @@ -43,21 +43,33 @@ void gray_interrupt(void) current ^= 1; } -/* - gray_init() - Initializes the gray engine. -*/ -__attribute__((constructor)) void gray_init(void) +/* gray_init() -- setup the video ram buffers and timer delays */ +__attribute__((constructor)) static void gray_init(void) { vrams[0] = display_getLocalVRAM(); +#ifdef GINT_STATIC_GRAY vrams[1] = internal_vrams[0]; vrams[2] = internal_vrams[1]; vrams[3] = internal_vrams[2]; - +#else + vrams[1] = NULL; + vrams[2] = NULL; + vrams[3] = NULL; +#endif delays[0] = 912; delays[1] = 1343; } +/* gray_quit() -- Free the gray engine's heap-allocated video rams */ +__attribute__((destructor)) static void gray_quit(void) +{ +#ifndef GINT_STATIC_GRAY + free(vrams[1]); + free(vrams[2]); + free(vrams[3]); +#endif +} + //--- @@ -71,6 +83,14 @@ __attribute__((constructor)) void gray_init(void) */ void gray_start(void) { +#ifndef GINT_STATIC_GRAY + for(int i = 0; i < 4; i++) + { + if(!vrams[i]) vrams[i] = malloc(1024); + /* Don't continue if any of the buffer is missing */ + if(!vrams[i]) return; + } +#endif if(runs) return; gray_timer = htimer_setup(timer_gray, delays[0], timer_Po_64, 0); diff --git a/src/init/crt0.c b/src/init/crt0.c new file mode 100644 index 0000000..92ccc69 --- /dev/null +++ b/src/init/crt0.c @@ -0,0 +1,306 @@ +#include +#include + +#include +#include +#include + +#include +#include +#include + +/* We need some more functionality to generate these */ +#ifdef GINT_STARTUP_LOG + #include + #include + #include + #include + #include + + #ifndef GINT_NO_SYSCALLS + #include + #endif +#endif + +int main(void); + +static void init(void); +static void fini(void); + +// Symbols provided by the linker script. +extern uint32_t + bdata, sdata, // Location of .data section + bbss, sbss, // Location of .bss section + bgint, egint, // Location of interrupt handler and gint data + bgbss, egbss, // Location of interrupt handler and gint data + gint_vbr, // VBR address + romdata, // ROM address of .data section contents + gint_data; // ROM address of .gint section contents +extern void + (*bctors)(void), (*ectors)(void), // Constructors + (*bdtors)(void), (*edtors)(void); // Destructors + +// 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. +static void (*atexit_handlers[ATEXIT_MAX])(void); +static int atexit_index = 0; + +#include + +/* + start() + Program entry point. Loads the data section into the memory and invokes + main(). Also prepares the execution environment by initializing all the + modules. +*/ +__attribute__((section(".pretext.entry"))) int start(void) +{ + /* Configure the display output or we won't get anywhere - this is also + needed for the add-in even if the startup logs are disabled */ + display_useVRAM(display_getLocalVRAM()); + text_configure(NULL, color_black); + +#ifdef GINT_STARTUP_LOG + /* Start outputting information on the screen so that we can quickly + debug anything that would fail */ + uint32_t rom_size = ((uint32_t)&romdata - 0x00300000) >> 10; + uint32_t ram_size = ((uint32_t)&gint_data - (uint32_t)&romdata) + + ((uint32_t)&sbss); + uint32_t rram_size = ((uint32_t)&egbss - (uint32_t)&gint_vbr); + + dclear(); + init_stage("Startup"); + dupdate(); + + print(1, 1, init_version()); + print(1, 2, "ROM RAM RRAM"); + print(4, 3, "k c d"); + print_dec(1, 3, rom_size, 3); + print_dec(6, 3, ram_size, 4); + print_dec(11, 3, rram_size, 4); + print_dec(17, 3, &ectors - &bctors, 2); + print_dec(20, 3, &edtors - &bdtors, 2); + dupdate(); +#endif + + /* Determining the processor type */ + mpu_t mpu = getMPU(); + +#ifdef GINT_STARTUP_LOG + const char *mpu_names[] = { "SH7337", "SH7355", "SH7305", "SH7724" }; + if(mpu >= 1 && mpu <= 4) print(16, 2, mpu_names[mpu - 1]); + else print_dec(16, 2, mpu, 6); + dupdate(); +#endif + + /* Make sure the MPU is of a valid type */ + if(!mpu || mpu > 4) init_halt(); + +#ifdef GINT_STARTUP_LOG + init_stage(" MMU"); + dupdate(); +#endif + + /* Try to get the TLB filled by the system by accessing all the pages + while the system still answers TLB misses */ + mmu_pseudoTLBInit(); + +#ifdef GINT_STARTUP_LOG + /* Read the TLB and count how much memory has been mapped */ + /* TODO: Debug TLB at startup */ + print(1, 4, "MMU ROM:???k RAM:???k"); + + init_stage("Section"); + dupdate(); +#endif + + /* Copying the data section, then clearing the bss section. This + doesn't affect the previously used variables, which are stored in + another section for this purpose */ + volatile uint32_t *data = &bdata; + volatile uint32_t *data_end = (void *)&bdata + (int)&sdata; + volatile uint32_t *src = &romdata; + while(data < data_end) *data++ = *src++; + volatile uint32_t *bss = &bbss; + volatile uint32_t *bss_end = (void *)&bbss + (int)&sbss; + while(bss < bss_end) *bss++ = 0; + +#ifdef GINT_STARTUP_LOG + init_stage("Handler"); + dupdate(); +#endif + + /* Initialize gint and debug all the interrupt priorities */ + gint_init(mpu); + +#ifdef GINT_STARTUP_LOG + if(isSH3()) + { + print(1, 5, "ABCD"); + print_hex( 6, 5, INTC._7705.iprs.IPRA->word, 4); + print_hex(10, 5, INTC._7705.iprs.IPRB->word, 4); + print_hex(14, 5, INTC._7705.iprs.IPRC->word, 4); + print_hex(18, 5, INTC._7705.iprs.IPRD->word, 4); + print(1, 6, "EFGH"); + print_hex( 6, 6, INTC._7705.iprs.IPRE->word, 4); + print_hex(10, 6, INTC._7705.iprs.IPRF->word, 4); + print_hex(14, 6, INTC._7705.iprs.IPRG->word, 4); + print_hex(18, 6, INTC._7705.iprs.IPRH->word, 4); + } + else + { + print(1, 5, "ACFG"); + print_hex( 6, 5, INTC._7305.iprs->IPRA.word, 4); + print_hex(10, 5, INTC._7305.iprs->IPRC.word, 4); + print_hex(14, 5, INTC._7305.iprs->IPRF.word, 4); + print_hex(18, 5, INTC._7305.iprs->IPRG.word, 4); + print(1, 6, "HJKL"); + print_hex( 6, 6, INTC._7305.iprs->IPRH.word, 4); + print_hex(10, 6, INTC._7305.iprs->IPRJ.word, 4); + print_hex(14, 6, INTC._7305.iprs->IPRK.word, 4); + print_hex(18, 6, INTC._7305.iprs->IPRL.word, 4); + } +#endif + + /* Checking that at least the required interrupts are enabled */ + if(isSH3() + ? (!INTC._7705.iprs.IPRA->word) + : (!INTC._7305.iprs->IPRA.word || !INTC._7305.iprs->IPRK.word) + ) init_halt(); + +#ifdef GINT_STARTUP_LOG + init_stage(" Clocks"); + dupdate(); +#endif + + /* Measuring the clock speed */ + clock_measure(); + clock_measure_end(); + +#ifdef GINT_STARTUP_LOG + clock_config_t clock = clock_config(); + print(1, 7, "Clock I B P"); + print_dec( 8, 7, clock.Iphi_f / 1000000, 2); + print_dec(12, 7, clock.Bphi_f / 1000000, 2); + print_dec(16, 7, clock.Pphi_f / 1000000, 2); + + init_stage("Boot OK"); + dupdate(); + + /* Displaying some interrupt controller config */ + if(isSH3()) + { + print(1, 8, "INTC:0"); + print_hex(7, 8, INTC._7705.ICR1->word, 4); + } + else + { + print(1, 8, "INTC:"); + print_hex(6, 8, INTC._7305.ICR0->word, 4); + print_hex(10, 8, (INTC._7305.USERIMASK->lword >> 4) & 0xf, 1); + } + + #ifndef GINT_NO_SYSCALLS + /* Print the OS version */ + char version[11]; + __get_os_version(version); + version[2] = version[3]; + version[3] = version[4]; + version[4] = version[6]; + version[5] = version[7]; + version[6] = version[8]; + version[7] = version[9]; + version[8] = 0; + print(12, 8, "OS"); + print(14, 8, version); + #endif + + dupdate(); +#endif + + /* Call the global constructors */ + init(); + +#ifdef GINT_STARTUP_LOG + /* Keep this visible for a second or so */ + keyboard_interrupt(); + if(pollevent().type != event_none) getkey(); +#endif + + /* Otherwise, call main() and get the show on the road! */ + int x = setjmp(env); + if(!x) exit_code = main(); + + while(atexit_index > 0) (*atexit_handlers[--atexit_index])(); + fini(); + + gint_quit(); + + return exit_code; +} + +/* init() -- call the constructors */ +static void init(void) +{ + extern void + (*bctors)(void), + (*ectors)(void); + void (**func)(void) = &bctors; + + while(func < &ectors) (*(*func++))(); +} + +/* fini() -- call the destructors */ +static void fini(void) +{ + extern void + (*bdtors)(void), + (*edtors)(void); + void (**func)(void) = &bdtors; + + while(func < &edtors) (*(*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 thus efficiently exits. +*/ +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/init/util.c b/src/init/util.c new file mode 100644 index 0000000..e930875 --- /dev/null +++ b/src/init/util.c @@ -0,0 +1,90 @@ +#include +#include +#include +#include + +/* qdiv10() -- quickly divide by 10 */ +struct qdiv qdiv10(uint32_t n) +{ + uint32_t magic10 = 0x1999999a; + struct qdiv result; + + __asm__( + "dmuls.l %1, %2 \n\t" + "sts mach, %0 " + : "=r"(result.q) + : "r"(n), "r"(magic10) + : "macl", "mach" + ); + + result.r = n - 10 * result.q; + return result; +} + +/* init_version() -- get a version string */ +const char *init_version(void) +{ + static char data[14]; + uint32_t s = (uint32_t)&GINT_VERSION; + + /* Force the string constant to reside in ROM because we haven't + initialized the data section yet */ + memcpy(data, "gint #0.0-000", 14); + + /* Quickly get the three digits of the build number */ + struct qdiv x = qdiv10(s & 0xffff); + struct qdiv y = qdiv10(x.q); + + data[5] = (s & 0xff000000) >> 24; + data[6] += ((s & 0x00f00000) >> 20); + data[8] += ((s & 0x000f0000) >> 16); + data[10] += y.q; + data[11] += y.r; + data[12] += x.r; + + return data; +} + +/* init_stage() -- change the current init stage */ +void init_stage(const char *name) +{ + drect(85, 0, 127, 7, color_white); + print(15, 1, name); +} + +/* init_halt() -- halt the program */ +void init_halt(void) +{ + while(1) sleep(); +} + +/* print_dec() -- print a number in base 10 */ +void print_dec(int x, int y, int n, int digits) +{ + char str[20]; + str[digits] = 0; + + while(--digits >= 0) + { + struct qdiv d = qdiv10(n); + str[digits] = '0' + d.r; + n = d.q; + } + + print(x, y, str); +} + +/* print_hex() -- print a number in base 16 */ +void print_hex(int x, int y, uint32_t n, int digits) +{ + char str[20]; + str[digits] = 0; + + while(--digits >= 0) + { + str[digits] = (n & 0xf) + '0' + 39 * ((n & 0xf) > 9); + n >>= 4; + } + + print(x, y, str); +} diff --git a/src/keyboard/getkey.c b/src/keyboard/getkey.c index 1fc3eb1..f75d086 100644 --- a/src/keyboard/getkey.c +++ b/src/keyboard/getkey.c @@ -16,7 +16,9 @@ int getkey(void) getkey_shift_modifier | getkey_alpha_modifier | getkey_manage_backlight | +#ifndef GINT_NO_SYSCALLS getkey_task_switch | +#endif getkey_repeat_arrow_keys, 0 @@ -105,12 +107,14 @@ int getkey_opt(getkey_option_t options, int delay_ms) break; case event_key_release: +#ifndef GINT_NO_SYSCALLS if((options & getkey_task_switch) && event.key.code == KEY_MENU && !modifier) { gint_switch(); continue; } +#endif if((int)event.key.code != last_key) break; last_key = KEY_NONE; diff --git a/src/keyboard/keyboard_core.c b/src/keyboard/keyboard_core.c index 6e956f4..530b5fc 100644 --- a/src/keyboard/keyboard_core.c +++ b/src/keyboard/keyboard_core.c @@ -34,45 +34,6 @@ timer_t *vtimer = NULL; // Interrupt management. //--- -static inline void push_press(int keycode) -{ - uint32_t id = key_id(keycode); - - event_t event = { - .type = event_key_press, - .key.code = keycode, - .key.id = id, - .key.character = key_char(keycode), - }; - event_push(event); -} - -static inline void push_repeat(int keycode) -{ - uint32_t id = key_id(keycode); - - event_t event = { - .type = event_key_repeat, - .key.code = keycode, - .key.id = id, - .key.character = key_char(keycode), - }; - event_push(event); -} - -static inline void push_release(int keycode) -{ - uint32_t id = key_id(keycode); - - event_t event = { - .type = event_key_release, - .key.code = keycode, - .key.id = id, - .key.character = key_char(keycode), - }; - event_push(event); -} - /* keyboard_interrupt() Callback function for keyboard update; called by the timer manager when diff --git a/src/keyboard/multigetkey.c b/src/keyboard/multigetkey.c deleted file mode 100644 index 74f9b6c..0000000 --- a/src/keyboard/multigetkey.c +++ /dev/null @@ -1,54 +0,0 @@ -#include -#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. -*/ -static void multigetkey_wait(int *cycles) -{ - while(!interrupt_flag) sleep(); - interrupt_flag = 0; - - if(*cycles > 0) (*cycles)--; -} -void multigetkey(int *keys, int count, int cycles) -{ - event_t event; - int number = 0; - - if(count <= 0) return; - if(cycles <= 0) cycles = -1; - - while(cycles != 0) - { - number = getPressedKeys(keyboard_state, keys, count); - - // We want to update the last key data when multigetkey() - // returns a single key, because getkey() could be called a - // short time after we return, and send a new event for this - // key. - if(number == 1) - { - last_key = keys[0]; - last_repeats = 0; - last_time = 0; - } - - if(number) break; - multigetkey_wait(&cycles); - } - - do event = pollevent(); - while(event.type != event_none); - - return; -} diff --git a/src/stdlib/free.c b/src/stdlib/free.c index b51d876..b967fda 100644 --- a/src/stdlib/free.c +++ b/src/stdlib/free.c @@ -3,7 +3,7 @@ #pragma GCC diagnostic ignored "-Wunused-parameter" #ifndef GINT_NO_SYSCALLS -void __free(void *ptr); +#include #endif /* @@ -12,6 +12,9 @@ void __free(void *ptr); */ void free(void *ptr) { + // Just to be sure. + if(!ptr) return; + #ifndef GINT_NO_SYSCALLS __free(ptr); #endif diff --git a/src/stdlib/malloc.c b/src/stdlib/malloc.c index 92366bc..3b7724a 100644 --- a/src/stdlib/malloc.c +++ b/src/stdlib/malloc.c @@ -7,8 +7,8 @@ */ #ifndef GINT_NO_SYSCALLS +#include -void *__malloc(size_t size); void *malloc(size_t size) { return __malloc(size); diff --git a/src/stdlib/realloc.c b/src/stdlib/realloc.c index b98530e..7c30537 100644 --- a/src/stdlib/realloc.c +++ b/src/stdlib/realloc.c @@ -6,8 +6,8 @@ */ #ifndef GINT_NO_SYSCALLS +#include -void *__realloc(void *ptr, size_t size); void *realloc(void *ptr, size_t size) { return __realloc(ptr, size); diff --git a/src/tales/tales_internals.c b/src/tales/tales_internals.c index 889fd7a..3607d0d 100644 --- a/src/tales/tales_internals.c +++ b/src/tales/tales_internals.c @@ -4,17 +4,10 @@ #include #include -font_t *font = NULL; -color_t operator; - -/* - tales_init() - Configures tales with the default font (which is part of gint). -*/ -void tales_init(void) -{ - text_configure(NULL, color_black); -} +/* Put these in gint's uninitialized bss section so that text rendering can be + used before the library is fully initialized */ +__attribute__((section(".gint.bss"))) font_t *font = NULL; +__attribute__((section(".gint.bss"))) color_t operator; /* getCharacterIndex() diff --git a/version b/version index 18bb01c..96648ab 100644 --- a/version +++ b/version @@ -1 +1 @@ -beta-0.9-410 +beta-0.9-566