From 7f174043a5b9d6fcb66908715cb21025e2b5cecf Mon Sep 17 00:00:00 2001 From: lephe Date: Mon, 25 Jul 2016 09:04:22 +0200 Subject: [PATCH] Reported TLB issues. Moved internal headers files, added rtc module and alloca. --- Makefile | 39 +- TODO | 15 +- demo/gintdemo.c | 475 +++++++++++++----- demo/gintdemo.ld | 21 +- demo/resources/{font.bmp => font_modern.bmp} | Bin 24698 -> 24698 bytes demo/resources/illustration.bmp | Bin 32906 -> 0 bytes demo/resources/items.bmp | Bin 0 -> 92378 bytes demo/resources/opt_gray.bmp | Bin 0 -> 3194 bytes demo/resources/opt_menu.bmp | Bin 0 -> 3194 bytes gintdemo.g1a | Bin 24444 -> 18890 bytes include/alloca.h | 23 + include/ctype.h | 6 +- include/gint.h | 130 +++-- .../internals/bopti.h | 6 +- .../internals/display.h | 6 +- include/internals/gint.h | 30 ++ .../internals/keyboard.h | 6 +- include/internals/mmu.h | 21 + .../internals/tales.h | 6 +- .../internals/timer.h | 6 +- include/rtc.h | 76 +++ include/string.h | 16 +- include/tales.h | 6 + libc.a | Bin 2500 -> 3106 bytes libgint.a | Bin 58406 -> 66120 bytes src/bopti/bopti_internals.c | 16 +- src/bopti/dimage.c | 11 +- src/bopti/gimage.c | 5 +- src/core/crt0.c | 9 +- src/core/gint.c | 155 +++++- src/core/gint_str.c | 37 ++ src/core/syscalls.s | 12 +- src/display/adjustRectangle.c | 2 +- src/display/dclear.c | 2 +- src/display/dclear_area.c | 2 +- src/display/dline.c | 2 +- src/display/dpixel.c | 2 +- src/display/dreverse_area.c | 2 +- src/display/dupdate.c | 2 +- src/display/font_system.bmp | Bin 0 -> 32762 bytes src/keyboard/getPressedKey.c | 2 +- src/keyboard/getPressedKeys.c | 2 +- src/keyboard/getkey.c | 2 +- src/keyboard/keyboard_config.c | 2 +- src/keyboard/keyboard_interrupt.c | 2 +- src/keyboard/keyboard_misc.c | 2 +- src/keyboard/multigetkey.c | 2 +- src/keyboard/sleep.c | 2 +- src/mmu/pseudoTLBInit.c | 25 + src/mpu/gint_sh7305.c | 62 ++- src/mpu/gint_sh7705.c | 63 ++- src/mpu/{various_7305.c => rtc_7305.c} | 21 +- src/mpu/{various_7705.c => rtc_7705.c} | 21 +- .../gint_callback.c => rtc/rtc_interrupt.c} | 43 +- src/string/strlen.c | 12 + src/tales/dtext.c | 10 +- src/tales/tales_configuration.c | 12 +- src/tales/tales_internals.c | 2 +- src/timer/timer_get.c | 2 +- src/timer/timer_interrupt.c | 2 +- src/timer/timer_reload.c | 2 +- src/timer/timer_start.c | 2 +- src/timer/timer_stop.c | 2 +- 63 files changed, 1117 insertions(+), 327 deletions(-) rename demo/resources/{font.bmp => font_modern.bmp} (99%) delete mode 100644 demo/resources/illustration.bmp create mode 100644 demo/resources/items.bmp create mode 100644 demo/resources/opt_gray.bmp create mode 100644 demo/resources/opt_menu.bmp create mode 100644 include/alloca.h rename src/bopti/bopti_internals.h => include/internals/bopti.h (98%) rename src/display/display_internals.h => include/internals/display.h (56%) create mode 100644 include/internals/gint.h rename src/keyboard/keyboard_internals.h => include/internals/keyboard.h (88%) create mode 100644 include/internals/mmu.h rename src/tales/tales_internals.h => include/internals/tales.h (93%) rename src/timer/timer_internals.h => include/internals/timer.h (90%) create mode 100644 include/rtc.h create mode 100644 src/core/gint_str.c create mode 100644 src/display/font_system.bmp create mode 100644 src/mmu/pseudoTLBInit.c rename src/mpu/{various_7305.c => rtc_7305.c} (51%) rename src/mpu/{various_7705.c => rtc_7705.c} (51%) rename src/{core/gint_callback.c => rtc/rtc_interrupt.c} (57%) create mode 100644 src/string/strlen.c diff --git a/Makefile b/Makefile index bb6d41b..9a01f78 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,8 @@ #--- # Modules -modules-gint = bopti core display gray keyboard mpu screen tales timer +modules-gint = core keyboard mmu mpu rtc screen timer \ + bopti display gray tales modules-libc = setjmp string # Targets @@ -28,7 +29,7 @@ ob = sh3eb-elf-objcopy wr = g1a-wrapper # Flags -cflags = -m3 -mb -nostdlib -I include -ffreestanding -std=c11 +cflags = -m3 -mb -nostdlib -I include -ffreestanding -std=c11 -Os # Demo application (could be done better) demo-src = $(notdir $(wildcard demo/*.[cs])) @@ -40,6 +41,10 @@ demo-elf = build/gintdemo.elf demo-bin = build/gintdemo.bin demo-libs = -lgcc -L. -lgint -lc +# Specific objects +obj-lib-spec = build/display_font_system.bmp.o +obj-std-spec = + #--- @@ -58,14 +63,16 @@ endef $(foreach mod, $(modules), $(eval \ mod-$(mod)-c = $(notdir $(wildcard src/$(mod)/*.c)) $n\ mod-$(mod)-asm = $(notdir $(wildcard src/$(mod)/*.s)) $n\ - mod-$(mod)-dep = $(wildcard include/*.h src/$(mod)/*.h) $n\ mod-$(mod)-src = $$(mod-$(mod)-c)$$(mod-$(mod)-asm) $n\ mod-$(mod)-obj = $$(patsubst %,build/$(mod)_%.o,$$(mod-$(mod)-src)) \ )) # Target-scope variables. -obj-std = $(foreach mod,$(modules-libc),$(mod-$(mod)-obj)) -obj-lib = $(foreach mod,$(modules-gint),$(mod-$(mod)-obj)) +obj-std = $(foreach mod,$(modules-libc),$(mod-$(mod)-obj)) $(obj-std-spec) +obj-lib = $(foreach mod,$(modules-gint),$(mod-$(mod)-obj)) $(obj-lib-spec) + +# Dependencies +hdr-dep = $(wildcard include/*.h include/internals/*.h) @@ -77,8 +84,8 @@ obj-lib = $(foreach mod,$(modules-gint),$(mod-$(mod)-obj)) # $1 module name # $2 filename define rule-c-source -build/$1_$2.o: src/$1/$2 $(mod-$1-dep) - $(cc) -c $$< -o $$@ $(cflags) -I src/$1 -O2 +build/$1_$2.o: src/$1/$2 $(hdr-dep) + $(cc) -c $$< -o $$@ $(cflags) -I src/$1 endef # asm source file template: @@ -98,21 +105,24 @@ endef # Generic rules all: build $(target-std) $(target-lib) $(target-g1a) - @ echo 'All done!' + @echo "[ \033[32;1mOK\033[0m ] All done!" build: mkdir -p $@ $(target-std): $(obj-std) $(ar) rcs $@ $^ + @echo "[ \033[32;1mOK\033[0m ] libc: `stat -c %s $@` bytes" $(target-lib): $(target-std) $(obj-lib) $(ar) rcs $@ $(obj-lib) + @echo "[ \033[32;1mOK\033[0m ] libgint: `stat -c %s $@` bytes" $(target-g1a): $(target-std) $(target-lib) $(demo-obj) $(cc) -o $(demo-elf) $(cflags) -T $(demo-ld) $(demo-obj) $(demo-libs) $(ob) -R .comment -R .bss -O binary $(demo-elf) $(demo-bin) $(wr) $(demo-bin) -o $@ -i $(demo-icon) + @echo "[ \033[32;1mOK\033[0m ] demo app: `stat -c %s $@` bytes" # Automated rules @@ -123,22 +133,27 @@ $(foreach mod,$(modules), \ $(call rule-asm-source,$(mod),$(source)))) \ ) +# Specific rules + # This one should not be optimized. It makes __attribute__((interrupt_handler)) # buggy... maybe. Anyway there's a bug in this file. build/core_gint.c.o: src/core/gint.c $(mod-core-dep) - $(cc) -c $< -o $@ $(cflags) -I src/core + $(cc) -c $< -o $@ $(cflags) -I src/core -O0 + +build/display_font_system.bmp.o: src/display/font_system.bmp + fxconv $< -o $@ --font -n gint_font_system # Demo application build/demo_%.c.o: demo/%.c $(cc) -c $< -o $@ $(cflags) +build/demo_font_%.bmp.o: demo/resources/font_%.bmp + fxconv $< -o $@ --font -n $(patsubst demo/resources/%.bmp,res_%,$<) + build/demo_%.bmp.o: demo/resources/%.bmp fxconv $< -o $@ -n $(patsubst demo/resources/%.bmp,res_%,$<) -build/demo_font.bmp.o: demo/resources/font.bmp - fxconv $< -o $@ --font -n res_font - #--- diff --git a/TODO b/TODO index 81094a0..9a46c54 100644 --- a/TODO +++ b/TODO @@ -10,24 +10,21 @@ @ vram overflow -@ keyboard test threading interface +@ keyboard test threaded interface ++ full and partial transparency + gint vs. ML with 248x124 at (-60, -28) -+ use alloca() for tales + call exit handlers + compute frequencies + gray text -+ effective rtc callback -+ properly test gray drawing + upgraded blending modes + blending modes for text + information masks for text + test all font encodings + font clipping + bitmap parts -+ bitmap clipping -- install critical failure handler to prevent failing resets +- improve exception handler debugging information (if possible) - write and test gray engine - full rtc driver (time) - callbacks and complete user API @@ -35,7 +32,7 @@ ~ shadowy rectangle effect for Shift + Alpha + Left + Down ~ exhaustive save for setjmp() ~ registers that need to be saved when configuring gint -~ possible bug when -O2 __attribute__((interrupt_handler)) +~ possible bug when -O2'ing __attribute__((interrupt_handler)) @@ -43,8 +40,8 @@ Some notes ---------- Test cases for bitmap drawing: -- aligned 32 / non-aligned 32 +- 32-alignment - monochrome / gray - small / large -- does not overflow / overflows +- clipping # blending modes diff --git a/demo/gintdemo.c b/demo/gintdemo.c index f41d596..cfadaae 100644 --- a/demo/gintdemo.c +++ b/demo/gintdemo.c @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -10,62 +11,67 @@ #include #include <7305.h> + + //--- // A few ugly procedures for displaying text. Will have to enhance this // soon -- which means printf(). //--- -void print(const char *str, int x, int y) +void locate(const char *str, int x, int y) { - dtext(str, x, y); + if(x < 1 || x > 21 || y < 1 || y > 8) return; + if(gray_runs()) gtext(str, x * 6 - 5, y * 8 - 7); + else dtext(str, x * 6 - 5, y * 8 - 7); } -void print_hex(unsigned int n, int x, int y) + +void locate_hex(unsigned int n, int x, int y) { - char ch[11] = "0x"; + char str[11] = "0x"; int i; for(i = 0; i < 8; i++) { - ch[9 - i] = (n & 0xf) + '0' + 39 * ((n & 0xf) > 9); + str[9 - i] = (n & 0xf) + '0' + 39 * ((n & 0xf) > 9); n >>= 4; } - ch[10] = 0; - print(ch, x, y); + str[10] = 0; + locate(str, x, y); } -void print_bin(unsigned char n, int x, int y) +void locate_bin(unsigned char n, int x, int y) { - char ch[9]; + char str[9]; int i; for(i = 0; i < 8;i ++) { - ch[7 - i] = (n & 1) + '0'; + str[7 - i] = (n & 1) + '0'; n >>= 1; } - ch[8] = 0; - print(ch, x, y); + str[8] = 0; + locate(str, x, y); } -void print_hexa(unsigned int n, int digits, int x, int y) +void locate_hexa(unsigned int n, int digits, int x, int y) { - char ch[20]; + char str[20]; int i; for(i = digits - 1; i >= 0; i--) { - ch[i] = (n & 0xf) + '0' + 39 * ((n & 0xf) > 9); + str[i] = (n & 0xf) + '0' + 39 * ((n & 0xf) > 9); n >>= 4; } - ch[digits] = 0; - print(ch, x, y); + str[digits] = 0; + locate(str, x, y); } -void print_int(int n, int x, int y) +void locate_int(int n, int x, int y) { char str[20] = { 0 }; int i, o = 0; int digits = 0, copy = n; - if(!n) { str[o++] = '0'; print(str, x, y); return; } + if(!n) { str[o++] = '0'; locate(str, x, y); return; } if(n < 0) str[o++] = '-', n = -n; while(copy) digits++, copy /= 10; @@ -75,7 +81,7 @@ void print_int(int n, int x, int y) n /= 10; } - gtext(str, x, y); + locate(str, x, y); } @@ -97,17 +103,17 @@ void keyboard_test_timer(void) dclear_area(5, 10, 71, 34); - print_bin(state[0], 5, 10); - print_bin(state[1], 5, 16); - print_bin(state[2], 5, 22); - print_bin(state[3], 5, 28); - print_bin(state[4], 5, 34); + locate_bin(state[0], 5, 10); + locate_bin(state[1], 5, 16); + locate_bin(state[2], 5, 22); + locate_bin(state[3], 5, 28); + locate_bin(state[4], 5, 34); - print_bin(state[5], 40, 10); - print_bin(state[6], 40, 16); - print_bin(state[7], 40, 22); - print_bin(state[8], 40, 28); - print_bin(state[9], 40, 34); + locate_bin(state[5], 40, 10); + locate_bin(state[6], 40, 16); + locate_bin(state[7], 40, 22); + locate_bin(state[8], 40, 28); + locate_bin(state[9], 40, 34); dupdate(); } @@ -127,8 +133,8 @@ void keyboard_test(void) timer_start(TIMER_USER, 1700, TIMER_Po_256, keyboard_test_timer, 0); dclear(); - print("Keyboard state:", 0, 0); - print("multi-getkey ^^", 50, 55); + locate("Keyboard state:", 0, 0); + locate("multi-getkey ^^", 50, 55); dupdate(); while(1) @@ -142,14 +148,14 @@ void keyboard_test(void) x = (x + 1) & 15; str[0] = hexa(x); str[1] = 0; - print(str, 100, 0); + locate(str, 100, 0); for(i = 0; i < 4; i++) { str[0] = hexa((keys[i] >> 4) & 0x0f); str[1] = hexa(keys[i] & 0x0f); str[2] = 0; - print(str, 100, 16 + 10 * i); + locate(str, 100, 16 + 10 * i); } #undef hexa @@ -160,10 +166,12 @@ void keyboard_test(void) timer_stop(TIMER_USER); } + /* bitmap_test() Displays various bitmaps to ensure bopti is working correctly. */ +/* void bitmap_test(void) { extern Image res_bitmap_opt_start; @@ -171,12 +179,14 @@ void bitmap_test(void) extern Image res_symbol2_start; extern Image res_sprites_start; extern Image res_swords_start; + extern Image res_items_start; Image *opt = &res_bitmap_opt_start; Image *sybl = &res_symbol_start; Image *sybl2 = &res_symbol2_start; Image *sprites = &res_sprites_start; Image *swords = &res_swords_start; + Image *items = &res_items_start; uint32_t a32 = 0xffffffff; int black_bg = 0, gray = 0; @@ -191,10 +201,9 @@ void bitmap_test(void) gclear(); if(black_bg) greverse_area(0, 0, 127, 63); - gimage(opt, 0, 57); + gimage(swords, 0, 57); - gimage(sprites, x, y); - gimage(swords, x, y + 35); + gimage(items, x, y); gupdate(); } @@ -229,29 +238,28 @@ void bitmap_test(void) gray_stop(); return; } - +*/ /* text_test() Renders text. */ - void text_test(void) { - extern Font res_font_start; - Font *font = &res_font_start; + extern Font res_font_modern_start; + Font *font = &res_font_modern_start; text_configure(font); dclear(); - print(" !\"#$%&'()*+,-./", 10, 10); - print("0123456789:;<=>?", 10, 16); - print("@ABCDEFGHIJKLMNO", 10, 22); - print("PQRSTUVWXYZ[\\]^_", 10, 28); - print("`abcdefghijklmno", 10, 34); - print("pqrstuvwxyz{|}~", 10, 40); + dtext(" !\"#$%&'()*+,-./", 10, 10); + dtext("0123456789:;<=>?", 10, 16); + dtext("@ABCDEFGHIJKLMNO", 10, 22); + dtext("PQRSTUVWXYZ[\\]^_", 10, 28); + dtext("`abcdefghijklmno", 10, 34); + dtext("pqrstuvwxyz{|}~", 10, 40); dupdate(); @@ -264,11 +272,9 @@ void text_test(void) gray_test() Runs the gray engine. */ - void gray_test(void) { - extern Image res_illustration_start; - Image *illustration = &res_illustration_start; + extern Image res_opt_gray_start; int *v1, *v2; @@ -297,16 +303,15 @@ void gray_test(void) -(i < 32); } -// gimage(illustration, 0, 0); -// gclear_area(64, 0, 127, 63); + locate("light", 15, 2); + locate_int(delays[0], 15, 3); - gtext("light", 78, 6); - print_int(delays[0], 103, 6); + locate("dark", 15, 5); + locate_int(delays[1], 15, 6); - gtext("dark", 78, 15); - print_int(delays[1], 103, 15); + locate("\x02", 14, selected ? 6 : 3); - gtext(">", 70, selected ? 15 : 6); + gimage(&res_opt_gray_start, 0, 56); gupdate(); } @@ -320,19 +325,15 @@ void gray_test(void) switch(key) { case KEY_F1: - delays[0] = 860; - delays[1] = 1298; + selected = !selected; break; case KEY_F2: - delays[0] = 912; - delays[1] = 1343; - break; - case KEY_F3: delays[0] = 993; delays[1] = 1609; break; - case KEY_F6: - selected = !selected; + case KEY_F3: + delays[0] = 860; + delays[1] = 1298; break; case KEY_UP: delays[selected] += 10; @@ -356,56 +357,6 @@ void gray_test(void) } /* - main_menu() - Displays the main menu and returns user's choice. - - @return User choice. 0 means EXIT, other numbers are applications. -*/ -int main_menu(void) -{ - extern unsigned int bgint, egint; - const char *mpu_names[] = { - "MPU_Unkown", - "MPU_SH7337", - "MPU_SH7355", - "MPU_SH7305", - "MPU_SH7724", - "MPU Error !" - }; - int key; - - dclear(); - - print("gint test application", 19, 1); - dline(19, 8, 107, 8, Color_Black); - - print("[1] Keyboard", 10, 17); - print("[2] Bitmap drawing", 10, 24); - print("[3] Text rendering", 10, 31); - print("[4] Gray engine", 10, 38); - - print("mpu type:", 2, 49); - print(mpu_names[MPU_CURRENT < 5 ? MPU_CURRENT : 5], 50, 48); - print("gint size:", 2, 56); - print_hex(&egint - &bgint, 50, 56); - - dupdate(); - - while(1) - { - key = getkey(); - if(key == KEY_EXIT) return 0; - - if(key == KEY_1) return 1; - if(key == KEY_2) return 2; - if(key == KEY_3) return 3; - if(key == KEY_4) return 4; - if(key == KEY_5) return 5; - } - - return 0; -} - static const unsigned char screen[1024] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 159, 0, 0, 1, 192, 0, 0, 0, 0, 0, 121, 240, 0, 0, 0, @@ -505,7 +456,7 @@ void ML_bmp_or_cl(const unsigned char *bmp, int x, int y, int width, int height) } } -#include <../src/timer/timer_internals.h> +#include void debug(void) { extern Image res_screen_start; @@ -551,32 +502,292 @@ void debug(void) dupdate(); while(getkey() != KEY_EXIT); } +*/ /* - main() - Handles application calls. - - @return 0. + tlb_debug() + Displays the TLB contents and some information. Only available for + SH7705, because the SH7305's TLB is much more complicated. */ -int main(void) +void tlb_debug(void) { - extern Font res_font_start; - Font *font = &res_font_start; + // Entry address address (pointer in the address array), entry data + // address (pointer in the data address), and their contents. + unsigned int address, data, a, d; + // Virtual page number and physical page number. + unsigned int vpn, ppn; + // Contents of register MMUCR. + unsigned mmucr; - text_configure(font); + int i, r, key = 0; + int way = 0, entry = 0; + int pointer_base; - int app; + const char *protection[] = { "pr", "prw", "ar", "arw" }; + mmucr = *((volatile unsigned int *)gint_reg(Register_MMUCR)); + + dclear(); + locate("MMU register info", 1, 1); + locate("MMUCR.IX = ", 2, 3); + locate(mmucr & 0x02 ? "1" : "0", 13, 3); + dupdate(); + getkey(); + + while(key != KEY_EXIT && way < 4) + { + dclear(); + + locate("TLB", 1, 1); + locate("way=", 8, 1); + locate("0\0001\0002\0003" + (way << 1), 12, 1); + locate_int(entry, 16 + (entry < 10), 1); + locate("-", 18, 1); + locate_int((entry + 2 > 31) ? (31) : (entry + 2) , 19, 1); + + for(i = 0; i < 3 && entry < 32; i++, entry++) + { + address = 0xf2000000 | (entry << 12) | (way << 8); + data = 0xf3000000 | (entry << 12) | (way << 8); + + a = *((volatile unsigned int *)address); + d = *((volatile unsigned int *)data); + + ppn = (d >> 10) & 0x00007ffff; + // 4-kbyte page + if(d & 0x08) + { + vpn = (a >> 12) | entry; + pointer_base = vpn << 12; + } + // 1-kbyte page + else + { + vpn = (a >> 10) | (entry << 2); + pointer_base = vpn << 10; + } + + r = 2 * i + 3; + locate_hexa(pointer_base, 8, 1, r); + locate(":", 11, r); + locate_hexa(ppn << 10, 8, 12, r); + + r++; + locate((d & 0x08) ? "4k" : "1k", 1, r); + locate("pr=", 5, r); + locate(protection[(d >> 5) & 3], 8, r); + locate((d & 0x02) ? "shared" : "exclusive", 13, r); + } + + if(entry == 32) entry = 0, way++; + + dupdate(); + key = getkey(); + } +} + +/* + main_menu() + Displays the main menu and returns user's choice: 0 for [EXIT], + application numbers otherwise. Sets the ctaegory and application + number. +*/ +void main_menu(int *category, int *app) +{ + //--- + // Quite a few things to declare... + //--- + + extern Image res_opt_menu_start; + + const char *mpu, *mpu_names[] = { + "Unknown", + "SH7337", + "SH7355", + "SH7305", + "SH7724", + "[error]" + }; + + const char *list_tests[] = { + "Keyboard", + "Gray engine", + "Image rendering", + "Text rendering", + "Real-time clock", + NULL + }; + const char *list_perfs[] = { + "Image rendering", + "Text rendering", + NULL + }; + const char *list_debug[] = { + "View TLB (SH3 only)", + NULL + }; + const char **list; + + extern unsigned int bgint, egint; + extern unsigned int romdata; + int gint_size = &egint - &bgint; + + + + static int tab = 0, index = 0; + // Set to 1 when interface has to be redrawn. + int leave = 1; + int i; + + mpu = mpu_names[MPU_CURRENT < 5 ? MPU_CURRENT : 5]; + text_configure_default(); while(1) { - app = main_menu(); - if(!app) break; + //--- + // Displaying the current tab. + //--- - if(app == 1) keyboard_test(); - if(app == 2) bitmap_test(); - if(app == 3) text_test(); - if(app == 4) gray_test(); - if(app == 5) debug(); + dclear(); + dupdate(); + + switch(tab) + { + case 0: + locate("Demo application", 1, 1); + locate("gint version:", 2, 3); + locate(GINT_VERSION_STR, 16, 3); + locate("handler size:", 2, 4); + locate_int(gint_size, (gint_size < 1000 ? 18 : 17), 4); + locate("mpu type:", 2, 5); + locate(mpu, 21 - strlen(mpu), 5); + locate("romdata:", 2, 6); + locate_hex((unsigned int)&romdata, 11, 6); + + list = NULL; + break; + + case 1: + locate("Test list", 1, 1); + list = list_tests; + break; + + case 2: + locate("Performance", 1, 1); + list = list_perfs; + break; + + case 3: + locate("Debug", 1, 1); + list = list_debug; + break; + + default: + locate("Tab ", 1, 1); + locate_int(tab, 5, 1); + break; + } + dimage(&res_opt_menu_start, 0, 56); + + if(list) + { + for(i = 0; list[i]; i++) locate(list[i], 2, i + 2); + dreverse_area(0, 8 * index + 9, 127, 8 * index + 16); + } + dupdate(); + + //--- + // Waiting for events. + //--- + + do + { + leave = 1; + + switch(getkey()) + { + case KEY_F1: + tab = 0; + index = 0; + break; + case KEY_F2: + tab = 1; + index = 0; + break; + case KEY_F3: + tab = 2; + index = 0; + break; + case KEY_F4: + tab = 3; + index = 0; + break; + + case KEY_UP: + if(list && index) index--; + break; + case KEY_DOWN: + if(list && list[index + 1]) index++; + break; + + case KEY_EXE: + if(!tab) break; + if(category) *category = tab; + if(app) *app = index + 1; + return; + + case KEY_EXIT: + case KEY_MENU: + if(category) *category = 0; + if(app) *app = 0; + return; + + default: + leave = 0; + } + } + while(!leave); + } + + if(category) *category = 0; + if(app) *app = 0; + return; +} + +/* + main() + No need for description. +*/ +int main(void) +{ + int category, app; + + while(1) + { + main_menu(&category, &app); + if(!category) break; + + switch((category << 8) | app) + { + case 0x0101: + keyboard_test(); + break; + case 0x0102: + gray_test(); + break; + case 0x0103: +// bitmap_test(); + break; + case 0x0104: + text_test(); + break; + case 0x0105: +// rtc_test(); + break; + + case 0x0301: + if(isSH3()) tlb_debug(); + break; + } } return 0; diff --git a/demo/gintdemo.ld b/demo/gintdemo.ld index 512f5db..cf7bb2f 100644 --- a/demo/gintdemo.ld +++ b/demo/gintdemo.ld @@ -17,9 +17,8 @@ ENTRY(_start) MEMORY { rom : o = 0x00300200, l = 512k - ram : o = 0x08100000, l = 64k - /* The "real ram" accessible length remains unknown because some parts - are used by the system. At least 12k seem accessible. Use with care. */ + /* 0x0810000 is apparently mapped to 0x8801c0000. */ + ram : o = 0x08100000, l = 8k realram : o = 0x8800d000, l = 12k } @@ -46,6 +45,7 @@ SECTIONS } > rom .rodata : { + *(.rodata.fxconv); *(.rodata) *(.rodata.*) @@ -84,16 +84,25 @@ SECTIONS /* - Real RAM : interrupt handler. + Real RAM : interrupt, exception and TLB miss handlers. */ - .gint_int : AT(_gint_data) ALIGN(4) { + .gint : AT(_gint_data) ALIGN(4) { /* The vbr needs to be 0x100-aligned because of an ld issue. */ . = ALIGN(0x100) ; _gint_vbr = . ; - _bgint = . ; + /* Exception handler. */ + . = _gint_vbr + 0x100 ; + *(.gint.exc.entry) + *(.gint.exc) + + /* TLB miss handler. */ + . = _gint_vbr + 0x400 ; + *(.gint.tlb.entry) + *(.gint.tlb) + /* Interrupt handler. */ . = _gint_vbr + 0x600 ; *(.gint.int.entry) diff --git a/demo/resources/font.bmp b/demo/resources/font_modern.bmp similarity index 99% rename from demo/resources/font.bmp rename to demo/resources/font_modern.bmp index c577abd54f611c45e93b80eb1f9589d8d24ca441..5c1c91bfa51ba593c94c6414d0a139fb51451f6c 100644 GIT binary patch delta 153 zcmex$fbrJ>#todliql}=KNv7DFhCeE;c1gM>PSy^aORxsASOEbfe_DR0}-~#eO8>4 z1)SL?f6x?~yg^84;snvjA9R2e+vEfhp~(e7T@xp8LPS(HZ}2N&nLI&B(|} ioRbd-@=X392vi0%#Ltv-@&iB4$@7ERHctqC#RC9CJwoOH delta 136 zcmex$fbrJ>#todloDDEASy5SW@&rxM$s4rTCOe3UPJST7Guc3dZE~L#=VSqAw#gqf zg(hzh5}G(cbn*usAjLL0K}2YBK~UGk37ilSmCYOcN?4eICQfG5mY6(2kZp2-80X{# f8f+7*q$d{u&G9qkoczF#bMpLPw#^fQU-19{(1|jo diff --git a/demo/resources/illustration.bmp b/demo/resources/illustration.bmp deleted file mode 100644 index ca8755ad1f4de5b1c1e1d53199583e333d5d2a36..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32906 zcmeIxJ#u5|4TWLZ4jp;}UW#iHM^0QdD{<;z;#o>>vaOe%#|3|NsTMCukl0&JDOGGR%&MZF+Z+gx1cKO9FecL-9rR&e<&E`txtl6;gr$6^FcXO-R^_Rv!cN^v{8pc00 z|IRB z&e?N5zM3_6Zx6kFYtdu68Qg5^ovj(0&3ti8A6M9{z32S6y`A=nZO!&0Os!c~emf8^ zpN%^V5A2@Wdv9sGsgG%I^;LYGGauGF)3>9rY2R}Paht=N>1*CJS35DEnc~hS*?I^Q z54)xZ{O2_Osn6wxm#1$%hG(CXnP+|+)tE0#9GBW~d1ANJ=F$Vb_s#0IYUe!qHya(U zpDhk`d$r#7aOjA#b@|ItX`Z$uQi%nj$ zhWXy&-xHhf?WtdD@abLL{`gbRn7X-_$thkvTdusxeXSj5{ppc?>05Z}Rll?Uc;$F2 z-*@dCZ`Jq4tpwMcEp9Vyy;E#!C*_7uPP}5XR^HYdd$BmZp~w77-zs1I>>Zc5c`xPP zJDn-z<*xEwtB)1Ggy@9g!xUH$Cq(zj;5IpV}`j{KQh&PR&( z_x4bo`R2ZwA%E+WUyhrm;W+ttajM(fbM@y0=j^*a;OFWlUhdj+KD^vZIVb}DXY-5Ay@-V+e4OgkEP?|ZWz2P~dTxb89EdpYZQep_|L zo5yYB@ZB&RHghJH-Dg*8ja<6Cd&rzA{!4GBui2*^6%)Tl@Au@?`>M@mPxWB-*$*sD zVEOF$gxED#f>@xm@?u~43WzRdZ<;`3%d^p3| zr^mj?pE`F>-!PkwR=_Xp6Tx8mTWgHUra7NW7+fbo0$45{0y40`EU8HoO6%! zo$xK0`O~(0nA&_d?6wJCuKO1Y%b(xOgTvxd7e>VIp}p}Dy8h=~uCZ6H{3Om9gU|WG zws1K!jxWr;(sJPGgl{&u8hqZGoY^y8t$O*l)c7yedwb{|d%0Fmu4&iX^t1QMi=~t4 zXX7cBP1YFv*|h%mXgk}hdvn%K-=4yft^VY^rPaG3p2^v*e8tyXST*wG=pSEkF}Zpu z=PQX_uG&t1r0uml9QMPf;d^u(?vkD8Eu5e2J$5nmGd64F;!69>R{rlr>}l0@PS1F| zS^aDGg|GMABON}m-U$yYmZ;sr%S&*w)zIb1#d|9Jo&K?xsqeK4`)>d4za92Nb#SeY|4cL1xb)UpN#lpkf>6G;P$35lCqr=I(H6HcF4teYb+S8;9FR+Lq28$-G+1v z_ked>_mx)+CO-Z0aHW%KVA+#{KlQ2T`12tfuy?oYPGO0d+qrW%EDfJFK0I>N=8K(- z2fB2I1bty^7x1TxDD97ySYtzy|Wv_)4pO8 zH$gmNIEzh8?x7#E0XOd^B-_2*6$V$g`sL4bh;luLhZ$@2M_94%=f$rkdom;JXy>C9u z-K)uVa~yF`+gpczz72Gz^;Uc_clR4ei#3sa_KZE>#79SS1M_z9^?q{J|L1F-`a^%M o4Y)sTy48mt`fF|A_<#Pj?s-geY~a|yv4LX)#|DlKe98^{2Z{t)MgRZ+ diff --git a/demo/resources/items.bmp b/demo/resources/items.bmp new file mode 100644 index 0000000000000000000000000000000000000000..ec6a4197916d61a3c6d3d2aa355301e987407267 GIT binary patch literal 92378 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 acd{MlI8&G>rm9kWM~D9Q`VNdU1%3d9PYO8z literal 0 HcmV?d00001 diff --git a/demo/resources/opt_menu.bmp b/demo/resources/opt_menu.bmp new file mode 100644 index 0000000000000000000000000000000000000000..4d682e41f8ba32f159a4d11eed322f74220e798b GIT binary patch literal 3194 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 literal 24444 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 + +/* + alloca() + Allocates a memory block on the stack. +*/ +void *alloca(size_t size); + +#define alloca(size) __builtin_alloca(size) + +#endif // _ALLOCA_H diff --git a/include/ctype.h b/include/ctype.h index 82748b5..8c5bbd5 100644 --- a/include/ctype.h +++ b/include/ctype.h @@ -1,5 +1,5 @@ -#ifndef _CTYPE_H -#define _CTYPE_H 1 +#ifndef _CTYPE_H +#define _CTYPE_H 1 // Character definition macros. #define isalnum(c) (isdigit(c) || isalpha(c)) @@ -24,4 +24,4 @@ #define tolower(c) (isupper(c) ? (c) | 32 : (c)) #define toupper(c) (islower(c) ? (c) & ~32 : (c)) -#endif // _CTYPE_H +#endif // _CTYPE_H diff --git a/include/gint.h b/include/gint.h index e842bbd..879d576 100644 --- a/include/gint.h +++ b/include/gint.h @@ -10,6 +10,9 @@ #ifndef _GINT_H #define _GINT_H 1 +#define GINT_VERSION 0x01000000 +#define GINT_VERSION_STR "01.00" + //--- // Interrupt handler control. //--- @@ -29,42 +32,6 @@ unsigned int gint_systemVBR(void); -//--- -// Callback API. -//--- - -/* - enum RTCFrequency - Describes the possible frequencies available for the real-time clock - interrupt. -*/ -enum RTCFrequency -{ - RTCFreq_500mHz = 7, - RTCFreq_1Hz = 6, - RTCFreq_2Hz = 5, - RTCFreq_4Hz = 4, - RTCFreq_16Hz = 3, - RTCFreq_64Hz = 2, - RTCFreq_256Hz = 1, -}; - -/* - gint_setRTCCallback() - Sets the callback function for the real-time clock interrupt. If - frequency is non-NULL, the clock frequency is set to the given value. -*/ -void gint_setRTCCallback(void (*callback)(void), enum RTCFrequency frequency); - -/* - gint_getRTCCallback() - Returns the callback function. If frequency is non-NULL, it is set to - the current frequency value. -*/ -void (*gint_getRTCCallback(enum RTCFrequency *frequency))(void); - - - //--- // Internal API. // Referenced here for documentation purposes only. @@ -108,33 +75,86 @@ void gint_setup_7305(void); void gint_stop_7705(void); void gint_stop_7305(void); + + +//--- +// Exception handling. +//--- + /* - gint() + gint_exc() + Handles exceptions. +*/ +void gint_exc(void) __attribute__((section(".gint.exc.entry"), + interrupt_handler)); +void gint_exc_7705(void) __attribute__((section(".gint.exc"))); +void gint_exc_7305(void) __attribute__((section(".gint.exc"))); + +/* + gint_tlb() + Handles TLB misses. +*/ +void gint_tlb(void) __attribute__((section(".gint.tlb.entry"), + interrupt_handler)); +void gint_tlb_7705(void) __attribute__((section(".gint.tlb"))); +void gint_tlb_7305(void) __attribute__((section(".gint.tlb"))); + +/* + gint_int() Handles interrupts. */ -void gint(void) __attribute__((section(".gint.int.entry"), +void gint_int(void) __attribute__((section(".gint.int.entry"), interrupt_handler)); -void gint_7705(void) __attribute__((section(".gint.int"))); -void gint_7305(void) __attribute__((section(".gint.int"))); - -/* - gint_setRTCFrequency() - Sets the RTC interrupt frequency and enables interrupts. -*/ -void gint_setRTCFrequency_7705(enum RTCFrequency frequency); -void gint_setRTCFrequency_7305(enum RTCFrequency frequency); - -/* - gint_getRTCFrequency() - Returns the RTC interrupt frequency. -*/ -enum RTCFrequency gint_getRTCFrequency_7705(void); -enum RTCFrequency gint_getRTCFrequency_7305(void); +void gint_int_7705(void) __attribute__((section(".gint.int"))); +void gint_int_7305(void) __attribute__((section(".gint.int"))); //--- -// Internal priority definitions. +// Register access. +//--- + +/* + enum Register + Represents common registers. Used as identifiers to retrieve their + values using gint_register(). +*/ +enum Register +{ + Register_EXPEVT, + Register_MMUCR, + Register_TEA, +}; + +/* + gint_register() + Returns the address of a common register. All common registers exist + on both platforms but they may hold different values for the same + information (f.i. EXPEVT may not return the same value for a given + exception on both 7705 and 7305). +*/ +volatile void *gint_reg(enum Register reg); +volatile void *gint_reg_7705(enum Register reg); +volatile void *gint_reg_7305(enum Register reg); + +/* + gint_strerror() + Returns a string that describe the error set in EXPEVT in case of + general exception of TLB miss exception. This string is platform- + independent. + Some exception codes represent different errors when invoked inside the + general exception handler and the TLB error handler. Parameter 'is_tlb' + should be set to zero for general exception meanings, and anything non- + zero for TLB error meanings. +*/ +const char *gint_strerror(int is_tlb); +const char *gint_strerror_7705(int is_tlb); +const char *gint_strerror_7305(int is_tlb); + + + +//--- +// Internal platform-independent definitions. //--- #define GINT_INTP_WDT 4 diff --git a/src/bopti/bopti_internals.h b/include/internals/bopti.h similarity index 98% rename from src/bopti/bopti_internals.h rename to include/internals/bopti.h index 1883613..3e0116c 100644 --- a/src/bopti/bopti_internals.h +++ b/include/internals/bopti.h @@ -14,8 +14,8 @@ // //--- -#ifndef _BOPTI_INTERNALS_H -#define _BOPTI_INTERNALS_H 1 +#ifndef _INTERNALS_BOPTI_H +#define _INTERNALS_BOPTI_H 1 #include #include @@ -157,4 +157,4 @@ void bopti(const unsigned char *layer, struct Structure *s, struct Command *c); */ void getStructure(struct Image *img, struct Structure *structure); -#endif // _BOPTI_INTERNALS_H +#endif // _INTERNALS_BOPTI_H diff --git a/src/display/display_internals.h b/include/internals/display.h similarity index 56% rename from src/display/display_internals.h rename to include/internals/display.h index 560a0c8..a227edd 100644 --- a/src/display/display_internals.h +++ b/include/internals/display.h @@ -6,9 +6,9 @@ // //--- -#ifndef _DISPLAY_INTERNALS_H -#define _DISPLAY_INTERNALS_H +#ifndef _INTERNALS_DISPLAY_H +#define _INTERNALS_DISPLAY_H 1 extern int *vram; -#endif // _DISPLAY_INTERNALS_H +#endif // _INTERNALS_DISPLAY_H diff --git a/include/internals/gint.h b/include/internals/gint.h new file mode 100644 index 0000000..4f038d2 --- /dev/null +++ b/include/internals/gint.h @@ -0,0 +1,30 @@ +#ifndef _INTERNALS_GINT_H +#define _INTERNALS_GINT_H 1 + +//--- +// Exception code strings. +//--- + +extern const char *gint_str[]; + + + +//--- +// Register access. +//--- + +/* + gint_spc() + Returns the saved program counter, which is the last state of execution + saved by interrupt processing. +*/ +unsigned int gint_spc(void); + +/* + gint_ssr() + Returns the saved status register, which is the last configuration + saved by interrupt processing. +*/ +unsigned int gint_ssr(void); + +#endif // _INTERNALS_GINT_H diff --git a/src/keyboard/keyboard_internals.h b/include/internals/keyboard.h similarity index 88% rename from src/keyboard/keyboard_internals.h rename to include/internals/keyboard.h index b08678b..3524f60 100644 --- a/src/keyboard/keyboard_internals.h +++ b/include/internals/keyboard.h @@ -1,5 +1,5 @@ -#ifndef _KEYBOARD_INTERNALS_H -#define _KEYBOARD_INTERNALS_H 1 +#ifndef _INTERNALS_KEYBOARD_H +#define _INTERNALS_KEYBOARD_H 1 #include @@ -31,4 +31,4 @@ int getPressedKey(volatile unsigned char *keyboard_state); int getPressedKeys(volatile unsigned char *keyboard_state, int *keys, int count); -#endif // _KEYBOARD_INTERNALS_H +#endif // _INTERNALS_KEYBOARD_H diff --git a/include/internals/mmu.h b/include/internals/mmu.h new file mode 100644 index 0000000..23aa121 --- /dev/null +++ b/include/internals/mmu.h @@ -0,0 +1,21 @@ +//--- +// +// gint core module: mmu +// +// A wise application should avoid tampering with the system's +// configuration of the MMU and the TLB. This module implicitly calls the +// system but does nothing by itself. +// +//--- + +#ifndef _MMU_H +#define _MMU_H 1 + +/* + mmu_pseudoTLBInit() + Tries to have the system load enough data into TLB to allow add-in to + execute. +*/ +void mmu_pseudoTLBInit(void); + +#endif // _MMU_H diff --git a/src/tales/tales_internals.h b/include/internals/tales.h similarity index 93% rename from src/tales/tales_internals.h rename to include/internals/tales.h index 4908aaf..5e101cd 100644 --- a/src/tales/tales_internals.h +++ b/include/internals/tales.h @@ -7,8 +7,8 @@ // //--- -#ifndef _TALES_INTERNALS_H -#define _TALES_INTERNALS_H 1 +#ifndef _INTERNALS_TALES_H +#define _INTERNALS_TALES_H 1 #include #include @@ -44,4 +44,4 @@ void operate(uint32_t *operators, int height, int x, int y); */ int update(uint32_t *operators, int height, int available, uint32_t *glyph); -#endif // _TALES_INTERNALS_H +#endif // _INTERNALS_TALES_H diff --git a/src/timer/timer_internals.h b/include/internals/timer.h similarity index 90% rename from src/timer/timer_internals.h rename to include/internals/timer.h index 4cc9e5d..b3334cc 100644 --- a/src/timer/timer_internals.h +++ b/include/internals/timer.h @@ -1,5 +1,5 @@ -#ifndef _TIMER_INTERNALS_H -#define _TIMER_INTERNALS_H +#ifndef _INTERNALS_TIMER_H +#define _INTERNALS_TIMER_H 1 /* struct Timer @@ -51,4 +51,4 @@ struct mod_tmu */ void timer_get(int timer, struct mod_tmu **tmu, unsigned char **tstr); -#endif // _TIMER_INTERNALS_H +#endif // _INTERNALS_TIMER_H diff --git a/include/rtc.h b/include/rtc.h new file mode 100644 index 0000000..f1c6439 --- /dev/null +++ b/include/rtc.h @@ -0,0 +1,76 @@ +//--- +// +// gint core module: rtc +// +// Manages RTC. This module is used behind standard module time. +// +//--- + +#ifndef _RTC_H +#define _RTC_H 1 + +//--- +// Callback API. +//--- + +/* + enum RTCFrequency + Describes the possible frequencies available for the real-time clock + interrupt. +*/ +enum RTCFrequency +{ + RTCFreq_500mHz = 7, + RTCFreq_1Hz = 6, + RTCFreq_2Hz = 5, + RTCFreq_4Hz = 4, + RTCFreq_16Hz = 3, + RTCFreq_64Hz = 2, + RTCFreq_256Hz = 1, +}; + +/* + rtc_setCallback() + Sets the callback function for the real-time clock interrupt. If + frequency is non-zero, the clock frequency is set to the given value. + Set the callback to NULL to deactivate an existing callback. +*/ +void rtc_setCallback(void (*callback)(void), enum RTCFrequency frequency); + +/* + rtc_getCallback() + Returns the callback function. If frequency is non-NULL, it is set to + the current frequency value. +*/ +void (*rtc_getCallback(enum RTCFrequency *frequency))(void); + + + +//--- +// Internal API. +// Referenced here for documentation purposes only. Do not call. +//--- + +/* + rtc_interrupt() + Handles an RTC interrupt by calling the callback. +*/ +void rtc_interrupt(void) __attribute__((section(".gint.int"))); +void rtc_interrupt_7705(void) __attribute__((section(".gint.int"))); +void rtc_interrupt_7305(void) __attribute__((section(".gint.int"))); + +/* + rtc_setFrequency() + Sets the RTC interrupt frequency and enables interrupts. +*/ +void rtc_setFrequency_7705(enum RTCFrequency frequency); +void rtc_setFrequency_7305(enum RTCFrequency frequency); + +/* + rtc_getFrequency() + Returns the RTC interrupt frequency. +*/ +enum RTCFrequency rtc_getFrequency_7705(void); +enum RTCFrequency rtc_getFrequency_7305(void); + +#endif // _RTC_H diff --git a/include/string.h b/include/string.h index d5c96dc..e746347 100644 --- a/include/string.h +++ b/include/string.h @@ -8,7 +8,7 @@ //--- /* - memcpy() + memcpy() O(byte_number) Copies a memory area. The two areas must not overlap (if they do, use memmove()). A smart copy is performed when possible. To enhance performance, make sure than destination and source are both 4-aligned. @@ -16,9 +16,21 @@ void *memcpy(void *destination, const void *source, size_t byte_number); /* - memset() + memset() O(byte_number) Sets the contents of a memory area. A smart copy is performed. */ void *memset(void *destination, int byte, size_t byte_number); + + +//--- +// String manipulation. +//--- + +/* + strlen() O(length) + Returns the length of a string. +*/ +size_t strlen(const char *str); + #endif // _STRING_H diff --git a/include/tales.h b/include/tales.h index 4013829..bb990b9 100644 --- a/include/tales.h +++ b/include/tales.h @@ -95,6 +95,12 @@ typedef struct Font Font; */ void text_configure(struct Font *font); +/* + text_configure_default() + Configures tales with the default font (which is part of gint). +*/ +void text_configure_default(void) __attribute__((constructor)); + /* dtext() Prints the given string, without any analysis. diff --git a/libc.a b/libc.a index 587b56ed54bc5700434dc6acb1a7b2aa76b95c85..6bdac151fd258bc70e76e2d7afac13fcabca487d 100644 GIT binary patch delta 865 zcmaJ}U{Mnz{R4CPCZ7K?u zQYe(Vv|&JcES?K1SUidc4?#S5_U6eRJr&yub!N8-_TmTo_~zT?oA=(n&&u12TbD+Q zxlFM*TtrAkto}uWblo3PFd_f|5de5Dc=$B{LLUGKziCd#q7R*C_4!8&0Ho8+m21r{ zkt^uUT|7j`j~A+^Z&P;aNjj1aZfNgCT27}F3I$DlAAvOvb@*tiN@&-2X&Xor1MH5?<8l31u zjgv)a*<-LeX)AR&Ca?1|i-}S1$l=)3PGn2Es+HVGzGPK)x?*TTc12^=nu;Osum+7) z5S=?9pM+(&M@GbrZYHQ*9Qh_)fcxZ^*w2A|B8La)VI(vFUlD`$f5;Z?=gGTp5BVBW z{%@FG2n?H{%g-40qf75~yO^{FoRHTCVioVW22ER&sA;@*8&$mDPhs_5^|^IF{<4}V zCn-{^X89#pmR;WF`{UkGLtrz@8I!bRc95C3&L!w32ZE@9K^f!gC|SO9mwXWx;S3p; zHo6&;b_Ghe1Et%((rsU9%2&GUE4|E=X4CmXCo-%FViP2{laU}Vep2$q3`@#Yncj6q zxQPwL>WL>ekJTF>NWrNeWk{CBcUPw2)*@|`rjK>4U<38hY%9#GB O?>^;eN|_#7jPqX}1Jeiq delta 719 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ℜ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 diff --git a/src/bopti/bopti_internals.c b/src/bopti/bopti_internals.c index 90f3601..60caec1 100644 --- a/src/bopti/bopti_internals.c +++ b/src/bopti/bopti_internals.c @@ -1,4 +1,4 @@ -#include +#include // Monochrome video ram, light and dark buffers (in this order). int *vram, *v1, *v2; @@ -103,6 +103,7 @@ void bopti_grid(const uint32_t *layer, int column_count, int height, const uint32_t *p1, *p2; uint32_t l1, l2, operator; int right_column, line; + int actual_column_count; int vram_column_offset = (c->y << 2) + (c->x >> 5) + (c->x < 0); int vram_offset = vram_column_offset; @@ -117,12 +118,19 @@ void bopti_grid(const uint32_t *layer, int column_count, int height, p1 = layer - height; p2 = layer; - // We don't want to write the first vram column when x is negative. + // We don't want to write the first vram column when x is negative + // because it's outside the screen. if(c->x < 0) p1 += height, p2 += height; right_column = (c->x < 0); + // For the same reason, we don't to draw the additional rightmost + // column when it begins after 96. + if(c->x + (column_count << 5) > 128) + actual_column_count = column_count - 1; + else + actual_column_count = column_count; // Drawing vram longwords, using pairs of columns. - while(right_column <= column_count) + while(right_column <= actual_column_count) { for(line = c->top; line < c->bottom; line++) { @@ -311,7 +319,7 @@ void getStructure(struct Image *img, struct Structure *s) } // The layer size must be rounded to a multiple of 4. - layer = img->height * ((column_count << 2) + end_bytes); + layer = s->height * ((column_count << 2) + end_bytes); if(layer & 3) layer += 4 - (layer & 3); s->columns = column_count; diff --git a/src/bopti/dimage.c b/src/bopti/dimage.c index 3da393f..8c2f5f9 100644 --- a/src/bopti/dimage.c +++ b/src/bopti/dimage.c @@ -1,4 +1,4 @@ -#include +#include #include /* @@ -29,11 +29,10 @@ void dimage(struct Image *img, int x, int y) actual_width = (x + s.width > 128) ? (128 - x) : (s.width); command.right = ((actual_width + 31) >> 5) - 1; - command.x = x; - command.y = y; command.op = bopti_op_mono; - getMasks(x, x + actual_width - 1, command.masks); + if(x >= 0) getMasks(x, x + actual_width - 1, command.masks); + else getMasks(0, actual_width + x - 1, command.masks); vram = display_getCurrentVRAM(); @@ -42,7 +41,11 @@ void dimage(struct Image *img, int x, int y) // Drawing every layer, in order of formats. if(format & 1) { + // These members are modified by bopti()! + command.x = x; + command.y = y; command.channel = (1 << i); + bopti(s.data, &s, &command); s.data += s.layer_size; } diff --git a/src/bopti/gimage.c b/src/bopti/gimage.c index dd31143..65e0ed3 100644 --- a/src/bopti/gimage.c +++ b/src/bopti/gimage.c @@ -1,4 +1,4 @@ -#include +#include #include #include @@ -20,7 +20,7 @@ void gimage(struct Image *img, int x, int y) //--- // Adjusting image parameters. //--- -//-65:-68 + if(x + s.width < 0 || x > 127 || y + s.height < 0 || y > 63) return; command.top = (y < 0) ? (-y) : (0); @@ -54,5 +54,4 @@ void gimage(struct Image *img, int x, int y) format >>= 1; i++; } - } diff --git a/src/core/crt0.c b/src/core/crt0.c index 3bb31da..1643e05 100644 --- a/src/core/crt0.c +++ b/src/core/crt0.c @@ -1,8 +1,10 @@ #include -#include #include #include +#include +#include + void __Hmem_SetMMU(unsigned int, unsigned int, int); void __GLibAddinAplExecutionCheck(int, int, int); int main(void); @@ -42,9 +44,6 @@ int start(void) unsigned int *data = &bdata, *src = &romdata; int x; - // Setting up the TLB. - __Hmem_SetMMU(0x08102000, 0x8801e000, 108); - // Clearing the .bss section. while(bss < &ebss) *bss++ = 0; // Copying the .data section. @@ -52,6 +51,8 @@ int start(void) __GLibAddinAplExecutionCheck(0, 1, 1); + mmu_pseudoTLBInit(); + // Initializing everything. gint_init(); init(); diff --git a/src/core/gint.c b/src/core/gint.c index d6098e0..ec5f526 100644 --- a/src/core/gint.c +++ b/src/core/gint.c @@ -7,6 +7,7 @@ // //--- +#include #include #include #include @@ -63,18 +64,6 @@ inline unsigned int gint_systemVBR(void) return sys_vbr; } -/* - gint() - Handles interrupts. -*/ -void gint(void) -{ - if(isSH3()) - gint_7705(); - else - gint_7305(); -} - /* gint_init() Initializes gint. Loads the interrupt handler into the memory and sets @@ -113,3 +102,145 @@ void gint_quit(void) { gint_setVBR(sys_vbr, gint_stop); } + + + +//--- +// VBR space. +//--- + +#include +#define print(str, x, y) dtext(str, 6 * (x) - 5, 8 * (y) - 7) +#define hexdigit(n) ((n) + '0' + 39 * ((n) > 9)) + +void hex(unsigned int x, int digits, char *str) +{ + str[0] = '0'; + str[1] = 'x'; + str[digits + 2] = 0; + + while(digits) + { + str[digits + 1] = hexdigit(x & 0xf); + x >>= 4; + digits--; + } +} + +/* + gint_exc() + Handles exceptions. +*/ +void gint_exc(void) +{ + volatile unsigned int *expevt = gint_reg(Register_EXPEVT); + volatile unsigned int *tea = gint_reg(Register_TEA); + unsigned int spc; + char str[11]; + + text_configure_default(); + + __asm__("\tstc spc, %0" : "=r"(spc)); + + dclear(); + print("Exception raised!", 3, 1); + dreverse_area(0, 0, 127, 8); + print(gint_strerror(0), 2, 3); + + print("expevt", 2, 4); + hex(*expevt, 3, str); + print(str, 16, 4); + + print("pc", 2, 5); + hex(spc, 8, str); + print(str, 11, 5); + + print("tea", 2, 6); + hex(*tea, 8, str); + print(str, 11, 6); + + print("Please reset.", 2, 7); + dupdate(); + while(1); +} + +/* + gint_tlb() + Handles TLB misses. +*/ +void gint_tlb(void) +{ + volatile unsigned int *expevt = gint_reg(Register_EXPEVT); + volatile unsigned int *tea = gint_reg(Register_TEA); + unsigned int spc; + char str[11]; + + text_configure_default(); + + __asm__("\tstc spc, %0" : "=r"(spc)); + + dclear(); + print("TLB error!", 6, 1); + dreverse_area(0, 0, 127, 8); + print(gint_strerror(1), 2, 3); + + print("expevt", 2, 4); + hex(*expevt, 3, str); + print(str, 16, 4); + + print("pc", 2, 5); + hex(spc, 8, str); + print(str, 11, 5); + + print("tea", 2, 6); + hex(*tea, 8, str); + print(str, 11, 6); + + print("Please reset.", 2, 7); + dupdate(); + while(1); +} + +/* + gint_int() + Handles interrupts. +*/ +void gint_int(void) +{ + if(isSH3()) + gint_int_7705(); + else + gint_int_7305(); +} + +/* + gint_reg() + Returns the address of a common register. All common registers exist + on both platforms but they may hold different values for the same + information (f.i. EXPEVT may not return the same value for a given + exception on both 7705 and 7305). +*/ +inline volatile void *gint_reg(enum Register reg) +{ + if(isSH3()) + return gint_reg_7705(reg); + else + return gint_reg_7305(reg); +} + +/* + gint_strerror() + Returns a string that describe the error set in EXPEVT. This string is + not platform-dependent. + Some exception codes represent different errors when invoked inside the + general exception handler and the TLB error handler. Parameter 'is_tlb' + should be set to zero for general exception meanings, and anything non- + zero for TLB error meanings. +*/ +const char *gint_strerror(int is_tlb) +{ + if(isSH3()) + return gint_strerror_7705(is_tlb); + else + return gint_strerror_7305(is_tlb); +} diff --git a/src/core/gint_str.c b/src/core/gint_str.c new file mode 100644 index 0000000..c7e9957 --- /dev/null +++ b/src/core/gint_str.c @@ -0,0 +1,37 @@ +#include + +const char *gint_str[] = { + "Unknown", + + // User breaks. + "User break (before)", + "User break (after)", + "User breakpoint", + + // General. + "Inst. address error", + "Data access error", + "Illegal instruction", + "Illegal slot", + "Data address (r)", + "Data address (w)", + + // Instruction TLB. + "Inst. TLB miss", + "Inst. TLB invalid", + "Inst. TLB protect.", + + // Data TLB. + "Data TLB miss", + "Data TLB miss (r)", + "Data TLB miss (w)", + "Data TLB protection", + "Data TLB prot. (r)", + "Data TLB prot. (w)", + "Data TLB invalid", + + // Others. + "Initial page write", + "Trap", + "DMA address error", +}; diff --git a/src/core/syscalls.s b/src/core/syscalls.s index 5e67fa9..ca5397f 100644 --- a/src/core/syscalls.s +++ b/src/core/syscalls.s @@ -1,11 +1,10 @@ /* gint core module: syscalls - All the system calls used by the library. Let's hope one day we won't - depend on them anymore. + All the system calls used by the library. Somehow "the less, the + better". */ - .global ___Hmem_SetMMU .global ___GLibAddinAplExecutionCheck .global _malloc .global _calloc @@ -13,13 +12,6 @@ -___Hmem_SetMMU: - mov.l syscall_table, r2 - mov.l 1f, r0 - jmp @r2 - nop -1: .long 0x3fa - ___GLibAddinAplExecutionCheck: mov.l syscall_table, r2 mov #0x13, r0 diff --git a/src/display/adjustRectangle.c b/src/display/adjustRectangle.c index 3b5b237..a865e4f 100644 --- a/src/display/adjustRectangle.c +++ b/src/display/adjustRectangle.c @@ -1,4 +1,4 @@ -#include +#include /* adjustRectangle() diff --git a/src/display/dclear.c b/src/display/dclear.c index d33503b..ed45a6d 100644 --- a/src/display/dclear.c +++ b/src/display/dclear.c @@ -1,4 +1,4 @@ -#include +#include #include /* diff --git a/src/display/dclear_area.c b/src/display/dclear_area.c index 2648178..a8755c5 100644 --- a/src/display/dclear_area.c +++ b/src/display/dclear_area.c @@ -1,4 +1,4 @@ -#include +#include #include /* diff --git a/src/display/dline.c b/src/display/dline.c index 69e331d..7a76173 100644 --- a/src/display/dline.c +++ b/src/display/dline.c @@ -1,4 +1,4 @@ -#include +#include #include #define sgn(x) ((x) < 0 ? -1 : 1) diff --git a/src/display/dpixel.c b/src/display/dpixel.c index c5bfb9a..60c3a06 100644 --- a/src/display/dpixel.c +++ b/src/display/dpixel.c @@ -1,4 +1,4 @@ -#include +#include #include /* diff --git a/src/display/dreverse_area.c b/src/display/dreverse_area.c index c9eeaee..286f221 100644 --- a/src/display/dreverse_area.c +++ b/src/display/dreverse_area.c @@ -1,4 +1,4 @@ -#include +#include #include /* diff --git a/src/display/dupdate.c b/src/display/dupdate.c index 6942c60..6ca42f8 100644 --- a/src/display/dupdate.c +++ b/src/display/dupdate.c @@ -1,4 +1,4 @@ -#include +#include #include #include #include diff --git a/src/display/font_system.bmp b/src/display/font_system.bmp new file mode 100644 index 0000000000000000000000000000000000000000..e866558a1efb2b18fbaa6c2d36c784e0ee4d29c9 GIT binary patch literal 32762 zcmeI4v65s*6+{ItCJx^t2TKkS`~@B!4txb4iz9M7r_ZMHR=s}H-7ARItB9@1dv4yW z>RPozjkbCxL)9Tf$IgX7x<06fc|qRKXH}Wvc`Z&k02|#w0S~^MDZ*=%kCBr5?#6Ayj7a|y`mBRJr;crM zdf6t8AB~_Tkq|ABYv(tgP7y{@*Kv3zcV-%_muZHy5E;9KGrveqRcl$|N63aoJO@3c zkY!F~;z7ue9+&J(TfsSQL+R%4pT6mtqDcEu-(CzpFj!t5~g|SbVAN%CgT=P zNb@A_PVNMUS3;F`;%8);Ibo(vow4ptGN(jN+G_U9)Vn-&bd|ePcD%;lRnFr?CY;Be z@jN|syTUKNRuy${`mR;HO6LnMd7XZh*9%-P@Rk>-uUnOQ#Fua8Z5c|^EuFTdhlKM^ zjnpZ-oV!jk<{ry zTjcKK9m%fsl8}Gk*|l;ub^1^08qX4qP$nAj5c($R&ym#WK_i}X`gHHhC=A&JBC6}M zAm;O;5>&D>WI~9cELdCMU>Lj#E?407|yvpkZt{3>!3(POk{JNzFjSb>+ z;amff&V+CTvz3VfAp?5%yOIoe2;>M_H`mwg*g3~V7^eGBaJro?b9XE`_z`J%4$g2$ zhNoU0>m<9ubmBjN^Q^i?m1NFAS_pa2h}R)k z%FHFifXLH5k}X2Yh6hmw24%1ZVW(kEK@yU)6FFs%4=O$(9WoZe>X6<+weXE%R|%{wz}~q{@fn*q>cAVuoj{y49+#%juamksWla z_GM;y9+nlN5`u6@l?Sj|UlL=@E2&u{DuJ_A-EvO94>xDuK@8;BdEQ?M$E9M^;4*i* z4)4cA3xy|Mv$Eoj+0rn5`I>n8DDyqSNiPfm;ZW! z-_8rv_lRFfEc_1nTZwc+{JfY0D^}e}JR+VgN+3sA)akP2m0T{J3At?w8%W4jX*p#( z%bt(h+ShSDc=$ge9DBC7Ye~F_(M^Jy;=Ca<2L8*6CMyy}R#I?0LnRX_vlU;Cg}o zlNYEjwaQ$+q<{5bpYWT0mb{Pd@Z4Dn$-&HAw$l7f^*o*9swG~eN*e@O$5GfMaL!YR zO%Jx3g{OIXvYQ$w!rdxA3-gH5m7Ha2O{siHD%_<9*_WQ_Oq*wmsPuij&#npQ?m`&E z2|+B6co@j|fvDsxOD~Tr=#o9p6|53lwQNghXN{}02d8c9_|pJn{0wnIEsvASTpruf!=T5H{dm#_%vc+8pWR7_CDX!AU=B(j@aZh_uvB<@vP^AHkt)eK z&zH_6BphMeG*40^yHcE4gw0ic7INYgm8>$?^q(XOdFVXjafq+78dV%W&{^u{?e+{zdzZIojT1?I5-O4fvS^_OI`i4JRhP251Ud8;pljK{a=9Q*c z+Wdyo3}GsXr@q%+pVVvjIK@@UU$1dYvb)rRUWBWxBfi(tpEP%W(t3d`(TIAtGn|nW s)*8i7Ph7KvrHmxXu)1QJ*m?#eXZ*SzR?T(7r!*g8~^|S literal 0 HcmV?d00001 diff --git a/src/keyboard/getPressedKey.c b/src/keyboard/getPressedKey.c index 5e53a01..ca8ba32 100644 --- a/src/keyboard/getPressedKey.c +++ b/src/keyboard/getPressedKey.c @@ -1,4 +1,4 @@ -#include +#include /* getPressedKey() diff --git a/src/keyboard/getPressedKeys.c b/src/keyboard/getPressedKeys.c index 20f52dc..b6dd739 100644 --- a/src/keyboard/getPressedKeys.c +++ b/src/keyboard/getPressedKeys.c @@ -1,4 +1,4 @@ -#include +#include /* getPressedKeys() diff --git a/src/keyboard/getkey.c b/src/keyboard/getkey.c index faf9853..2cfc156 100644 --- a/src/keyboard/getkey.c +++ b/src/keyboard/getkey.c @@ -1,5 +1,5 @@ +#include #include -#include /* getkey() diff --git a/src/keyboard/keyboard_config.c b/src/keyboard/keyboard_config.c index 909952d..f3a9361 100644 --- a/src/keyboard/keyboard_config.c +++ b/src/keyboard/keyboard_config.c @@ -1,5 +1,5 @@ +#include #include -#include /* keyboard_setFrequency() diff --git a/src/keyboard/keyboard_interrupt.c b/src/keyboard/keyboard_interrupt.c index e76aca1..4273445 100644 --- a/src/keyboard/keyboard_interrupt.c +++ b/src/keyboard/keyboard_interrupt.c @@ -2,7 +2,7 @@ #include #include -#include +#include //--- // Keyboard variables. diff --git a/src/keyboard/keyboard_misc.c b/src/keyboard/keyboard_misc.c index 4837c8b..abdf59c 100644 --- a/src/keyboard/keyboard_misc.c +++ b/src/keyboard/keyboard_misc.c @@ -1,5 +1,5 @@ #include -#include +#include /* keylast() diff --git a/src/keyboard/multigetkey.c b/src/keyboard/multigetkey.c index fb7d355..dbe8a44 100644 --- a/src/keyboard/multigetkey.c +++ b/src/keyboard/multigetkey.c @@ -1,5 +1,5 @@ #include -#include +#include /* multigetkey() diff --git a/src/keyboard/sleep.c b/src/keyboard/sleep.c index 92ae174..8e71e84 100644 --- a/src/keyboard/sleep.c +++ b/src/keyboard/sleep.c @@ -1,4 +1,4 @@ -#include +#include /* sleep() diff --git a/src/mmu/pseudoTLBInit.c b/src/mmu/pseudoTLBInit.c new file mode 100644 index 0000000..d9e827b --- /dev/null +++ b/src/mmu/pseudoTLBInit.c @@ -0,0 +1,25 @@ +#include + +/* + mmu_pseudoTLBInit() + We need the system to fill the TLB for us, so that it knows what + happens to its contents. We don't want to edit the TLB ourselves, so + we'll just read random data from every 4k-page in the rom area to have + the system virtualize it entirely. + The index system for TLB entries ensures this process will work for + 128-k or less add-ins. On SH7705 there is a limit, which is 384-k (it + does probably not exist on SH7305) but there is no guarantee that the + system will not go wild after 128-k. +*/ +void mmu_pseudoTLBInit(void) +{ + extern unsigned int romdata; + unsigned int address = 0x00300000; + unsigned int x; + + while(address <= (unsigned int)&romdata) + { + x = *((volatile unsigned int *)address); + address += 0x1000; + } +} diff --git a/src/mpu/gint_sh7305.c b/src/mpu/gint_sh7305.c index f5e8c85..03570b3 100644 --- a/src/mpu/gint_sh7305.c +++ b/src/mpu/gint_sh7305.c @@ -8,9 +8,13 @@ // //--- +#include #include #include #include <7305.h> +#include + +#include //--- // Interrupt codes. @@ -25,10 +29,10 @@ //--- -// Interrupt handler. +// Exception handling. //--- -void gint_7305(void) +void gint_int_7305(void) { volatile unsigned int *intevt = (unsigned int *)0xff000028; unsigned int code = *intevt; @@ -36,7 +40,7 @@ void gint_7305(void) switch(code) { case IC_RTC_PRI: - RTC.RCR2.PEF = 0; + rtc_interrupt(); break; case IC_TMU0_TUNI0: @@ -53,6 +57,58 @@ void gint_7305(void) } } +/* + gint_reg() + Returns the address of a common register. All common registers exist + on both platforms but they may hold different values for the same + information (f.i. EXPEVT may not return the same value for a given + exception on both 7705 and 7305). +*/ +volatile void *gint_reg_7305(enum Register reg) +{ + volatile unsigned int *expevt = (unsigned int *)0xff000024; + volatile unsigned int *tea = (unsigned int *)0xff00000c; + volatile unsigned int *mmucr = (unsigned int *)0xff000010; + + switch(reg) + { + case Register_EXPEVT: return expevt; + case Register_TEA: return tea; + case Register_MMUCR: return mmucr; + default: return NULL; + } +} + +/* + gint_strerror() + Returns a string that describe the error set in EXPEVT. This string is + not platform-dependent. + Some exception codes represent different errors when invoked inside the + general exception handler and the TLB error handler. Parameter 'is_tlb' + should be set to zero for general exception meanings, and anything non- + zero for TLB error meanings. +*/ +const char *gint_strerror_7305(int is_tlb) +{ + volatile unsigned int *expevt = gint_reg_7305(Register_EXPEVT); + + switch(*expevt) + { + case 0x1e0: return gint_str[3]; + case 0x0e0: return gint_str[8]; + case 0x040: return gint_str[14]; + case 0x0a0: return gint_str[17]; + case 0x180: return gint_str[6]; + case 0x1a0: return gint_str[7]; + case 0x100: return gint_str[9]; + case 0x060: return gint_str[15]; + case 0x0c0: return gint_str[18]; + case 0x080: return gint_str[20]; + case 0x160: return gint_str[21]; + } + return gint_str[0]; +} + //--- diff --git a/src/mpu/gint_sh7705.c b/src/mpu/gint_sh7705.c index f17aafb..61a0e2e 100644 --- a/src/mpu/gint_sh7705.c +++ b/src/mpu/gint_sh7705.c @@ -8,9 +8,13 @@ // //--- +#include #include #include #include <7705.h> +#include + +#include //--- // Interrupt codes. @@ -25,10 +29,10 @@ //--- -// Interrupt handler. +// Exception handling. //--- -void gint_7705(void) +void gint_int_7705(void) { volatile unsigned int *intevt2 = (unsigned int *)0xa4000000; unsigned int code = *intevt2; @@ -36,7 +40,7 @@ void gint_7705(void) switch(code) { case IC_RTC_PRI: - RTC.RCR2.BIT.PEF = 0; + rtc_interrupt(); break; case IC_TMU0_TUNI0: @@ -53,6 +57,59 @@ void gint_7705(void) } } +/* + gint_reg() + Returns the address of a common register. All common registers exist + on both platforms but they may hold different values for the same + information (f.i. EXPEVT may not return the same value for a given + exception on both 7705 and 7305). +*/ +volatile void *gint_reg_7705(enum Register reg) +{ + volatile unsigned int *expevt = (unsigned int *)0xffffffd4; + volatile unsigned int *mmucr = (unsigned int *)0xfffffff4; + volatile unsigned int *tea = (unsigned int *)0xfffffffc; + + switch(reg) + { + case Register_EXPEVT: return expevt; + case Register_MMUCR: return mmucr; + case Register_TEA: return tea; + default: return NULL; + } +} + +/* + gint_strerror() + Returns a string that describe the error set in EXPEVT. This string is + not platform-dependent. + Some exception codes represent different errors when invoked inside the + general exception handler and the TLB error handler. Parameter 'is_tlb' + should be set to zero for general exception meanings, and anything non- + zero for TLB error meanings. +*/ +const char *gint_strerror_7705(int is_tlb) +{ + volatile unsigned int *expevt = gint_reg_7705(Register_EXPEVT); + + switch(*expevt) + { + case 0x1e0: return gint_str[3]; + case 0x0e0: return gint_str[4]; + case 0x040: return gint_str[is_tlb ? 10 : 11]; + case 0x0a0: return gint_str[12]; + case 0x180: return gint_str[6]; + case 0x1a0: return gint_str[7]; + case 0x100: return gint_str[5]; + case 0x060: return gint_str[is_tlb ? 13 : 19]; + case 0x0c0: return gint_str[16]; + case 0x080: return gint_str[20]; + case 0x160: return gint_str[21]; + case 0x5c0: return gint_str[22]; + } + return gint_str[0]; +} + //--- diff --git a/src/mpu/various_7305.c b/src/mpu/rtc_7305.c similarity index 51% rename from src/mpu/various_7305.c rename to src/mpu/rtc_7305.c index 6182968..89d8cbd 100644 --- a/src/mpu/various_7305.c +++ b/src/mpu/rtc_7305.c @@ -1,27 +1,34 @@ -#include -#include -#include #include <7305.h> +#include //--- // Various MPU-dependent procedures. //--- /* - gint_setRTCFrequency() + rtc_setFrequency() Sets the RTC interrupt frequency and enables interrupts. */ -void gint_setRTCFrequency_7305(enum RTCFrequency frequency) +void rtc_setFrequency_7305(enum RTCFrequency frequency) { if(frequency < 1 || frequency > 7) return; RTC.RCR2.BYTE = (frequency << 4) | 0x09; } /* - gint_getRTCFrequency() + rtc_getFrequency() Returns the RTC interrupt frequency. */ -enum RTCFrequency gint_getRTCFrequency_7305(void) +enum RTCFrequency rtc_getFrequency_7305(void) { return (RTC.RCR2.BYTE & 0x70) >> 4; } + +/* + rtc_interrupt() + Handles an RTC interrupt by calling the callback. +*/ +void rtc_interrupt_7305(void) +{ + RTC.RCR2.PEF = 0; +} diff --git a/src/mpu/various_7705.c b/src/mpu/rtc_7705.c similarity index 51% rename from src/mpu/various_7705.c rename to src/mpu/rtc_7705.c index c046813..b677bc2 100644 --- a/src/mpu/various_7705.c +++ b/src/mpu/rtc_7705.c @@ -1,27 +1,34 @@ -#include -#include -#include #include <7705.h> +#include //--- // Various MPU-dependent procedures. //--- /* - gint_setRTCFrequency() + rtc_setFrequency() Sets the RTC interrupt frequency and enables interrupts. */ -void gint_setRTCFrequency_7705(enum RTCFrequency frequency) +void rtc_setFrequency_7705(enum RTCFrequency frequency) { if(frequency < 1 || frequency > 7) return; RTC.RCR2.BYTE = (frequency << 4) | 0x09; } /* - gint_getRTCFrequency() + rtc_getFrequency() Returns the RTC interrupt frequency. */ -enum RTCFrequency gint_getRTCFrequency_7705(void) +enum RTCFrequency rtc_getFrequency_7705(void) { return (RTC.RCR2.BYTE & 0x70) >> 4; } + +/* + rtc_interrupt() + Handles an RTC interrupt by calling the callback. +*/ +void rtc_interrupt_7705(void) +{ + RTC.RCR2.BIT.PEF = 0; +} diff --git a/src/core/gint_callback.c b/src/rtc/rtc_interrupt.c similarity index 57% rename from src/core/gint_callback.c rename to src/rtc/rtc_interrupt.c index d9d1ee7..a606a45 100644 --- a/src/core/gint_callback.c +++ b/src/rtc/rtc_interrupt.c @@ -1,31 +1,32 @@ -#include +#include #include #include static void (*rtc_callback)(void) = NULL; +//--- +// Callback API. +//--- + /* - gint_setRTCCallback() + rtc_setCallback() Sets the callback function for the real-time clock interrupt. If frequency is non-NULL, the clock frequency is set to the given value. - - @arg callback Callback function. - @arg frequency Interrupt frequency. */ void gint_setRTCCallback(void (*callback)(void), enum RTCFrequency frequency) { - if(frequency < 1 || frequency > 7) return; rtc_callback = callback; + if(frequency < 1 || frequency > 7) return; if(isSH3()) - gint_setRTCFrequency_7705(frequency); + rtc_setFrequency_7705(frequency); else - gint_setRTCFrequency_7305(frequency); + rtc_setFrequency_7305(frequency); } /* - gint_getRTCCallback() + rtc_getCallback() Returns the callback function. If frequency is non-NULL, it is set to the current frequency value. */ @@ -34,9 +35,29 @@ void (*gint_getRTCCallback(enum RTCFrequency *frequency))(void) if(!frequency) return rtc_callback; if(isSH3()) - *frequency = gint_getRTCFrequency_7705(); + *frequency = rtc_getFrequency_7705(); else - *frequency = gint_getRTCFrequency_7305(); + *frequency = rtc_getFrequency_7305(); return rtc_callback; } + + + +//--- +// Interrupt management. +//--- + +/* + rtc_interrupt() + Handles an RTC interrupt by calling the callback. +*/ +void rtc_interrupt(void) +{ + if(rtc_callback) (*rtc_callback)(); + + if(isSH3()) + rtc_interrupt_7705(); + else + rtc_interrupt_7305(); +} diff --git a/src/string/strlen.c b/src/string/strlen.c new file mode 100644 index 0000000..7b5a9a1 --- /dev/null +++ b/src/string/strlen.c @@ -0,0 +1,12 @@ +#include + +/* + strlen() + Returns the length of a string. +*/ +size_t strlen(const char *str) +{ + int len = 0; + while(str[len]) len++; + return len; +} diff --git a/src/tales/dtext.c b/src/tales/dtext.c index 7f52aaa..6d44e2b 100644 --- a/src/tales/dtext.c +++ b/src/tales/dtext.c @@ -1,8 +1,9 @@ -#include +#include #include #include #include +#include /* dtext() @@ -24,6 +25,8 @@ void dtext(const char *str, int x, int y) // format requires it: it allows greater optimization. int height; + int i; + if(!font) return; @@ -32,7 +35,8 @@ void dtext(const char *str, int x, int y) height = font->data_height; if(x > 127 || y > 63 || y <= -height) return; - operators = calloc(height, sizeof(uint32_t)); + operators = alloca(height * sizeof(uint32_t)); + for(i = 0; i < height; i++) operators[i] = 0; if(!operators) return; // Computing the initial operator offset to have 32-aligned operators. @@ -84,5 +88,5 @@ void dtext(const char *str, int x, int y) // Final operation. if(x <= 96 && available < 32) operate(operators, height, x, y); - free(operators); +// free(operators); } diff --git a/src/tales/tales_configuration.c b/src/tales/tales_configuration.c index eb2aefa..394dd0f 100644 --- a/src/tales/tales_configuration.c +++ b/src/tales/tales_configuration.c @@ -1,4 +1,4 @@ -#include +#include #include /* @@ -9,3 +9,13 @@ void text_configure(struct Font *next_font) { font = next_font; } + +/* + text_configure_default() + Configures tales with the default font (which is part of gint). +*/ +void text_configure_default(void) +{ + extern Font gint_font_system_start; + text_configure(&gint_font_system_start); +} diff --git a/src/tales/tales_internals.c b/src/tales/tales_internals.c index 8470254..7e29d3f 100644 --- a/src/tales/tales_internals.c +++ b/src/tales/tales_internals.c @@ -1,4 +1,4 @@ -#include +#include #include struct Font *font; diff --git a/src/timer/timer_get.c b/src/timer/timer_get.c index c3ab7f0..0d4b5cb 100644 --- a/src/timer/timer_get.c +++ b/src/timer/timer_get.c @@ -1,4 +1,4 @@ -#include +#include #include /* diff --git a/src/timer/timer_interrupt.c b/src/timer/timer_interrupt.c index 5af1d6c..aea22bf 100644 --- a/src/timer/timer_interrupt.c +++ b/src/timer/timer_interrupt.c @@ -1,5 +1,5 @@ +#include #include -#include #include diff --git a/src/timer/timer_reload.c b/src/timer/timer_reload.c index 6d9112c..3b725e0 100644 --- a/src/timer/timer_reload.c +++ b/src/timer/timer_reload.c @@ -1,5 +1,5 @@ +#include #include -#include /* timer_reload() diff --git a/src/timer/timer_start.c b/src/timer/timer_start.c index f753e5d..c320edf 100644 --- a/src/timer/timer_start.c +++ b/src/timer/timer_start.c @@ -1,5 +1,5 @@ +#include #include -#include /* timer_start() diff --git a/src/timer/timer_stop.c b/src/timer/timer_stop.c index 1c77d5a..8d8d860 100644 --- a/src/timer/timer_stop.c +++ b/src/timer/timer_stop.c @@ -1,5 +1,5 @@ +#include #include -#include #include