commit 0a7f22d4c1f8d34f2cc01193d629cbdb785526f6 Author: lephe Date: Thu May 5 11:49:05 2016 +0200 Initial commit. Includes interrupt handler, drivers for keyboard and screen, and parts of the drawing library. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..767efe3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +# Sources for old gint versions. +gint.old.1/** +gint.old.2/** + +# Build directory +build/** + +# Sublime Text files +*.sublime-project +*.sublime-workspace + +# Object files. +*.o diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0a75411 --- /dev/null +++ b/Makefile @@ -0,0 +1,119 @@ +# +# fx-9860g lib Makefile. +# + +.PHONY: all clean fclean re install + + + +# +# Variables and configuration. +# + +# Tools +cc = sh3eb-elf-gcc +as = sh3eb-elf-as +ar = sh3eb-elf-ar +ob = sh3eb-elf-objcopy +wr = g1a-wrapper + +# Output files +g1a = addin.g1a +bin = build/addin.bin +elf = build/addin.elf + +# Command-line options +cflags = -m3 -mb -nostdlib -ffreestanding \ + -W -Wall -pedantic -std=c11 \ + -I . -isystem include +lib = -lgcc -L. -lgint -lc + + + +# +# Source and object files. +# + +# Gint library. +src-lib = crt0.c syscalls.s \ + gint.c gint_vbr.s gint_7705.c gint_7305.c \ + mpu.c keyboard.c screen.c display.c gray.c timer.c +hea-lib = 7305.h 7705.h gint.h \ + stdlib.h \ + mpu.h keyboard.h screen.h display.h gray.h timer.h +obj-lib = $(addprefix build/, $(addsuffix .o, $(src-lib))) +hdr-lib = $(addprefix include/, $(hea-lib)) + +# Standard library. +src-std = setjmp.s string.c +hea-std = setjmp.h string.h +obj-std = $(addprefix build/, $(addsuffix .o, $(src-std))) +hdr-std = $(addprefix include/, $(hea-std)) + +# Test application. +src-app = addin.c +res-app = icon.o swords.o sprites.o symbol.o symbol2.o + + +# +# Building rules. +# + +all: build libgint.a libc.a addin.g1a + +build: + mkdir -p build + +libgint.a: $(obj-lib) + $(ar) rcs libgint.a $(obj-lib) + @ echo "\033[32;1mLibrary file size: "`stat -c %s libgint.a` \ + "bytes\033[0m" + +libc.a: $(obj-std) + $(ar) rcs libc.a $(obj-std) + @ echo "\033[32;1mStandard file size: "`stat -c %s libc.a` \ + "bytes\033[0m" + +addin.g1a: libgint.a $(src-app) $(res-app) + $(cc) $(src-app) $(res-app) -T addin.ld -o $(elf) $(cflags) $(lib) + $(ob) -R .comment -R .bss -O binary $(elf) $(bin) + $(wr) $(bin) -o addin.g1a -i icon.bmp + @ echo "\033[32;1mBinary file size: "`stat -c %s $(bin)`" bytes\033[0m" +# @ sh3eb-elf-objdump -h build/addin.elf + +build/%.c.o: src/%.c $(hdr-lib) $(hdr-std) + $(cc) $(cflags) -O2 -c $< -o $@ +build/%.s.o: src/%.s + $(as) -c $^ -o $@ + +build/gint.c.o: src/gint.c $(hdr-lib) $(hdr-std) + $(cc) $(cflags) -c $< -o $@ + +%.c.o: %.c $(hdr-lib) $(hdr-std) + $(cc) $(cflags) -c $< -o $@ +%.s.o: %.s + $(as) -c $^ -o $@ +%.o: %.bmp + fxconv $^ + + + +# +# Cleaning rules. +# + +clean: + @ rm -f $(obj-lib) $(obj-std) $(obj-app) $(bin) $(elf) +fclean: clean + @ rm -f build/* + @ rm -f addin.g1a libc.a libgint.a +re: fclean all + + + +# +# Installing shorthand. +# + +install: + usb-connector SEND addin.g1a addin.g1a fls0 diff --git a/TODO b/TODO new file mode 100644 index 0000000..eb9bb0a --- /dev/null +++ b/TODO @@ -0,0 +1,7 @@ +- screen, display +- timer +- gray engine +- full rtc driver (time) + +_ 7305.h +_ libc diff --git a/addin.c b/addin.c new file mode 100644 index 0000000..5133959 --- /dev/null +++ b/addin.c @@ -0,0 +1,311 @@ +#include +#include +#include +#include +#include + +extern void __Print(const char *msg, int x, int y); +extern unsigned int gint_vbr, bgint, egint, gint_data; +#define print __Print + +void print_hex(unsigned int n, int x, int y) +{ + char ch[11] = "0x"; + int i; + + for(i = 0; i < 8; i++) + { + ch[9 - i] = (n & 0xf) + '0' + 39 * ((n & 0xf) > 9); + n >>= 4; + } + ch[10] = 0; + print(ch, x, y); +} +void print_bin(unsigned char n, int x, int y) +{ + char ch[9]; + int i; + + for(i = 0; i < 8;i ++) + { + ch[7 - i] = (n & 1) + '0'; + n >>= 1; + } + ch[8] = 0; + print(ch, x, y); +} + +void print_hexa(unsigned int n, int digits, int x, int y) +{ + char ch[20]; + int i; + + for(i = digits - 1; i >= 0; i--) + { + ch[i] = (n & 0xf) + '0' + 39 * ((n & 0xf) > 9); + n >>= 4; + } + + ch[digits] = 0; + print(ch, x, y); +} + +// Don't forget to enable key state debugging in the interrupt handler. +void keyboard_test(void) +{ + const char *names[] = { + "MPU_Unkown", + "MPU_SH7337", + "MPU_SH7355", + "MPU_SH7305", + "MPU_SH7724", + "Error" + }; + int x = 0; + char str[3]; + int keys[4] = { 0 }; + int i; + + print(names[MPU_CURRENT < 5 ? MPU_CURRENT : 5], 0, 0); + + print("gint size:", 0, 1); + print_hex(&egint - &bgint, 11, 1); + + while(1) + { + multigetkey(keys, 4, 0); + + if(keys[0] == KEY_EXIT && keys[1] == KEY_NONE) break; + + #define hexa(h) ('0' + (h) + 39 * ((h) > 9)) + + x = (x + 1) & 15; + str[0] = hexa(x); + str[1] = 0; + print(str, 20, 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, 19, i + 3); + } + + #undef hexa + } +} + +/* +const unsigned char data[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, +31, 191, 192, 0, 3, 224, 27, 216, 0, 0, 1, 251, 252, 0, 0, 0, 57, 247, 222, +30, 7, 240, 36, 36, 62, 25, 131, 159, 24, 255, 129, 224, 0, 227, 142, 126, 1, +192, 45, 172, 127, 127, 192, 14, 1, 255, 199, 224, 0, 227, 140, 240, 1, 192, +26, 88, 115, 127, 224, 14, 57, 221, 207, 0, 0, 227, 13, 192, 1, 192, 34, 68, +120, 30, 0, 14, 25, 156, 220, 0, 0, 227, 253, 252, 1, 192, 36, 36, 126, 28, +0, 14, 219, 156, 223, 192, 0, 227, 253, 252, 1, 192, 36, 36, 31, 12, 0, 46, +27, 140, 223, 192, 0, 227, 141, 193, 193, 192, 40, 20, 7, 140, 0, 206, 25, 140, +220, 28, 0, 227, 140, 225, 129, 199, 24, 24, 99, 156, 1, 14, 25, 204, 206, 24, +0, 227, 142, 127, 1, 195, 39, 228, 255, 156, 2, 14, 24, 237, 199, 240, 1, 247, +222, 62, 1, 198, 44, 44, 223, 30, 2, 31, 28, 237, 131, 224, 1, 224, 0, 0, 3, +254, 27, 216, 0, 0, 4, 30, 0, 0, 0, 0, 3, 192, 0, 0, 7, 252, 0, 0, 0, 0, 4, +60, 1, 249, 240, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 4, 0, 97, 240, 56, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 1, 224, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +4, 0, 47, 192, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 32, 255, 128, 63, 128, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 32, 255, 0, 48, 78, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 15, 176, 255, 0, 112, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 8, 56, 255, 0, +96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 8, 60, 255, 0, 224, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 130, 56, 126, 255, 3, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 192, +62, 255, 15, 224, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 14, 191, 255, 192, 0, +0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 6, 129, 255, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, +1, 0, 0, 6, 0, 255, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 7, 128, 63, 192, +1, 0, 96, 1, 224, 1, 0, 0, 0, 2, 0, 0, 7, 0, 31, 192, 0, 0, 95, 1, 11, 68, 88, +0, 0, 4, 0, 0, 7, 128, 31, 192, 0, 1, 192, 129, 204, 85, 100, 0, 0, 8, 0, 0, +15, 128, 63, 224, 0, 0, 95, 1, 8, 85, 68, 0, 1, 144, 0, 0, 31, 128, 143, 224, +64, 0, 96, 1, 232, 41, 68, 0, 2, 96, 0, 31, 255, 129, 7, 248, 96, 0, 0, 0, 0, +0, 0, 0, 4, 0, 0, 96, 254, 129, 7, 254, 96, 0, 0, 0, 0, 0, 0, 0, 4, 0, 1, 128, +254, 131, 135, 255, 224, 0, 0, 1, 192, 64, 16, 0, 8, 0, 7, 0, 254, 131, 255, +63, 224, 0, 0, 1, 38, 113, 208, 0, 8, 0, 13, 0, 222, 147, 254, 31, 224, 0, 0, +1, 41, 74, 80, 0, 8, 0, 25, 0, 222, 67, 254, 31, 160, 0, 0, 1, 41, 74, 80, 0, +12, 0, 49, 0, 222, 19, 254, 62, 48, 0, 0, 1, 198, 113, 208, 0, 2, 0, 32, 128, +222, 195, 255, 252, 56, 0, 0, 0, 0, 0, 0, 0, 2, 0, 124, 64, 220, 151, 135, 248, +127, 0, 0, 0, 0, 0, 0, 0, 2, 0, 66, 32, 221, 223, 7, 240, 255, 0, 0, 0, 0, 0, +0, 0, 2, 0, 129, 23, 93, 159, 15, 241, 131, 0, 0, 0, 0, 0, 0, 0, 4, 0, 128, +136, 217, 95, 3, 226, 9, 0, 0, 1, 240, 0, 0, 0, 4, 0, 128, 72, 89, 95, 129, +228, 18, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0, 72, 73, 127, 128, 224, 36, 0, 0, 0, 0, +0, 0, 0, 28, 1, 0, 76, 129, 127, 192, 96, 8, 0, 0, 0, 0, 0, 0, 0, 16, 1, 0, +231, 203, 124, 96, 64, 0, 0, 0, 0, 0, 0, 0, 0, 16, 1, 1, 28, 123, 240, 12, 64, +1, 0, 0, 0, 0, 0, 0, 0, 16, 1, 2, 28, 143, 128, 15, 192, 7, 0, 0, 0, 0, 0, 0, +0, 16, 1, 4, 17, 143, 24, 15, 192, 14, 0, 0, 0, 0, 0, 0, 0, 28, 1, 4, 1, 135, +24, 31, 192, 24, 0, 0, 0, 0, 0, 0, 0, 18, 1, 62, 1, 135, 248, 63, 224, 192, +0, 0, 0, 0, 0, 0, 0, 35, 1, 195, 1, 135, 128, 254, 126, 1, 0, 0, 0, 0, 0, 0, +0, 35, 193, 131, 195, 135, 255, 248, 112, 1, 0, 0, 0, 0, 0, 0, 0, 67, 241, 131, +14, 207, 255, 192, 224, 3, 0, 0, 0, 0, 0, 0, 3, 67, 15, 143, 56, 255, 7, 1, +224, 7, 0, 0, 0, 0, 0, 0, 28, 130, 7, 255, 112, 204, 7, 131, 224, 31, 0, 0, +0, 0, 0, 0, 32, 134, 30, 29, 120, 156, 7, 255, 224, 127, 0, 0, 0, 0, 0, 63, +197, 206, 60, 56, 192, 248, 15, 255, 248, 255, 0, 0, 0, 0, 0, 120, 5, 227, 248, +56, 195, 248, 127, 191, 254, 63, 0, 0, 0, 0, 7, 254, 255, 193, 255, 15, 193, +255, 15, 31, 252, 31 }; +*/ + + +/* +static const unsigned char icon[76] = { +0, 0, 0, 0, 51, 156, 10, 68, 74, 82, 11, 68, 74, 82, 234, 196, 122, 82, 10, +68, 75, 156, 10, 68, 0, 0, 0, 4, 0, 254, 0, 4, 0, 130, 124, 4, 0, 130, 68, 4, +0, 2, 4, 4, 3, 238, 196, 4, 2, 170, 93, 252, 0, 254, 65, 252, 7, 40, 65, 252, +5, 232, 65, 252, 7, 15, 193, 252, 0, 0, 1, 252, 127, 255, 255, 252 }; + +char *ML_vram_adress(void) +{ + return display_getVRAM(); +} + +void ML_bmp_or_cl(const unsigned char *bmp, int x, int y, int width, int height) +{ + unsigned short line; + char shift, *screen, *p; + int i, j, real_width, begin_x, end_x, begin_y, end_y; + char bool1=1, bool2=1, bool3; + if(!bmp || x<1-width || x>127 || y<1-height || y>63 || height<1 || width<1) return; + p = (char*)&line; + real_width = (width-1>>3<<3)+8; + if(y < 0) begin_y = -y; + else begin_y = 0; + if(y+height > 64) end_y = 64-y; + else end_y = height; + shift = 8-(x&7); + if(x<0) + { + begin_x = -x>>3; + if(shift != 8) bool1 = 0; + } else begin_x = 0; + if(x+real_width > 128) end_x = 15-(x>>3), bool2 = 0; + else end_x = real_width-1>>3; + bool3 = (end_x == real_width-1>>3); + screen = ML_vram_adress()+(y+begin_y<<4)+(x>>3); + + for(i=begin_y ; i>3)+begin_x] << shift; + if(bool1) screen[begin_x] |= *p; + if(shift!=8) screen[begin_x+1] |= *(p+1); + for(j=begin_x+1 ; j>3)+j] << shift; + screen[j] |= *p; + if(shift!=8) screen[j+1] |= *(p+1); + } + } + line = bmp[i*(real_width>>3)+end_x]; + if(bool3) line &= -1< +#include <7305.h> + +/* +unsigned int exec(void (*f)(void)) +{ + int t, s, dt, ds; + + t = (int)RTC.R64CNT; + s = 10 * (RTC.RSECCNT.TENS) + RTC.RSECCNT.ONES; + + (*f)(); + + dt = (int)RTC.R64CNT - t; + ds = (10 * (RTC.RSECCNT.TENS) + RTC.RSECCNT.ONES) - s; + if(dt < 0) ds--, dt += 64; + + return (ds << 8) | dt; +} + +void btest_ml_icon(void) +{ + int i; + for(i = 0; i < 5000; i++) + { + ML_bmp_or_cl(icon, 0, 30, 30, 19); + } +} +void btest_gint_icon(void) +{ + extern Image binary_icon_start; + + int i; + for(i = 0; i < 5000; i++) + { + dimage(&binary_icon_start, 0, 0, Blend_Or); + } +} +*/ + +int main(void) +{ + extern Image binary_symbol_start; + extern Image binary_symbol2_start; + extern Image binary_icon_start; + extern Image binary_sprites_start; + extern Image binary_swords_start; + + extern const void *vrams[4]; + + Image *sybl = &binary_symbol_start; + Image *sybl2 = &binary_symbol2_start; + + dclear(); + dreverse_area(0, 0, 127, 30); + + dimage(sybl, 0, 0, Blend_Or); + dimage(sybl, 20, 0, Blend_And); + dimage(sybl, 40, 0, Blend_Or | Blend_And); + dimage(sybl, 90, 0, Blend_Or | Blend_Invert); + + dimage(sybl2, 0, 20, Blend_Or); + dimage(sybl2, 20, 20, Blend_And); + dimage(sybl2, 28, 20, Blend_And); + dimage(sybl2, 40, 20, Blend_Or | Blend_And); + dimage(sybl2, 90, 20, Blend_Or | Blend_Invert); + + dimage(&binary_icon_start, 2, 35, Blend_Or); + + dreverse_area(35, 31, 127, 63); + dimage(&binary_sprites_start, 50, 31, Blend_And); + + dupdate(); +/* + do key = getkey(); + while(key != KEY_EXE && key != KEY_EXIT); + if(key == KEY_EXIT) return 0; + + print("h'sszz 64z=1s", 0, 0); + print("ML", 14, 0); + print("gint", 17, 0); + print("---------------------", 0, 1); + + print("30*19 icon", 0, 2); + print(wait, 12, 2); + print_hexa(exec(btest_ml_icon), 4, 12, 2); + print(wait, 17, 2); + print_hexa(exec(btest_gint_icon), 4, 17, 2); +*/ + while(getkey() != KEY_EXE); + + dclear(); + dimage(&binary_swords_start, 20, 20, Blend_Or); + dupdate(); + + while(getkey() != KEY_EXE); + return 0; +} diff --git a/addin.g1a b/addin.g1a new file mode 100644 index 0000000..422f6b6 Binary files /dev/null and b/addin.g1a differ diff --git a/addin.ld b/addin.ld new file mode 100644 index 0000000..512f5db --- /dev/null +++ b/addin.ld @@ -0,0 +1,104 @@ +/* + This linker script links the object files when generating the ELF + output. Note how symbols romdata, bbss, ebss, bdata and edata are used + in the initialization routine (crt0.c) to initialize the application. + + Two ram areas are specified. It happens, if I'm not wrong, that the + "real ram" is accessed directly while the "common" ram is accessed + through the mmu. The interrupt handler resides in "real ram" because it + couldn't execute well in ram. While SH7335 and SH7355 had no problems, + executing the interrupt handler in the common ram on SH7305-based new + models caused trouble to the OS, apparently overwriting ram data. +*/ + +OUTPUT_ARCH(sh3) +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. */ + realram : o = 0x8800d000, l = 12k +} + +SECTIONS +{ + /* + ROM sections : binary code and read-only data. + */ + + .text : { + /* Initialization code. */ + *(.pretext.entry) + *(.pretext) + + _bctors = . ; + *(.ctors) + _ectors = . ; + _bdtors = . ; + *(.dtors) + _edtors = . ; + + *(.text) + *(.text.*) + } > rom + + .rodata : { + *(.rodata) + *(.rodata.*) + + _romdata = ALIGN(4) ; + } > rom + + + + /* + RAM sections : bss section and read/write data. + The BSS section is meant to be stripped from the ELF file (to + reduce the binary size) and initialized with zeros in the + initialization routine, therefore its location is undefined. + */ + + .bss : { + _bbss = . ; + *(.bss) + _ebss = . ; + } > ram + + .data : AT(_romdata) ALIGN(4) { + _bdata = . ; + *(.data) + *(.data.*) + _edata = . ; + } > ram + + .cc : AT(_romdata + SIZEOF(.data)) ALIGN(4) { + *(.eh_frame) + *(.jcr) + + _gint_data = _romdata + SIZEOF(.data) + SIZEOF(.cc) ; + } > ram + + + + /* + Real RAM : interrupt handler. + */ + + .gint_int : AT(_gint_data) ALIGN(4) { + /* The vbr needs to be 0x100-aligned because of an ld issue. */ + . = ALIGN(0x100) ; + _gint_vbr = . ; + + _bgint = . ; + + /* Interrupt handler. */ + . = _gint_vbr + 0x600 ; + *(.gint.int.entry) + *(.gint.int) + + _egint = . ; + } > realram +} diff --git a/icon.bmp b/icon.bmp new file mode 100644 index 0000000..c97606c Binary files /dev/null and b/icon.bmp differ diff --git a/include/7305.h b/include/7305.h new file mode 100644 index 0000000..f6ff1a3 --- /dev/null +++ b/include/7305.h @@ -0,0 +1,914 @@ +#ifndef _7305_H +#define _7305_H 1 + +/* + Double-underscore prefixed structures (e.g. __st_rtc_counter) are used + internally but are not meant to be used in user programs. + + Underscore-prefixed names (e.g. _R64CNT) indicate write-only registers. +*/ + +#pragma pack(push, 1) +#define gap(n) unsigned: n << 3 + + + +//--- +// Real-time clock. +//--- + +struct _st_rtc +{ + unsigned char const R64CNT; + + gap(1); + + union { + unsigned char BYTE; + struct { + unsigned :1; + unsigned TENS :3; + unsigned ONES :4; + }; + } RSECCNT; + + gap(1); + + union { + unsigned char BYTE; + struct { + unsigned :1; + unsigned TENS :3; + unsigned ONES :4; + }; + } RMINCNT; + + gap(1); + + union { + unsigned char BYTE; + struct { + unsigned :2; + unsigned TENS :2; + unsigned ONES :4; + }; + } RHRCNT; + + gap(1); + + // 0=Sunday, 1=Monday, ..., 6=Saturday, 7=Reserved (prohibited). + unsigned char RWKCNT; + + gap(1); + + union { + unsigned char; + struct { + unsigned :2; + unsigned TENS :2; + unsigned ONES :4; + }; + } RDAYCNT; + + gap(1); + + union { + unsigned char BYTE; + struct { + unsigned :3; + unsigned TENS :1; + unsigned ONES :4; + }; + } RMONCNT; + + gap(1); + + union { + unsigned short WORD; + struct { + unsigned THOUSANDS :4; + unsigned HUNDREDS :4; + unsigned TENS :4; + unsigned ONES :4; + }; + } RYRCNT; + + union { + unsigned char BYTE; + struct { + unsigned ENB :1; + unsigned TENS :3; + unsigned ONES :4; + }; + } RSECAR; + + gap(1); + + union { + unsigned char BYTE; + struct { + unsigned ENB :1; + unsigned TENS :3; + unsigned ONES :4; + }; + } RMINAR; + + gap(1); + + union { + unsigned char BYTE; + struct { + unsigned ENB :1; + unsigned :1; + unsigned TENS :2; + unsigned ONES :4; + }; + } RHRAR; + + gap(1); + + union { + unsigned char BYTE; + struct { + unsigned ENB :1; + unsigned :4; + // See RTC.RDAYCNT for day encoding. + unsigned DAY :3; + }; + } RWKAR; + + gap(1); + + union { + unsigned char BYTE; + struct { + unsigned ENB :1; + unsigned :1; + unsigned TENS :2; + unsigned ONES :4; + }; + } RDAYAR; + + gap(1); + + union { + unsigned char BYTE; + struct { + unsigned ENB :1; + unsigned :2; + unsigned TENS :1; + unsigned ONES :4; + }; + } RMONAR; + + gap(1); + + union { + unsigned char BYTE; + struct { + unsigned CF :1; + unsigned :2; + unsigned CIE :1; + unsigned AIE :1; + unsigned :2; + unsigned AF :1; + }; + } RCR1; + + gap(1); + + union { + unsigned char BYTE; + struct { + unsigned PEF :1; + unsigned PES :3; + unsigned :1; + unsigned ADJ :1; + unsigned RESET :1; + unsigned START :1; + }; + } RCR2; + + gap(1); + + union { + unsigned short WORD; + struct { + unsigned THOUSANDS :4; + unsigned HUNDREDS :4; + unsigned TENS :4; + unsigned ONES :4; + }; + } RYRAR; + + gap(2); + + union { + unsigned char BYTE; + struct { + unsigned ENB :1; + unsigned :7; + } + } RCR3; + +} __attribute__((packed)); + + + +//--- +// Interrupt controller, part 1. +//--- + +struct _st_intc +{ + union { + unsigned short WORD; + struct { + unsigned const NMIL :1; + unsigned MAI :1; + unsigned :4; + unsigned NMIB :1; + unsigned NMIE :1; + unsigned :2; + unsigned LVLMODE :1; + unsigned :5; + }; + } ICR0; + + char gap1[14]; + + union { + unsigned int LONG; + struct { + unsigned IRQ0 :4; + unsigned IRQ1 :4; + unsigned IRQ2 :4; + unsigned IRQ3 :4; + unsigned IRQ4 :4; + unsigned IRQ5 :4; + unsigned IRQ6 :4; + unsigned IRQ7 :4; + }; + } INTPRI00; + + char gap2[8]; + + union { + unsigned short WORD; + struct { + unsigned IRQ0S :2; + unsigned IRQ1S :2; + unsigned IRQ2S :2; + unsigned IRQ3S :2; + unsigned IRQ4S :2; + unsigned IRQ5S :2; + unsigned IRQ6S :2; + unsigned IRQ7S :2; + }; + } ICR1; + + char gap3[6]; + + union { + unsigned char BYTE; + struct { + unsigned IRQ0 :1; + unsigned IRQ1 :1; + unsigned IRQ2 :1; + unsigned IRQ3 :1; + unsigned IRQ4 :1; + unsigned IRQ5 :1; + unsigned IRQ6 :1; + unsigned IRQ7 :1; + }; + } INTREQ00; + + char gap4[31]; + + union { + unsigned char BYTE; + struct { + unsigned IRQ0 :1; + unsigned IRQ1 :1; + unsigned IRQ2 :1; + unsigned IRQ3 :1; + unsigned IRQ4 :1; + unsigned IRQ5 :1; + unsigned IRQ6 :1; + unsigned IRQ7 :1; + }; + } INTMSK00; + + char gap5[31]; + + union { + unsigned char BYTE; + struct { + unsigned _IRQ0 :1; + unsigned _IRQ1 :1; + unsigned _IRQ2 :1; + unsigned _IRQ3 :1; + unsigned _IRQ4 :1; + unsigned _IRQ5 :1; + unsigned _IRQ6 :1; + unsigned _IRQ7 :1; + }; + } INTMSKCLR00; + + char gap6[91]; + + union { + unsigned short WORD; + struct { + unsigned const NMIL :1; + unsigned :14; + unsigned NMIFL :1; + }; + } NMIFCR; + + char gap7[6029118]; + + union { + unsigned int LONG; + struct { + unsigned HEXA_A5 :8; + unsigned :16; + unsigned UIMASK :4; + unsigned :4; + }; + } USERIMSK; + +} __attribute__((packed)); + + + +//--- +// Interrupt controller, part 2. +//--- + +struct _st_intx +{ + union { + unsigned short WORD; + struct { + unsigned TMU0_0 :4; + unsigned TMU0_1 :4; + unsigned TMU0_2 :4; + unsigned IrDA :4; + }; + } IPRA; + + gap(2); + + union { + unsigned short WORD; + struct { + unsigned JPU :4; + unsigned LCDC :4; + unsigned DMAC1A :4; + unsigned BEU2_1 :4; + }; + } IPRB; + + gap(2); + + union { + unsigned short WORD; + struct { + unsigned TMU1_0 :4; + unsigned TMU1_1 :4; + unsigned TMU1_2 :4; + unsigned SPU :4; + }; + } IPRC; + + gap(2); + + union { + unsigned short WORD; + struct { + unsigned :4; + unsigned MMCIF :4; + unsigned :4; + unsigned ATAPI :4; + }; + } IPRD; + + gap(2); + + union { + unsigned short WORD; + struct { + unsigned DMAC0A :4; + unsigned VARIOUS :4; + unsigned SCIFA3 :4; + unsigned VPU5F :4; + }; + } IPRE; + + gap(2); + + union { + unsigned short WORD; + struct { + unsigned KEYSC :4; + unsigned DMAC0B :4; + unsigned USB01 :4; + unsigned CMT :4; + }; + } IPRF; + + gap(2); + + union { + unsigned short WORD; + struct { + unsigned SCIF0 :4; + unsigned SCIF1 :4; + unsigned SCIF2 :4; + unsigned VEU3F0 :4; + }; + } IPRG; + + gap(2); + + union { + unsigned short WORD; + struct { + unsigned MSIOF0 :4; + unsigned MSIOF1 :4; + unsigned I2C1 :4; + unsigned I2C0 :4; + }; + } IPRH; + + gap(2); + + union { + unsigned short WORD; + struct { + unsigned SCIFA4 :4; + unsigned ICB :4; + unsigned TSIF :4; + unsigned _2DG_ICB :4; + }; + } IPRI; + + gap(2); + + union { + unsigned short WORD; + struct { + unsigned CEU2_1 :4; + unsigned EtherMAC :4; + unsigned FSI :4; + unsigned SDHI1 :4; + }; + } IPRJ; + + gap(2); + + union { + unsigned short WORD; + struct { + unsigned _RTC :4; + unsigned DMAC1B :4; + unsigned ICB :4; + unsigned SDHI0 :4; + }; + } IPRK; + + gap(2); + + union { + unsigned short WORD; + struct { + unsigned SCIFA5 :4; + unsigned :4; + unsigned TPU :4; + unsigned _2DDMAC :4; + }; + } IPRL; + + char gap1[82]; + + union + { + unsigned char BYTE; + struct { + unsigned :1; + unsigned TUNI2 :1; + unsigned TUNI1 :1; + unsigned TUNI0 :1; + unsigned SDHII3 :1; + unsigned SDHII2 :1; + unsigned SDHII1 :1; + unsigned SDHII0 :1; + }; + } IMR0; + + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned VOUI :1; + unsigned VEU1I :1; + unsigned BEU0I :1; + unsigned CEUOI :1; + unsigned DEI3 :1; + unsigned DEI2 :1; + unsigned DEI1 :1; + unsigned DEI0 :1; + }; + } IMR1; + + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned :3; + unsigned VPUI :1; + unsigned ATAPI :1; + unsigned EtherMAC :1; + unsigned :1; + unsigned SCIFA0 :1; + }; + } IMR2; + + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned DEI3 :1; + unsigned DEI2 :1; + unsigned DEI1 :1; + unsigned DEI0 :1; + unsigned :3; + unsigned IRDAI :1; + }; + } IMR3; + + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned :1; + unsigned TUNI2 :1; + unsigned TUNI1 :1; + unsigned TUNI0 :1; + unsigned JPUI :1; + unsigned :2; + unsigned LCDCI :1; + }; + } IMR4; + + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned KEYI :1; + unsigned DADERR :1; + unsigned DEI5 :1; + unsigned DEI4 :1; + unsigned VEU0I :1; + unsigned SCIF2 :1; + unsigned SCIF1 :1; + unsigned SCIF0 :1; + }; + } IMR5; + + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned :2; + unsigned ICBI :1; + unsigned SCIFA4 :1; + unsigned CEU1I :1; + unsigned :1; + unsigned MSIOFI0 :1; + unsigned MSIOFI1 :1; + }; + } IMR6; + + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned DTE0I :1; + unsigned WAITOI :1; + unsigned TACK0I :1; + unsigned AL0I :1; + unsigned DTE1I :1; + unsigned WAIT1I :1; + unsigned TACK1I :1; + unsigned AL1I :1; + }; + } IMR7; + + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned SDHII3 :1; + unsigned SDHII2 :1; + unsigned SDHII1 :1; + unsigned SDHII0 :1; + unsigned :2; + unsigned SCFIA5 :1; + unsigned FSI :1; + }; + } IMR8; + + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned :3; + unsigned CMTI :1; + unsigned :1; + unsigned USI1 :1; + unsigned USI0 :1; + unsigned :1; + }; + } IMR9; + + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned :1; + unsigned DADERR :1; + unsigned DEI5 :1; + unsigned DEI4 :1; + unsigned :1; + unsigned ATI :1; + unsigned PRI :1; + unsigned CUI :1; + }; + } IMR10; + + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned BRK :1; + unsigned CEI :1; + unsigned INI :1; + unsigned TRI :1; + unsigned :1; + unsigned TPUI :1; + unsigned LMBI :1; + unsigned TSIFI :1; + }; + } IMR11; + + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned :7; + unsigned _2DDMAC :1; + }; + } IMR12; + + char gap2[15]; + + union + { + unsigned char BYTE; + struct { + unsigned :1; + unsigned TUNI2 :1; + unsigned TUNI1 :1; + unsigned TUNI0 :1; + unsigned SDHII3 :1; + unsigned SDHII2 :1; + unsigned SDHII1 :1; + unsigned SDHII0 :1; + }; + } _IMCR0; + + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned VOUI :1; + unsigned VEU1I :1; + unsigned BEU0I :1; + unsigned CEUOI :1; + unsigned DEI3 :1; + unsigned DEI2 :1; + unsigned DEI1 :1; + unsigned DEI0 :1; + }; + } _IMCR1; + + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned :3; + unsigned VPUI :1; + unsigned ATAPI :1; + unsigned EtherMAC :1; + unsigned :1; + unsigned SCIFA0 :1; + }; + } _IMCR2; + + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned DEI3 :1; + unsigned DEI2 :1; + unsigned DEI1 :1; + unsigned DEI0 :1; + unsigned :3; + unsigned IRDAI :1; + }; + } _IMCR3; + + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned :1; + unsigned TUNI2 :1; + unsigned TUNI1 :1; + unsigned TUNI0 :1; + unsigned JPUI :1; + unsigned :2; + unsigned LCDCI :1; + }; + } _IMCR4; + + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned KEYI :1; + unsigned DADERR :1; + unsigned DEI5 :1; + unsigned DEI4 :1; + unsigned VEU0I :1; + unsigned SCIF2 :1; + unsigned SCIF1 :1; + unsigned SCIF0 :1; + }; + } _IMCR5; + + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned :2; + unsigned ICBI :1; + unsigned SCIFA4 :1; + unsigned CEU1I :1; + unsigned :1; + unsigned MSIOFI0 :1; + unsigned MSIOFI1 :1; + }; + } _IMCR6; + + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned DTE0I :1; + unsigned WAITOI :1; + unsigned TACK0I :1; + unsigned AL0I :1; + unsigned DTE1I :1; + unsigned WAIT1I :1; + unsigned TACK1I :1; + unsigned AL1I :1; + }; + } _IMCR7; + + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned SDHII3 :1; + unsigned SDHII2 :1; + unsigned SDHII1 :1; + unsigned SDHII0 :1; + unsigned :2; + unsigned SCFIA5 :1; + unsigned FSI :1; + }; + } _IMCR8; + + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned :3; + unsigned CMTI :1; + unsigned :1; + unsigned USI1 :1; + unsigned USI0 :1; + unsigned :1; + }; + } _IMCR9; + + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned :1; + unsigned DADERR :1; + unsigned DEI5 :1; + unsigned DEI4 :1; + unsigned :1; + unsigned ATI :1; + unsigned PRI :1; + unsigned CUI :1; + }; + } _IMCR10; + + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned BRK :1; + unsigned CEI :1; + unsigned INI :1; + unsigned TRI :1; + unsigned :1; + unsigned TPUI :1; + unsigned LMBI :1; + unsigned TSIFI :1; + }; + } _IMCR11; + + gap(3); + + union + { + unsigned char BYTE; + struct { + unsigned :7; + unsigned _2DDMAC :1; + }; + } _IMCR12; + +} __attribute__((packed)); + + + +#define RTC (*(volatile struct _st_rtc *)0xa413fec0) +#define INTC (*(volatile struct _st_intc *)0xa4140000) +#define INTX (*(volatile struct _st_intx *)0xa4080000) + +#pragma pack(pop) +#endif // _7305_H diff --git a/include/7705.h b/include/7705.h new file mode 100644 index 0000000..e5e934c --- /dev/null +++ b/include/7705.h @@ -0,0 +1,1296 @@ +#ifndef _7705_H +#define _7705_H 1 + + +// Internal Control Registers definition : + +struct st_cpg { /* struct CPG */ + union { /* FRQCR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short :3; /* */ + unsigned short CKOEN:1; /* CKOEN */ + unsigned short :2; /* */ + unsigned short STC :2; /* STC */ + unsigned short :2; /* */ + unsigned short IFC :2; /* IFC */ + unsigned short :2; /* */ + unsigned short _PFC :2; /* PFC */ + } BIT; /* */ + } FRQCR; /* */ +}; /* */ +struct st_wdt { /* struct WDT */ + union { /* WTCNT */ + unsigned char READ; /* Read Access*/ + unsigned short WRITE; /* Write Access*/ + } WTCNT; /* */ + union { /* WTCSR */ + union { /* Read Access*/ + unsigned char BYTE; /* Byte Access*/ + struct { /* Bit Access*/ + unsigned char TME :1; /* TME */ + unsigned char WTIT:1; /* WT/IT */ + unsigned char RSTS:1; /* RSTS */ + unsigned char WOVF:1; /* WOVF */ + unsigned char IOVF:1; /* IOVF */ + unsigned char CKS :3; /* CKS */ + } BIT; /* */ + } READ; /* */ + unsigned short WRITE; /* Write Access*/ + } WTCSR; /* */ +}; + +struct st_pa { /* struct PA */ + union { /* */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char B7:1; /* Bit 7 */ + unsigned char B6:1; /* Bit 6 */ + unsigned char B5:1; /* Bit 5 */ + unsigned char B4:1; /* Bit 4 */ + unsigned char B3:1; /* Bit 3 */ + unsigned char B2:1; /* Bit 2 */ + unsigned char B1:1; /* Bit 1 */ + unsigned char B0:1; /* Bit 0 */ + } BIT; /* */ + } DR; /* */ +}; /* */ +struct st_pb { /* struct PB */ + union { /* */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char B7:1; /* Bit 7 */ + unsigned char B6:1; /* Bit 6 */ + unsigned char B5:1; /* Bit 5 */ + unsigned char B4:1; /* Bit 4 */ + unsigned char B3:1; /* Bit 3 */ + unsigned char B2:1; /* Bit 2 */ + unsigned char B1:1; /* Bit 1 */ + unsigned char B0:1; /* Bit 0 */ + } BIT; /* */ + } DR; /* */ +}; /* */ +struct st_pc { /* struct PC */ + union { /* */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char B7:1; /* Bit 7 */ + unsigned char B6:1; /* Bit 6 */ + unsigned char B5:1; /* Bit 5 */ + unsigned char B4:1; /* Bit 4 */ + unsigned char B3:1; /* Bit 3 */ + unsigned char B2:1; /* Bit 2 */ + unsigned char B1:1; /* Bit 1 */ + unsigned char B0:1; /* Bit 0 */ + } BIT; /* */ + } DR; /* */ +}; /* */ +struct st_pd { /* struct PD */ + union { /* */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char B7:1; /* Bit 7 */ + unsigned char B6:1; /* Bit 6 */ + unsigned char B5:1; /* Bit 5 */ + unsigned char B4:1; /* Bit 4 */ + unsigned char B3:1; /* Bit 3 */ + unsigned char B2:1; /* Bit 2 */ + unsigned char B1:1; /* Bit 1 */ + unsigned char B0:1; /* Bit 0 */ + } BIT; /* */ + } DR; /* */ +}; /* */ +struct st_pe { /* struct PE */ + union { /* */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char B7:1; /* Bit 7 */ + unsigned char B6:1; /* Bit 6 */ + unsigned char B5:1; /* Bit 5 */ + unsigned char B4:1; /* Bit 4 */ + unsigned char B3:1; /* Bit 3 */ + unsigned char B2:1; /* Bit 2 */ + unsigned char B1:1; /* Bit 1 */ + unsigned char B0:1; /* Bit 0 */ + } BIT; /* */ + } DR; /* */ +}; /* */ +struct st_pf { /* struct PF */ + union { /* */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char B7:1; /* Bit 7 */ + unsigned char B6:1; /* Bit 6 */ + unsigned char B5:1; /* Bit 5 */ + unsigned char B4:1; /* Bit 4 */ + unsigned char B3:1; /* Bit 3 */ + unsigned char B2:1; /* Bit 2 */ + unsigned char B1:1; /* Bit 1 */ + unsigned char B0:1; /* Bit 0 */ + } BIT; /* */ + } DR; /* */ +}; /* */ +struct st_pg { /* struct PG */ + union { /* */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char B7:1; /* Bit 7 */ + unsigned char B6:1; /* Bit 6 */ + unsigned char B5:1; /* Bit 5 */ + unsigned char B4:1; /* Bit 4 */ + unsigned char B3:1; /* Bit 3 */ + unsigned char B2:1; /* Bit 2 */ + unsigned char B1:1; /* Bit 1 */ + unsigned char B0:1; /* Bit 0 */ + } BIT; /* */ + } DR; /* */ +}; /* */ +struct st_ph { /* struct PH */ + union { /* */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :1; /* Bit 7 */ + unsigned char B6:1; /* Bit 6 */ + unsigned char B5:1; /* Bit 5 */ + unsigned char B4:1; /* Bit 4 */ + unsigned char B3:1; /* Bit 3 */ + unsigned char B2:1; /* Bit 2 */ + unsigned char B1:1; /* Bit 1 */ + unsigned char B0:1; /* Bit 0 */ + } BIT; /* */ + } DR; /* */ +}; /* */ +struct st_pj { /* struct PJ */ + union { /* */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char B7:1; /* Bit 7 */ + unsigned char B6:1; /* Bit 6 */ + unsigned char B5:1; /* Bit 5 */ + unsigned char B4:1; /* Bit 4 */ + unsigned char B3:1; /* Bit 3 */ + unsigned char B2:1; /* Bit 2 */ + unsigned char B1:1; /* Bit 1 */ + unsigned char B0:1; /* Bit 0 */ + } BIT; /* */ + } DR; /* */ +}; /* */ +struct st_pk { /* struct PK */ + union { /* */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char B7:1; /* Bit 7 */ + unsigned char B6:1; /* Bit 6 */ + unsigned char B5:1; /* Bit 5 */ + unsigned char B4:1; /* Bit 4 */ + unsigned char B3:1; /* Bit 3 */ + unsigned char B2:1; /* Bit 2 */ + unsigned char B1:1; /* Bit 1 */ + unsigned char B0:1; /* Bit 0 */ + } BIT; /* */ + } DR; /* */ +}; /* */ +struct st_pl { /* struct PL */ + union { /* */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :4; /* Bit 7-4 */ + unsigned char B3:1; /* Bit 3 */ + unsigned char B2:1; /* Bit 2 */ + unsigned char B1:1; /* Bit 1 */ + unsigned char B0:1; /* Bit 0 */ + } BIT; /* */ + } DR; /* */ +}; /* */ +struct st_scp { /* struct SCP */ + union { /* */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :2; /* Bit 7,6 */ + unsigned char B5:1; /* Bit 5 */ + unsigned char B4:1; /* Bit 4 */ + unsigned char B3:1; /* Bit 3 */ + unsigned char B2:1; /* Bit 2 */ + unsigned char B1:1; /* Bit 1 */ + unsigned char B0:1; /* Bit 0 */ + } BIT; /* */ + } DR; /* */ +}; /* */ +struct st_pm { /* struct PM */ + union { /* */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :1; /* Bit 7 */ + unsigned char B6:1; /* Bit 6 */ + unsigned char :1; /* Bit 5 */ + unsigned char B4:1; /* Bit 4 */ + unsigned char B3:1; /* Bit 3 */ + unsigned char B2:1; /* Bit 2 */ + unsigned char B1:1; /* Bit 1 */ + unsigned char B0:1; /* Bit 0 */ + } BIT; /* */ + } DR; /* */ +}; /* */ +struct st_pn { /* struct PN */ + union { /* */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char B7:1; /* Bit 7 */ + unsigned char B6:1; /* Bit 6 */ + unsigned char B5:1; /* Bit 5 */ + unsigned char B4:1; /* Bit 4 */ + unsigned char B3:1; /* Bit 3 */ + unsigned char B2:1; /* Bit 2 */ + unsigned char B1:1; /* Bit 1 */ + unsigned char B0:1; /* Bit 0 */ + } BIT; /* */ + } DR; /* */ +}; /* */ + +struct st_rtc { /* struct RTC */ + unsigned char R64CNT; /* R64CNT */ + char wk1; /* */ + union { /* RSECCNT */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :1; /* */ + unsigned char S10:3; /* 10sec */ + unsigned char S1 :4; /* 1sec */ + } BIT; /* */ + } RSECCNT; /* */ + char wk2; /* */ + union { /* RMINCNT */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :1; /* */ + unsigned char M10:3; /* 10min */ + unsigned char M1 :4; /* 1min */ + } BIT; /* */ + } RMINCNT; /* */ + char wk3; /* */ + union { /* RHRCNT */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :2; /* */ + unsigned char H10:2; /* 10sec */ + unsigned char H1 :4; /* 1sec */ + } BIT; /* */ + } RHRCNT; /* */ + char wk4; /* */ + union { /* RWKCNT */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :5; /* */ + unsigned char WK:3; /* week */ + } BIT; /* */ + } RWKCNT; /* */ + char wk5; /* */ + union { /* RDAYCNT */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :2; /* */ + unsigned char D10:2; /* 10day */ + unsigned char D1 :4; /* 1day */ + } BIT; /* */ + } RDAYCNT; /* */ + char wk6; /* */ + union { /* RMONCNT */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :3; /* */ + unsigned char M10:1; /* 10mon */ + unsigned char M1 :4; /* 1mon */ + } BIT; /* */ + } RMONCNT; /* */ + char wk7; /* */ + union { /* RYRCNT */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short Y1000:4; /* 1000year */ + unsigned short Y100 :4; /* 100year */ + unsigned short Y10 :4; /* 10year */ + unsigned short Y1 :4; /* 1year */ + } BIT; /* */ + } RYRCNT; /* */ + union { /* RSECAR */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char ENB:1; /* ENB */ + unsigned char S10:3; /* 10sec */ + unsigned char S1 :4; /* 1sec */ + } BIT; /* */ + } RSECAR; /* */ + char wk8; /* */ + union { /* RMINAR */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char ENB:1; /* ENB */ + unsigned char M10:3; /* 10min */ + unsigned char M1 :4; /* 1min */ + } BIT; /* */ + } RMINAR; /* */ + char wk9; /* */ + union { /* RHRAR */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char ENB:1; /* ENB */ + unsigned char :1; /* */ + unsigned char H10:2; /* 10sec */ + unsigned char H1 :4; /* 1sec */ + } BIT; /* */ + } RHRAR; /* */ + char wk10; /* */ + union { /* RWKAR */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char ENB:1; /* ENB */ + unsigned char :4; /* */ + unsigned char WK :3; /* week */ + } BIT; /* */ + } RWKAR; /* */ + char wk11; /* */ + union { /* RDAYAR */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char ENB:1; /* ENB */ + unsigned char :1; /* */ + unsigned char D10:2; /* 10day */ + unsigned char D1 :4; /* 1day */ + } BIT; /* */ + } RDAYAR; /* */ + char wk12; /* */ + union { /* RMONAR */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char ENB:1; /* ENB */ + unsigned char :2; /* */ + unsigned char M10:1; /* 10mon */ + unsigned char M1 :4; /* 1mon */ + } BIT; /* */ + } RMONAR; /* */ + char wk13; /* */ + union { /* RCR1 */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char CF :1; /* CF */ + unsigned char :2; /* */ + unsigned char CIE:1; /* CIE */ + unsigned char AIE:1; /* AIE */ + unsigned char :2; /* */ + unsigned char AF :1; /* AF */ + } BIT; /* */ + } RCR1; /* */ + char wk14; /* */ + union { /* RCR2 */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char PEF :1; /* PEF */ + unsigned char PES :3; /* PES */ + unsigned char RTCEN:1; /* RTCEN */ + unsigned char ADJ :1; /* ADJ */ + unsigned char RESET:1; /* RESET */ + unsigned char START:1; /* START */ + } BIT; /* */ + } RCR2; /* */ +}; + +struct st_tmu { /* struct TMU */ + union { /* TSTR */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :5; /* */ + unsigned char STR2:1; /* STR2 */ + unsigned char STR1:1; /* STR1 */ + unsigned char STR0:1; /* STR0 */ + } BIT; /* */ + } TSTR; /* */ +}; /* */ +struct st_tmu0 { /* struct TMU0 */ + unsigned int TCOR; /* TCOR */ + unsigned int TCNT; /* TCNT */ + union { /* TCR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short :7; /* */ + unsigned short UNF :1; /* UNF */ + unsigned short :2; /* */ + unsigned short UNIE:1; /* UNIE */ + unsigned short CKEG:2; /* CKEG */ + unsigned short TPSC:3; /* TPSC */ + } BIT; /* */ + } TCR; /* */ +}; /* */ +struct st_tmu2 { /* struct TMU2 */ + unsigned int TCOR; /* TCOR */ + unsigned int TCNT; /* TCNT */ + union { /* TCR */ + unsigned short WORD; /* Word Access */ + struct { + unsigned short :6; + unsigned short ICPF:1; + unsigned short UNF :1; + unsigned short ICPE:2; + unsigned short UNIE:1; + unsigned short CKEG:2; + unsigned short TPSC:3; + } BIT; + } TCR; + char wk[2]; + unsigned int TCPR; +}; + +struct st_usb { /* struct USB */ + union { /* UCLKCR */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char USSCS:2; /* USSCS */ + unsigned char USBEN:1; /* USBEN */ + } BIT; /* */ + } UCLKCR; /* */ + char wk1[4063223]; /* */ + unsigned char EPDR0i; /* EPDR0i */ + char wk2[3]; /* */ + unsigned char EPDR0o; /* EPDR0o */ + char wk3[3]; /* */ + unsigned char EPDR0s; /* EPDR0s */ + char wk4[3]; /* */ + unsigned char EPDR1; /* EPDR1 */ + char wk5[3]; /* */ + unsigned char EPDR2; /* EPDR2 */ + char wk6[3]; /* */ + unsigned char EPDR3; /* EPDR3 */ + char wk7[3]; /* */ + union { /* IFR0 */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char BRST :1; /* BRST */ + unsigned char EP1FULL :1; /* EP1FULL */ + unsigned char EP2TR :1; /* EP2TR */ + unsigned char EP2EMPTY:1; /* EP2EMPTY */ + unsigned char SETUPTS :1; /* SETUPTS */ + unsigned char EP0oTS :1; /* EP0oTS */ + unsigned char EP0iTR :1; /* EP0iTR */ + unsigned char EP0iTS :1; /* EP0iTS */ + } BIT; /* */ + } IFR0; /* */ + char wk8[3]; /* */ + union { /* IFR1 */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :4; /* */ + unsigned char VBUSMN:1; /* VBUSMN */ + unsigned char EP3TS :1; /* EP3TS */ + unsigned char EP3TR :1; /* EP3TR */ + unsigned char VBUS :1; /* VBUS */ + } BIT; /* */ + } IFR1; /* */ + char wk9[3]; /* */ + union { /* TRG */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :1; /* */ + unsigned char EP3PKTE :1; /* EP3PKTE */ + unsigned char EP1RDFN :1; /* EP1RDFN */ + unsigned char EP2PKTE :1; /* EP2PKTE */ + unsigned char :1; /* */ + unsigned char EP0sRDFN:1; /* EP0sRDFN */ + unsigned char EP0oRDFN:1; /* EP0oRDFN */ + unsigned char EP0iPKTE:1; /* EP0iPKTE */ + } BIT; /* */ + } TRG; /* */ + char wk10[3]; /* */ + union { /* FCLR */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :1; /* */ + unsigned char EP3CLR :1; /* EP3CLR */ + unsigned char EP1CLR :1; /* EP1CLR */ + unsigned char EP2CLR :1; /* EP2CLR */ + unsigned char :2; /* */ + unsigned char EP0oCLR:1; /* EP0oCLR */ + unsigned char EP0iCLR:1; /* EP0iCLR */ + } BIT; /* */ + } FCLR; /* */ + char wk11[3]; /* */ + unsigned char EPSZ0o; /* EPSZ0o */ + char wk12[3]; /* */ + union { /* DASTS */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :2; /* */ + unsigned char EP3DE :1; /* EP3DE */ + unsigned char EP2DE :1; /* EP2DE */ + unsigned char :3; /* */ + unsigned char EP0iDE:1; /* EP0iDE */ + } BIT; /* */ + } DASTS; /* */ + char wk13[3]; /* */ + union { /* EPSTL */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :4; /* */ + unsigned char EP3STL:1; /* EP3STL */ + unsigned char EP2STL:1; /* EP2STL */ + unsigned char EP1STL:1; /* EP1STL */ + unsigned char EP0STL:1; /* EP0STL */ + } BIT; /* */ + } EPSTL; /* */ + char wk14[3]; /* */ + union { /* IER0 */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char BRST :1; /* BRST */ + unsigned char EP1FULL :1; /* EP1FULL */ + unsigned char EP2TR :1; /* EP2TR */ + unsigned char EP2EMPTY:1; /* EP2EMPTY */ + unsigned char SETUPTS :1; /* SETUPTS */ + unsigned char EP0oTS :1; /* EP0oTS */ + unsigned char EP0iTR :1; /* EP0iTR */ + unsigned char EP0iTS :1; /* EP0iTS */ + } BIT; /* */ + } IER0; /* */ + char wk15[3]; /* */ + union { /* IER1 */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :5; /* */ + unsigned char EP3TS:1; /* EP3TS */ + unsigned char EP3TR:1; /* EP3TR */ + unsigned char VBUS :1; /* VBUS */ + } BIT; /* */ + } IER1; /* */ + char wk16[3]; /* */ + unsigned char EPSZ1; /* EPSZ1 */ + char wk17[3]; /* */ + union { /* DMAR */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :6; /* */ + unsigned char EP2DMAE:1; /* EP2DMAE */ + unsigned char EP1DMAE:1; /* EP1DMAE */ + } BIT; /* */ + } DMAR; /* */ + char wk18[3]; /* */ + union { /* ISR0 */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char BRST :1; /* BRST */ + unsigned char EP1FULL :1; /* EP1FULL */ + unsigned char EP2TR :1; /* EP2TR */ + unsigned char EP2EMPTY:1; /* EP2EMPTY */ + unsigned char SETUPTS :1; /* SETUPTS */ + unsigned char EP0oTS :1; /* EP0oTS */ + unsigned char EP0iTR :1; /* EP0iTR */ + unsigned char EP0iTS :1; /* EP0iTS */ + } BIT; /* */ + } ISR0; /* */ + char wk19[3]; /* */ + union { /* ISR1 */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :5; /* */ + unsigned char EP3TS:1; /* EP3TS */ + unsigned char EP3TR:1; /* EP3TR */ + unsigned char VBUS :1; /* VBUS */ + } BIT; /* */ + } ISR1; /* */ + char wk20[23]; /* */ + union { /* XVERCR */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :6; /* */ + unsigned char XVEROFF:1; /* XVEROFF */ + } BIT; /* */ + } XVERCR; /* */ +}; +struct st_intc { /* struct INTC */ + union { /* ICR0 */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short NMIL:1; /* NMIL */ + unsigned short :6; /* */ + unsigned short NMIE:1; /* NMIE */ + } BIT; /* */ + } ICR0; /* */ + union { /* IPRA */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short _TMU0:4; /* TMU0 */ + unsigned short _TMU1:4; /* TMU1 */ + unsigned short _TMU2:4; /* TMU2 */ + unsigned short _RTC :4; /* RTC */ + } BIT; /* */ + } IPRA; /* */ + union { /* IPRB */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short _WDT:4; /* WDT */ + unsigned short _REF:4; /* REF */ + } BIT; /* */ + } IPRB; /* */ + char wk[234]; /* */ + unsigned int TRA; /* TRA */ + unsigned int EXPEVT; /* EXPEVT */ + unsigned int INTEVT; /* INTEVT */ +}; +struct st_intx { /* struct INTX */ + unsigned int INTEVT2; /* INTEVT2 */ + union { /* IRR0 */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char PINT0R:1; /* PINT0R */ + unsigned char PINT1R:1; /* PINT1R */ + unsigned char IRQ5R :1; /* IRQ5R */ + unsigned char IRQ4R :1; /* IRQ4R */ + unsigned char IRQ3R :1; /* IRQ3R */ + unsigned char IRQ2R :1; /* IRQ2R */ + unsigned char IRQ1R :1; /* IRQ1R */ + unsigned char IRQ0R :1; /* IRQ0R */ + } BIT; /* */ + } IRR0; /* */ + char wk1; /* */ + union { /* IRR1 */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char TXI0R:1; /* TXI0R */ + unsigned char :1; /* */ + unsigned char RXI0R:1; /* RXI0R */ + unsigned char ERI0R:1; /* ERI0R */ + unsigned char DEI3R:1; /* DEI3R */ + unsigned char DEI2R:1; /* DEI2R */ + unsigned char DEI1R:1; /* DEI1R */ + unsigned char DEI0R:1; /* DEI0R */ + } BIT; /* */ + } IRR1; /* */ + char wk2; /* */ + union { /* IRR2 */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :3; /* */ + unsigned char ADIR :1; /* ADIR */ + unsigned char TXI2R:1; /* TXI2R */ + unsigned char :1; /* */ + unsigned char RXI2R:1; /* RXI2R */ + unsigned char ERI2R:1; /* ERI2R */ + } BIT; /* */ + } IRR2; /* */ + char wk3[7]; /* */ + union { /* ICR1 */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short MAI :1; /* MAI */ + unsigned short IRQLVL:1; /* IRQLVL */ + unsigned short BLMSK :1; /* BLMSK */ + unsigned short :1; /* */ + unsigned short IRQ5S :2; /* IRQ5S */ + unsigned short IRQ4S :2; /* IRQ4S */ + unsigned short IRQ3S :2; /* IRQ3S */ + unsigned short IRQ2S :2; /* IRQ2S */ + unsigned short IRQ1S :2; /* IRQ1S */ + unsigned short IRQ0S :2; /* IRQ0S */ + } BIT; /* */ + } ICR1; /* */ + union { /* ICR2 */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short PINT15S:1; /* PINT15S */ + unsigned short PINT14S:1; /* PINT14S */ + unsigned short PINT13S:1; /* PINT13S */ + unsigned short PINT12S:1; /* PINT12S */ + unsigned short PINT11S:1; /* PINT11S */ + unsigned short PINT10S:1; /* PINT10S */ + unsigned short PINT9S :1; /* PINT9S */ + unsigned short PINT8S :1; /* PINT8S */ + unsigned short PINT7S :1; /* PINT7S */ + unsigned short PINT6S :1; /* PINT6S */ + unsigned short PINT5S :1; /* PINT5S */ + unsigned short PINT4S :1; /* PINT4S */ + unsigned short PINT3S :1; /* PINT3S */ + unsigned short PINT2S :1; /* PINT2S */ + unsigned short PINT1S :1; /* PINT1S */ + unsigned short PINT0S :1; /* PINT0S */ + } BIT; /* */ + } ICR2; /* */ + union { /* PINTER */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short PINT15E:1; /* PINT15E */ + unsigned short PINT14E:1; /* PINT14E */ + unsigned short PINT13E:1; /* PINT13E */ + unsigned short PINT12E:1; /* PINT12E */ + unsigned short PINT11E:1; /* PINT11E */ + unsigned short PINT10E:1; /* PINT10E */ + unsigned short PINT9E :1; /* PINT9E */ + unsigned short PINT8E :1; /* PINT8E */ + unsigned short PINT7E :1; /* PINT7E */ + unsigned short PINT6E :1; /* PINT6E */ + unsigned short PINT5E :1; /* PINT5E */ + unsigned short PINT4E :1; /* PINT4E */ + unsigned short PINT3E :1; /* PINT3E */ + unsigned short PINT2E :1; /* PINT2E */ + unsigned short PINT1E :1; /* PINT1E */ + unsigned short PINT0E :1; /* PINT0E */ + } BIT; /* */ + } PINTER; /* */ + union { /* IPRC */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short _IRQ3:4; /* IRQ3 */ + unsigned short _IRQ2:4; /* IRQ2 */ + unsigned short _IRQ1:4; /* IRQ1 */ + unsigned short _IRQ0:4; /* IRQ0 */ + } BIT; /* */ + } IPRC; /* */ + union { /* IPRD */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short _PINT0_7 :4; /* PINT0-7 */ + unsigned short _PINT8_15:4; /* PINT8-15 */ + unsigned short _IRQ5 :4; /* IRQ5 */ + unsigned short _IRQ4 :4; /* IRQ4 */ + } BIT; /* */ + } IPRD; /* */ + union { /* IPRE */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short _DMAC :4; /* DMAC */ + unsigned short _SCIF0:4; /* SCIF0 */ + unsigned short _SCIF2:4; /* SCIF2 */ + unsigned short _ADC :4; /* ADC */ + } BIT; /* */ + } IPRE; /* */ + char wk4[524260]; /* */ + union { /* IPRF */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short :8; /* */ + unsigned short _USB:4; /* USB */ + } BIT; /* */ + } IPRF; /* */ + union { /* IPRG */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short _TPU0:4; /* TPU0 */ + unsigned short _TPU1:4; /* TPU1 */ + } BIT; /* */ + } IPRG; /* */ + union { /* IPRH */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short _TPU2:4; /* TPU2 */ + unsigned short _TPU3:4; /* TPU3 */ + } BIT; /* */ + } IPRH; /* */ +}; +struct st_scif { /* struct SCIF */ + union { /* SCSMR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short :5; /* */ + unsigned short SRC :3; /* SRC */ + unsigned short CA :1; /* CA */ + unsigned short CHR :1; /* CHR */ + unsigned short _PE :1; /* PE */ + unsigned short OE :1; /* O/E */ + unsigned short STOP:1; /* STOP */ + unsigned short :1; /* */ + unsigned short CKS :2; /* CKS */ + } BIT; /* */ + } SCSMR; /* */ + char wk1[2]; /* */ + unsigned char SCBRR; /* SCBRR */ + char wk2[3]; /* */ + union { /* SCSCR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short :4; /* */ + unsigned short TSIE:1; /* TSIE */ + unsigned short ERIE:1; /* ERIE */ + unsigned short BRIE:1; /* BRIE */ + unsigned short DRIE:1; /* DRIE */ + unsigned short TIE :1; /* TIE */ + unsigned short RIE :1; /* RIE */ + unsigned short TE :1; /* TE */ + unsigned short RE :1; /* RE */ + unsigned short :2; /* */ + unsigned short CKE :2; /* CKE */ + } BIT; /* */ + } SCSCR; /* */ + char wk3[2]; /* */ + unsigned char SCTDSR; /* SCTDSR */ + char wk4[3]; /* */ + union { /* SCFER */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short :2; /* */ + unsigned short PER:6; /* PER */ + unsigned short :2; /* */ + unsigned short FER:6; /* FER */ + } BIT; /* */ + } SCFER; /* */ + char wk5[2]; /* */ + union { /* SCSSR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short :6; /* */ + unsigned short ORER:1; /* ORER */ + unsigned short TSF :1; /* TSF */ + unsigned short ER :1; /* ER */ + unsigned short TEND:1; /* TEND */ + unsigned short TDFE:1; /* TDFE */ + unsigned short BRK :1; /* BRK */ + unsigned short FER :1; /* FER */ + unsigned short PER :1; /* PER */ + unsigned short RDF :1; /* RDF */ + unsigned short DR :1; /* DR */ + } BIT; /* */ + } SCSSR; /* */ + char wk6[2]; /* */ + union { /* SCFCR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short TSE :1; /* TSE */ + unsigned short TCRST:1; /* TCRST */ + unsigned short :3; /* */ + unsigned short RSTRG:3; /* RSTRG */ + unsigned short RTRG :2; /* RTRG */ + unsigned short TTRG :2; /* TTRG */ + unsigned short MCE :1; /* MCE */ + unsigned short TFRST:1; /* TFRST */ + unsigned short RFRST:1; /* RFRST */ + unsigned short LOOP :1; /* LOOP */ + } BIT; /* */ + } SCFCR; /* */ + char wk7[2]; /* */ + union { /* SCFDR */ + unsigned short WORD; /* Word Access */ + struct { /* Byte Access */ + unsigned short :1; /* */ + unsigned short T:7; /* T */ + unsigned short :1; /* */ + unsigned short R:7; /* R */ + } BIT; /* */ + } SCFDR; /* */ + char wk8[2]; /* */ + unsigned char SCFTDR; /* SCFTDR */ + char wk9[3]; /* */ + unsigned char SCFRDR; /* SCFRDR */ +}; /* */ +union un_stbcr3 { /* union STBCR3 */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char _USB :1; /* USB */ + unsigned char :1; /* */ + unsigned char _CMT :1; /* CMT */ + unsigned char _TPU :1; /* TPU */ + unsigned char _ADC :1; /* ADC */ + unsigned char _IrDA :1; /* IrDA */ + unsigned char _SCIF2:1; /* SCIF2 */ + unsigned char _SCIF0:1; /* SCIF0 */ + } BIT; /* */ +}; /* */ +struct st_pfc { /* struct PFC */ + union { /* PACR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short PA7MD:2; /* PA7MD */ + unsigned short PA6MD:2; /* PA6MD */ + unsigned short PA5MD:2; /* PA5MD */ + unsigned short PA4MD:2; /* PA4MD */ + unsigned short PA3MD:2; /* PA3MD */ + unsigned short PA2MD:2; /* PA2MD */ + unsigned short PA1MD:2; /* PA1MD */ + unsigned short PA0MD:2; /* PA0MD */ + } BIT; /* */ + } PACR; /* */ + union { /* PBCR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short PB7MD:2; /* PB7MD */ + unsigned short PB6MD:2; /* PB6MD */ + unsigned short PB5MD:2; /* PB5MD */ + unsigned short PB4MD:2; /* PB4MD */ + unsigned short PB3MD:2; /* PB3MD */ + unsigned short PB2MD:2; /* PB2MD */ + unsigned short PB1MD:2; /* PB1MD */ + unsigned short PB0MD:2; /* PB0MD */ + } BIT; /* */ + } PBCR; /* */ + union { /* PCCR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short PC7MD:2; /* PC7MD */ + unsigned short PC6MD:2; /* PC6MD */ + unsigned short PC5MD:2; /* PC5MD */ + unsigned short PC4MD:2; /* PC4MD */ + unsigned short PC3MD:2; /* PC3MD */ + unsigned short PC2MD:2; /* PC2MD */ + unsigned short PC1MD:2; /* PC1MD */ + unsigned short PC0MD:2; /* PC0MD */ + } BIT; /* */ + } PCCR; /* */ + union { /* PDCR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short PD7MD:2; /* PD7MD */ + unsigned short PD6MD:2; /* PD6MD */ + unsigned short PD5MD:2; /* PD5MD */ + unsigned short PD4MD:2; /* PD4MD */ + unsigned short PD3MD:2; /* PD3MD */ + unsigned short PD2MD:2; /* PD2MD */ + unsigned short PD1MD:2; /* PD1MD */ + unsigned short PD0MD:2; /* PD0MD */ + } BIT; /* */ + } PDCR; /* */ + union { /* PECR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short PE7MD:2; /* PE7MD */ + unsigned short PE6MD:2; /* PE6MD */ + unsigned short PE5MD:2; /* PE5MD */ + unsigned short PE4MD:2; /* PE4MD */ + unsigned short PE3MD:2; /* PE3MD */ + unsigned short PE2MD:2; /* PE2MD */ + unsigned short PE1MD:2; /* PE1MD */ + unsigned short PE0MD:2; /* PE0MD */ + } BIT; /* */ + } PECR; /* */ + union { /* PFCR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short PF7MD:2; /* PF7MD */ + unsigned short PF6MD:2; /* PF6MD */ + unsigned short PF5MD:2; /* PF5MD */ + unsigned short PF4MD:2; /* PF4MD */ + unsigned short PF3MD:2; /* PF3MD */ + unsigned short PF2MD:2; /* PF2MD */ + unsigned short PF1MD:2; /* PF1MD */ + unsigned short PF0MD:2; /* PF0MD */ + } BIT; /* */ + } PFCR; /* */ + union { /* PGCR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short PG7MD:2; /* PG7MD */ + unsigned short PG6MD:2; /* PG6MD */ + unsigned short PG5MD:2; /* PG5MD */ + unsigned short PG4MD:2; /* PG4MD */ + unsigned short PG3MD:2; /* PG3MD */ + unsigned short PG2MD:2; /* PG2MD */ + unsigned short PG1MD:2; /* PG1MD */ + unsigned short PG0MD:2; /* PG0MD */ + } BIT; /* */ + } PGCR; /* */ + union { /* PHCR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short :2; /* */ + unsigned short PH6MD:2; /* PH6MD */ + unsigned short PH5MD:2; /* PH5MD */ + unsigned short PH4MD:2; /* PH4MD */ + unsigned short PH3MD:2; /* PH3MD */ + unsigned short PH2MD:2; /* PH2MD */ + unsigned short PH1MD:2; /* PH1MD */ + unsigned short PH0MD:2; /* PH0MD */ + } BIT; /* */ + } PHCR; /* */ + union { /* PJCR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short PJ7MD:2; /* PJ7MD */ + unsigned short PJ6MD:2; /* PJ6MD */ + unsigned short PJ5MD:2; /* PJ5MD */ + unsigned short PJ4MD:2; /* PJ4MD */ + unsigned short PJ3MD:2; /* PJ3MD */ + unsigned short PJ2MD:2; /* PJ2MD */ + unsigned short PJ1MD:2; /* PJ1MD */ + unsigned short PJ0MD:2; /* PJ0MD */ + } BIT; /* */ + } PJCR; /* */ + union { /* PKCR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short PK7MD:2; /* PK7MD */ + unsigned short PK6MD:2; /* PK6MD */ + unsigned short PK5MD:2; /* PK5MD */ + unsigned short PK4MD:2; /* PK4MD */ + unsigned short PK3MD:2; /* PK3MD */ + unsigned short PK2MD:2; /* PK2MD */ + unsigned short PK1MD:2; /* PK1MD */ + unsigned short PK0MD:2; /* PK0MD */ + } BIT; /* */ + } PKCR; /* */ + union { /* PLCR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short :8; /* */ + unsigned short PL3MD:2; /* PL3MD */ + unsigned short PL2MD:2; /* PL2MD */ + unsigned short PL1MD:2; /* PL1MD */ + unsigned short PL0MD:2; /* PL0MD */ + } BIT; /* */ + } PLCR; /* */ + union { /* SCPCR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short :4; /* */ + unsigned short SCP5MD:2; /* SCP5MD */ + unsigned short SCP4MD:2; /* SCP4MD */ + unsigned short SCP3MD:2; /* SCP3MD */ + unsigned short SCP2MD:2; /* SCP2MD */ + unsigned short SCP1MD:2; /* SCP1MD */ + unsigned short SCP0MD:2; /* SCP0MD */ + } BIT; /* */ + } SCPCR; /* */ + union { /* PMCR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short :2; /* */ + unsigned short PM6MD:2; /* PM6MD */ + unsigned short :2; /* */ + unsigned short PM4MD:2; /* PM4MD */ + unsigned short PM3MD:2; /* PM3MD */ + unsigned short PM2MD:2; /* PM2MD */ + unsigned short PM1MD:2; /* PM1MD */ + unsigned short PM0MD:2; /* PM0MD */ + } BIT; /* */ + } PMCR; /* */ + union { /* PNCR */ + unsigned short WORD; /* Word Access */ + struct { /* Bit Access */ + unsigned short PN7MD:2; /* PN7MD */ + unsigned short PN6MD:2; /* PN6MD */ + unsigned short PN5MD:2; /* PN5MD */ + unsigned short PN4MD:2; /* PN4MD */ + unsigned short PN3MD:2; /* PN3MD */ + unsigned short PN2MD:2; /* PN2MD */ + unsigned short PN1MD:2; /* PN1MD */ + unsigned short PN0MD:2; /* PN0MD */ + } BIT; /* */ + } PNCR; /* */ + char wk1[327724]; /* */ + union { /* PECR2 */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :1; /* */ + unsigned char PE6MD:1; /* PE6MD */ + unsigned char PE5MD:1; /* PE5MD */ + unsigned char PE4MD:1; /* PE4MD */ + } BIT; /* */ + } PECR2; /* */ + char wk2; /* */ + union { /* PFCR2 */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :4; /* */ + unsigned char PF3MD:1; /* PF3MD */ + unsigned char PF2MD:1; /* PF2MD */ + unsigned char PF1MD:1; /* PF1MD */ + unsigned char PF0MD:1; /* PF0MD */ + } BIT; /* */ + } PFCR2; /* */ + char wk3[15]; /* */ + union { /* PNCR2 */ + unsigned char BYTE; /* Byte Access */ + struct { /* Bit Access */ + unsigned char :1; /* */ + unsigned char PN6MD:1; /* PN6MD */ + unsigned char PN5MD:1; /* PN5MD */ + unsigned char PN4MD:1; /* PN4MD */ + unsigned char PN3MD:1; /* PN3MD */ + unsigned char PN2MD:1; /* PN2MD */ + unsigned char PN1MD:1; /* PN1MD */ + unsigned char PN0MD:1; /* PN0MD */ + } BIT; /* */ + } PNCR2; /* */ +}; /* */ + +struct st_mmu { + union { + unsigned int LONG; + struct { + unsigned int :23; + unsigned char SV :1; + unsigned char :2; + unsigned char RC :2; + unsigned char :1; + unsigned char TF :1; + unsigned char IX :1; + unsigned char AT :1; + } BIT; + } MMUCR; + + char wk1[12]; + union { + unsigned int LONG; + struct { + unsigned int VPN :22; + unsigned char :2; + unsigned char ASID :8; + } BIT; + } PTEH; + + union { + unsigned int LONG; + struct { + unsigned char :3; + unsigned int :19; + unsigned char :1; + unsigned char V :1; + unsigned char :1; + unsigned char PR :2; + unsigned char SZ :1; + unsigned char C :1; + unsigned char D :1; + unsigned char SH :1; + unsigned char :1; + } BIT; + } PTEL; + + unsigned int TTB; +}; + + +struct st_ubc { + unsigned int BDRB; + + unsigned int BDMRB; + + union { + unsigned int LONG; + struct { + unsigned short :10; + unsigned int BASMA :1; + unsigned int BASMB :1; + unsigned int :4; + unsigned int SCMFCA :1; + unsigned int SCMFCB :1; + unsigned int SCMFDA :1; + unsigned int SCMFDB :1; + unsigned int PCTE :1; + unsigned int PCBA :1; + unsigned int :2; + unsigned int DBEB :1; + unsigned int PCBB :1; + unsigned int :2; + unsigned int SEQ :1; + unsigned int :2; + unsigned int ETBE :1; + } BIT; + } BRCR; + + unsigned short BETR; + + char wk1[2]; + + unsigned int BARB; + + unsigned int BAMRB; + + union { + unsigned short WORD; + struct { + unsigned short :8; + unsigned short CDB :2; + unsigned short IDB :2; + unsigned short RWB :2; + unsigned short SZB :2; + } BIT; + } BBRB; + + char wk2[2]; + + union { + unsigned int LONG; + struct { + unsigned int SVF :1; + unsigned char :3; + unsigned int BSA :28; + } BIT; + } BRSR; + + unsigned int BARA; + + unsigned int BAMRA; + + union { + unsigned short WORD; + struct { + unsigned short :8; + unsigned short CDA :2; + unsigned short IDA :2; + unsigned short RWA :2; + unsigned short SZA :2; + } BIT; + } BBRA; + + char wk3[2]; + + union { + unsigned int LONG; + struct { + unsigned int DVF :1; + unsigned char :3; + unsigned int BDA :28; + } BIT; + } BRDR; + + char wk4[36]; + + unsigned char BASRA; + + char wk5[3]; + + unsigned char BASRB; +}; + + +union un_stbcr2 { + unsigned char BYTE; + struct { + unsigned char _UDI :1; + unsigned char _UBC :1; + unsigned char _DMAC :1; + unsigned char :1; + unsigned char _TLB :1; + unsigned char _CACHE :1; + unsigned char :2; + } BIT; +}; + + + +#define CPG (*(volatile struct st_cpg *)0xffffff80) +#define WDT (*(volatile struct st_wdt *)0xffffff84) +#define RTC (*(volatile struct st_rtc *)0xfffffec0) +#define INTC (*(volatile struct st_intc *)0xfffffee0) +#define INTX (*(volatile struct st_intx *)0xa4000000) +#define PA (*(volatile struct st_pa *)0xa4000120) +#define PB (*(volatile struct st_pb *)0xa4000122) +#define PC (*(volatile struct st_pc *)0xa4000124) +#define PD (*(volatile struct st_pd *)0xa4000126) +#define PE (*(volatile struct st_pe *)0xa4000128) +#define PF (*(volatile struct st_pf *)0xa400012a) +#define PG (*(volatile struct st_pg *)0xa400012c) +#define PH (*(volatile struct st_ph *)0xa400012e) +#define PJ (*(volatile struct st_pj *)0xa4000130) +#define PK (*(volatile struct st_pk *)0xa4000132) +#define PL (*(volatile struct st_pl *)0xa4000134) +#define SCP (*(volatile struct st_scp *)0xa4000136) +#define PM (*(volatile struct st_pm *)0xa4000138) +#define PN (*(volatile struct st_pn *)0xa400013a) +#define TMU (*(volatile struct st_tmu *)0xfffffe92) +#define TMU0 (*(volatile struct st_tmu0 *)0xfffffe94) +#define TMU1 (*(volatile struct st_tmu0 *)0xfffffea0) +#define TMU2 (*(volatile struct st_tmu2 *)0xfffffeac) +#define USB (*(volatile struct st_usb *)0xa40a0008) +#define SCIF0 (*(volatile struct st_scif *)0xa4400000) +#define SCIF2 (*(volatile struct st_scif *)0xa4410000) +#define STBCR3 (*(volatile union un_stbcr3 *)0xa40a0000) +#define PFC (*(volatile struct st_pfc *)0xa4000100) +#define TEA (*(volatile unsigned int *)0xfffffffc) +#define MMU (*(volatile struct st_mmu *)0xffffffe0) +#define UBC (*(volatile struct st_ubc *)0xffffff90) +#define STBCR2 (*(volatile union un_stbcr2 *)0xffffff88) + +#endif // _7705_H diff --git a/include/display.h b/include/display.h new file mode 100644 index 0000000..20e0240 --- /dev/null +++ b/include/display.h @@ -0,0 +1,181 @@ +#ifndef _DISPLAY_H +#define _DISPLAY_H 1 + +//--- +// Types and constants. +//--- + +enum Color +{ + Color_White = 0, // White (AND 0) + Color_Black = 1, // Black (OR 1) + Color_None = 2, // Transparent (NOP) + Color_Invert = 3, // Invert (XOR 1) +}; + +/* + enum BlendingMode + Describes the various blending modes available for drawing images. + Blending modes may be combined for special effects! For instance: + - Or Only sets black pixels. + - And Only erases white pixels. + - Or | And Fully draws the bitmap. + - Invert Inverts pixels where the bitmap is black. + - Or | Invert Erases black pixels. + Adding Checker to an existing combination limits the operation to + pixels (x, y) that satisfy (x + y) & 1 == 1. + Operations are done in the following order : Or - Invert - And. +*/ +enum BlendingMode +{ + Blend_Or = 0x01, + Blend_Invert = 0x02, + Blend_And = 0x04, + + Blend_Checker = 0x10, +}; + +enum ImageFormat +{ + ImageFormat_Mono = 0x01, + ImageFormat_Gray = 0x02, + + ImageFormat_Alpha = 0x10, + + ImageFormat_ColorMask = 0x0f, +}; + +struct Image +{ + unsigned char width; + unsigned char height; + unsigned char format; + + // Ensures data is 4-aligned. + unsigned char gap; + + const unsigned char __attribute__((aligned(4))) data[]; + +} __attribute__((aligned(4))); + +typedef struct Image Image; + + + +#define DISPLAY_WIDTH 128 +#define DISPLAY_HEIGHT 64 + + + +//--- +// Generic functions. +//--- + +/* + display_getLocalVRAM() + Returns the local video ram. This address should not be used directly + when running the gray engine. + + @return Video ram address of the monochrome display module. +*/ +void *display_getLocalVRAM(void); + +/* + display_useVRAM() + Changes the current video ram address. Expects a *4-aligned* 1024-byte + buffer. + Do not use this function while running the gray engine. + + @arg New video ram address. +*/ +void display_useVRAM(void *vram); + + + +//--- +// Global drawing functions. +//--- + +/* + dupdate() + Displays the vram on the physical screen. +*/ +void dupdate(void); + +/* + dclear() + Clears the whole video ram. +*/ +void dclear(void); + +/* + dclear_area() + Clears an area of the video ram. + + @arg x1 + @arg y1 + @arg x2 + @arg y2 +*/ +void dclear_area(int x1, int y1, int x2, int y2); + +/* + dreverse_area() + Reverses an area of the screen. + + @arg x1 + @arg y1 + @arg x2 + @arg y2 +*/ +void dreverse_area(int x1, int y1, int x2, int y2); + + + +//--- +// Local drawing functions. +//--- + +/* + dpixel() + Puts a pixel on the screen. + + @arg x + @arg y + @arg color +*/ +void dpixel(int x, int y, enum Color color); + +/* + dline() + Draws a line on the screen. Automatically optimizes horizontal and + vertical lines. + + Uses an algorithm written by PierrotLL for MonochromeLib. + + @arg x1 + @arg y1 + @arg x2 + @arg y2 + @arg color +*/ +void dline(int x1, int y1, int x2, int y2, enum Color color); + + + +//--- +// Image drawing. +//--- + +/* + dimage() + Displays an image in the vram. + + @arg image + @arg x + @arg y + @arg mode +*/ +void dimage(struct Image *image, int x, int y, enum BlendingMode mode); + +#endif // _DISPLAY_H diff --git a/include/gint.h b/include/gint.h new file mode 100644 index 0000000..de06883 --- /dev/null +++ b/include/gint.h @@ -0,0 +1,97 @@ +#ifndef _GINT_H +#define _GINT_H 1 + +//--- +// Public API. +//--- + +/* + gint_getVBR() + Returns the current vbr address. + + @return vbr address currently in use. +*/ +unsigned int gint_getVBR(void); + +/* + gint_systemVBR() + Returns the vbr address used by the system (saved when execution + starts). + + @return vbr address used by the system. +*/ +unsigned int gint_systemVBR(void); + + + +//--- +// Internal API. +// Referenced here for documentation purposes only. +// Do NOT call these functions, you'll most probably screw up the whole +// interrupt handling system. +//--- + +/* + gint_setVBR() + Sets the vbr address and does some configuration while interrupts are + disabled. + + @arg new_vbr_address + @arg setup Will be called for configuration under interrupt-safe + environment. +*/ +void gint_setVBR(unsigned int new_vbr_address, void (*setup)(void)); + +/* + gint_init() + Initializes gint. Loads the interrupt handler into the memory and sets + the new vbr address. +*/ +void gint_init(void); + +/* + gint_quit() + Stops gint. Restores the system's configuration and vbr address. +*/ +void gint_quit(void); + +/* + gint_setup() + Configures interrupt priorities and some parameters to allow gint to + take control of the interrupt flow. +*/ +void gint_setup_7705(void); +void gint_setup_7305(void); + +/* + gint_stop() + Un-configures the interrupt flow to give back the interrupt control to + the system. +*/ +void gint_stop_7705(void); +void gint_stop_7305(void); + +/* + gint() + Handles interrupts. +*/ +void gint(void) __attribute__(( + section(".gint.int.entry"), + interrupt_handler +)); +void gint_7705(void) __attribute__((section(".gint.int"))); +void gint_7305(void) __attribute__((section(".gint.int"))); + + + +//--- +// Internal priority definitions. +//--- + +#define GINT_INTP_WDT 4 +#define GINT_INTP_RTC 9 +#define GINT_INTP_KEY 8 + + + +#endif // _GINT_H diff --git a/include/gray.h b/include/gray.h new file mode 100644 index 0000000..c91b0e5 --- /dev/null +++ b/include/gray.h @@ -0,0 +1,57 @@ +#ifndef _GRAY_H +#define _GRAY_H 1 + +//--- +// Public API. +//--- + +/* + gray_start() + Starts the gray engine. The control of the screen is transferred to the + gray engine. +*/ +void gray_start(void); + +/* + gray_stop() + Stops the gray engine. The monochrome display system takes control of + the video ram. +*/ +void gray_stop(void); + +/* + gray_lightVRAM() + Returns the module's gray vram address. +*/ +void *gray_lightVRAM(void); + +/* + gray_lightVRAM() + Returns the module's dark vram address. +*/ +void *gray_darkVRAM(void); + +//--- +// Internal API. +// Referenced here for documentation purposes only. Do not call. +//-- + +/* + gray_swap() + Swaps the vram buffers. +*/ +void gray_swap(void); + +/* + gray_interrupt() + Answers a timer interrupt. Swaps the two buffers. +*/ +void gray_interrupt(void) __attribute__((section(".gint.int"))); + +/* + gray_init() + Initializes the gray engine. +*/ +void gray_init(void) __attribute__((constructor)); + +#endif // _GRAY_H diff --git a/include/keyboard.h b/include/keyboard.h new file mode 100644 index 0000000..534f570 --- /dev/null +++ b/include/keyboard.h @@ -0,0 +1,254 @@ +#ifndef _KEYBOARD_H +#define _KEYBOARD_H 1 + +//--- +// Keycodes and related. +//--- + +// The following codes are gint matrix codes. They are not compatible with the +// system's. + +#define KEY_F1 0x69 +#define KEY_F2 0x59 +#define KEY_F3 0x49 +#define KEY_F4 0x39 +#define KEY_F4 0x39 +#define KEY_F5 0x29 +#define KEY_F6 0x19 + +#define KEY_SHIFT 0x68 +#define KEY_OPTN 0x58 +#define KEY_VARS 0x48 +#define KEY_MENU 0x38 +#define KEY_LEFT 0x28 +#define KEY_UP 0x18 + +#define KEY_ALPHA 0x67 +#define KEY_SQUARE 0x57 +#define KEY_POWER 0x47 +#define KEY_EXIT 0x37 +#define KEY_DOWN 0x27 +#define KEY_RIGHT 0x17 + +#define KEY_XOT 0x66 +#define KEY_LOG 0x56 +#define KEY_LN 0x46 +#define KEY_SIN 0x36 +#define KEY_COS 0x26 +#define KEY_TAN 0x16 + +#define KEY_FRAC 0x65 +#define KEY_FD 0x55 +#define KEY_LEFTP 0x45 +#define KEY_RIGHTP 0x35 +#define KEY_COMMA 0x25 +#define KEY_ARROW 0x15 + +#define KEY_7 0x64 +#define KEY_8 0x54 +#define KEY_9 0x44 +#define KEY_DEL 0x34 +#define KEY_AC_ON 0x24 + +#define KEY_4 0x63 +#define KEY_5 0x53 +#define KEY_6 0x43 +#define KEY_MUL 0x33 +#define KEY_DIV 0x23 + +#define KEY_1 0x62 +#define KEY_2 0x52 +#define KEY_3 0x42 +#define KEY_PLUS 0x32 +#define KEY_MINUS 0x22 + +#define KEY_0 0x61 +#define KEY_DOT 0x51 +#define KEY_EXP 0x41 +#define KEY_NEG 0x31 +#define KEY_EXE 0x21 + +// Key modifiers. +#define MOD_SHIFT 0x80 +#define MOD_ALPHA 0x100 +#define MOD_CLEAR ~(MOD_SHIFT | MOD_ALPHA) + +// Key events. +#define KEY_NONE 0x00 +#define KEY_NOEVENT 0xff + + + +//--- +// Keyboard configuration. +//--- + +/* + enum KeyboardFrequency + Describes the various frequencies available for the keyboard analysis. + Default frequency is 16 Hz (system frequency is about 40 Hz). Very few + applications will need to change this setting. + Be aware that you will miss key hits at low frequencies. + At high frequencies, you will lose important execution power. Some + loop-driven programs will freeze at 64 Hz because they will never + leave the interrupt handling routine. SH3 also have difficulties with + 64 Hz. +*/ +enum KeyboardFrequency { + KeyFreq_500mHz = 7, + KeyFreq_1Hz = 6, + KeyFreq_2Hz = 5, + KeyFreq_4Hz = 4, + KeyFreq_16Hz = 3, + KeyFreq_64Hz = 2, + KeyFreq_256Hz = 1, +}; + +/* + keyboard_setFrequency() + Sets the keyboard frequency. Does nothing when the argument is not a + valid KeyboardFrequency value. + + @arg frequency +*/ +void keyboard_setFrequency(enum KeyboardFrequency frequency); + +/* + keyboard_setRepeatRate() + Sets the default repeat rate for key events. The unit for the argument + is the keyboard period. + For example at 16 Hz, values of (10, 2) will imitate the system + default. + Set to 0 to disable repetition. If first = 0, no repetition will be + allowed. If first != 0 and next = 0, only one repetition will be + allowed. + + @arg first Delay before first repeat, in keyboard period units. + @arg next Delay before following repeats, in keyboard period + units. +*/ +void keyboard_setRepeatRate(int first, int next); + + + +//--- +// Keyboard access. +//--- + +/* + enum GetKeyOpt + Options available for use with getkey_opt(). +*/ +enum GetkeyOpt +{ + Getkey_NoOption = 0x00, + + // Return KEY_NONE when a key is released. + Getkey_ReleaseEvent = 0x01, + + // Consider [SHIFT] and [ALPHA] as modifiers instead of returning + // KEY_SHIFT and KEY_ALPHA. + Getkey_ShiftModifier = 0x02, + Getkey_AlphaModifier = 0x04, + + // Key repetition. Notice that modifiers will never be repeated. + Getkey_RepeatArrowKeys = 0x10, + Getkey_RepeatCharKeys = 0x20, + Getkey_RepeatCtrlKeys = 0x40, + Getkey_RepeatFuncKeys = 0x80, + // Shorthand for the four previous properties. + Getkey_RepeatAllKeys = 0xf0, +}; + +/* + keylast() + Returns the matrix code of the last pressed key. If repeat_count is + non-NULL, it is set to the number of repetitions. + + @arg repeat_count + @return Key matrix code. +*/ +int keylast(int *repeat_count); + +/* + getkey() + Blocking function with auto-repeat and SHIFT modifying functionalities. + Reproduces the behavior of the system's GetKey(). + + @return Pressed key matrix code. +*/ +int getkey(void); + +/* + getkey_opt() + Enhances getkey() with most general functionalities. + If max_cycles is non-zero and positive, getkey_opt() will return + KEY_NOEVENT if no event occurs during max_cycle analysis. + + @arg options OR-combination of GetkeyOpt values. + @arg max_cycles + + @return Pressed key matrix code. +*/ +int getkey_opt(enum GetkeyOpt options, int max_cycles); + +/* + multigetkey() + Listens the keyboard for simultaneous key hits. Uses the same options + as getkey_opt(). + multigetkey() fills the 'keys' array with 'count' key codes, adding + KEY_NONE if less than 'count' keys are pressed. + Be aware that rectangle and column effects can make multigetkey() read + unpressed keys as pressed (see documentation for more information). + Setting count = 3 is generally safe. + + @arg keys Key code array. + @arg count Maximum number of keys that will be read. + @arg max_cycles +*/ +void multigetkey(int *keys, int count, int max_cycles); + + + +//--- +// Key analysis. +//--- + +enum KeyType +{ + KeyType_Arrow = 1, + KeyType_Character = 2, + KeyType_Control = 4, + KeyType_Function = 8, +}; + +/* + keyid() + Returns a non-matrix key code that can be used for array subscript. + Ignores modifiers. + + @arg key + @return Modified keycode. +*/ +int keyid(int key); + +/* + keychar() + Returns the ASCII character associated with a character key ; 0 for + other keys. + + @arg key + @return Key character. +*/ +int keychar(int key); + +/* + keytype() + Returns a key's type. Ignores modifiers. + + @arg key + @return Key type. +*/ +enum KeyType keytype(int key); + +#endif // _KEYBOARD_H diff --git a/include/mpu.h b/include/mpu.h new file mode 100644 index 0000000..eb8ddc1 --- /dev/null +++ b/include/mpu.h @@ -0,0 +1,52 @@ +#ifndef _MPU_H +#define _MPU_H 1 + +//--- +// enum MPU +// This type holds information about the calculator's MPU. +//--- + +enum MPU +{ + MPU_Unknown = 0, + // fx-9860G SH3. + MPU_SH7337 = 1, + // fx-9860G II SH3. + MPU_SH7355 = 2, + // fx-9860G II SH4. + MPU_SH7305 = 3, + // Just for reference. + MPU_SH7724 = 4 +}; + + + +//--- +// MPU type tests. +// Prefer using an 'if(isSH3()) { ... } else { ... }' alternative for best +// results. +//--- + +// Global MPU variable, accessible for direct tests. +extern enum MPU MPU_CURRENT; + +// Quick SH3 test. It is safer to assume that an unknown model is SH4 because +// SH3-based models are not produced anymore. +#define isSH3() (MPU_CURRENT == MPU_SH7337 || MPU_CURRENT == MPU_SH7355) +#define isSH4() !isSH3() + + + +//--- +// Public API. +//--- + +/* + getMPU() + Determines the MPU type and returns it. MPU_CURRENT is not updated. + + @return MPU type. +*/ +enum MPU getMPU(void); + +#endif // _MPU_H diff --git a/include/screen.h b/include/screen.h new file mode 100644 index 0000000..f54d8f8 --- /dev/null +++ b/include/screen.h @@ -0,0 +1,12 @@ +#ifndef _SCREEN_H +#define _SCREEN_H 1 + +/* + screen_display() + Displays contents on the full screen. Expects a 1024-byte buffer. + + @arg vram 1024-byte video buffer. +*/ +void screen_display(const void *vram); + +#endif diff --git a/include/setjmp.h b/include/setjmp.h new file mode 100644 index 0000000..c43c204 --- /dev/null +++ b/include/setjmp.h @@ -0,0 +1,31 @@ +#ifndef _SETJMP_H +#define _SETJMP_H 1 + +// There are 16 CPU registers that *must* be saved to ensure a basically +// safe jump. +typedef unsigned int jmp_buf[16]; + + + +//--- +// Long jump functions. +//--- + +/* + setjmp() + Configures a jump by saving data to the given jump buffer. + + @arg env Empty jump buffer. +*/ +int setjmp(jmp_buf env); + +/* + longjmp() + Performs a long jump. + + @arg env Jump buffer configure with setjmp(). + @arg value setjmp() will return this integer after the jump. +*/ +void longjmp(jmp_buf env, int value); + +#endif // _SETJMP_H diff --git a/include/stdlib.h b/include/stdlib.h new file mode 100644 index 0000000..66f7396 --- /dev/null +++ b/include/stdlib.h @@ -0,0 +1,31 @@ +#ifndef _STDLIB_H +#define _STDLIB_H 1 + +#include + +// Common exit codes. +#define EXIT_SUCCESS 1 +#define EXIT_FAILURE 0 + + + +//--- +// Program exit functions. +//--- + +/* + abort() + Aborts the program execution without calling the exit handlers. +*/ +void abort(void); + +/* + exit() + Stops the program execution with the given status code, after calling + the exit handlers. + + @arg status +*/ +void exit(int status); + +#endif // _STDLIB_H diff --git a/include/string.h b/include/string.h new file mode 100644 index 0000000..d74977a --- /dev/null +++ b/include/string.h @@ -0,0 +1,32 @@ +#ifndef _STRING_H +#define _STRING_H 1 + +#include + +//--- +// Memory manipulation. +//--- + +/* + memcpy() + 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. + + @arg destination + @arg source + @arg byte_number +*/ +void *memcpy(void *destination, const void *source, size_t byte_number); + +/* + memset() + Sets the contents of a memory area. A smart copy is performed. + + @arg area + @arg byte Byte to write in the area. + @arg byte_number +*/ +void *memset(void *destination, int byte, size_t byte_number); + +#endif // _STRING_H diff --git a/include/timer.h b/include/timer.h new file mode 100644 index 0000000..786b259 --- /dev/null +++ b/include/timer.h @@ -0,0 +1,73 @@ +#ifndef _TIMER_H +#define _TIMER_H 1 + +//--- +// Constants. +//--- + +// Timer identifiers. +#define TIMER_0 0 +#define TIMER_TMU0 TIMER_0 +#define TIMER_1 1 +#define TIMER_TMU1 TIMER_1 +#define TIMER_2 2 +#define TIMER_TMU2 TIMER_2 +// Timer function identifiers. +#define TIMER_GRAY TIMER_TMU0 +#define TIMER_USER1 TIMER_TMU1 +#define TIMER_USER2 TIMER_TMU2 + +// Timer prescalers. +#define TIMER_Po_4 0 +#define TIMER_Po_16 1 +#define TIMER_Po_64 2 +#define TIMER_Po_256 3 +#define TIMER_TCLK 5 + + + +//--- +// Public API. +//--- + +/* + timer_set() + Configures and starts a timer. + + @arg timer Timer identifier. Use only TIMER_USER1 and + TIMER_USER2. + @arg delay Delay before expiration, in clock counts. + @arg prescaler Clock prescaler value. Possible values are + TIMER_Po_4, TIMER_Po_16, TIMER_Po_64, + TIMER_Po_256 and TIMER_TCLK. + @arg callback Callback function. + @arg repetitions Number of repetitions, 0 for infinite. +*/ +void timer_set(int timer, int delay, int prescaler, void (*callback)(void), + int repetitions); + +/* + timer_stop() + Stops the given timer. This function may be called even if the timer is + not running. + + @arg timer Timer identifier. +*/ +void timer_stop(int timer); + + + +//--- +// Internal API. +// Referenced for documentation purposes only. Do not call. +//--- + +/* + timer_interrupt() + Handles the interrupt for the given timer. + + @timer Timer that generated the interrupt. +*/ +void timer_interrupt(int timer); + +#endif // _TIMER_H diff --git a/info b/info new file mode 100644 index 0000000..8a2dc33 --- /dev/null +++ b/info @@ -0,0 +1,16 @@ + +Experimental power reduction as function of the keyboard analysis frequency. + +SH3 + None 0 % + 4 Hz 2.8 % + 16 Hz 2.8 % + 64 Hz 2.8 % + 256 Hz 20.0 % + +SH4 + None 0 % + 4 Hz 1.8 % + 16 Hz 1.8 % + 64 Hz 1.8 % + 256 Hz 3.6 % diff --git a/libc.a b/libc.a new file mode 100644 index 0000000..c4d5af7 Binary files /dev/null and b/libc.a differ diff --git a/libgint.a b/libgint.a new file mode 100644 index 0000000..e392e53 Binary files /dev/null and b/libgint.a differ diff --git a/sprites.bmp b/sprites.bmp new file mode 100644 index 0000000..2cbe277 Binary files /dev/null and b/sprites.bmp differ diff --git a/src/crt0.c b/src/crt0.c new file mode 100644 index 0000000..bbb3383 --- /dev/null +++ b/src/crt0.c @@ -0,0 +1,145 @@ +// Used by the exit()-family functions to save and restore the execution state. +#include +static jmp_buf env; +// Provides EXIT_SUCCESS and EXIT_FAILURE. +#include +// Provides gint initialization functionalities. +#include +// Provides memset() and memcpy(). +#include + +// Some syscall prototypes. +void __Hmem_SetMMU(unsigned int, unsigned int, int); +void __GLibAddinAplExecutionCheck(int, int, int); +int main(void); + +// Local functions. +static void init(void); +static void fini(void); + +// Symbols imported from the linker script. +extern unsigned int + romdata, + bbss, ebss, + bdata, edata; + +// This variable should be overwritten before being returned, so the default +// value doesn't matter much. +static int exit_code = EXIT_SUCCESS; + + + +/* + start() + + Program entry point. Loads the data section into the memory and invokes + main(). Also prepares the execution environment by initializing all the + modules. + + @return Execution status returned to the OS. +*/ + +int start(void) + __attribute__(( + section(".pretext.entry") + )); + +int start(void) +{ + // Linker symbols. + unsigned int *bss = &bbss; + 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. + while(data < &edata) *data++ = *src++; + + __GLibAddinAplExecutionCheck(0, 1, 1); + + // Initializing everything. + init(); + gint_init(); + + + + // Saving the execution state there. + x = setjmp(env); + // If the program has just started, executing main(). Otherwise, the + // exit code has already been set by abort() or similar. + if(!x) exit_code = main(); + + + + // Remember to flush and close opened streams. + + // Un-initializing everything. + gint_quit(); + fini(); + + return exit_code; +} + +static void init(void) +{ + extern void + (*bctors)(void), + (*ectors)(void); + void (**func)(void) = &bctors; + + // Calling the constructors. + while(func < &ectors) + { + (*(*func))(); + func++; + } +} + +static void fini(void) +{ + extern void + (*bdtors)(void), + (*edtors)(void); + void (**func)(void) = &bdtors; + + // Calling the destructors. + while(func < &edtors) + { + (*(*func))(); + func++; + } +} + + + +/* + abort() + + Immediately ends the program without invoking the exit handlers. +*/ + +void abort(void) +{ + exit_code = EXIT_FAILURE; + longjmp(env, 1); +} + +/* + exit() + + Ends the program and returns the given exit code status. + Calls exit handlers before returning. + + @arg status Exit status. +*/ + +void exit(int status) +{ + exit_code = status; + longjmp(env, 1); +} + diff --git a/src/display.c b/src/display.c new file mode 100644 index 0000000..92b2315 --- /dev/null +++ b/src/display.c @@ -0,0 +1,715 @@ +/* + display + + Handles vram manipulation and drawing. + + :: Rectangle masks + + The concept of 'rectangle masks' is used several times in this module. + It consists in saying that an operation that affects a rectangle acts + the same on all the lines (considering that only the lines that + intersect the rectangle are changed) and therefore it is possible to + represent the behavior on a single line using 'masks' that indicate + whether a pixel is affected (1) or not (0). + + For example when clearing the screen rectangle (16, 16, 112, 48), the + masks will represent information '16 to 112 on x-axis', and will hold + the following values : 0000ffff, ffffffff, ffffffff and ffff0000. These + masks can then be used by setting vram[offset] &= ~masks[i]. This + appears to be very flexible : for instance, reversing a rectangle of + vram only needs vram[offset] ^= masks[i]. + + This technique can also be used in more subtle cases with more complex + patterns, but within this module it is unlikely to happen. +*/ + +#include +#include +#include +#include +#include + +// Program video ram. It resides in .bss section, therefore it is cleared at +// program initialization and stripped from the executable file. +static int local_vram[256]; +static int *vram = local_vram; + +#define sgn(x) ((x) < 0 ? -1 : 1) +#define abs(x) ((x) < 0 ? -(x) : (x)) +#define rnd(x) ((int)((x) + 0.5)) + + + +//--- +// Local helper functions. +//--- + +/* + adjust() + Adjusts the given rectangle coordinates to ensure that : + - The rectangle is entirely contained in the screen, + - x1 < x2 and y1 < y2, + which is needed when working with screen rectangles. + + @arg x1 + @arg y1 + @arg x2 + @arg y2 +*/ +static void adjust(int *x1, int *y1, int *x2, int *y2) +{ + #define swap(a, b) tmp = a, a = b, b = tmp + int tmp; + + if(*x2 < *x1) swap(*x1, *x2); + if(*y2 < *y1) swap(*y1, *y2); + + if(*x1 < 0) *x1 = 0; + if(*y1 < 0) *y1 = 0; + if(*x2 > 127) *x2 = 127; + if(*y2 > 63) *y2 = 63; + #undef swap +} + +/* + getmasks() + + Computes the rectangle masks needed to affect pixels located between x1 + and x2 (both included). + + @arg x1 + @arg x2 + @arg masks Four-integer-array pointer. +*/ +static void getmasks(int x1, int x2, unsigned int *masks) +{ + // Indexes of the first and last longs that are non-blank. + int l1 = x1 >> 5; + int l2 = x2 >> 5; + int i = 0; + + // Setting the base masks. Those are the final values, except for the + // longs with indexes l1 and l2, that still need to be adjusted. + while(i < l1) masks[i++] = 0x00000000; + while(i <= l2) masks[i++] = 0xffffffff; + while(i < 4) masks[i++] = 0x00000000; + + // Removing the long number information in x1 and x2 (that is, the + // multiples of 32) to keep only the interesting information -- the + // number of null bits to add in l1 and l2. + x1 &= 31; + // Inverting x2 is here the same as computing 32 - x, since 32 is a + // power of 2 (actually it creates positive bits at the left but those + // ones are removed by the bitwise-and mask). + x2 = ~x2 & 31; + + // Setting the last masks. + masks[l1] &= (0xffffffff >> x1); + masks[l2] &= (0xffffffff << x2); +} + + + +//--- +// Generic functions. +//--- + +/* + display_getVRAM() + Returns the current video ram. + + @return Video ram address. +*/ +void *display_getLocalVRAM(void) +{ + return (void*)local_vram; +} + +/* + display_useVRAM() + Changes the current video ram address. Expects a *4-aligned* 1024-byte + buffer. + + @arg New video ram address. +*/ +void display_useVRAM(void *ptr) +{ + vram = (int *)ptr; +} + + + +//--- +// Global drawing functions. +//--- + +/* + dupdate() + Displays the vram on the physical screen. +*/ +void dupdate(void) +{ + screen_display((const void *)local_vram); +} + +/* + dclear() + Clears the whole vram. +*/ +void dclear(void) +{ + int i; + for(i = 0; i < 256; i++) vram[i] = 0; +} + +/* + dclear_area() + Clears an area of the vram using rectangle masks. + + @arg x1 + @arg y1 + @arg x2 + @arg y2 +*/ +void dclear_area(int x1, int y1, int x2, int y2) +{ + unsigned int masks[4]; + adjust(&x1, &y1, &x2, &y2); + getmasks(x1, x2, masks); + + int offset = y1 << 2; + int end = (y2 + 1) << 2; + int i; + + for(i = 0; i < 4; i++) masks[i] = ~masks[i]; + while(offset < end) vram[offset] &= masks[offset & 3], offset++; +} + +/* + dreverse_area() + Reverses an area of the vram. This function is a simple application of + the rectangle masks concept. + + @arg x1 + @arg y1 + @arg x2 + @arg y2 +*/ +void dreverse_area(int x1, int y1, int x2, int y2) +{ + unsigned int masks[4]; + adjust(&x1, &y1, &x2, &y2); + getmasks(x1, x2, masks); + + int offset = y1 << 2; + int end = (y2 + 1) << 2; + + while(offset < end) vram[offset] ^= masks[offset & 3], offset++; +} + + + +//--- +// Local drawing functions. +//--- + +/* + dpixel() + Puts a pixel on the screen. + + @arg x + @arg y + @arg color +*/ +void dpixel(int x, int y, enum Color color) +{ + if((unsigned int)x > 127 || (unsigned int)y > 63) return; + int offset = (y << 2) + (x >> 5); + int mask = 0x80000000 >> (x & 31); + + switch(color) + { + case Color_White: + vram[offset] &= ~mask; + break; + + case Color_Black: + vram[offset] |= mask; + break; + + case Color_None: + return; + + case Color_Invert: + vram[offset] ^= mask; + break; + } +} + +/* + dline() + Draws a line on the screen. Automatically optimizes horizontal and + vertical lines. + + @arg x1 + @arg y1 + @arg x2 + @arg y2 + @arg color +*/ + +static void dhline(int x1, int x2, int y, enum Color color) +{ + unsigned int masks[4]; + int offset = y << 2; + int i; + + getmasks(x1, x2, masks); + + switch(color) + { + case Color_White: + for(i = 0; i < 4; i++) vram[offset + i] &= ~masks[i]; + break; + + case Color_Black: + for(i = 0; i < 4; i++) vram[offset + i] |= masks[i]; + break; + + case Color_None: + return; + + case Color_Invert: + for(i = 0; i < 4; i++) vram[offset + i] ^= masks[i]; + break; + } +} + +static void dvline(int y1, int y2, int x, enum Color color) +{ + int offset = (y1 << 2) + (x >> 5); + int end = (y2 << 2) + (x >> 5); + int mask = 0x80000000 >> (x & 31); + + switch(color) + { + case Color_White: + while(offset <= end) vram[offset] &= ~mask, offset += 4; + break; + + case Color_Black: + while(offset <= end) vram[offset] |= mask, offset += 4; + break; + + case Color_None: + return; + + case Color_Invert: + while(offset <= end) vram[offset] ^= mask, offset += 4; + break; + } +} + +void dline(int x1, int y1, int x2, int y2, enum Color color) +{ + adjust(&x1, &y1, &x2, &y2); + + // Possible optimizations. + if(y1 == y2) + { + dhline(x1, x2, y1, color); + return; + } + if(x1 == x2) + { + dvline(y1, y2, x1, color); + return; + } + + int i, x = x1, y = y1, cumul; + int dx = x2 - x1, dy = y2 - y1; + int sx = sgn(dx), sy = sgn(dy); + + dx = abs(dx), dy = abs(dy); + + dpixel(x1, y1, color); + + if(dx >= dy) + { + cumul = dx >> 1; + for(i = 1; i < dx; i++) + { + x += sx; + cumul += dy; + if(cumul > dx) cumul -= dx, y += sy; + dpixel(x, y, color); + } + } + else + { + cumul = dy >> 1; + for(i = 1; i < dy; i++) + { + y += sy; + cumul += dx; + if(cumul > dy) cumul -= dy, x += sx; + dpixel(x, y, color); + } + } + + dpixel(x2, y2, color); +} + + + +//--- +// Image drawing. There is only one public function dimage(), but there +// are lots of local methods and optimizations. +// +// Some expressions may look nonsense sometimes. The procedure is always +// the same : get a part of the image in an operator, shift it depending +// on the drawing x-coordinate, compute a mask that indicates which bits +// of the operator contain information, and modify a vram long using the +// operator. +//--- + +/* + bopti_op() + Operates on a vram long. The operator will often not contain 32 bits of + image information. In this case, the bits outside the image must be set + to 0 for Or and Invert operations... 1 for And operations. Which means + that the calling produre must indicate what part of the operator + belongs to the image, which is done through the image_mask argument. + + @arg offset Vram offset where edition is planned. + @arg operator Longword to operate with. + @arg image_mask Part of the operator that is inside the image. + @arg mode Operation mode. +*/ +static void bopti_op(int offset, uint32_t operator, uint32_t image_mask, + enum BlendingMode mode) +{ + if(mode & Blend_Checker) operator &= 0x55555555; + if(mode & Blend_Or) vram[offset] |= operator; + if(mode & Blend_Invert) vram[offset] ^= operator; + operator |= ~image_mask; + if(mode & Blend_And) vram[offset] &= operator; +} + +/* + bopti_grid() -- general form + bopti_grid_a32() -- when x is a multiple of 32 + + Draws a layer, whose width is a multiple of 32, in the vram. + The need for bopti_grid_a32() is not only linked to optimization, + because one of the bit shifts in bopti_grid() will reach 32 when x is + a multiple of 32, which is undefined behavior. + + @arg layer Raw column data (column data is located at the + beginning of layer data). + @arg column_number + @arg width + @arg height + @arg x + @arg y + @arg mode +*/ + +static void bopti_grid_a32(const uint32_t *layer, int column_number, int width, + int height, int x, int y, enum BlendingMode mode) +{ + int vram_column_offset = (y << 2) + (x >> 5); + int vram_offset = vram_column_offset; + + int column, line; + uint32_t operator, and_mask; + uint32_t rightest_and_mask; + + if(width & 31) rightest_and_mask = ~(0xffffffff >> (width & 31)); + else rightest_and_mask = 0xffffffff; + + for(column = 0; column < column_number; column++) + { + for(line = 0; line < height; line++) + { + operator = *layer++; + + and_mask = (column < column_number - 1) ? + (0xffffffff) : (rightest_and_mask); + bopti_op(vram_offset, operator, and_mask, mode); + vram_offset += 4; + } + + vram_column_offset++; + vram_offset = vram_column_offset; + } +} + +static void bopti_grid(const uint32_t *layer, int column_number, int width, + int height, int x, int y, enum BlendingMode mode) +{ + const uint32_t *p1, *p2; + uint32_t l1, l2; + int right_column, line; + + int vram_column_offset = (y << 2) + (x >> 5); + int vram_offset = vram_column_offset; + + int shift1 = 32 - (x & 31); + int shift2 = (x & 31); + int combined_shift_last = shift1 + 32 - (width & 31); + + uint32_t operator, and_mask; + uint32_t and_mask_0 = 0xffffffff >> shift2; + uint32_t and_mask_1 = (0xffffffff) << combined_shift_last; + + if(!column_number) return; + if(!(x & 31)) + { + bopti_grid_a32(layer, column_number, width, height, x, y, + mode); + return; + } + + // Initializing two pointers. Since the columns are written one after + // another, they will be updated directly to parse the whole grid. + p1 = layer - height; + p2 = layer; + + // Drawing vram longwords, using pairs of columns. + for(right_column = 0; right_column <= column_number; right_column++) + { + for(line = 0; line < height; line++) + { + l1 = (right_column > 0) ? (*p1) : (0); + l2 = (right_column < column_number) ? (*p2) : (0); + p1++, p2++; + + operator = (l1 << shift1) | (l2 >> shift2); + + and_mask = 0xffffffff; + if(!right_column) and_mask &= and_mask_0; + if(right_column == column_number) + and_mask &= and_mask_1; + + bopti_op(vram_offset, operator, and_mask, mode); + vram_offset += 4; + } + + vram_column_offset++; + vram_offset = vram_column_offset; + } +} + +/* + bopti_rest8() -- general form, width below 8 + bopti_rest8_nover() -- when the rest does not meet two longs + bopti_rest16() -- general form, width below 16 + bopti_rest16_nover() -- when the rest does not meet two longs + + Draw rests of row size of 8 and 16 bits, respectively. + + @arg rest Rest data, located at the end of the layer data. + @arh width + @arg height + @arg x + @arg y + @arg mode +*/ + +static void bopti_rest8_nover(const uint8_t *rest, int width, int height, + int x, int y, enum BlendingMode mode) +{ + int vram_offset = (y << 2) + (x >> 5); + int shift = x & 31; + + uint32_t operator; + uint32_t and_mask = ~(0xffffffff >> width) >> shift; + int line; + + for(line = 0; line < height; line++) + { + operator = *rest++; + // Optimization possible ? Probably not. + operator <<= 24; + operator >>= shift; + + bopti_op(vram_offset, operator, and_mask, mode); + vram_offset += 4; + } +} + +static void bopti_rest8(const uint8_t *rest, int width, int height, int x, + int y, enum BlendingMode mode) +{ + if((x & 31) + width < 32) + { + bopti_rest8_nover(rest, width, height, x, y, mode); + return; + } + + int vram_offset = (y << 2) + (x >> 5); + int shift1 = (x & 31) - 24; + int shift2 = 56 - (x & 31); + uint32_t and_mask_1 = 0xffffffff >> (x & 31); + uint32_t and_mask_2 = ~(0xffffffff >> ((x & 31) + width - 32)); + + uint32_t operator; + int line; + + for(line = 0; line < height; line++) + { + operator = *rest++; + + bopti_op(vram_offset, operator >> shift1, and_mask_1, mode); + bopti_op(vram_offset + 1, operator << shift2, and_mask_2, + mode); + vram_offset += 4; + } +} + +static void bopti_rest16_nover(const uint16_t *rest, int width, int height, + int x, int y, enum BlendingMode mode) +{ + int vram_offset = (y << 2) + (x >> 5); + int shift = x & 31; + + uint32_t operator; + uint32_t and_mask = ~(0xffffffff >> width) >> shift; + int line; + + for(line = 0; line < height; line++) + { + operator = *rest++; + // As far as I know, no, we can't optimize this into a single + // shift. + operator <<= 16; + operator >>= shift; + + bopti_op(vram_offset, operator, and_mask, mode); + vram_offset += 4; + } +} + +static void bopti_rest16(const uint16_t *rest, int width, int height, int x, + int y, enum BlendingMode mode) +{ + if((x & 31) + width < 32) + { + bopti_rest16_nover(rest, width, height, x, y, mode); + return; + } + + int vram_offset = (y << 2) + (x >> 5); + int shift1 = (x & 31) - 16; + int shift2 = 48 - (x & 31); + uint32_t and_mask_1 = 0xffffffff >> (x & 31); + uint32_t and_mask_2 = ~(0xffffffff >> ((x & 31) + width - 32)); + + uint32_t operator; + int line; + + for(line = 0; line < height; line++) + { + operator = *rest++; + + bopti_op(vram_offset, operator >> shift1, and_mask_1, mode); + bopti_op(vram_offset + 1, operator << shift2, and_mask_2, + mode); + vram_offset += 4; + } +} + +/* + bopti() + Draws an image layer in the video ram. + + @arg bitmap Raw layer data. + @arg x + @arg y + @arg width + @arg height + @arg mode +*/ +void bopti(const unsigned char *layer, int x, int y, int width, int height, + enum BlendingMode mode) +{ + int column_number = width >> 5; + int rest_width = width & 31; + int grid_width = width & ~31; + + if(rest_width > 16) + { + column_number++; + rest_width = 0; + grid_width = width; + } + + const unsigned char *rest = layer + ((column_number * height) << 2); + int rest_x = x + (width - rest_width); + + bopti_grid((const uint32_t *)layer, column_number, grid_width, height, + x, y, mode); + if(!rest_width) return; + + if(rest_width <= 8) + bopti_rest8((const uint8_t *)rest, rest_width, height, rest_x, + y, mode); + else + bopti_rest16((const uint16_t *)rest, rest_width, height, + rest_x, y, mode); +} + +/* + dimage() + Displays an image in the vram. + + @arg image + @arg x + @arg y + @arg mode +*/ + +void dimage(struct Image *image, int x, int y, enum BlendingMode mode) +{ + int width = image->width; + int height = image->height; + const unsigned char *data = (const unsigned char *)&(image->data); + + // Computing the layer size. + int columns = image->width >> 5; + int rest = image->width & 31; + int rest_size = + !rest ? 0 : + rest <= 8 ? 1 : + rest <= 16 ? 2 : + 4; + int layer_size = ((columns << 2) + rest_size) * image->height; + // The layer size must be a multiple of 4. + if(layer_size & 3) layer_size += 4 - (layer_size & 3); + + switch(image->format & ImageFormat_ColorMask) + { + case ImageFormat_Mono: + if(image->format & ImageFormat_Alpha) + { + bopti(data + layer_size, x, y, width, height, + Blend_And); + } + bopti(data, x, y, width, height, mode); + break; + + case ImageFormat_Gray: + if(image->format & ImageFormat_Alpha) + { + bopti(data + 2 * layer_size, x, y, width, height, + Blend_And); + } + + display_useVRAM(gray_darkVRAM()); + bopti(data, x, y, width, height, mode); + display_useVRAM(gray_lightVRAM()); + bopti(data + layer_size, x, y, width, height, mode); + break; + } +} diff --git a/src/gint.c b/src/gint.c new file mode 100644 index 0000000..19198c9 --- /dev/null +++ b/src/gint.c @@ -0,0 +1,107 @@ +#include +#include +#include + +//--- +// Local variables. +//--- + +static unsigned int + new_vbr, + sys_vbr; + + + +//--- +// Local functions. +//--- + +/* + gint_setup() + Configures interrupt priorities and some parameters to allow gint to + take control of the interrupt flow. +*/ +static void gint_setup(void) +{ + if(isSH3()) + gint_setup_7705(); + else + gint_setup_7305(); +} + +/* + gint_stop() + Un-configures the interrupt flow to give back the interrupt control to + the system. +*/ +static void gint_stop(void) +{ + if(isSH3()) + gint_stop_7705(); + else + gint_stop_7305(); +} + + + +//--- +// Public API. +//--- + +/* + gint_systemVBR() + Returns the vbr address used by the system (saved when execution + starts). + + @return vbr address used by the system. +*/ +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 + the new vbr address. +*/ +void gint_init(void) +{ + // Linker script symbols -- gint. + extern unsigned int + gint_vbr, + gint_data, + bgint, egint; + + unsigned int *ptr = &bgint; + unsigned int *src = &gint_data; + + // Loading the interrupt handler into the memory. + while(ptr < &egint) *ptr++ = *src++; + + sys_vbr = gint_getVBR(); + new_vbr = (unsigned int)&gint_vbr; + + gint_setVBR(new_vbr, gint_setup); +} + +/* + gint_quit() + Stops gint. Restores the system's configuration and vbr address. +*/ +void gint_quit(void) +{ + gint_setVBR(sys_vbr, gint_stop); +} diff --git a/src/gint_7305.c b/src/gint_7305.c new file mode 100644 index 0000000..0947749 --- /dev/null +++ b/src/gint_7305.c @@ -0,0 +1,292 @@ +#include +#include <7305.h> + +extern void print_hex(unsigned int value, int x, int y); +extern void print_bin(unsigned char value, int x, int y); + + + +//--- +// Interrupt codes. +//--- + +#define IC_RTC_PRI 0xaa0 +#define IC_KEYSC 0xbe0 + + + +//--- +// Keyboard management. +//--- + +extern volatile unsigned char keyboard_state[10]; +extern void keyboard_interrupt(void); + +/* + kdelay() + Should sleep during a few milliseconds. Well... + This delay has a great influence on key detection. Here are a few + observations of what happens with common numbers of "nop" (without + overclock). Take care of the effect of overclock ! + + Column effects + May have something to do with register HIZCRB not being used here. When + many keys on the same column are pressed, other keys of the same column + may be triggered. + + - Less Bad key detection. + - 8 Very few column effects. Most often, three keys may be pressed + simultaneously. However, [UP] has latencies and is globally not + detected. + - 12 Seems best. Every individual key is detected well. No column + effect observed before four keys. + - 16 Every single key is detected correctly. Pressing two keys on a + same column does not usually create a column effect. Three keys + almost always. + - More Does not improve single key detection, and increase column + effects. At 256 every single key press create a whole column + effect. +*/ +static void kdelay(void) +{ + #define r4(str) str str str str + + __asm__ + ( + r4("nop\n\t") + r4("nop\n\t") + r4("nop\n\t") + ); + + #undef r4 +} + +/* + krow() + Reads a keyboard row. Works like krow() for SH7705. See gint_7705.c for + more details. + + @arg row Row to check (0 <= row <= 9). + @return Bit-based representation of pressed keys in the checked row. +*/ +static int krow(int row) +{ + volatile unsigned short *injector1 = (unsigned short *)0xa4050116; + volatile unsigned char *data1 = (unsigned char *)0xa4050136; + + volatile unsigned short *injector2 = (unsigned short *)0xa4050118; + volatile unsigned char *data2 = (unsigned char *)0xa4050138; + + volatile unsigned short *detector = (unsigned short *)0xa405014c; + volatile unsigned char *keys = (unsigned char *)0xa405016c; + + volatile unsigned char *key_register = (unsigned char *)0xa40501c6; +// volatile unsigned short *hizcrb = (unsigned short *)0xa405015a; + + unsigned short smask; + unsigned char cmask; + int result = 0; + + if(row < 0 || row > 9) return 0; + + // Additional configuration for SH7305. + *detector = 0xaaaa; + *key_register = 0xff; + *injector1 = (*injector1 & 0xf000) | 0x0555; + *injector2 = (*injector2 & 0xf000) | 0x0555; + *data1 |= 0x3f; + *data2 |= 0x3f; + kdelay(); + + if(row < 6) + { + smask = 0x0003 << (row * 2); + cmask = ~(1 << row); + + *injector1 = ((*injector1 & 0xf000) | 0x0aaa) ^ smask; + *injector2 = (*injector2 & 0xf000) | 0x0aaa; + kdelay(); + + *data1 = (*data1 & 0xc0) | cmask; + *data2 |= 0x3f; + kdelay(); + } + else + { + smask = 0x0003 << ((row - 6) * 2); + cmask = ~(1 << (row - 6)); + + *injector1 = (*injector1 & 0xf000) | 0x0aaa; + *injector2 = ((*injector2 & 0xf000) | 0x0aaa) ^ smask; + kdelay(); + + *data1 |= 0x3f; + *data2 = (*data2 & 0xc0) | cmask; + kdelay(); + } + + // Reading the keyboard row. + result = ~*keys; + kdelay(); + + // Re-initializing the port configuration and data. + *injector1 = (*injector1 & 0xf000) | 0x0aaa; + *injector2 = (*injector2 & 0xf000) | 0x0aaa; + kdelay(); + *injector1 = (*injector1 & 0xf000) | 0x0555; + *injector2 = (*injector2 & 0xf000) | 0x0555; + kdelay(); + *data1 &= 0xc0; + *data2 &= 0xc0; + + return result; +} + +/* + kstate() + Updates the keyboard state. +*/ +static void kstate(void) +{ + int i; + + for(i = 0; i < 10; i++) keyboard_state[i] = krow(i); + + keyboard_interrupt(); +} + + + +//--- +// Interrupt handler. +//--- + +void gint_7305(void) +{ + volatile unsigned int *intevt = (unsigned int *)0xff000028; + unsigned int code = *intevt; + + switch(code) + { + case IC_RTC_PRI: + // Clearing the interrupt flag. + RTC.RCR2.PEF = 0; + // Updating the keyboard state. + kstate(); +/* + print_bin(keyboard_state[0], 0, 2); + print_bin(keyboard_state[1], 0, 3); + print_bin(keyboard_state[2], 0, 4); + print_bin(keyboard_state[3], 0, 5); + print_bin(keyboard_state[4], 0, 6); + + print_bin(keyboard_state[5], 9, 2); + print_bin(keyboard_state[6], 9, 3); + print_bin(keyboard_state[7], 9, 4); + print_bin(keyboard_state[8], 9, 5); + print_bin(keyboard_state[9], 9, 6); +*/ + break; + } +} + + + +//--- +// Setup. +//--- + +static unsigned short ipr[12]; +static unsigned char rcr2; +// Saves of the keyboard registres. Could be better. +static unsigned short inj1, inj2, det; +static unsigned char data1, data2, keys, reg; + +static void gint_priority_lock_7305(void) +{ + // Saving the current interrupt priorities. + ipr[0] = INTX.IPRA.WORD; + ipr[1] = INTX.IPRB.WORD; + ipr[2] = INTX.IPRC.WORD; + ipr[3] = INTX.IPRD.WORD; + ipr[4] = INTX.IPRE.WORD; + ipr[5] = INTX.IPRF.WORD; + ipr[6] = INTX.IPRG.WORD; + ipr[7] = INTX.IPRH.WORD; + ipr[8] = INTX.IPRI.WORD; + ipr[9] = INTX.IPRJ.WORD; + ipr[10] = INTX.IPRK.WORD; + ipr[11] = INTX.IPRL.WORD; + + // Disabling everything by default to avoid freezing on unhandled + // interrupts. + INTX.IPRA.WORD = 0x0000; + INTX.IPRB.WORD = 0x0000; + INTX.IPRC.WORD = 0x0000; + INTX.IPRD.WORD = 0x0000; + INTX.IPRE.WORD = 0x0000; + INTX.IPRF.WORD = 0x0000; + INTX.IPRG.WORD = 0x0000; + INTX.IPRH.WORD = 0x0000; + INTX.IPRI.WORD = 0x0000; + INTX.IPRJ.WORD = 0x0000; + INTX.IPRK.WORD = 0x0000; + INTX.IPRL.WORD = 0x0000; + + // Saving keyboard registers. + inj1 = *((volatile unsigned short *)0xa4050116); + data1 = *((volatile unsigned char *)0xa4050136); + inj2 = *((volatile unsigned short *)0xa4050118); + data2 = *((volatile unsigned char *)0xa4050138); + det = *((volatile unsigned short *)0xa405014c); + keys = *((volatile unsigned char *)0xa405016c); + reg = *((volatile unsigned char *)0xa40501c6); + + // Allowing RTC. Keyboard analysis is done regularly using a RTC + // because SH7305's special KEYSC interface does not allow us to clear + // the keyboard interrupt flags. + INTX.IPRK._RTC = GINT_INTP_RTC; +} + +static void gint_priority_unlock_7305(void) +{ + // Restoring the interrupt priorities. + INTX.IPRA.WORD = ipr[0]; + INTX.IPRB.WORD = ipr[1]; + INTX.IPRC.WORD = ipr[2]; + INTX.IPRD.WORD = ipr[3]; + INTX.IPRE.WORD = ipr[4]; + INTX.IPRF.WORD = ipr[5]; + INTX.IPRG.WORD = ipr[6]; + INTX.IPRH.WORD = ipr[7]; + INTX.IPRI.WORD = ipr[8]; + INTX.IPRJ.WORD = ipr[9]; + INTX.IPRK.WORD = ipr[10]; + INTX.IPRL.WORD = ipr[11]; + + // Restoring keyboard registers. + *((volatile unsigned short *)0xa4050116) = inj1; + *((volatile unsigned char *)0xa4050136) = data1; + *((volatile unsigned short *)0xa4050118) = inj2; + *((volatile unsigned char *)0xa4050138) = data2; + *((volatile unsigned short *)0xa405014c) = det; + *((volatile unsigned char *)0xa405016c) = keys; + *((volatile unsigned char *)0xa40501c6) = reg; +} + +void gint_setup_7305(void) +{ + gint_priority_lock_7305(); + + // Configuring the RTC to have a 16-Hz keyboard. + rcr2 = RTC.RCR2.BYTE; + RTC.RCR2.BYTE = 0x39; +} + +void gint_stop_7305(void) +{ + gint_priority_unlock_7305(); + + // Stopping the RTC interrupt. + RTC.RCR2.BYTE = rcr2; +} diff --git a/src/gint_7705.c b/src/gint_7705.c new file mode 100644 index 0000000..02ff8b2 --- /dev/null +++ b/src/gint_7705.c @@ -0,0 +1,244 @@ +#include +#include <7705.h> + +extern void print_hex(unsigned int value, int x, int y); +extern void print_bin(unsigned char value, int x, int y); + + + +//--- +// Interrupt codes. +//--- + +#define IC_RTC_PRI 0x4a0 +#define IC_PINT07 0x700 + + + +//--- +// Keyboard management. +//--- + +extern volatile unsigned char keyboard_state[10]; +extern void keyboard_interrupt(void); + +/* + kdelay() + Low-level sleep using the watchdog. +*/ +static void kdelay(void) +{ + #define r4(str) str str str str + + __asm__ + ( + r4("nop\n\t") + r4("nop\n\t") + r4("nop\n\t") + ); + + #undef r4 + +/* + const int delay = 0xf4; + + // Disabling the watchdog timer interrupt and resetting the + // configuration. Setting the delay. + INTC.IPRB.BIT._WDT = 0; + WDT.WTCSR.WRITE = 0xa500; + WDT.WTCNT.WRITE = 0x5a00 | (delay & 0xff); + + // Counting on Po/256. + WDT.WTCSR.WRITE = 0xa505; + // Starting the timer (sets again to Po/256). + WDT.WTCSR.WRITE = 0xa585; + + // Waiting until it overflows (delaying), then clearing the overflow + // flag. + while((WDT.WTCSR.READ.BYTE & 0x08) == 0); + WDT.WTCSR.WRITE = 0xa500 | (WDT.WTCSR.READ.BYTE & 0xf7); + + // Resetting the configuration and the counter. + WDT.WTCSR.WRITE = 0xa500; + WDT.WTCSR.WRITE = 0x5a00; + + // Enabling back the watchdog timer interrupt. + INTC.IPRB.BIT._WDT = GINT_INTP_WDT; +*/ +} + +/* + krow() + Reads a keyboard row. + + @arg row Row to check (0 <= row <= 9). + @return Bit-based representation of pressed keys in the checked row. +*/ +static int krow(int row) +{ + // '11' on the active row, '00' everywhere else. + unsigned short smask = 0x0003 << ((row % 8) * 2); + // '0' on the active row, '1' everywhere else. + unsigned char cmask = ~(1 << (row % 8)); + // Line results. + int result = 0; + + if(row < 0 || row > 9) return 0; + + // Initial configuration. + PFC.PBCR.WORD = 0xaaaa; + PFC.PMCR.WORD = (PFC.PMCR.WORD & 0xff00) | 0x0055; + kdelay(); + + if(row < 8) + { + // Configuring port B/M as input except for the row to check, + // which has to be an output. This sets '01' (output) on the + // active row, '10' (input) everywhere else. + PFC.PBCR.WORD = 0xaaaa ^ smask; + PFC.PMCR.WORD = (PFC.PMCR.WORD & 0xff00) | 0x00aa; + kdelay(); + + // Every bit set to 1 except the active row bit. + PB.DR.BYTE = cmask; + PM.DR.BYTE = (PM.DR.BYTE & 0xf0) | 0x0f; + kdelay(); + } + else + { + // The same, but deals with port M. + PFC.PBCR.WORD = 0xaaaa; + PFC.PMCR.WORD = ((PFC.PMCR.WORD & 0xff00) | 0x00aa) ^ smask; + kdelay(); + + PB.DR.BYTE = 0xff; + PM.DR.BYTE = (PM.DR.BYTE & 0xf0) | cmask; + kdelay(); + } + + // Reading the keyboard row. + result = ~PA.DR.BYTE; + kdelay(); + + // Re-initializing the port configuration and data. + PFC.PBCR.WORD = 0xaaaa; + PFC.PMCR.WORD = (PFC.PMCR.WORD & 0xff00) | 0x00aa; + kdelay(); + PFC.PBCR.WORD = 0x5555; + PFC.PMCR.WORD = (PFC.PMCR.WORD & 0xff00) | 0x0055; + kdelay(); + PB.DR.BYTE = 0x00; + PM.DR.BYTE &= 0xf0; + + return result; +} + +/* + kstate() + Updates the keyboard state. +*/ +static void kstate(void) +{ + int i; + + for(i = 0; i < 10; i++) keyboard_state[i] = krow(i); + + keyboard_interrupt(); +} + + + +//--- +// Interrupt handler. +//--- + +void gint_7705(void) +{ + volatile unsigned int *intevt2 = (unsigned int *)0xa4000000; + unsigned int code = *intevt2; + + switch(code) + { + case IC_RTC_PRI: + // Clearing the interrupt flag. + RTC.RCR2.BIT.PEF = 0; + // Updating the keyboard state. + kstate(); +/* + print_bin(keyboard_state[0], 0, 2); + print_bin(keyboard_state[1], 0, 3); + print_bin(keyboard_state[2], 0, 4); + print_bin(keyboard_state[3], 0, 5); + print_bin(keyboard_state[4], 0, 6); + + print_bin(keyboard_state[5], 9, 2); + print_bin(keyboard_state[6], 9, 3); + print_bin(keyboard_state[7], 9, 4); + print_bin(keyboard_state[8], 9, 5); + print_bin(keyboard_state[9], 9, 6); +*/ + break; + } +} + + + +//--- +// Setup. +//--- + +static unsigned short iprs[8]; + +static void gint_priority_lock_7705(void) +{ + // Saving the interrupt masks from registers IPRA to IPRH. + iprs[0] = INTC.IPRA.WORD; + iprs[1] = INTC.IPRB.WORD; + iprs[2] = INTX.IPRC.WORD; + iprs[3] = INTX.IPRD.WORD; + iprs[4] = INTX.IPRE.WORD; + iprs[5] = INTX.IPRF.WORD; + iprs[6] = INTX.IPRG.WORD; + iprs[7] = INTX.IPRH.WORD; + + // Disabling everything by default to avoid receiving an interrupt that + // the handler doesn't handle, which would cause the user program to + // freeze. + INTC.IPRA.WORD = 0x0000; + INTC.IPRB.WORD = 0x0000; + INTX.IPRC.WORD = 0x0000; + INTX.IPRD.WORD = 0x0000; + INTX.IPRE.WORD = 0x0000; + INTX.IPRF.WORD = 0x0000; + INTX.IPRG.WORD = 0x0000; + INTX.IPRH.WORD = 0x0000; + + // Allowing RTC, which handles keyboard. + INTC.IPRA.BIT._RTC = GINT_INTP_RTC; +} + +static void gint_priority_unlock_7705(void) +{ + // Restoring the saved states. + INTC.IPRA.WORD = iprs[0]; + INTC.IPRB.WORD = iprs[1]; + INTX.IPRC.WORD = iprs[2]; + INTX.IPRD.WORD = iprs[3]; + INTX.IPRE.WORD = iprs[4]; + INTX.IPRF.WORD = iprs[5]; + INTX.IPRG.WORD = iprs[6]; + INTX.IPRH.WORD = iprs[7]; +} + +void gint_setup_7705(void) +{ + gint_priority_lock_7705(); + + // Configuring the RTC to have a 16-Hz keyboard. + RTC.RCR2.BYTE = 0x39; +} + +void gint_stop_7705(void) +{ + gint_priority_unlock_7705(); +} diff --git a/src/gint_vbr.s b/src/gint_vbr.s new file mode 100644 index 0000000..92a8a29 --- /dev/null +++ b/src/gint_vbr.s @@ -0,0 +1,71 @@ +/* + gint_vbr + + Some of the work, especially related to setting and un-setting the vbr + address needs to be done in assembler. +*/ + + .global _gint_getVBR + .global _gint_setVBR + + + +/* + gint_getVBR() + Returns the current vbr address. + + @return vbr address currently in use. +*/ +_gint_getVBR: + rts + stc vbr, r0 + + + +/* + gint_setVBR() + + This is quite the hard part when modifying the vbr. We need to set + immediately the interrupt priorities of our own handler, or restore + the ones used by the system ; otherwise we may receive interrupts + requests that the new handler doesn't handle, which will cause the + whole program to freeze. + + Therefore, we must set vbr *and* change interrupt priorities while + having disabled all the interrupts in the status register. That's why + this function takes as parameter the priority management function. + + @arg New vbr address. + @arg Priority management function. +*/ +_gint_setVBR: + sts.l pr, @-r15 + + /* Blocking all interrupts. */ + mov.l sr_block, r0 + stc sr, r3 + or r0, r3 + ldc r3, sr + + /* Setting the vbr address. */ + ldc r4, vbr + + /* Calling the priority manager. */ + jsr @r5 + nop + + /* Activating interrupts again. */ + mov.l sr_block, r0 + not r0, r0 + stc sr, r3 + and r0, r3 + ldc r3, sr + + lds.l @r15+, pr + rts + nop + + .align 4 + +sr_block: + .long (1 << 28) diff --git a/src/gray.c b/src/gray.c new file mode 100644 index 0000000..53bcb56 --- /dev/null +++ b/src/gray.c @@ -0,0 +1,76 @@ +#include +#include +#include + +static int internal_vrams[3][256]; +const void *vrams[4]; + +static int current = 0; + +/* + gray_start() + Starts the gray engine. The control of the screen is transferred to the + gray engine. +*/ +void gray_start(void) +{ +} + +/* + gray_stop() + Stops the gray engine. The monochrome display system takes control of + the video ram. +*/ +void gray_stop(void) +{ + display_useVRAM(display_getLocalVRAM()); +} + +/* + gray_lightVRAM() + Returns the module's gray vram address. +*/ +void *gray_lightVRAM(void) +{ + return (void *)vrams[current]; +} + +/* + gray_lightVRAM() + Returns the module's dark vram address. +*/ +void *gray_darkVRAM(void) +{ + return (void *)vrams[current + 1]; +} + +/* + gray_swap() + Swaps the vram buffers. +*/ +void gray_swap(void) +{ + current = (current + 2) & 3; +} + +/* + gray_interrupt() + Answers a timer interrupt. Swaps the two buffers. +*/ +void gray_interrupt(void) +{ + screen_display(vrams[current]); + current ^= 1; +} + +/* + gray_init() + Initializes the gray engine. +*/ +void gray_init(void) +{ + vrams[0] = (const void *)display_getLocalVRAM(); + vrams[1] = (const void *)internal_vrams[0]; + vrams[2] = (const void *)internal_vrams[1]; + vrams[3] = (const void *)internal_vrams[2]; +} diff --git a/src/keyboard.c b/src/keyboard.c new file mode 100644 index 0000000..8b3985a --- /dev/null +++ b/src/keyboard.c @@ -0,0 +1,444 @@ +#include +#include + +//--- +// Keyboard variables. +//--- + +volatile unsigned char keyboard_state[10] = { 0 }; +static int repeat_first = 10, repeat_next = 2; +static int last_key = KEY_NONE, last_repeats = 0, last_events = 0; +static volatile int interrupt_flag = 0; + + + +//--- +// Auxiliary functions. +//--- + +/* + sleep() + Puts the CPU in sleep mode and waits for an interrupt to return. +*/ +void sleep(void) +{ + __asm__ + ( + "sleep\n\t" + ); +} + +/* + getPressedKey() + Finds a pressed key in the keyboard state and returns it. + + @return A pressed key. +*/ +int getPressedKey(void) +{ + int row = 1, column = 0; + int state; + if(keyboard_state[0] & 1) return KEY_AC_ON; + + while(row <= 9 && !keyboard_state[row]) row++; + if(row > 9) return KEY_NONE; + + state = keyboard_state[row]; + while(!(state & 1)) + { + state >>= 1; + column++; + } + + return (column << 4) | row; +} + +/* + getPressedKeys() + Find 'count' pressed keys in the keyboard state. + + @arg keys Will be filled. + @arg count Size of array. + + @return Number of actual pressed keys found. +*/ +int getPressedKeys(int *keys, int count) +{ + int row = 1, column; + int found = 0, actually_pressed; + int state; + if(count <= 0) return 0; + + if(keyboard_state[0] & 1) + { + keys[found++] = KEY_AC_ON; + count--; + } + + while(count && row <= 9) + { + while(row <= 9 && !keyboard_state[row]) row++; + if(row > 9) break; + + state = keyboard_state[row]; + column = 0; + + while(count && column < 8) + { + if(state & 1) + { + keys[found++] = (column << 4) | row; + count--; + } + + state >>= 1; + column++; + } + + row++; + } + + actually_pressed = found; + + while(count) + { + keys[found++] = KEY_NONE; + count--; + } + + return actually_pressed; +} + +/* + keyboard_interrupt() + Callback for keyboard update. Allows keyboard analysis functions to + wake only when RTC interrupts happen. +*/ +void keyboard_interrupt(void) +{ + interrupt_flag = 1; +} + + + +//--- +// Keyboard configuration. +//--- + +/* + keyboard_setFrequency() + Sets the keyboard frequency. Does nothing when the argument is not a + valid KeyboardFrequency value. + + @arg frequency +*/ +void keyboard_setFrequency(enum KeyboardFrequency frequency) +{ + volatile unsigned char *rcr2; + + if(frequency < 1 || frequency > 7) return; + rcr2 = (unsigned char *)(isSH3() ? 0xfffffede : 0xa413fede); + + frequency <<= 4; + *rcr2 = (*rcr2 & 0x8f) | frequency; +} + +/* + keyboard_setRepeatRate() + Sets the default repeat rate for key events. The unit for the argument + is the keyboard period. + For example at 16 Hz, values of (10, 2) will imitate the system + default. + + @arg first Delay before first repeat, in keyboard period units. + @arg next Delay before following repeats, in keyboard period + units. +*/ +void keyboard_setRepeatRate(int first, int next) +{ + if(first < 0) first = 0; + if(next < 0) next = 0; + + repeat_first = first; + repeat_next = next; +} + + + +//--- +// Keyboard access. +//--- + +/* + keylast() + Returns the matrix code of the last pressed key. If repeat_count is + non-NULL, it is set to the number of repetitions. + + @arg repeat_count + @return Key matrix code. +*/ +int keylast(int *repeat_count) +{ + if(repeat_count) *repeat_count = last_repeats; + return last_key; +} + + + +/* + getkey() + Blocking function with auto-repeat and SHIFT modifying functionalities. + Roughly reproduces the behavior of the system's GetKey(). + + @return Pressed key matrix code. +*/ +int getkey(void) +{ + return getkey_opt( + Getkey_ShiftModifier | + Getkey_AlphaModifier | + + Getkey_RepeatArrowKeys, + + 0 + ); +} + + + +/* + getkey_opt() + Enhances getkey() with most general functionalities. + If max_cycles is non-zero and positive, getkey_opt() will return + KEY_NOEVENT if no event occurs during max_cycle analysis. + + @arg options OR-combination of GetkeyOpt values. + @arg max_cycles + + @return Pressed key matrix code. +*/ +int getkey_opt(enum GetkeyOpt options, int max_cycles) +{ + int key; + enum KeyType type; + int modifier = 0, last_modifier = KEY_NONE; + int r; + + if(!max_cycles) max_cycles = -1; + + while(max_cycles != 0) + { + while(!interrupt_flag) sleep(); + interrupt_flag = 0; + if(max_cycles > 0) max_cycles--; + + // Getting key and adding modifiers. + key = getPressedKey(); + + // Handling "no_key" event; + if(key == KEY_NONE) + { + // Condition for returning. + r = (last_key != KEY_NONE && + options & Getkey_ReleaseEvent); + + last_key = KEY_NONE; + last_modifier = KEY_NONE; + last_repeats = 0; + last_events = 0; + + if(r) return KEY_NONE; + } + + // Handling "new key" events. + else if(key != last_key) + { + if(options & Getkey_ShiftModifier && key == KEY_SHIFT) + { + if(last_modifier != KEY_SHIFT) + modifier ^= MOD_SHIFT; + last_modifier = KEY_SHIFT; + + continue; + } + if(options & Getkey_AlphaModifier && key == KEY_ALPHA) + { + if(last_modifier != KEY_ALPHA) + modifier ^= MOD_ALPHA; + last_modifier = KEY_ALPHA; + + continue; + } + + last_key = key; + last_repeats = 0; + last_events = 0; + + return key | modifier; + } + + // Handling key repetitions. + else + { + type = keytype(key); + + // Checking whether this key type is repeated. + if(options & (type << 4)) + { + last_events++; + r = last_repeats ? repeat_next : repeat_first; + + if(last_events >= r) + { + last_repeats++; + last_events = 0; + + return key; + } + } + } + } + + // When no key was pressed during the given delay... + return KEY_NOEVENT; +} + +/* + multigetkey() + Listens the keyboard for simultaneous key hits. Uses the same options + as getkey_opt(). + multigetkey() fills the 'keys' array with 'count' key codes, adding + KEY_NOKEY if less than 'count' keys are pressed. + Be aware that rectangle and column effects can make multigetkey() read + unpressed keys as pressed (see documentation for more information). + Setting count = 3 is generally safe. + + @arg keys Key code array. + @arg count Maximum number of keys that will be read. + @arg max_cycles +*/ +void multigetkey(int *keys, int count, int max_cycles) +{ + int number; + + if(!max_cycles) max_cycles = -1; + + while(max_cycles != 0) + { + while(!interrupt_flag) sleep(); + interrupt_flag = 0; + if(max_cycles > 0) max_cycles--; + + number = getPressedKeys(keys, count); + if(number) return; + + // Handle key repetitions. +/* + else + { + type = keytype(key); + + // Checking whether this key type is repeated. + if(options & (type << 4)) + { + last_events++; + r = last_repeats ? repeat_next : repeat_first; + + if(last_events >= r) + { + last_repeats++; + last_events = 0; + + return key; + } + } + } +*/ + } + + // When no key was pressed during the given delay... (no need to fill + // the array, it has already been done by getPressedKeys()). + return; +} + + + +//--- +// Key analysis. +//--- + +/* + keyid() + Returns a non-matrix key code that can be used for array subscript. + Ignores modifiers. + + @arg key + @return Modified keycode. +*/ +int keyid(int key) +{ + if(key < 0) return -1; + key &= MOD_CLEAR; + + int row = 9 - (key & 0x0f); + int column = 6 - ((key & 0xf0) >> 4); + + return 6 * row + column; +} + +/* + keychar() + Returns the ASCII character associated with a key, or 0 for control + keys. + + @arg key +*/ +int keychar(int key) +{ + char flat[] = { + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, '2', '^', 0x0, 0x0, 0x0, + 'X', 'l', 'l', 's', 'c', 't', + 0x0, 0x0, '(', ')', ',', '>', + '7', '8', '9', 0x0, 0x0, 0x0, + '4', '5', '6', '*', '/', 0x0, + '1', '2', '3', '+', '-', 0x0, + '0', '.', 'e', '-', 0x0, 0x0 + }; + char alpha[] = { + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 'r', 'o', 0x0, 0x0, 0x0, + 'A', 'B', 'C', 'D', 'E', 'F', + 'G', 'H', 'I', 'J', 'K', 'L', + 'M', 'N', 'O', 0x0, 0x0, 0x0, + 'P', 'Q', 'R', 'S', 'T', 0x0, + 'U', 'V', 'W', 'X', 'Y', 0x0, + 'Z', ' ', '"', 0x0, 0x0, 0x0 + }; + + int id = keyid(key); + + if(key & MOD_ALPHA) return alpha[id]; + return flat[id]; +} + +/* + keytype() + Returns a key's type. Ignores modifiers. + + @arg key + @return Key type. +*/ +enum KeyType keytype(int key) +{ + key &= MOD_CLEAR; + + if(key == KEY_UP || key == KEY_RIGHT || key == KEY_DOWN || + key == KEY_LEFT) return KeyType_Arrow; + + if((key & 0x0f) == 0x09) return KeyType_Function; + + return keychar(key) ? KeyType_Character : KeyType_Control; +} diff --git a/src/mpu.c b/src/mpu.c new file mode 100644 index 0000000..ccc38d6 --- /dev/null +++ b/src/mpu.c @@ -0,0 +1,75 @@ +#include + +enum MPU MPU_CURRENT; + +/* + getMPU() + + Returns the MPU identifier of the calculator. + Thanks to SimonLothar for this function and related informations. + + Processor version register (PVR) and product control register (PRR) + hold information about the MPU version but are only accessible for + SH-4-based MPUs. + Therefore, this function uses port L control register (PLCR), whose + bits 8 to 15 cannot be set with SH7337 where bits 8 to 11 can be set + with SH7355. + + Additionally, the CPU core ID register (CPIDR) at 0xff000048 returns 1 + on SH7305. + + @return MPU identifier as integer value. +*/ + +enum MPU getMPU(void) +{ + // Processor version register. + volatile unsigned int *pvr = (unsigned int *)0xff000030; + // Product version register. + volatile unsigned int *prr = (unsigned int *)0xff000044; + // Port L control register. + volatile unsigned short *plcr = (unsigned short *)0xa4000114; + // Saved value for PLCR. + unsigned short saved_plcr; + unsigned int tested_plcr; + + + // Looking for SH-3-based MPUs by testing PLCR writing access. + saved_plcr = *plcr; + *plcr = 0xffff; + tested_plcr = *plcr; + *plcr = saved_plcr; + + // Checking whether we are working with an SH7337 or an SH7355. + if(tested_plcr == 0x00ff) return MPU_SH7337; + if(tested_plcr == 0x0fff) return MPU_SH7355; + + // Looking for SH-4-based MPUs by testing the version registers. This + // needs to have the three upper bytes of the processor version + // register match 0x10300b : + if((*pvr & 0xffffff00) != 0x10300b00) return MPU_Unknown; + + // Now that we have an SH-4-based MPU, checking whether it is SH7305 or + // SH7724. + switch(*prr & 0xfffffff0) + { + case 0x00002c00: + return MPU_SH7305; + case 0x00002200: + return MPU_SH7724; + } + + // By default, the MPU is unknown. + return MPU_Unknown; +} + +static void mpu_init(void) + __attribute__(( + section(".pretext"), + constructor + )); + +static void mpu_init(void) +{ + MPU_CURRENT = getMPU(); +} diff --git a/src/screen.c b/src/screen.c new file mode 100644 index 0000000..e3ac5e6 --- /dev/null +++ b/src/screen.c @@ -0,0 +1,51 @@ +/* + screen.c + + This module is in charge of interaction with the physical screen. See + module 'display' for video ram management and drawing. + + The screen basically has two input values, which are a register + selector and the selected register's value. What this module does is + essentially selecting registers by setting *selector and assigning them + values by setting *data. +*/ + +#include + + + +/* + screen_display() + + Displays the given vram on the screen. Only bytes can be transferred + through the screen registers, which is unfortunate because most of the + vram-related operations use longword-base computations. + + @arg vram 1024-byte video buffer. +*/ +void screen_display(const void *ptr) +{ + const char *vram = (const char *)ptr; + volatile char *selector = (char *)0xb4000000; + volatile char *data = (char *)0xb4010000; + int line, bytes; + + for(line = 0; line < 64; line++) + { + // Setting the x-address register. + *selector = 4; + *data = line + 0xc0; + + // Setting Y-Up mode. + *selector = 1; + *data = 1; + + // Setting y-address. + *selector = 4; + *data = 0; + + // Selecting data write register 7 and sending a line's bytes. + *selector = 7; + for(bytes = 0; bytes < 16; bytes++) *data = *vram++; + } +} diff --git a/src/setjmp.s b/src/setjmp.s new file mode 100644 index 0000000..27a070e --- /dev/null +++ b/src/setjmp.s @@ -0,0 +1,82 @@ +/* + This file implements long jumps. An example of their use is with crt0.c + and exit()-family functions that use them to restore the execution + state when leaving the program from an unknown location. + + The register contents are saved in a buffer when setjmp() is called and + restored at any time when longjmp() performs the jump, through an + exit() or abort() call, for instance. + + This is actually a question of playing with pr ; the user program is + resumed after the setjmp() call when longjmp() is invoked but setjmp() + has nothing to do with this operation. longjmp() restores the pr value + that was saved by setjmp() and performs an rts instruction. + + setjmp() returns 0 when called to set up the jump point and a non-zero + value when invoked through a long jump. If 0 is given as return value + to longjmp(), then 1 is returned. +*/ + + .global _setjmp + .global _longjmp + +_setjmp: + /* Getting some free space. */ + add #64, r4 + + /* Saving general-purpose registers. */ + mov.l r15, @-r4 + mov.l r14, @-r4 + mov.l r13, @-r4 + mov.l r12, @-r4 + mov.l r11, @-r4 + mov.l r10, @-r4 + mov.l r9, @-r4 + mov.l r8, @-r4 + + /* Saving control and system registers. */ + stc.l sr, @-r4 + stc.l ssr, @-r4 + stc.l spc, @-r4 + stc.l gbr, @-r4 + stc.l vbr, @-r4 + sts.l mach, @-r4 + sts.l macl, @-r4 + sts.l pr, @-r4 + + /* This function always return 0. The cases where setjmp() seems to + return non-zero values, when a long jump has just been performed, is + actually handled by longjmp(). */ + rts + mov #0, r0 + + + +_longjmp: + /* Restoring the system and control registers. Restoring pr is actually + what performs the jump -- and makes the user program thinks that + setjmp() has returned. */ + lds.l @r4+, pr + lds.l @r4+, macl + lds.l @r4+, mach + ldc.l @r4+, vbr + ldc.l @r4+, gbr + ldc.l @r4+, spc + ldc.l @r4+, ssr + ldc.l @r4+, sr + + /* Restoring the general-purpose registers. */ + mov.l @r4+, r8 + mov.l @r4+, r9 + mov.l @r4+, r10 + mov.l @r4+, r11 + mov.l @r4+, r12 + mov.l @r4+, r13 + mov.l @r4+, r14 + mov.l @r4+, r15 + + /* Preventing return value from being 0 (must be at least 1). */ + tst r5, r5 + movt r0 + rts + add r5, r0 diff --git a/src/string.c b/src/string.c new file mode 100644 index 0000000..6edd334 --- /dev/null +++ b/src/string.c @@ -0,0 +1,134 @@ +#include +#include + +//--- +// Memory manipulation. +//--- + +/* + memcpy() + Copies a memory area. A smart copy is performed if possible. + + @arg destination + @arg source + @arg byte_number +*/ +void *memcpy(void *d, const void *s, size_t n) +{ + uint8_t *dest = (uint8_t *)d; + const uint8_t *src = (const uint8_t *)s; + + // A long-based copy needs the source and destination to be 4-aligned + // at the same time. + if(((intptr_t)dest & 3) == ((intptr_t)src & 3)) + { + // Getting to a long offset. + while((intptr_t)dest & 3) + { + *dest++ = *src++; + n--; + } + + // Copying groups of four bytes. + while(n >= 4) + { + *((uint32_t *)dest) = *((const uint32_t *)src); + + dest += 4, src += 4; + n -= 4; + } + + // Ending the copy. + while(n) + { + *dest++ = *src++; + n--; + } + } + + // Or we could try a word-based copy. + else if(((intptr_t)dest & 1) == ((intptr_t)src & 1)) + { + // Getting to a word offset. + if((intptr_t)dest & 1) + { + *dest++ = *src++; + n--; + } + + // Copying groups of two bytes. + while(n >= 2) + { + *((uint16_t *)dest) = *((const uint16_t *)src); + + dest += 2, src += 2; + n -= 2; + } + + // Ending the copy. + while(n) + { + *dest++ = *src++; + n--; + } + } + + // In some cases we can just perform a raw copy. + else while(n) + { + *dest++ = *src++; + n--; + } + + return d; +} + +/* + memset() + Sets the contents of a memory area. A smart copy is performed. + + @arg area + @arg byte Byte to write in the area. + @arg byte_number +*/ +void *memset(void *d, int byte, size_t byte_number) +{ + uint8_t *dest = (uint8_t *)d; + unsigned short word = (byte << 8) | byte; + unsigned int longword = (word << 16) | word; + + // When the area is small, simply copying using byte operations. The + // minimum length used for long operations must be at least 3. + if(byte_number < 8) + { + while(byte_number) + { + *dest++ = byte; + byte_number--; + } + + return d; + } + + // Reaching a long offset. + while((intptr_t)dest & 3) + { + *dest++ = byte; + byte_number--; + } + // Copying using long operations. + while(byte_number >= 4) + { + *((uint32_t *)dest) = longword; + dest += 4; + byte_number -= 4; + } + // Ending the copy. + while(byte_number) + { + *dest++ = byte; + byte_number--; + } + + return d; +} diff --git a/src/syscalls.s b/src/syscalls.s new file mode 100644 index 0000000..c76d3e3 --- /dev/null +++ b/src/syscalls.s @@ -0,0 +1,37 @@ +/* + This file contains all the system calls used by the library. Maybe one + day we won't need them anymore ? +*/ + + .global ___Hmem_SetMMU + .global ___GLibAddinAplExecutionCheck + .global ___Print + + + +___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 + jmp @r2 + nop + +___Print: + mov.l syscall_table, r2 + mov.l 1f, r0 + jmp @r2 + nop +1: .long 0x15d + + + + .align 4 + +syscall_table: + .long 0x80010070 diff --git a/src/timer.c b/src/timer.c new file mode 100644 index 0000000..f05b1a0 --- /dev/null +++ b/src/timer.c @@ -0,0 +1,162 @@ +#include +#include +#include + +/* + struct Timer + This structure handles a running timer information. +*/ +struct Timer +{ + void (*callback)(void); + int repetitions; +}; + +// Static timers. +static struct Timer timers[3] = { { NULL, 0 }, { NULL, 0 }, { NULL, 0 } }; + +/* + struct mod_tmu + This structure allows access to a timer using its address. +*/ +struct mod_tmu +{ + // Timer constant register. + unsigned int TCOR; + // Timer counter. + unsigned int TCNT; + + // Timer control register. + union + { + unsigned short WORD; + struct + { + unsigned :7; + // Underflow flag. + unsigned UNF :1; + unsigned :2; + // Underflow interrupt enable. + unsigned UNIE :1; + // Clock edge, reserved on SH7305. + unsigned CKEG :2; + // Timer prescaler. + unsigned TPSC :3; + }; + } TCR; +}; + + + +/* + timer_get() + + Returns the timer and TSTR register addresses. + + @arg timer Timer id. + @arg tmu mod_tmu structure pointer address. + @arg tstr mod_tstr structure pointer address. +*/ +void timer_get(int timer, struct mod_tmu **tmu, unsigned char **tstr) +{ + // Using SH7705 information for SH-3-based MPUs. + if(MPU_CURRENT == MPU_SH7337 || MPU_CURRENT == MPU_SH7355) + { + if(tstr) *tstr = (unsigned char *)0xfffffe92; + if(tmu) *tmu = (struct mod_tmu *)0xfffffe94; + } + // Assuming SH7305 by default. + else + { + if(tstr) *tstr = (unsigned char *)0xa4490004; + if(tmu) *tmu = (struct mod_tmu *)0xa4490008; + } + + // Shifting tmu value to get to the timer-nth timer in the unit. + if(tmu) *tmu += timer; +} + +/* + timer_set() + Configures and starts a timer. + + @arg timer Timer identifier. + @arg delay Delay before expiration. + @arg prescaler Clock prescaler value. + @arg callback Callback function. + @arg repetitions Number of repetitions, 0 for infinite. +*/ +void timer_set(int timer, int delay, int prescaler, void (*callback)(void), + int repetitions) +{ + // Getting the timer address. Using a byte to alter TSTR. + struct mod_tmu *tmu; + unsigned char *tstr; + int byte = (1 << timer); + timer_get(timer, &tmu, &tstr); + + // Setting the constant register. + (*tmu).TCOR = delay; + // Loading the delay in the counter. + (*tmu).TCNT = delay; + + // Resetting underflow flag. + (*tmu).TCR.UNF = 0; + // Enabling interruptions on underflow. + (*tmu).TCR.UNIE = 1; + // Counting on rising edge. On SH7305 these two bits are reserved but + // writing 0 is ignored. + (*tmu).TCR.CKEG = 0; + // Setting the prescaler. + (*tmu).TCR.TPSC = prescaler; + + // Loading the structure information. + timers[timer].callback = callback; + timers[timer].repetitions = repetitions; + + // Starting the timer and returning. + *tstr |= byte; +} + +/* + timer_stop() + Stops the given timer. This function may be called even if the timer is + not running. + + @arg timer Timer to stop. +*/ +void timer_stop(int timer) +{ + // Getting TSTR address and the corresponding byte. + unsigned char *tstr; + int byte = (1 << timer); + timer_get(timer, NULL, &tstr); + + // Stopping the timer. + *tstr &= ~byte; +} + +/* + timer_interrupt() + Handles the interrupt for the given timer. + + @timer Timer that generated the interrupt. +*/ +void timer_interrupt(int timer) +{ + // Getting the timer address. + struct mod_tmu *tmu; + timer_get(timer, &tmu, NULL); + + // Resetting the interrupt flag. + (*tmu).TCR.UNF = 0; + + // Calling the callback function. + if(timers[timer].callback) timers[timer].callback(); + + // Reducing the number of repetitions left, if not infinite. + if(!timers[timer].repetitions) return; + // And stopping it if necessary. + if(timers[timer].repetitions == 1) timer_stop(timer); + else timers[timer].repetitions--; +} diff --git a/swords.bmp b/swords.bmp new file mode 100644 index 0000000..695bc8d Binary files /dev/null and b/swords.bmp differ diff --git a/symbol.bmp b/symbol.bmp new file mode 100644 index 0000000..74772f7 Binary files /dev/null and b/symbol.bmp differ diff --git a/symbol2.bmp b/symbol2.bmp new file mode 100644 index 0000000..9493760 Binary files /dev/null and b/symbol2.bmp differ diff --git a/syscall_0x24a.txt b/syscall_0x24a.txt new file mode 100644 index 0000000..a85e926 --- /dev/null +++ b/syscall_0x24a.txt @@ -0,0 +1,190 @@ + +----------------------------------- +Syscall information +----------------------------------- + + Syscall id: 0x24a + Syscall address: 0x8003fc48 + + r4 {short *matrixcode} + + Syscall 0x24a redirects to 8003 f9d6. + + + +----------------------------------- +Stack +----------------------------------- + + ------ Pointer sent at <3f9fe> (also as first parameter) and <3fa12> + (12) Data from a44b 0000 + ------ Pointer sent at <3f9de> + (4) {short *matrixcode} at <3f9fe> + pr + r14 + ------ Bottom + + + +----------------------------------- +Syscall code +----------------------------------- + +# Saves some data. + 3f9d6: 2fe6 mov.l r14, @-r15 + 3f9d8: 4f22 sts.l pr, @-r15 + 3f9da: 7ff0 add #-16, r15 + +# First subroutine call: disables keyboard interrupts. +# Also pushes {short *matrixcode} on the stack. + 3f9dc: d128 mov.l #0x8003e264, r1 + 3f9de: 410b jsr @r1 + 3f9e0: 1f43 mov.l r4, @(12, r15) + +# Loads KEYSC data to the stack. +# Second subroutine call, with parameters : stack top and {short *matrixcode}. +# Checks whether the key given in the matrixcode was pressed. + 3f9e2: d528 mov.l #0xa44b0000, r5 + 3f9e4: 6451 mov.w @r5, r4 + 3f9e6: 2f41 mov.w r4, @r15 + 3f9e8: 64f3 mov r15, r4 + 3f9ea: 8551 mov.w @(2, r5), r0 + 3f9ec: 81f1 mov.w r0, @(2, r15) + 3f9ee: 8552 mov.w @(4, r5), r0 + 3f9f0: 81f2 mov.w r0, @(4, r15) + 3f9f2: 8553 mov.w @(6, r5), r0 + 3f9f4: 81f3 mov.w r0, @(6, r15) + 3f9f6: 8554 mov.w @(8, r5), r0 + 3f9f8: 81f4 mov.w r0, @(8, r15) + 3f9fa: 8555 mov.w @(10, r5), r0 + 3f9fc: 81f5 mov.w r0, @(10, r15) + 3f9fe: bd30 bsr <3f462> + 3fa00: 55f3 mov.l @(12, r15), r5 + +# Loads IPRF address to r6, sets the keyboard interrupt priority to 13 and +# performs a third subroutine call : enables keyboard interrupts (curiously +# the interrupt priority is set two times). +# Also saves the last subroutine result (key pressed) to r14. + 3fa02: d621 mov.l <3fa88>(#0xa4080014), r6 + 3fa04: 9113 mov.w <3fa2e>(#0x0fff), r1 + 3fa06: 9213 mov.w <3fa30>(#0xd000), r2 + 3fa08: 6e03 mov r0, r14 + 3fa0a: 6761 mov.w @r6, r7 + 3fa0c: 2719 and r1, r7 + 3fa0e: 272b or r2, r7 + 3fa10: d212 mov.l #0x8003e26c, r2 + 3fa12: 420b jsr @r2 + 3fa14: 2671 mov.w r7, @r6 + +# Restores the 'key pressed' result to r0, restores saved data and returns. + 3fa16: 60e3 mov r14, r0 + 3fa18: 7f10 add #16, r15 + 3fa1a: 4f26 lds.l @r15+, pr + 3fa1c: 000b rts + 3fa1e: 6ef6 mov.l @r15+, r14 + + + +----------------------------------- +Subroutine call at <3f9de> +- Denies keyboard interrupt in IMR5. +- Disables keyboard interrupt in IPRF. +----------------------------------- + + Call redirects to 8003 e278. + +# Loads IMR5 address to r4. + 3e278: d478 mov.l <3e45c>(#0xa4080094), r4 + 3e27a: e180 mov #-128, r1 + 3e27c: 955b mov.w <3e336>(#0x0fff), r5 +# Writes 0x80 to IMR5. + 3e27e: 2410 mov.b r1, @r4 + +# Loads IPRF address to r4. + 3e280: 7480 add #-128, r4 +# Sets the four upper bits of IPRF to 0. + 3e282: 6241 mov.w @r4, r2 + 3e284: 2259 and r5, r2 + 3e286: 000b rts + 3e288: 2421 mov.w r2, @r4 + + + +----------------------------------- +Subroutine call at <3f9fe> +- Detects whether a specific key is pressed using the KEYSC data loaded onto + the stack. +- Returns 1 if the key is pressed, 0 otherwise. +----------------------------------- + +Stack: + r4 (bottom stack address) + {short *matrixcode} + ------ Bottom stack address. + +# Pushes {short *matrixcode} on the stack and on top, pushes r4. +# Loads the key column to r2 and replaces r5 by #1 (r5 will then be shifted to +# be used as a mask in a KEYSC word). + 3f462: 7ff8 add #-8, r15 + 3f464: 1f51 mov.l r5, @(4, r15) + 3f466: 6250 mov.b @r5, r2 + 3f468: e501 mov #1, r5 + 3f46a: 51f1 mov.l @(4, r15), r1 + 3f46c: 622c extu.b r2, r2 + 3f46e: 2f42 mov.l r4, @r15 + +# Loads the key row to r0. + 3f470: 8411 mov.b @(1, r1), r0 + 3f472: 600c extu.b r0, r0 +# Shifts it right within r6 and tests the row's lower bit. + 3f474: 6603 mov r0, r6 + 3f476: 4621 shar r6 + 3f478: c801 tst #1, r0 + +# Shift r5 by its column number. +# If the row's lower bit was 1, then also shift r5 by 8 (because there are two +# rows for each word). + 3f47a: 8d01 bt/s <3f480> + 3f47c: 452d shld r2, r5 + 3f47e: 4518 shll8 r5 + +# Loads the bottom stack address to r1. + 3f480: 61f2 mov.l @r15, r1 +# Erases the even/odd bit of the row in r6 (because the KEYSC data is read in +# words so we don't want to get on a byte offset, and the lower bit has +# already been handled when shifting r5). + 3f482: 4600 shll r6 + +# Loads the final mask into r2. + 3f484: 625d extu.w r5, r2 + 3f486: 6063 mov r6, r0 +# Tests whether the key represented by the parameter matrixcode is pressed. + 3f488: 041d mov.w @(r0, r1), r4 + 3f48a: 2428 tst r2, r4 +# Returns the KEYSC bit, that is 1 if the key was pressed, 0 otherwise. + 3f48c: 0029 movt r0 + 3f48e: ca01 xor #1, r0 + 3f490: 000b rts + 3f492: 7f08 add #8, r15 + + + +----------------------------------- +Subroutine call at <3fa12> +- Sets the keyboard interrupt priority to 13. +- Clears the keyboard interrupt mask. +----------------------------------- + + Calls redirects to 8003 e28a. + + 3e28a: d475 mov.l #0xa4080014, r4 + 3e28c: 9753 mov.w #0x0fff, r7 + 3e28e: 9253 mov.w #0xd000, r2 + 3e290: e580 mov #-128, r5 + 3e292: 6141 mov.w @r4, r1 + 3e294: 2179 and r7, r1 + 3e296: 212b or r2, r1 + 3e298: 2411 mov.w r1, @r4 + 3e29a: d472 mov.l <3e464>(#0xa40800d4), r4 + 3e29c: 000b rts + 3e29e: 2450 mov.b r5, @r4 diff --git a/syscall_0x24a_7705.txt b/syscall_0x24a_7705.txt new file mode 100644 index 0000000..e1edb3b --- /dev/null +++ b/syscall_0x24a_7705.txt @@ -0,0 +1,558 @@ + +----------------------------------- +Syscall information +----------------------------------- + + Syscall id: 0x24a + Syscall address: 0x8003fa28 + + r4 {short *matrixcode} + + + +----------------------------------- +Stack +----------------------------------- + + #1 + pr + r8 + r9 + r10 + r11 + r12 + r13 + r14 + ------ Bottom + + + +----------------------------------- +Variables +----------------------------------- + + r14 Current row + r13 + r12 + r11 Delay routine address + r10 1 << r14 ? Could be the data register mask. + r9 Current column. + r8 {short *matrixcode} + + + +----------------------------------- +Syscall code +----------------------------------- + +# Saves r8-r14 to the stack. Loads data: +# r13 = 8, r12 = 1, r11 = 8003 e47a, r10 = 1, r9 = 0, r8 = {short *matrixcode}. + 3fa28: 2fe6 mov.l r14, @-r15 + 3fa2a: 2fd6 mov.l r13, @-r15 + 3fa2c: 2fc6 mov.l r12, @-r15 + 3fa2e: ed08 mov #8, r13 + 3fa30: 2fb6 mov.l r11, @-r15 + 3fa32: ec01 mov #1, r12 + 3fa34: 2fa6 mov.l r10, @-r15 + 3fa36: 6ac3 mov r12, r10 + 3fa38: 2f96 mov.l r9, @-r15 + 3fa3a: e900 mov #0, r9 + 3fa3c: db22 mov.l #0x8003e47a, r11 + 3fa3e: 2f86 mov.l r8, @-r15 + 3fa40: 4f22 sts.l pr, @-r15 + 3fa42: 6843 mov r4, r8 + +# r14 = 0, pushes #1 on the stack and branches to <3fb1a>. This branch does +# nothing if r14 is lower than 12 (thus here it does nothing). + 3fa44: 7ffc add #-4, r15 + 3fa46: 2fc2 mov.l r12, @r15 + 3fa48: a067 bra <3fb1a> + 3fa4a: 6e93 mov r9, r14 + +# Sets gbr = a400 0100: area where the port control registers are located. + 3fa4c: d21f mov.l #0xa4000100, r2 + 3fa4e: 421e ldc r2, gbr + +# B_CTRL = h'aaaa + 3fa50: d01f mov.l #0x0000aaaa, r0 + 3fa52: c101 mov.w r0, @(2, gbr) + +# M_CTRL = h'__55 + 3fa54: c50c mov.w @(24, gbr), r0 + 3fa56: d31f mov.l #0x0000ff00, r3 + 3fa58: 2039 and r3, r0 + 3fa5a: cbaa or #0x55, r0 + 3fa5c: c10c mov.w r0, @(24, gbr) + +# Delay. + 3fa5e: 4b0b jsr @r11 + 3fa60: e402 mov #2, r4 + +# Loads 801b e65c as a data segment base. It contains words in this order: +# aaa9 aaa6 aa9a aa6a ... 9aaa 6aaa 00a9 00a6 009a 006a. +# These words are the B_CTRL/M_CTRL values. +# Loads the r14-th word into B_CTRL (r14 <= 8) or the lowest byte of M_CTRL +# (r14 > 8). The row-to-check pin is configured as output, and all the others +# are configured as inputs. + 3fa62: 3ed3 cmp/ge r13, r14 + 3fa64: d41c mov.l #0x801be65c, r4 + 3fa66: 8904 bt <3fa72> + 3fa68: 60e3 mov r14, r0 + 3fa6a: 4000 shll r0 + 3fa6c: 004d mov.w @(r0, r4), r0 + 3fa6e: a009 bra <3fa84> + 3fa70: c101 mov.w r0, @(2, gbr) + 3fa72: 60e3 mov r14, r0 + 3fa74: 4000 shll r0 + 3fa76: 004d mov.w @(r0, r4), r0 + 3fa78: 6203 mov r0, r2 + 3fa7a: c50c mov.w @(24, gbr), r0 + 3fa7c: d315 mov.l #0x0000ff00, r3 + 3fa7e: 2039 and r3, r0 + 3fa80: 202b or r2, r0 + 3fa82: c10c mov.w r0, @(24, gbr) + +# Delay. + 3fa84: 4b0b jsr @r11 + 3fa86: e402 mov #2, r4 + +# Loads the port data registers section into gbr. + 3fa88: d314 mov.l #0xa4000120, r3 + 3fa8a: 431e ldc r3, gbr + 3fa8c: 3ed3 cmp/ge r13, r14 + 3fa8e: 8d27 bt/s <3fae0> + +# When the row-to-check is lower than or equal to 8. +# Writes ~r10 to B_DATA. Sets M_DATA to 0x-f. + 3fa90: 64a7 not r10, r4 + 3fa92: 6043 mov r4, r0 + 3fa94: c002 mov.b r0, @(2, gbr) + 3fa96: c418 mov.b @(24, gbr), r0 + 3fa98: c9f0 and #0xf0, r0 + 3fa9a: a026 bra <3faea> + 3fa9c: cb0f or #15, r0 + + 3fa9e: 0000 .word 0x0000 + 3faa0: 801b mov.b r0, @(11, r1) + 3faa2: e6dc mov #-36, r6 + 3faa4: 8006 mov.b r0, @(6, r0) + 3faa6: 9088 mov.w <3fbba>(#0xc10c), r0 + 3faa8: 8002 mov.b r0, @(2, r0) + 3faaa: 4e4e ldc r14, spc + 3faac: 8800 cmp/eq #0, r0 + 3faae: 77ed add #-19, r7 + 3fab0: 8003 mov.b r0, @(3, r0) + 3fab2: d446 mov.l <3fbcc>(#0x004da007), r4 + 3fab4: 8003 mov.b r0, @(3, r0) + 3fab6: da54 mov.l <3fc08>(#0x0000aaaa), r10 + 3fab8: 8003 mov.b r0, @(3, r0) + 3faba: de9c mov.l <3fd2c>(#0xee00eb0a), r14 + 3fabc: 8006 mov.b r0, @(6, r0) + 3fabe: 90d8 mov.w <3fc72>(#0x421e), r0 + 3fac0: 8006 mov.b r0, @(6, r0) + 3fac2: 2ed8 tst r13, r14 + 3fac4: 8800 cmp/eq #0, r0 + 3fac6: 7054 add #84, r0 + +# Data segment. + 3fac8: 8003 e47a + 3facc: a400 0100 + 3fad0: 0000 aaaa + 3fad4: 0000 ff00 + 3fad8: 801b e65c + 3fadc: a400 0120 + +# When the row-to-check is strictly greater than 8. +# Writes 0xff to B_DATA, and ~r10 to M_DATA. + 3fae0: 908e mov.w <3fc00>(#0x00ff), r0 + 3fae2: c002 mov.b r0, @(2, gbr) + 3fae4: c418 mov.b @(24, gbr), r0 + 3fae6: c9f0 and #0xf0, r0 + 3fae8: 204b or r4, r0 + +# Delay. + 3faea: c018 mov.b r0, @(24, gbr) + 3faec: 4b0b jsr @r11 + 3faee: e402 mov #2, r4 + +# Loads result in r5, as ~A_DATA. + 3faf0: c400 mov.b @(0, gbr), r0 + 3faf2: 6507 not r0, r5 + +# r9 = 0 the first time. Compares r12 with the result. If none of the bits of +# r12 are set in checked row, branches to <3fb04>. + 3faf4: 6493 mov r9, r4 + 3faf6: 635c extu.b r5, r3 + 3faf8: 23c8 tst r12, r3 + 3fafa: 8903 bt <3fb04> + +# r9 seems to be the key column and r14 the row. + 3fafc: 2840 mov.b r4, @r8 + 3fafe: 60e3 mov r14, r0 + 3fb00: a00f bra <3fb22> + 3fb02: 8081 mov.b r0, @(1, r8) + + 3fb04: 655c extu.b r5, r5 + 3fb06: 4501 shlr r5 + 3fb08: 7401 add #1, r4 + 3fb0a: 34d3 cmp/ge r13, r4 + 3fb0c: 8bf3 bf <3faf6> + 3fb0e: 4a00 shll r10 + 3fb10: 60e3 mov r14, r0 + 3fb12: 8807 cmp/eq #7, r0 + 3fb14: 8f01 bf/s <3fb1a> + 3fb16: 7e01 add #1, r14 + 3fb18: 6ac3 mov r12, r10 + 3fb1a: e30c mov #12, r3 + 3fb1c: 3e33 cmp/ge r3, r14 + 3fb1e: 8b95 bf <3fa4c> + 3fb20: 2f92 mov.l r9, @r15 + +# Ends the procedure and restores everything ? + +# B_CTRL = 0xaaaa. M_CTRL = 0x--aa. Delay. + 3fb22: d338 mov.l <3fc04>(#0xa4000100), r3 + 3fb24: d038 mov.l <3fc08>(#0x0000aaaa), r0 + 3fb26: 431e ldc r3, gbr + 3fb28: c101 mov.w r0, @(2, gbr) + 3fb2a: c50c mov.w @(24, gbr), r0 + 3fb2c: d237 mov.l <3fc0c>(#0x0000ff00), r2 + 3fb2e: 2029 and r2, r0 + 3fb30: cbaa or #0xaa, r0 + 3fb32: c10c mov.w r0, @(24, gbr) + 3fb34: 4b0b jsr @r11 + 3fb36: e402 mov #2, r4 + +# B_CTRL = 0x5555. M_CTRL = 0x--55. Delay. + 3fb38: 9063 mov.w <3fc02>(#0x5555), r0 + 3fb3a: c101 mov.w r0, @(2, gbr) + 3fb3c: c50c mov.w @(24, gbr), r0 + 3fb3e: d333 mov.l <3fc0c>(#0x0000ff00), r3 + 3fb40: 2039 and r3, r0 + 3fb42: cb55 or #0x55, r0 + 3fb44: c10c mov.w r0, @(24, gbr) + 3fb46: 4b0b jsr @r11 + 3fb48: e402 mov #2, r4 + +# B_DATA = 0x00. M_DATA = 0x-0. + 3fb4a: e000 mov #0, r0 + 3fb4c: d230 mov.l <3fc10>(#0xa4000120), r2 + 3fb4e: 421e ldc r2, gbr + 3fb50: c002 mov.b r0, @(2, gbr) + 3fb52: c418 mov.b @(24, gbr), r0 + 3fb54: c9f0 and #0xf0, r0 + 3fb56: c018 mov.b r0, @(24, gbr) + +# Returns the value at the top of the stack (originally 1). + 3fb58: 60f2 mov.l @r15, r0 + 3fb5a: 7f04 add #4, r15 + 3fb5c: 4f26 lds.l @r15+, pr + 3fb5e: 68f6 mov.l @r15+, r8 + 3fb60: 69f6 mov.l @r15+, r9 + 3fb62: 6af6 mov.l @r15+, r10 + 3fb64: 6bf6 mov.l @r15+, r11 + 3fb66: 6cf6 mov.l @r15+, r12 + 3fb68: 6df6 mov.l @r15+, r13 + 3fb6a: 000b rts + 3fb6c: 6ef6 mov.l @r15+, r14 + + + +----------------------------------- +First subroutine +----------------------------------- + +# Go back to <3fa4c> (first call to this subroutine) until r14 reaches 12. + 3fb1a: e30c mov #12, r3 + 3fb1c: 3e33 cmp/ge r3, r14 + 3fb1e: 8b95 bf <3fa4c> + + 3fb20: 2f92 mov.l r9, @r15 + 3fb22: d338 mov.l <3fc04>(#0xa4000100), r3 + 3fb24: d038 mov.l <3fc08>(#0x0000aaaa), r0 + 3fb26: 431e ldc r3, gbr + 3fb28: c101 mov.w r0, @(2, gbr) + 3fb2a: c50c mov.w @(24, gbr), r0 + 3fb2c: d237 mov.l <3fc0c>(#0x0000ff00), r2 + 3fb2e: 2029 and r2, r0 + 3fb30: cbaa or #-86, r0 + 3fb32: c10c mov.w r0, @(24, gbr) + 3fb34: 4b0b jsr @r11 + 3fb36: e402 mov #2, r4 + 3fb38: 9063 mov.w <3fc02>(#0x5555), r0 + 3fb3a: c101 mov.w r0, @(2, gbr) + 3fb3c: c50c mov.w @(24, gbr), r0 + 3fb3e: d333 mov.l <3fc0c>(#0x0000ff00), r3 + 3fb40: 2039 and r3, r0 + 3fb42: cb55 or #85, r0 + 3fb44: c10c mov.w r0, @(24, gbr) + 3fb46: 4b0b jsr @r11 + 3fb48: e402 mov #2, r4 + 3fb4a: e000 mov #0, r0 + 3fb4c: d230 mov.l <3fc10>(#0xa4000120), r2 + 3fb4e: 421e ldc r2, gbr + 3fb50: c002 mov.b r0, @(2, gbr) + 3fb52: c418 mov.b @(24, gbr), r0 + 3fb54: c9f0 and #-16, r0 + 3fb56: c018 mov.b r0, @(24, gbr) + 3fb58: 60f2 mov.l @r15, r0 + 3fb5a: 7f04 add #4, r15 + 3fb5c: 4f26 lds.l @r15+, pr + 3fb5e: 68f6 mov.l @r15+, r8 + 3fb60: 69f6 mov.l @r15+, r9 + 3fb62: 6af6 mov.l @r15+, r10 + 3fb64: 6bf6 mov.l @r15+, r11 + 3fb66: 6cf6 mov.l @r15+, r12 + 3fb68: 6df6 mov.l @r15+, r13 + 3fb6a: 000b rts + 3fb6c: 6ef6 mov.l @r15+, r14 + + + +----------------------------------- +Second subroutine +Just a delay ! If also configures IRQ0. +----------------------------------- + +Stack: + gbr + macl + pr + r14 + ------ Bottom + +# Saves r14, pr, macl and gbr to the stack. Saves parameter (r4 = 2) to r14. +# Loads data: r2 = 8006 31dc, r5 = 1 (parameter 'set' for syscall 0x3ed). + 3e47a: 0312 stc gbr, r3 + 3e47c: d235 mov.l <3e554>(#0x800631dc), r2 + 3e47e: e501 mov #1, r5 + 3e480: 2fe6 mov.l r14, @-r15 + 3e482: 6e43 mov r4, r14 + 3e484: 4f22 sts.l pr, @-r15 + 3e486: 4f12 sts.l macl, @-r15 + 3e488: 7ffc add #-4, r15 + 3e48a: 2f32 mov.l r3, @r15 + +# Sets the "watchdog occupied" status in the RAM interrupt status byte. + 3e48c: 420b jsr @r2 + 3e48e: e410 mov #16, r4 + +# Ensures 1 <= r14 <= 40 by setting r14 = 1 or 40 if needed. +# Here r14 is always 2. + 3e490: 4e15 cmp/pl r14 + 3e492: 8d01 bt/s <3e498> + 3e494: e428 mov #40, r4 + 3e496: ee01 mov #1, r14 + 3e498: 3e47 cmp/gt r4, r14 + 3e49a: 8b00 bf <3e49e> + 3e49c: 6e43 mov r4, r14 + +# r4 = ~((r14 * 92) >> 4) on a single byte, which is 244 when r14 = 2. +# 256 - r4 will be used as a delay for the watchdog timer. +# Sets gbr to 0xfffffee0 and disables the watchdog interrupt. + 3e49e: e45c mov #92, r4 + 3e4a0: 924b mov.w <3e53a>(#0xfee0), r2 + 3e4a2: e3fc mov #-4, r3 + 3e4a4: 0e47 mul.l r4, r14 + 3e4a6: 421e ldc r2, gbr + 3e4a8: 041a sts macl, r4 + 3e4aa: 443c shad r3, r4 + 3e4ac: 6447 not r4, r4 + 3e4ae: 644c extu.b r4, r4 + 3e4b0: c502 mov.w @(4, gbr), r0 + 3e4b2: 9343 mov.w <3e53c>(#0x0fff), r3 + 3e4b4: 2039 and r3, r0 + 3e4b6: c102 mov.w r0, @(4, gbr) + +# Loads the watchdog module base address into gbr. Resets everything in the +# watchdog configuration. Then loads r4 (here 244) to the counter, sets the +# frequency at Po/256, starts the timer and waits until it overflows. +# This is probably just a way of delaying port usage. + 3e4b8: d027 mov.l <3e558>(#0x0000a500), r0 + 3e4ba: e180 mov #-128, r1 + 3e4bc: 411e ldc r1, gbr + 3e4be: c103 mov.w r0, @(6, gbr) + 3e4c0: 903d mov.w <3e53e>(#0x5a00), r0 + 3e4c2: 204b or r4, r0 + 3e4c4: c102 mov.w r0, @(4, gbr) + 3e4c6: d025 mov.l <3e55c>(#0x0000a505), r0 + 3e4c8: c103 mov.w r0, @(6, gbr) + 3e4ca: d025 mov.l <3e560>(#0x0000a585), r0 + 3e4cc: c103 mov.w r0, @(6, gbr) + 3e4ce: e408 mov #8, r4 + 3e4d0: c406 mov.b @(6, gbr), r0 + 3e4d2: 600c extu.b r0, r0 + 3e4d4: 2048 tst r4, r0 + 3e4d6: 89fb bt <3e4d0> + +# Resets the overflow flag, then resets the whole configuration. + 3e4d8: c406 mov.b @(6, gbr), r0 + 3e4da: 600c extu.b r0, r0 + 3e4dc: d31e mov.l <3e558>(#0x0000a500), r3 + 3e4de: c9f7 and #0xf7, r0 + 3e4e0: 203b or r3, r0 + 3e4e2: c103 mov.w r0, @(6, gbr) + 3e4e4: 6033 mov r3, r0 + 3e4e6: c103 mov.w r0, @(6, gbr) + +# Resets the counter. + 3e4e8: 9029 mov.w <3e53e>(#0x5a00), r0 + 3e4ea: c102 mov.w r0, @(4, gbr) + +# Unsets the "watchdog occupied" bit in the RAM interrupt status byte. + 3e4ec: d219 mov.l <3e554>(#0x800631dc), r2 + 3e4ee: e500 mov #0, r5 + 3e4f0: 420b jsr @r2 + 3e4f2: e410 mov #16, r4 + +# Configures IRQ0 if possible (that is, if both the watchdog and the SD card +# are idle). + 3e4f4: d31b mov.l <3e564>(#0x8003dbec), r3 + 3e4f6: 430b jsr @r3 + 3e4f8: 0009 nop + +# Un-stacks everything and returns. + 3e4fa: 62f2 mov.l @r15, r2 + 3e4fc: 421e ldc r2, gbr + 3e4fe: 7f04 add #4, r15 + 3e500: 4f16 lds.l @r15+, macl + 3e502: 4f26 lds.l @r15+, pr + 3e504: 000b rts + 3e506: 6ef6 mov.l @r15+, r14 + + + +----------------------------------- +Third subroutine +----------------------------------- + +# Erases the lowest bit in an unknown byte (probably an extension of the +# interrupt status byte). Returns if this bit was 0. + 3dbec: 4f22 sts.l pr, @-r15 + 3dbee: e501 mov #1, r5 + 3dbf0: d349 mov.l <3dd18>(#0x80063236), r3 + 3dbf2: 430b jsr @r3 + 3dbf4: 6453 mov r5, r4 + 3dbf6: 8801 cmp/eq #1, r0 + 3dbf8: 8b07 bf <3dc0a> + +# Checks if the watchdog timer is occupied, or if the SD-card is busy (?). +# If any of them is in use, aborts. Otherwise controls is transferred to the +# extract below, as if called directly. +# Probably the SD-card has something to do with generating IRQ0 interrupts. + 3dbfa: e500 mov #0, r5 + 3dbfc: d347 mov.l <3dd1c>(#0x800631f6), r3 + 3dbfe: 430b jsr @r3 + 3dc00: e418 mov #24, r4 + 3dc02: 2008 tst r0, r0 + 3dc04: 8b01 bf <3dc0a> + 3dc06: af82 bra <3db0e> + 3dc08: 4f26 lds.l @r15+, pr + +# Returns. + 3dc0a: 4f26 lds.l @r15+, pr + 3dc0c: 000b rts + 3dc0e: 0009 nop + + Here's the extract of code that takes control when the interrupt conditions + required by the main procedure are fulfilled. + It configures IRQ0 interrupts. + +# Disables IRQ0 interrupt in IPRC. + 3db0e: d32d mov.l <3dbc4>(#0xa4000000), r3 + 3db10: 431e ldc r3, gbr + 3db12: c50b mov.w @(22, gbr), r0 + 3db14: d22e mov.l <3dbd0>(#0x0000fff0), r2 + 3db16: 2029 and r2, r0 + 3db18: c10b mov.w r0, @(22, gbr) + +# Sets PTH0 to 'other functions' mode, which is IRQ0 and IRL0 input for the +# interrupt controller. + 3db1a: d12e mov.l <3dbd4>(#0xa4000100), r1 + 3db1c: 411e ldc r1, gbr + 3db1e: c507 mov.w @(14, gbr), r0 + 3db20: d32d mov.l <3dbd8>(#0x0000fffc), r3 + 3db22: 2039 and r3, r0 + 3db24: c107 mov.w r0, @(14, gbr) + +# Sets IRQ0 detection mode to low level input in ICR1. + 3db26: d227 mov.l <3dbc4>(#0xa4000000), r2 + 3db28: 421e ldc r2, gbr + 3db2a: c508 mov.w @(16, gbr), r0 + 3db2c: 2039 and r3, r0 + 3db2e: cb02 or #2, r0 + 3db30: c108 mov.w r0, @(16, gbr) + +# Clears the IRQ0 interrupt flag. + 3db32: c404 mov.b @(4, gbr), r0 + 3db34: c9fe and #-2, r0 + 3db36: c004 mov.b r0, @(4, gbr) + +# Enables IRQ0 interrupts with priority 13 in IPRC. + 3db38: c50b mov.w @(22, gbr), r0 + 3db3a: d125 mov.l <3dbd0>(#0x0000fff0), r1 + 3db3c: 2019 and r1, r0 + 3db3e: cb0d or #13, r0 + 3db40: c10b mov.w r0, @(22, gbr) + +# Returns 1. + 3db42: 000b rts + 3db44: e001 mov #1, r0 + + Here is the first subroutine, that handles an unknown byte at 0x8800713d. + This byte may be an extension of the interrupt status byte. + + Returns 1 if a bit in the unknown byte matches the mask r4. + Also, if r5 = 1, erases the bits according to the mask. + +# Sets r6 to 1 if a bit in the mask is set in the unknown byte, 0 otherwise. +# Also sets r0 = r5. + 63236: 624c extu.b r4, r2 + 63238: d72a mov.l <632e4>(#0x8800713d), r7 + 6323a: 6370 mov.b @r7, r3 + 6323c: 633c extu.b r3, r3 + 6323e: 2328 tst r2, r3 + 63240: 8f02 bf/s <63248> + 63242: 6053 mov r5, r0 + 63244: a001 bra <6324a> + 63246: e600 mov #0, r6 + 63248: e601 mov #1, r6 + +# Uses the mask comparison result as return value. If the operation is 0, then +# stop there. + 6324a: 8801 cmp/eq #1, r0 + 6324c: 8f04 bf/s <63258> + 6324e: 6063 mov r6, r0 + +# Otherwise, erase the mask in the unknown byte. + 63250: 6370 mov.b @r7, r3 + 63252: 6447 not r4, r4 + 63254: 2349 and r4, r3 + 63256: 2730 mov.b r3, @r7 + 63258: 000b rts + 6325a: 0009 nop + + Here is the second subroutine. + It does exactly the same as the first, except that it uses the common + interrupt status byte at 0x8800713c. + It's the syscall 0x3ee. + + 631f6: 624c extu.b r4, r2 + 631f8: d739 mov.l <632e0>(#0x8800713c), r7 + 631fa: 6370 mov.b @r7, r3 + 631fc: 633c extu.b r3, r3 + 631fe: 2328 tst r2, r3 + 63200: 8f02 bf/s <63208> + 63202: 6053 mov r5, r0 + 63204: a001 bra <6320a> + 63206: e600 mov #0, r6 + 63208: e601 mov #1, r6 + 6320a: 8801 cmp/eq #1, r0 + 6320c: 8f04 bf/s <63218> + 6320e: 6063 mov r6, r0 + 63210: 6370 mov.b @r7, r3 + 63212: 6447 not r4, r4 + 63214: 2349 and r4, r3 + 63216: 2730 mov.b r3, @r7 + 63218: 000b rts + 6321a: 0009 nop diff --git a/syscall_0x24b.txt b/syscall_0x24b.txt new file mode 100644 index 0000000..035600b --- /dev/null +++ b/syscall_0x24b.txt @@ -0,0 +1,91 @@ +fxos lephe$ fxos disasm -s 0x24b sh7305.fls -l 200 +Syscall table: 0x801cdd84 +Syscall id: 0x24b +Syscall address: 0x4cfc0380 + +=================================== + +Stack state: +r4 s1: Parameter of call located at +pr +r14 +r13 +------ Bottom + +=================================== + +Missing information: + +- Function of (negative offset relative to ) +- Function of (negative offset relative to <3e>, does not seem to be + the same as , curiously) +- Function of <8003e8c8> (probably syscall, but not found) + +=================================== + +# +# Initialization. +# + +# Saves the registers. + 0: 2fd6 mov.l r13, @-r15 + 2: 2fe6 mov.l r14, @-r15 + 4: 4f22 sts.l pr, @-r15 + 6: 7ffc add #-4, r15 + 8: 2f42 mov.l r4, @r15 + +# Loads 1 into r13. If jump at <16> is performed, r13 is changed to 0. + a: ed01 mov #1, r13 +# r14 gets decremented whenever call at is looped (considering the +# documentation, it is probably the number of tries before the function +# gives up). + c: ee05 mov #5, r14 + + + +# +# Main loop, calls . No more than initial_r14 turns. +# + +# Calls (r4). + e: bf19 bsr + 10: 64f2 mov.l @r15, r4 + +# If result != 0, then <1a>, else <24>. + 12: 2008 tst r0, r0 + 14: 8b01 bf <1a> + 16: a005 bra <24> + 18: ed00 mov #0, r13 + + + +# +# When returns non-zero, calls <8003e8c8>, decrements r14 and +# loops. +# + +# Call returned non-zero (r13 = 1). +# Calls <8003e8c8>(10). + 1a: d22d mov.l (0x8003e8c8), r2 + 1c: 420b jsr @r2 + 1e: e40a mov #10, r4 +# Decrementing the number of tries before returning, and looping to if the +# number of tries has not been exceeded. + 20: 4e10 dt r14 + 22: 8bf4 bf + + + +# +# When returns zero or the number of tries has been exceeded, +# return from the function with the correct value. +# + +# Call returned zero (r13 = 0). Ends the function and returns 1 if +# the key is pressed, 0 otherwise. + 24: 60d3 mov r13, r0 + 26: 7f04 add #4, r15 + 28: 4f26 lds.l @r15+, pr + 2a: 6ef6 mov.l @r15+, r14 + 2c: 000b rts + 2e: 6df6 mov.l @r15+, r13