Reported TLB issues. Moved internal headers files, added rtc module and alloca.

This commit is contained in:
lephe 2016-07-25 09:04:22 +02:00
parent 34dd27d7a3
commit 7f174043a5
63 changed files with 1117 additions and 327 deletions

View File

@ -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
#---

15
TODO
View File

@ -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

View File

@ -2,6 +2,7 @@
#include <string.h>
#include <mpu.h>
#include <gint.h>
#include <keyboard.h>
#include <display.h>
#include <timer.h>
@ -10,62 +11,67 @@
#include <stdint.h>
#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 <internals/timer.h>
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;

View File

@ -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)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

BIN
demo/resources/items.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

BIN
demo/resources/opt_gray.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
demo/resources/opt_menu.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

23
include/alloca.h Normal file
View File

@ -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 <stddef.h>
/*
alloca()
Allocates a memory block on the stack.
*/
void *alloca(size_t size);
#define alloca(size) __builtin_alloca(size)
#endif // _ALLOCA_H

View File

@ -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

View File

@ -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

View File

@ -14,8 +14,8 @@
//
//---
#ifndef _BOPTI_INTERNALS_H
#define _BOPTI_INTERNALS_H 1
#ifndef _INTERNALS_BOPTI_H
#define _INTERNALS_BOPTI_H 1
#include <stdint.h>
#include <display.h>
@ -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

View File

@ -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

30
include/internals/gint.h Normal file
View File

@ -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

View File

@ -1,5 +1,5 @@
#ifndef _KEYBOARD_INTERNALS_H
#define _KEYBOARD_INTERNALS_H 1
#ifndef _INTERNALS_KEYBOARD_H
#define _INTERNALS_KEYBOARD_H 1
#include <keyboard.h>
@ -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

21
include/internals/mmu.h Normal file
View File

@ -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

View File

@ -7,8 +7,8 @@
//
//---
#ifndef _TALES_INTERNALS_H
#define _TALES_INTERNALS_H 1
#ifndef _INTERNALS_TALES_H
#define _INTERNALS_TALES_H 1
#include <tales.h>
#include <stdint.h>
@ -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

View File

@ -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

76
include/rtc.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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.

BIN
libc.a

Binary file not shown.

BIN
libgint.a

Binary file not shown.

View File

@ -1,4 +1,4 @@
#include <bopti_internals.h>
#include <internals/bopti.h>
// 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;

View File

