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 6240f61..0000000 Binary files a/debug/icon.bmp and /dev/null differ diff --git a/debug/include/dispbios.h b/debug/include/dispbios.h deleted file mode 100644 index 7b2bdc6..0000000 --- a/debug/include/dispbios.h +++ /dev/null @@ -1,97 +0,0 @@ -/*****************************************************************/ -/* */ -/* CASIO fx-9860G SDK Library */ -/* */ -/* File name : dispbios.h */ -/* */ -/* Copyright (c) 2006 CASIO COMPUTER CO., LTD. */ -/* */ -/*****************************************************************/ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef __DISPBIOS_H__ -#define __DISPBIOS_H__ - - -// Defines - -#define IM_VRAM_WIDTH 128 -#define IM_VRAM_HEIGHT 64 - -#define IM_VRAM_SIZE 1024 - -#define IM_CHARACTERS_MAX_LINE 21 -#define IM_BYTES_MAX_LINE (IM_CHARACTERS_MAX_LINE*2) - -#define SAVEDISP_PAGE1 1 -#define SAVEDISP_PAGE2 5 -#define SAVEDISP_PAGE3 6 - -#define MINI_OVER 0x10 -#define MINI_OR 0x11 -#define MINI_REV 0x12 -#define MINI_REVOR 0x13 - -#define IM_BIOS_DD_WIDTH IM_VRAM_WIDTH -#define IM_BIOS_DD_HEIGHT IM_VRAM_HEIGHT - -#define WRITEKIND unsigned char -#define IMB_WRITEKIND_OVER 0x01 -#define IMB_WRITEKIND_OR 0x02 -#define IMB_WRITEKIND_AND 0x03 -#define IMB_WRITEKIND_XOR 0x04 - -#define WRITEMODIFY unsigned char -#define IMB_WRITEMODIFY_NORMAL 0x01 -#define IMB_WRITEMODIFY_REVERCE 0x02 -#define IMB_WRITEMODIFY_MESH 0x03 - -#define AREAKIND unsigned char -#define IMB_AREAKIND_OVER 0x01 -#define IMB_AREAKIND_MESH 0x02 -#define IMB_AREAKIND_CLR 0x03 -#define IMB_AREAKIND_REVERSE 0x04 - -#define EFFECTWIN unsigned char -#define IMB_EFFECTWIN_OK 0x01 -#define IMB_EFFECTWIN_NG 0x02 - - -// Structs - -typedef struct tag_DISPBOX{ - int left; - int top; - int right; - int bottom; -} DISPBOX; - -typedef struct tag_GRAPHDATA{ - int width; - int height; - unsigned char *pBitmap; -} GRAPHDATA; - -typedef struct tag_RECTANGLE{ - DISPBOX LineArea; - AREAKIND AreaKind; - EFFECTWIN EffectWin; -} RECTANGLE; - -typedef struct tag_DISPGRAPH{ - int x; - int y; - GRAPHDATA GraphData; - WRITEMODIFY WriteModify; - WRITEKIND WriteKind; -} DISPGRAPH; - - -#endif - -#ifdef __cplusplus -} -#endif diff --git a/debug/include/endian.h b/debug/include/endian.h deleted file mode 100644 index 0a4be82..0000000 --- a/debug/include/endian.h +++ /dev/null @@ -1,31 +0,0 @@ -/*****************************************************************/ -/* */ -/* CASIO fx-9860G SDK Library */ -/* */ -/* File name : endian.h */ -/* */ -/* Copyright (c) 2006 CASIO COMPUTER CO., LTD. */ -/* */ -/*****************************************************************/ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef __ENDIAN_H__ -#define __ENDIAN_H__ - - -// Macros - -#define UtlSwapWord(w) (unsigned short)((((w) & 0x00ff) << 8) | (((w) & 0xff00) >> 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 5ef92aa..0000000 Binary files a/debug/libfx.a and /dev/null differ diff --git a/debug/vsprintf.c b/debug/vsprintf.c deleted file mode 100644 index ad18ba3..0000000 --- a/debug/vsprintf.c +++ /dev/null @@ -1,160 +0,0 @@ -//--- -// vsprintf() -// -// Unfortunately this function, which is part of fxlib, was broken by a -// terribly un-professional port (incidentally, I am responsible for -// this, so I can't complain). So we'll need something simple... -// -// Format Flags Character count -// %d none no -// %x 0 yes -// %p none no -// %c none no -// %s none no -//--- - -#include -#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 0340f76..1286f30 100644 Binary files a/demo/resources/font_modern.bmp and b/demo/resources/font_modern.bmp differ diff --git a/demo/resources/opt_gray.bmp b/demo/resources/opt_gray.bmp index 87ba1c7..6d60c62 100644 Binary files a/demo/resources/opt_gray.bmp and b/demo/resources/opt_gray.bmp differ diff --git a/demo/test_gray.c b/demo/test_gray.c index 4a1ac03..894aa93 100644 --- a/demo/test_gray.c +++ b/demo/test_gray.c @@ -11,27 +11,26 @@ static void draw(int delay1, int delay2, int selected) { extern image_t res_opt_gray; + extern font_t res_font_modern; uint32_t *vl = gray_lightVRAM(); uint32_t *vd = gray_darkVRAM(); gclear(); locate(1, 1, "Gray engine"); - for(int i = 0; i < 36; i++) + for(int i = 0; i < 64; 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; + 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