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 c577abd..5c1c91b 100644 Binary files a/demo/resources/font.bmp and b/demo/resources/font_modern.bmp differ diff --git a/demo/resources/illustration.bmp b/demo/resources/illustration.bmp deleted file mode 100644 index ca8755a..0000000 Binary files a/demo/resources/illustration.bmp and /dev/null differ diff --git a/demo/resources/items.bmp b/demo/resources/items.bmp new file mode 100644 index 0000000..ec6a419 Binary files /dev/null and b/demo/resources/items.bmp differ diff --git a/demo/resources/opt_gray.bmp b/demo/resources/opt_gray.bmp new file mode 100644 index 0000000..a44613d Binary files /dev/null and b/demo/resources/opt_gray.bmp differ diff --git a/demo/resources/opt_menu.bmp b/demo/resources/opt_menu.bmp new file mode 100644 index 0000000..4d682e4 Binary files /dev/null and b/demo/resources/opt_menu.bmp differ diff --git a/gintdemo.g1a b/gintdemo.g1a index ec073c9..7a61a46 100644 Binary files a/gintdemo.g1a and b/gintdemo.g1a differ diff --git a/include/alloca.h b/include/alloca.h new file mode 100644 index 0000000..9cf0899 --- /dev/null +++ b/include/alloca.h @@ -0,0 +1,23 @@ +//--- +// +// gint core module: alloca +// +// Allows dynamic memory allocation on the stack. Memory is automatically +// freed when the calling function exits. +// +//--- + +#ifndef _ALLOCA_H +#define _ALLOCA_H 1 + +#include + +/* + alloca() + Allocates a memory block on the stack. +*/ +void *alloca(size_t size); + +#define alloca(size) __builtin_alloca(size) + +#endif // _ALLOCA_H diff --git a/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 587b56e..6bdac15 100644 Binary files a/libc.a and b/libc.a differ diff --git a/libgint.a b/libgint.a index 30b9985..072c42e 100644 Binary files a/libgint.a and b/libgint.a differ 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 0000000..e866558 Binary files /dev/null and b/src/display/font_system.bmp differ 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