@ -1,4 +1,4 @@
#include <bopti_internals.h>
#include <internals/bopti.h>
#include <display.h>
/*
@ -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;
}

View File

@ -1,4 +1,4 @@
#include <bopti_internals.h>
#include <internals/bopti.h>
#include <display.h>
#include <gray.h>
@ -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++;
}
}

View File

@ -1,8 +1,10 @@
#include <stdlib.h>
#include <gint.h>
#include <string.h>
#include <setjmp.h>
#include <gint.h>
#include <internals/mmu.h>
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();

View File

@ -7,6 +7,7 @@
//
//---
#include <internals/gint.h>
#include <gint.h>
#include <mpu.h>
#include <stddef.h>
@ -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 <display.h>
#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);
}

37
src/core/gint_str.c Normal file
View File

@ -0,0 +1,37 @@
#include <internals/gint.h>
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",
};

View File

@ -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

View File

@ -1,4 +1,4 @@
#include <display_internals.h>
#include <internals/display.h>
/*
adjustRectangle()

View File

@ -1,4 +1,4 @@
#include <display_internals.h>
#include <internals/display.h>
#include <display.h>
/*

View File

@ -1,4 +1,4 @@
#include <display_internals.h>
#include <internals/display.h>
#include <display.h>
/*

View File

@ -1,4 +1,4 @@
#include <display_internals.h>
#include <internals/display.h>
#include <display.h>
#define sgn(x) ((x) < 0 ? -1 : 1)

View File

@ -1,4 +1,4 @@
#include <display_internals.h>
#include <internals/display.h>
#include <display.h>
/*

View File

@ -1,4 +1,4 @@
#include <display_internals.h>
#include <internals/display.h>
#include <display.h>
/*

View File

@ -1,4 +1,4 @@
#include <display_internals.h>
#include <internals/display.h>
#include <display.h>
#include <screen.h>
#include <gray.h>

BIN
src/display/font_system.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

@ -1,4 +1,4 @@
#include <keyboard_internals.h>
#include <internals/keyboard.h>
/*
getPressedKey()

View File

@ -1,4 +1,4 @@
#include <keyboard_internals.h>
#include <internals/keyboard.h>
/*
getPressedKeys()

View File

@ -1,5 +1,5 @@
#include <internals/keyboard.h>
#include <keyboard.h>
#include <keyboard_internals.h>
/*
getkey()

View File

@ -1,5 +1,5 @@
#include <internals/keyboard.h>
#include <keyboard.h>
#include <keyboard_internals.h>
/*
keyboard_setFrequency()

View File

@ -2,7 +2,7 @@
#include <timer.h>
#include <mpu.h>
#include <keyboard_internals.h>
#include <internals/keyboard.h>
//---
// Keyboard variables.

View File

@ -1,5 +1,5 @@
#include <keyboard.h>
#include <keyboard_internals.h>
#include <internals/keyboard.h>
/*
keylast()

View File

@ -1,5 +1,5 @@
#include <keyboard.h>
#include <keyboard_internals.h>
#include <internals/keyboard.h>
/*
multigetkey()

View File

@ -1,4 +1,4 @@
#include <keyboard_internals.h>
#include <internals/keyboard.h>
/*
sleep()

25
src/mmu/pseudoTLBInit.c Normal file
View File

@ -0,0 +1,25 @@
#include <internals/mmu.h>
/*
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;
}
}

View File

@ -8,9 +8,13 @@
//
//---
#include <internals/gint.h>
#include <gint.h>
#include <timer.h>
#include <7305.h>
#include <rtc.h>
#include <stddef.h>
//---
// 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];
}
//---

View File

@ -8,9 +8,13 @@
//
//---
#include <internals/gint.h>
#include <gint.h>
#include <timer.h>
#include <7705.h>
#include <rtc.h>
#include <stddef.h>
//---
// 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];
}
//---

View File

@ -1,27 +1,34 @@
#include <gint.h>
#include <timer.h>
#include <keyboard.h>
#include <7305.h>
#include <rtc.h>
//---
// 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;
}

View File

@ -1,27 +1,34 @@
#include <gint.h>
#include <timer.h>
#include <keyboard.h>
#include <7705.h>
#include <rtc.h>
//---
// 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;
}

View File

@ -1,31 +1,32 @@
#include <gint.h>
#include <rtc.h>
#include <mpu.h>
#include <stddef.h>
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();
}

12
src/string/strlen.c Normal file
View File

@ -0,0 +1,12 @@
#include <string.h>
/*
strlen()
Returns the length of a string.
*/
size_t strlen(const char *str)
{
int len = 0;
while(str[len]) len++;
return len;
}

View File

@ -1,8 +1,9 @@
#include <tales_internals.h>
#include <internals/tales.h>
#include <tales.h>
#include <stdlib.h>
#include <string.h>
#include <alloca.h>
/*
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);
}

View File

@ -1,4 +1,4 @@
#include <tales_internals.h>
#include <internals/tales.h>
#include <tales.h>
/*
@ -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);
}

View File

@ -1,4 +1,4 @@
#include <tales_internals.h>
#include <internals/tales.h>
#include <ctype.h>
struct Font *font;

View File

@ -1,4 +1,4 @@
#include <timer_internals.h>
#include <internals/timer.h>
#include <mpu.h>
/*

View File

@ -1,5 +1,5 @@
#include <internals/timer.h>
#include <timer.h>
#include <timer_internals.h>
#include <stddef.h>

View File

@ -1,5 +1,5 @@
#include <internals/timer.h>
#include <timer.h>
#include <timer_internals.h>
/*
timer_reload()

View File

@ -1,5 +1,5 @@
#include <internals/timer.h>
#include <timer.h>
#include <timer_internals.h>
/*
timer_start()

View File

@ -1,5 +1,5 @@
#include <internals/timer.h>
#include <timer.h>
#include <timer_internals.h>
#include <stddef.h>