From b2151886bce4e5edd783282ace29ea1b78d41389 Mon Sep 17 00:00:00 2001 From: lephe Date: Mon, 25 Jul 2016 22:38:47 +0200 Subject: [PATCH] Added formatted printing for stdio: handles everything except doubles and %m. --- .gitignore | 7 +- Makefile | 4 +- Makefile.old | 141 ------ README.md | 36 +- TODO | 2 +- demo/gintdemo.c | 252 +++++----- doc/bopti.md | 17 +- gintdemo.g1a | Bin 18890 -> 30046 bytes include/7305.h | 58 +-- include/alloca.h | 2 +- include/ctype.h | 8 + include/display.h | 46 +- include/gint.h | 91 ++-- include/internals/bopti.h | 2 +- include/internals/display.h | 41 ++ include/internals/stdio.h | 32 ++ include/setjmp.h | 13 +- include/stdio.h | 44 ++ include/stdlib.h | 9 + include/string.h | 29 +- include/tales.h | 16 +- libc.a | Bin 3106 -> 12430 bytes libgint.a | Bin 66120 -> 68010 bytes src/bopti/bopti_internals.c | 18 +- src/bopti/dimage.c | 4 +- src/bopti/gimage.c | 6 +- src/display/font_system.bmp | Bin 32762 -> 32762 bytes src/gray/gray_engine.c | 3 +- src/rtc/rtc_interrupt.c | 4 +- src/setjmp/setjmp.s | 2 +- src/stdio/snprintf.c | 19 + src/stdio/sprintf.c | 19 + src/stdio/stdio_format.c | 912 ++++++++++++++++++++++++++++++++++++ src/stdio/vsnprintf.c | 15 + src/stdio/vsprintf.c | 15 + src/string/strchr.c | 11 + src/string/strcpy.c | 11 + src/string/strncpy.c | 20 + src/tales/dprint.c | 18 + src/tales/gprint.c | 18 + 40 files changed, 1496 insertions(+), 449 deletions(-) delete mode 100644 Makefile.old create mode 100644 include/internals/stdio.h create mode 100644 include/stdio.h create mode 100644 src/stdio/snprintf.c create mode 100644 src/stdio/sprintf.c create mode 100644 src/stdio/stdio_format.c create mode 100644 src/stdio/vsnprintf.c create mode 100644 src/stdio/vsprintf.c create mode 100644 src/string/strchr.c create mode 100644 src/string/strcpy.c create mode 100644 src/string/strncpy.c create mode 100644 src/tales/dprint.c create mode 100644 src/tales/gprint.c diff --git a/.gitignore b/.gitignore index 767efe3..6caafaa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,3 @@ -# Sources for old gint versions. -gint.old.1/** -gint.old.2/** - # Build directory build/** @@ -11,3 +7,6 @@ build/** # Object files. *.o + +# Some notes. +LIBC diff --git a/Makefile b/Makefile index 9a01f78..e358b80 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ # Modules modules-gint = core keyboard mmu mpu rtc screen timer \ bopti display gray tales -modules-libc = setjmp string +modules-libc = setjmp string stdio # Targets target-g1a = gintdemo.g1a @@ -39,7 +39,7 @@ demo-res = $(notdir $(wildcard demo/resources/*)) demo-obj = $(patsubst %,build/demo_%.o,$(demo-src) $(demo-res)) demo-elf = build/gintdemo.elf demo-bin = build/gintdemo.bin -demo-libs = -lgcc -L. -lgint -lc +demo-libs = -L. -lgint -lc -lgcc # Specific objects obj-lib-spec = build/display_font_system.bmp.o diff --git a/Makefile.old b/Makefile.old deleted file mode 100644 index ea3834a..0000000 --- a/Makefile.old +++ /dev/null @@ -1,141 +0,0 @@ -#! /usr/bin/make -f - -#--- -# fx-9860g lib Makefile. -#--- - - - -# -# 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 = ginttest.g1a -bin = build/ginttest.bin -elf = build/ginttest.elf - -# Command-line options -cflags = -m3 -mb -nostdlib -ffreestanding -W -Wall \ - -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 tales.c \ - bopti.c -hea-lib = 7305.h 7705.h gint.h \ - stdlib.h \ - mpu.h keyboard.h screen.h display.h gray.h timer.h tales.h -obj-lib = $(patsubst %, build/%.o, $(src-lib)) -hdr-lib = $(patsubst %, include/%, $(hea-lib)) - -# Standard library. -src-std = setjmp.s string.c -hea-std = setjmp.h string.h ctype.h -obj-std = $(patsubst %, build/%.o, $(src-std)) -hdr-std = $(patsubst %, include/%, $(hea-str)) - -# Test application. -src-app = ginttest.c -img-app = bitmap_opt.bmp swords.bmp sprites.bmp symbol.bmp symbol2.bmp \ - illustration.bmp -res-app = $(patsubst %, build/%.o, $(img-app)) build/font.o - - -# -# Building rules. -# - -all: build libgint.a libc.a ginttest.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" - -$(g1a): libgint.a $(src-app) $(res-app) - $(cc) $(src-app) $(res-app) -T ginttest.ld -o $(elf) $(cflags) $(lib) - $(ob) -R .comment -R .bss -O binary $(elf) $(bin) - $(wr) $(bin) -o ginttest.g1a -i icon.bmp - @ echo "\033[32;1mBinary file size: "`stat -c %s $(bin)`" bytes\033[0m" - @ sh3eb-elf-objdump -h build/ginttest.elf - - - -# -# Resource management. -# - -build/%.c.o: src/%.c $(hdr-lib) $(hdr-std) - $(cc) $(cflags) -O2 -c $< -o $@ - -build/%.s.o: src/%.s - $(as) -c $^ -o $@ - -build/%.bmp.o: resources/%.bmp - fxconv $^ -o $@ --preview - -build/font.o: resources/font.bmp - fxconv --font $^ -o $@ - -# File gint.c should not be optimized... looks like attribute((interrupt_ -# handler)) doesn't like it. (It could be a gint bug also, I should check.) -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 $@ - - - -# -# Cleaning rules. -# - -clean: - @ rm -f $(obj-lib) $(obj-std) $(obj-app) $(res-app) - @ rm -f $(bin) $(elf) -mrproper: clean - @ rm -f build/* - @ rm -f ginttest.g1a libc.a libgint.a -distclean: mrproper - -re: distclean all - - - -# -# Installing shorthand. -# - -install: - usb-connector SEND ginttest.g1a ginttest.g1a fls0 - - - -.PHONY: all clean mrproper distclean re install diff --git a/README.md b/README.md index 847a24b..5892e31 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ gint (pronounce 'guin') is a low-level library for fx-9860G calculators. It provides the tools needed to develop programs under Linux using the gcc toolchain (sh3eb-elf). -By the way, gint is free software ; you may use it for any purpose, share it, +By the way, gint is free software; you may use it for any purpose, share it, modify it and share you changes. No credit of any kind is needed, though appreciated. @@ -15,7 +15,8 @@ Interrupt handler ----------------- The interrupt handler is the lowest-level part of the library. It directly -accesses the peripheral modules and performs keyboard analyzes, swaps screen buffers, etc. +accesses the peripheral modules and performs keyboard analyzes, swaps screen +buffers, etc. gint does not allow user programs to use their own handlers. However, it is possible to map interrupt-driven events to user callbacks using the public API @@ -37,11 +38,15 @@ register access and implements a few standard functions. Building and installing ----------------------- +There a some dependencies: +* The `sh3eb-elf` toolchain somewhere in the PATH +* The fxSDK installed and available in the PATH + The easiest way to build gint is simply to enter a terminal and execute `make`. This will build the following components : * `libgint.a`, the gint library * `libc.a`, a (very) few standard procedures -* `ginttest.g1a`, a test application +* `gintdemo.g1a`, a test application The common `clean`, `mrproper`, and `distclean` rules will clean the directory. @@ -50,13 +55,18 @@ The common `clean`, `mrproper`, and `distclean` rules will clean the directory. Source organization ------------------- -gint is made of *modules*. Each module has its own source directory (which is -`/src/module`), and its associated header file in `/include`. A module folder -contains three types of files : -* Internal headers: shared only among the files of a module -* Single-function source files: to avoid linking against the whole library, - some functions have their own object files. Their names are the function - names. -* Other source files: contain multiple functions that always work together, or - are lightweight enough not to be separated. Their names often begin with - `module_`. +gint is made of *modules*. Each module may have any of the following +components: +* A header file in `/include` +* An internal header file in `/include/internals` +* Single-function source files in `/src/module`: to avoid linking against the + whole library, some functions have their own object files. Their names are + those of the functions. +* Other source files in `/src/module`: contain multiple functions that always + work together, or are lightweight enough not to be separated. Their names + often begin with `module_`. +* Other files in `/src/module`: the `display` module contains a font, I think. + +The demo application is in the `demo` directory. + +The `doc` folder contains some documentation. diff --git a/TODO b/TODO index 9a46c54..e2f2ba8 100644 --- a/TODO +++ b/TODO @@ -12,6 +12,7 @@ @ vram overflow @ keyboard test threaded interface ++ have timers use structures from 7705.h and 7305.h + full and partial transparency + gint vs. ML with 248x124 at (-60, -28) + call exit handlers @@ -25,7 +26,6 @@ + bitmap parts - improve exception handler debugging information (if possible) -- write and test gray engine - full rtc driver (time) - callbacks and complete user API diff --git a/demo/gintdemo.c b/demo/gintdemo.c index cfadaae..4f14e51 100644 --- a/demo/gintdemo.c +++ b/demo/gintdemo.c @@ -9,79 +9,36 @@ #include #include +#include #include <7305.h> +#include + //--- -// A few ugly procedures for displaying text. Will have to enhance this -// soon -- which means printf(). +// A few procedures for displaying text aligned on a 21*8 grid. +// Not really beautiful... but this will do. //--- +void print(int x, int y, const char *format, ...) +{ + if(x < 1 || x > 21 || y < 1 || y > 8) return; + + va_list args; + va_start(args, format); + __printf(0, format, args); + va_end(args); + + if(gray_runs()) gtext(__stdio_buffer, x * 6 - 5, y * 8 - 8); + else dtext(__stdio_buffer, x * 6 - 5, y * 8 - 8); +} + void locate(const char *str, int x, int y) { if(x < 1 || x > 21 || y < 1 || y > 8) return; - if(gray_runs()) gtext(str, x * 6 - 5, y * 8 - 7); - else dtext(str, x * 6 - 5, y * 8 - 7); -} - -void locate_hex(unsigned int n, int x, int y) -{ - char str[11] = "0x"; - int i; - - for(i = 0; i < 8; i++) - { - str[9 - i] = (n & 0xf) + '0' + 39 * ((n & 0xf) > 9); - n >>= 4; - } - str[10] = 0; - locate(str, x, y); -} -void locate_bin(unsigned char n, int x, int y) -{ - char str[9]; - int i; - - for(i = 0; i < 8;i ++) - { - str[7 - i] = (n & 1) + '0'; - n >>= 1; - } - str[8] = 0; - locate(str, x, y); -} -void locate_hexa(unsigned int n, int digits, int x, int y) -{ - char str[20]; - int i; - - for(i = digits - 1; i >= 0; i--) - { - str[i] = (n & 0xf) + '0' + 39 * ((n & 0xf) > 9); - n >>= 4; - } - - str[digits] = 0; - locate(str, x, y); -} -void locate_int(int n, int x, int y) -{ - char str[20] = { 0 }; - int i, o = 0; - int digits = 0, copy = n; - - if(!n) { str[o++] = '0'; locate(str, x, y); return; } - if(n < 0) str[o++] = '-', n = -n; - while(copy) digits++, copy /= 10; - - for(i = 0; i < digits; i++) - { - str[o + digits - i - 1] = n % 10 + '0'; - n /= 10; - } - - locate(str, x, y); + if(gray_runs()) gtext(str, x * 6 - 5, y * 8 - 8); + else dtext(str, x * 6 - 5, y * 8 - 8); } @@ -90,6 +47,26 @@ void locate_int(int n, int x, int y) // Test applications. //--- +/* + keyboard_test_binary() + Prints a byte as binary/ +*/ +void keyboard_test_binary(int byte, int x, int y) +{ + char str[9]; + int i = 7; + + str[8] = 0; + while(i >= 0) + { + str[i] = '0' + (byte & 1); + byte >>= 1; + i--; + } + + locate(str, x, y); +} + /* keyboard_test_timer() Displays a keyboard test. The keyboard state is displayed as well, but @@ -103,17 +80,17 @@ void keyboard_test_timer(void) dclear_area(5, 10, 71, 34); - locate_bin(state[0], 5, 10); - locate_bin(state[1], 5, 16); - locate_bin(state[2], 5, 22); - locate_bin(state[3], 5, 28); - locate_bin(state[4], 5, 34); + keyboard_test_binary(state[0], 1, 1); + keyboard_test_binary(state[1], 1, 2); + keyboard_test_binary(state[2], 1, 3); + keyboard_test_binary(state[3], 1, 4); + keyboard_test_binary(state[4], 1, 5); - locate_bin(state[5], 40, 10); - locate_bin(state[6], 40, 16); - locate_bin(state[7], 40, 22); - locate_bin(state[8], 40, 28); - locate_bin(state[9], 40, 34); + keyboard_test_binary(state[5], 10, 1); + keyboard_test_binary(state[6], 10, 2); + keyboard_test_binary(state[7], 10, 3); + keyboard_test_binary(state[8], 10, 4); + keyboard_test_binary(state[9], 10, 5); dupdate(); } @@ -304,10 +281,10 @@ void gray_test(void) } locate("light", 15, 2); - locate_int(delays[0], 15, 3); + print(15, 3, "%d", delays[0]); locate("dark", 15, 5); - locate_int(delays[1], 15, 6); + print(15, 6, "%d", delays[1]); locate("\x02", 14, selected ? 6 : 3); @@ -328,7 +305,7 @@ void gray_test(void) selected = !selected; break; case KEY_F2: - delays[0] = 993; + delays[0] = isSH3() ? 985 : 994; delays[1] = 1609; break; case KEY_F3: @@ -356,6 +333,25 @@ void gray_test(void) gray_stop(); } +/* + printf_test() + Tests formatting functions. +*/ +void printf_test(void) +{ + dclear(); + locate("Formatted printing", 1, 1); + + print(2, 3, "%%4.2d 5 :\"%4.2d\"", 5); + print(2, 4, "%%-3c '&':\"%-3c\"", '&'); + print(2, 5, "%%#05x 27 :\"%#05x\"", 27); + print(2, 6, "%%1s \"tr\":\"%1s\"", "tr"); + print(2, 7, "%%6p NULL :\"%7p\"", NULL); + + dupdate(); + while(getkey() != KEY_EXIT); +} + /* static const unsigned char screen[1024] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -537,12 +533,8 @@ void tlb_debug(void) { dclear(); - locate("TLB", 1, 1); - locate("way=", 8, 1); - locate("0\0001\0002\0003" + (way << 1), 12, 1); - locate_int(entry, 16 + (entry < 10), 1); - locate("-", 18, 1); - locate_int((entry + 2 > 31) ? (31) : (entry + 2) , 19, 1); + print(1, 1, "TLB way=%d %d-%d", way, entry, + entry > 29 ? 31 : entry + 2); for(i = 0; i < 3 && entry < 32; i++, entry++) { @@ -567,14 +559,11 @@ void tlb_debug(void) } r = 2 * i + 3; - locate_hexa(pointer_base, 8, 1, r); - locate(":", 11, r); - locate_hexa(ppn << 10, 8, 12, r); + print(1, r, "%08x :%08x", pointer_base, ppn << 10); r++; locate((d & 0x08) ? "4k" : "1k", 1, r); - locate("pr=", 5, r); - locate(protection[(d >> 5) & 3], 8, r); + print(5, r, "pr=%s", protection[(d >> 5) & 3]); locate((d & 0x02) ? "shared" : "exclusive", 13, r); } @@ -614,6 +603,7 @@ void main_menu(int *category, int *app) "Image rendering", "Text rendering", "Real-time clock", + "Text formatting", NULL }; const char *list_perfs[] = { @@ -626,14 +616,15 @@ void main_menu(int *category, int *app) NULL }; const char **list; + int list_len; extern unsigned int bgint, egint; extern unsigned int romdata; - int gint_size = &egint - &bgint; + int gint_size = (char *)&egint - (char *)&bgint; - static int tab = 0, index = 0; + static int tab = 0, index = 0, scroll = 0; // Set to 1 when interface has to be redrawn. int leave = 1; int i; @@ -654,14 +645,10 @@ void main_menu(int *category, int *app) { case 0: locate("Demo application", 1, 1); - locate("gint version:", 2, 3); - locate(GINT_VERSION_STR, 16, 3); - locate("handler size:", 2, 4); - locate_int(gint_size, (gint_size < 1000 ? 18 : 17), 4); - locate("mpu type:", 2, 5); - locate(mpu, 21 - strlen(mpu), 5); - locate("romdata:", 2, 6); - locate_hex((unsigned int)&romdata, 11, 6); + print(2, 3, "gint version: %5s", GINT_VERSION_STR); + print(2, 4, "handler size: %5d", gint_size); + print(2, 5, "mpu type: %7s", mpu); + print(2, 6, "romdata: %08x", &romdata); list = NULL; break; @@ -682,16 +669,24 @@ void main_menu(int *category, int *app) break; default: - locate("Tab ", 1, 1); - locate_int(tab, 5, 1); + print(1, 1, "Tab %d", tab); break; } dimage(&res_opt_menu_start, 0, 56); if(list) { - for(i = 0; list[i]; i++) locate(list[i], 2, i + 2); - dreverse_area(0, 8 * index + 9, 127, 8 * index + 16); + list_len = 0; + while(list[list_len]) list_len++; + + for(i = scroll; list[i] && i < scroll + 6; i++) + locate(list[i], 2, i - scroll + 2); + + if(scroll > 0) locate("\x0d", 20, 2); + if(scroll + 6 < list_len) locate("\x0e", 20, 7); + + dreverse_area(0, 8 * (index - scroll) + 8, 127, + 8 * (index - scroll) + 15); } dupdate(); @@ -706,27 +701,58 @@ void main_menu(int *category, int *app) switch(getkey()) { case KEY_F1: - tab = 0; - index = 0; + tab = 0; + index = 0; break; case KEY_F2: - tab = 1; - index = 0; + tab = 1; + index = 0; + scroll = 0; break; case KEY_F3: - tab = 2; - index = 0; + tab = 2; + index = 0; + scroll = 0; break; case KEY_F4: - tab = 3; - index = 0; + tab = 3; + index = 0; + scroll = 0; break; case KEY_UP: - if(list && index) index--; + if(list && list_len > 1) + { + if(index) + { + index--; + if(index < scroll) scroll--; + } + else + { + index = list_len - 1; + scroll = list_len - 6; + if(scroll < 0) scroll = 0; + } + } + else leave = 0; break; case KEY_DOWN: - if(list && list[index + 1]) index++; + if(list && list_len > 1) + { + if(list[index + 1]) + { + index++; + if(index >= scroll + 6) + scroll++; + } + else + { + index = 0; + scroll = 0; + } + } + else leave = 0; break; case KEY_EXE: @@ -735,7 +761,6 @@ void main_menu(int *category, int *app) if(app) *app = index + 1; return; - case KEY_EXIT: case KEY_MENU: if(category) *category = 0; if(app) *app = 0; @@ -783,6 +808,9 @@ int main(void) case 0x0105: // rtc_test(); break; + case 0x0106: + printf_test(); + break; case 0x0301: if(isSH3()) tlb_debug(); diff --git a/doc/bopti.md b/doc/bopti.md index 5113f56..4cb6b2b 100644 --- a/doc/bopti.md +++ b/doc/bopti.md @@ -38,7 +38,8 @@ bitwise instructions, so that performance is maintained. Consider for instance a logical and operation (`(a, b) -> a & b`). Operating on pixels would need to move some data, test the value of a bit in -the mask, edit the vram data, and eventually shift both the data and the mask, for all of the 32 pixels. +the mask, edit the vram data, and eventually shift both the data and the mask, +for all of the 32 pixels. One could not expect this from happening in less than 150 processor cycles (in comparison, using generic-purpose `setPixel()`-like functions would be at least 10 times as long). The smarter method operates directly on the longword @@ -76,10 +77,9 @@ operations that correspond to the kind of image. *Detailed article: [Gray engine](gray-engine)* -Gray pixels are made of one four colors, each of which is represented by two -bits. Arguments `light` and `dark` of gray operation functions are longwords -containing the least significant and most significant of these bits, -respectively. +Gray pixels are made of four colors represented by pairs of bits. Arguments +`light` and `dark` of gray operation functions are longwords containing the +least significant and most significant of these bits, respectively. white = 0 [00] lightgray = 1 [01] @@ -168,7 +168,7 @@ darken(light, dark, x) = (light | (dark & x), (light & x) | (x ^ dark)) darken2(light, dark, x) = (light | x, (light & x) | dark) ~~~ -One could easily check that these functions do their jobs when `x = 1` and +One could easily check that these functions do their jobs when `x = 1` and leave the data unchanged when `x = 0`. @@ -183,7 +183,8 @@ Images are made of *layers*, each of which describe the mask for an operation. When an image is rendered, *bopti* draws some of those layers in the vram using the operation functions. -* Non-transparent monochrome images only have one layer, which describes the mask for the `draw` operation. +* Non-transparent monochrome images only have one layer, which describes the +mask for the `draw` operation. * Transparent monochrome images have two layers. The first describes the mask for the `draw` operation, while the other is the `alpha` operation mask (which means that it indicates which pixels are transparent). @@ -199,7 +200,7 @@ transparent), and the third indicates the color. Layers are encoded as a bit map. The image is split into a *grid*, which is made of 32-pixel *columns*, and an *end*. - 32 32 32 e + 32 32 32 end +------+------+------+---+ | | | | | | | | | | diff --git a/gintdemo.g1a b/gintdemo.g1a index 7a61a460aecd0223d288e9ceb8b7a5ffce8b837e..10aa989fd952a1d114b5bd08b27235bcf2306b2e 100644 GIT binary patch delta 12458 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 Yi5uQ3Evp%~am;SB^huN``^m!p0xNWBC;$Ke diff --git a/include/7305.h b/include/7305.h index 1eb7e71..3288678 100644 --- a/include/7305.h +++ b/include/7305.h @@ -5,7 +5,8 @@ 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. + Underscore-prefixed names (e.g. _R64CNT) are used to avoid name + conflicts (e.g. STRUCTURE.RTC would expand to STRUCTURE.((T *)0x...)). */ #pragma pack(push, 1) @@ -20,7 +21,6 @@ struct _st_rtc { unsigned char const R64CNT; - gap(1); union { @@ -31,7 +31,6 @@ struct _st_rtc unsigned ONES :4; }; } RSECCNT; - gap(1); union { @@ -42,7 +41,6 @@ struct _st_rtc unsigned ONES :4; }; } RMINCNT; - gap(1); union { @@ -53,12 +51,10 @@ struct _st_rtc unsigned ONES :4; }; } RHRCNT; - gap(1); // 0=Sunday, 1=Monday, ..., 6=Saturday, 7=Reserved (prohibited). unsigned char RWKCNT; - gap(1); union { @@ -69,7 +65,6 @@ struct _st_rtc unsigned ONES :4; }; } RDAYCNT; - gap(1); union { @@ -80,7 +75,6 @@ struct _st_rtc unsigned ONES :4; }; } RMONCNT; - gap(1); union { @@ -101,7 +95,6 @@ struct _st_rtc unsigned ONES :4; }; } RSECAR; - gap(1); union { @@ -112,7 +105,6 @@ struct _st_rtc unsigned ONES :4; }; } RMINAR; - gap(1); union { @@ -124,7 +116,6 @@ struct _st_rtc unsigned ONES :4; }; } RHRAR; - gap(1); union { @@ -136,7 +127,6 @@ struct _st_rtc unsigned DAY :3; }; } RWKAR; - gap(1); union { @@ -148,7 +138,6 @@ struct _st_rtc unsigned ONES :4; }; } RDAYAR; - gap(1); union { @@ -160,7 +149,6 @@ struct _st_rtc unsigned ONES :4; }; } RMONAR; - gap(1); union { @@ -174,7 +162,6 @@ struct _st_rtc unsigned AF :1; }; } RCR1; - gap(1); union { @@ -188,7 +175,6 @@ struct _st_rtc unsigned START :1; }; } RCR2; - gap(1); union { @@ -200,7 +186,6 @@ struct _st_rtc unsigned ONES :4; }; } RYRAR; - gap(2); union { @@ -357,7 +342,6 @@ struct _st_intx unsigned IrDA :4; }; } IPRA; - gap(2); union { @@ -369,7 +353,6 @@ struct _st_intx unsigned BEU2_1 :4; }; } IPRB; - gap(2); union { @@ -381,7 +364,6 @@ struct _st_intx unsigned SPU :4; }; } IPRC; - gap(2); union { @@ -393,7 +375,6 @@ struct _st_intx unsigned ATAPI :4; }; } IPRD; - gap(2); union { @@ -405,19 +386,17 @@ struct _st_intx unsigned VPU5F :4; }; } IPRE; - gap(2); union { unsigned short WORD; struct { - unsigned KEYSC :4; + unsigned _KEYSC :4; unsigned DMAC0B :4; unsigned USB01 :4; unsigned CMT :4; }; } IPRF; - gap(2); union { @@ -429,7 +408,6 @@ struct _st_intx unsigned VEU3F0 :4; }; } IPRG; - gap(2); union { @@ -441,7 +419,6 @@ struct _st_intx unsigned I2C0 :4; }; } IPRH; - gap(2); union { @@ -453,7 +430,6 @@ struct _st_intx unsigned _2DG_ICB :4; }; } IPRI; - gap(2); union { @@ -465,7 +441,6 @@ struct _st_intx unsigned SDHI1 :4; }; } IPRJ; - gap(2); union { @@ -477,7 +452,6 @@ struct _st_intx unsigned SDHI0 :4; }; } IPRK; - gap(2); union { @@ -489,7 +463,6 @@ struct _st_intx unsigned _2DDMAC :4; }; } IPRL; - char gap1[82]; union @@ -506,7 +479,6 @@ struct _st_intx unsigned SDHII0 :1; }; } IMR0; - gap(3); union @@ -523,7 +495,6 @@ struct _st_intx unsigned DEI0 :1; }; } IMR1; - gap(3); union @@ -538,7 +509,6 @@ struct _st_intx unsigned SCIFA0 :1; }; } IMR2; - gap(3); union @@ -553,7 +523,6 @@ struct _st_intx unsigned IRDAI :1; }; } IMR3; - gap(3); union @@ -569,7 +538,6 @@ struct _st_intx unsigned LCDCI :1; }; } IMR4; - gap(3); union @@ -586,7 +554,6 @@ struct _st_intx unsigned SCIF0 :1; }; } IMR5; - gap(3); union @@ -602,7 +569,6 @@ struct _st_intx unsigned MSIOFI1 :1; }; } IMR6; - gap(3); union @@ -619,7 +585,6 @@ struct _st_intx unsigned AL1I :1; }; } IMR7; - gap(3); union @@ -635,7 +600,6 @@ struct _st_intx unsigned FSI :1; }; } IMR8; - gap(3); union @@ -650,7 +614,6 @@ struct _st_intx unsigned :1; }; } IMR9; - gap(3); union @@ -667,7 +630,6 @@ struct _st_intx unsigned CUI :1; }; } IMR10; - gap(3); union @@ -684,7 +646,6 @@ struct _st_intx unsigned TSIFI :1; }; } IMR11; - gap(3); union @@ -695,7 +656,6 @@ struct _st_intx unsigned _2DDMAC :1; }; } IMR12; - char gap2[15]; union @@ -712,7 +672,6 @@ struct _st_intx unsigned SDHII0 :1; }; } _IMCR0; - gap(3); union @@ -729,7 +688,6 @@ struct _st_intx unsigned DEI0 :1; }; } _IMCR1; - gap(3); union @@ -744,7 +702,6 @@ struct _st_intx unsigned SCIFA0 :1; }; } _IMCR2; - gap(3); union @@ -759,7 +716,6 @@ struct _st_intx unsigned IRDAI :1; }; } _IMCR3; - gap(3); union @@ -775,7 +731,6 @@ struct _st_intx unsigned LCDCI :1; }; } _IMCR4; - gap(3); union @@ -792,7 +747,6 @@ struct _st_intx unsigned SCIF0 :1; }; } _IMCR5; - gap(3); union @@ -808,7 +762,6 @@ struct _st_intx unsigned MSIOFI1 :1; }; } _IMCR6; - gap(3); union @@ -825,7 +778,6 @@ struct _st_intx unsigned AL1I :1; }; } _IMCR7; - gap(3); union @@ -841,7 +793,6 @@ struct _st_intx unsigned FSI :1; }; } _IMCR8; - gap(3); union @@ -856,7 +807,6 @@ struct _st_intx unsigned :1; }; } _IMCR9; - gap(3); union @@ -873,7 +823,6 @@ struct _st_intx unsigned CUI :1; }; } _IMCR10; - gap(3); union @@ -890,7 +839,6 @@ struct _st_intx unsigned TSIFI :1; }; } _IMCR11; - gap(3); union diff --git a/include/alloca.h b/include/alloca.h index 9cf0899..37c88e7 100644 --- a/include/alloca.h +++ b/include/alloca.h @@ -1,6 +1,6 @@ //--- // -// gint core module: alloca +// standard library module: alloca // // Allows dynamic memory allocation on the stack. Memory is automatically // freed when the calling function exits. diff --git a/include/ctype.h b/include/ctype.h index 8c5bbd5..8c7ee2d 100644 --- a/include/ctype.h +++ b/include/ctype.h @@ -1,3 +1,11 @@ +//--- +// +// standard library module: ctype +// +// Some character manipulation. +// +//--- + #ifndef _CTYPE_H #define _CTYPE_H 1 diff --git a/include/display.h b/include/display.h index 4cca184..2b53a14 100644 --- a/include/display.h +++ b/include/display.h @@ -14,8 +14,7 @@ // Heading declarations. //--- -#include -#include +#include enum Color { @@ -149,47 +148,4 @@ void dline(int x1, int y1, int x2, int y2, enum Color color); */ void dimage(struct Image *image, int x, int y); - - -//--- -// Rectangle masks. -// -// The concept of 'rectangle masks' is used several times in this module. -// It is based on the fact that an operation that affects a rectangle acts -// the same on all its lines. Therefore the behavior of the operation is -// determined by its behavior on a single line, which is represented using -// 'masks' whose bits 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, vram[offset] ^= masks[i] -// will reverse the pixels in the same rectangle. -// -// This technique can also be used in more subtle cases with more complex -// patterns, but within this module it is unlikely to happen. -// -//--- - -/* - adjustRectangle() - Adjusts the given rectangle coordinates to ensure that : - - the rectangle is entirely contained in the screen - - x1 < x2 - - y1 < y2 - which is needed when working with screen rectangles. -*/ -void adjustRectangle(int *x1, int *y1, int *x2, int *y2); - -/* - getMasks() - Computes the rectangle masks needed to affect pixels located between x1 - and x2 (both included). The four masks are stored in the third argument - (seen as an array). -*/ -void getMasks(int x1, int x2, uint32_t *masks); - - - #endif // _DISPLAY_H diff --git a/include/gint.h b/include/gint.h index 879d576..8e7fa35 100644 --- a/include/gint.h +++ b/include/gint.h @@ -32,6 +32,45 @@ unsigned int gint_systemVBR(void); +//--- +// Register access. +//--- + +/* + enum Register + Represents common registers. Used as identifiers to retrieve their + values using gint_register(). +*/ +enum Register +{ + Register_EXPEVT, + Register_MMUCR, + Register_TEA, +}; + +/* + gint_register() + Returns the address of a common register. All common registers exist + on both platforms but they may hold different values for the same + information (f.i. EXPEVT may not return the same value for a given + exception on both 7705 and 7305). +*/ +volatile void *gint_reg(enum Register reg); + +/* + gint_strerror() + Returns a string that describe the error set in EXPEVT in case of + general exception of TLB miss exception. This string is platform- + independent. + Some exception codes represent different errors when invoked inside the + general exception handler and the TLB error handler. Parameter 'is_tlb' + should be set to zero for general exception meanings, and anything non- + zero for TLB error meanings. +*/ +const char *gint_strerror(int is_tlb); + + + //--- // Internal API. // Referenced here for documentation purposes only. @@ -75,6 +114,15 @@ void gint_setup_7305(void); void gint_stop_7705(void); void gint_stop_7305(void); +/* + gint_reg() + gint_strerror() + See "Register access" section. +*/ +volatile void *gint_reg_7705(enum Register reg); +volatile void *gint_reg_7305(enum Register reg); +const char *gint_strerror_7705(int is_tlb); +const char *gint_strerror_7305(int is_tlb); //--- @@ -110,49 +158,6 @@ void gint_int_7305(void) __attribute__((section(".gint.int"))); -//--- -// Register access. -//--- - -/* - enum Register - Represents common registers. Used as identifiers to retrieve their - values using gint_register(). -*/ -enum Register -{ - Register_EXPEVT, - Register_MMUCR, - Register_TEA, -}; - -/* - gint_register() - Returns the address of a common register. All common registers exist - on both platforms but they may hold different values for the same - information (f.i. EXPEVT may not return the same value for a given - exception on both 7705 and 7305). -*/ -volatile void *gint_reg(enum Register reg); -volatile void *gint_reg_7705(enum Register reg); -volatile void *gint_reg_7305(enum Register reg); - -/* - gint_strerror() - Returns a string that describe the error set in EXPEVT in case of - general exception of TLB miss exception. This string is platform- - independent. - Some exception codes represent different errors when invoked inside the - general exception handler and the TLB error handler. Parameter 'is_tlb' - should be set to zero for general exception meanings, and anything non- - zero for TLB error meanings. -*/ -const char *gint_strerror(int is_tlb); -const char *gint_strerror_7705(int is_tlb); -const char *gint_strerror_7305(int is_tlb); - - - //--- // Internal platform-independent definitions. //--- diff --git a/include/internals/bopti.h b/include/internals/bopti.h index 3e0116c..3ed11cb 100644 --- a/include/internals/bopti.h +++ b/include/internals/bopti.h @@ -86,7 +86,7 @@ struct Command // The video ram addresses are set by the public functions and used internally // by the module. // Monochrome video ram, light and dark buffers (in this order). -extern int *vram, *v1, *v2; +extern int *bopti_vram, *bopti_v1, *bopti_v2; diff --git a/include/internals/display.h b/include/internals/display.h index a227edd..ac8d4bd 100644 --- a/include/internals/display.h +++ b/include/internals/display.h @@ -9,6 +9,47 @@ #ifndef _INTERNALS_DISPLAY_H #define _INTERNALS_DISPLAY_H 1 +#include + extern int *vram; +//--- +// Rectangle masks. +// +// The concept of 'rectangle masks' is used several times in this module. +// It is based on the fact that an operation that affects a rectangle acts +// the same on all its lines. Therefore the behavior of the operation is +// determined by its behavior on a single line, which is represented using +// 'masks' whose bits 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, vram[offset] ^= masks[i] +// will reverse the pixels in the same rectangle. +// +// This technique can also be used in more subtle cases with more complex +// patterns, but within this module it is unlikely to happen. +// +//--- + +/* + adjustRectangle() + Adjusts the given rectangle coordinates to ensure that : + - the rectangle is entirely contained in the screen + - x1 < x2 + - y1 < y2 + which is needed when working with screen rectangles. +*/ +void adjustRectangle(int *x1, int *y1, int *x2, int *y2); + +/* + getMasks() + Computes the rectangle masks needed to affect pixels located between x1 + and x2 (both included). The four masks are stored in the third argument + (seen as an array). +*/ +void getMasks(int x1, int x2, uint32_t *masks); + #endif // _INTERNALS_DISPLAY_H diff --git a/include/internals/stdio.h b/include/internals/stdio.h new file mode 100644 index 0000000..bf68b81 --- /dev/null +++ b/include/internals/stdio.h @@ -0,0 +1,32 @@ +//--- +// +// standard library module: stdio +// +// Handles most input/output for the program. This module does not +// interact with the file system directly. +// +//--- + +#ifndef _INTERNALS_STDIO_H +#define _INTERNALS_STDIO_H 1 + +#include +#include + +//--- +// Formatted printing. +//--- + +#ifndef __stdio_buffer_size +#define __stdio_buffer_size 256 +#endif + +extern char __stdio_buffer[]; + +/* + __printf() + Formatted printing to the stdio buffer. +*/ +int __printf(size_t size, const char *format, va_list args); + +#endif // _INTERNALS_STDIO_H diff --git a/include/setjmp.h b/include/setjmp.h index 0addccf..54dceea 100644 --- a/include/setjmp.h +++ b/include/setjmp.h @@ -1,3 +1,12 @@ +//--- +// +// gint standard module: setjmp +// +// Long jumps. The register contents are saved in a buffer when setjmp() +// is called and restored at any time when longjmp() performs the jump. +// +//--- + #ifndef _SETJMP_H #define _SETJMP_H 1 @@ -12,13 +21,13 @@ typedef unsigned int jmp_buf[16]; //--- /* - setjmp() + setjmp() O(1) Configures a jump by saving data to the given jump buffer. */ int setjmp(jmp_buf env); /* - longjmp() + longjmp() O(1) Performs a long jump. */ void longjmp(jmp_buf env, int value); diff --git a/include/stdio.h b/include/stdio.h new file mode 100644 index 0000000..f19ecdb --- /dev/null +++ b/include/stdio.h @@ -0,0 +1,44 @@ +//--- +// +// standard library module: stdio +// +// Handles most input/output for the program. This module does not +// interact with the file system directly. +// +//--- + +#ifndef _STDIO_H +#define _STDIO_H 1 + +#include +#include + +//--- +// Formatted printing. +//--- + +/* + sprintf() + Prints to a string. +*/ +int sprintf(char *str, const char *format, ...); + +/* + snprintf() + Prints to a string with a size limit. +*/ +int snprintf(char *str, size_t size, const char *format, ...); + +/* + vsprintf() + Prints to a string from an argument list. +*/ +int vsprintf(char *str, const char *format, va_list args); + +/* + vsnprintf() + The most generic formatted printing function around there. +*/ +int vsnprintf(char *str, size_t size, const char *format, va_list args); + +#endif // _STDIO_H diff --git a/include/stdlib.h b/include/stdlib.h index 0a0ff01..0eb5591 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -1,3 +1,12 @@ +//--- +// +// standard library module: stdlib +// +// Provides standard functionalities such as dynamic allocation, +// string/numeric conversion, and abort calls. +// +//--- + #ifndef _STDLIB_H #define _STDLIB_H 1 diff --git a/include/string.h b/include/string.h index e746347..dc0ac1c 100644 --- a/include/string.h +++ b/include/string.h @@ -1,3 +1,12 @@ +//--- +// +// standard library module: string +// +// String manipulation using NUL-terminated byte arrays, without extended +// characters. +// +//--- + #ifndef _STRING_H #define _STRING_H 1 @@ -28,9 +37,27 @@ void *memset(void *destination, int byte, size_t byte_number); //--- /* - strlen() O(length) + strlen() O(len(str)) Returns the length of a string. */ size_t strlen(const char *str); +/* + strcpy() O(len(source)) + Copies a string to another. +*/ +char *strcpy(char *destination, const char *source); + +/* + strchr() O(len(str)) + Searches a character in a string. +*/ +const char *strchr(const char *str, int value); + +/* + strncpy() O(min(len(source), size)) + Copies part of a string to another. +*/ +char *strncpy(char *destination, const char *source, size_t size); + #endif // _STRING_H diff --git a/include/tales.h b/include/tales.h index bb990b9..5d5c25f 100644 --- a/include/tales.h +++ b/include/tales.h @@ -2,8 +2,8 @@ // // gint drawing module: tales // -// Text displaying. Does some good optimization, though requires dynamic -// allocation. +// Text displaying. Does some pretty good optimization, though requires +// dynamic allocation. The stack is used. // //--- @@ -113,4 +113,16 @@ void dtext(const char *str, int x, int y); */ void gtext(const char *str, int x, int y); +/* + dprint() + Prints a formatted string. Works the same as printf(). +*/ +void dprint(int x, int y, const char *format, ...); + +/* + gprint() + Prints a formatted string. Works the same as printf(). +*/ +void gprint(int x, int y, const char *format, ...); + #endif // _TALES_H diff --git a/libc.a b/libc.a index 6bdac151fd258bc70e76e2d7afac13fcabca487d..ddbff9ece00dd69298253749f656d551b7a75216 100644 GIT binary patch literal 12430 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 l{Vd{}?ej6$}`2dU9W+uKECIDu7Bqsm> diff --git a/libgint.a b/libgint.a index 072c42e882f442112ec4584b8c8b47b01d08f81e..895e9b7e0aa7431398456c0b443402a7bfe1f16b 100644 GIT binary patch delta 2820 zcmd5;YfMx}6h3qJ#X?vFL{?joM+6G8523K&Yf)Q8ZCNW-qT&L}@~D)@vNbfNEEcs` zty-ob)skvZ5+Ml2sf}p~YGajDQ3J5#v3Uq;PM^^#y>n0RDZC5TXP4J4B}eOqngga2{YZ z%JA}GpDaRA$Q05rG!d$b+^ zXkQM{wG`k0+BxXC190f#x*Fk{kZ6Vf@`RI zV-VmLdgB+gBjO&)9OFb`__GlZ;RX=(0ybCJqtLtD4ttf;JtwcUG(XR=8th_2k<(3m z)E}zy%PZU^^qZD(0ba?z#te3;?OMxXrqXDIAbUZDtE9{g_9Ce^8fl<5K^1N`PfcdC zwHeA;?z~cGm8@oP7|M;lQj0V|YVmcHyPS51%Wd-V@Njcda%z$ozbSNPrJnWpPtvF) zs*4`S?vD)&lql0hE7YpzQ_V? z8CI>}3S08u;tDz^UjVIb#`P2jXl2_oD}(vo!)$t1Ry|1`P7O2kti5IyH$3FYoZM}uo zsWdEZLpAXg?xS8VLQAd7Cef4cR%^47nY=BwicsokFsT}lWl)nLihj{BgN68SMiwXBafCYg?WSmy5o2%@WMWc~^APmwpv zybVAh&bLS60_>-CEt!9rOj#^-cO)Slbmg9%v@0iuMz$u99%^fq9A%-p=up9&NDuqR z3koGW(z;mil~dA{_c{&Td!5uZw(TUnbXVIFQb2!g;{(Im^@2HB3WaP|(5?{z@otie zeDo!>rXwfpQHB?}^4_!;xJZ`Y9k236g@tzZVO$>#<-Ov8 z_aAGPDXZDiT&3QonCA*c6p#m>Hz$9m46;Z(Hv(}i`M);5PK5|d1HTYo$` z#k%`nCCdUbBdva*J*(>rh!6rJ`gDPjh^Q;%tS&F8@}W6;lhCN$ML^rAIqMq{*{BMP z$czRYp}3;Bpw1ZO;BX8ygbxC<%691<30aAOp~0XE7MsK(9t2x-IhfFSDu0%H#gAlI z@mUu0P%LxN1efQJk{6AVG2ljYvH-%kem33v!zD6I8?K7c5jzl1zl|G9iv|MJYB2}0 zXw5(rIY)O5#E@*-i{J0)?SU9o0rnNsGs#ifA910#k?H7>$zf{6_ejHO=^&3U(dYXH zI~3lZ4VH7GPP&{d-ZcGfXfyY*cy+bhnZ|p?6aW3LQH6K))YL>~7(Pst$LG#n#D0FT zOgX`5Hd#`oe-`g|Zx#g%8R5M*Q9_X`~t*+7SzTym&X`46wfg>U4_iZk|k$+ zJj3Q;r^6Uz^(zcMt1hJH)aicCdXF+Qy5w&0UGVcL>9%L;wZ2{(c=gdUUxv_xrDN;> zQF5DfJxXt!!2u($o!#zz?h3KR?X1S<&u*`B7nGFS^WP{ebh^BwacvrY40vDoaCtgC zHM5>rsclviSxIwG#1J>lUFQ8_=FjuQk~+FSCx$f8>DCxyEZR!stHIi9#b`F0QvOE{ W;&1uLZvgs(JE-Wtbx_Dt9rP!k9O)MT delta 2083 zcmb7GeNa?Y6hHUvdrParu(Gf?mGYsO@iA{#Yax{&b`--8a4=0vKE#2<4^+n1ac6MG zkHJDE4t-ddlcXQ8V}eiNAONTW2(5VlM?1j3VN@SLV!wuzS^zU# zB>(~*6(H>%z(j|J3?G1wDr54GSVbxOm;x}PmC|*D-nH!mXeTEpS^!R+0qCp;_?pIVTLFHc0R9Vl`~Ww+ z0Jq55oeB+iX>K4)O!^%L_*7|^C8qSHrIiIM7go;9&&n!Vytue%K{*rzUzP@6;zQPY z+-Z%pta1T*8uPd_#3rF?b6M0hm6zD2$k-7YrMT15Qq!;{$H^^WF(EqbO^M>^k#@UD zEl;?qC~l9(rDAW2ldnwjNgCz7DW_@rmzfK$7FsAMuk{=?luPZ-#$``gO!i-yIK`mC z`|XTev-i2#dAiD5a++mrU)@j9+@CvEXB0;iKc4@aVMT;>Va|G!N4{oWpH9Wrn)zA5 zt!d&2QT#^n!k|c$qT}TYuNzdTOUvvw;gwVo-aE_ttr``U4*EuzE#2~G27}No<*ZFL zC~cL-xp8?}qGb7=pIX<*GO1^@CtMr04&Zx;rxG%T0x%js9iVsOfejUdP1VOS8&fr| z6`q%E^f9YNY%9dW5%FlN_Sp)FsRSDaUUuSp)hesSuEYeqSDnm$#Dq$Nm9rhE^QyLRAo~zxr9pn zn6qh4cMfDb+`mKPyaBv`cpJf|uU|&lnLxZ>=W75Ykv6~1=?f_xB;KI&Hvufd-!6?y z@Gc(SIm2{8^7-b*7{=bhz^)zmOJFos?oMX=aOZA4HPi;tOfMzyp?mTq>#7w+O8{`m z`_~n^!H|uIpN>QS-qoxP(;E`-k)~ueAD?Y{V8Cf{tK)D>QzDzn4>g5I_I%nFeDr2m zfSvnZ97;E~pmasi>VlG@73I&(%$x>%+J2cSEwq$MN=|%%)hs;dB)U17mExpkqkt97 z+HKUD9H(D;yY}0N^D%6Y>%Ch0Hj+kW6Q;1{Hu$7Oz~2cL-_g2 z5e$!Xk3dKF&!I^Gk>WmyN5w // Monochrome video ram, light and dark buffers (in this order). -int *vram, *v1, *v2; +int *bopti_vram, *bopti_v1, *bopti_v2; /* bopti_op() @@ -19,11 +19,11 @@ void bopti_op_mono(int offset, uint32_t operator, struct Command *c) switch(c->channel) { case Channel_Mono: - vram[offset] |= operator; + bopti_vram[offset] |= operator; break; case Channel_FullAlpha: - vram[offset] &= ~operator; + bopti_vram[offset] &= ~operator; break; default: @@ -37,21 +37,21 @@ void bopti_op_gray(int offset, uint32_t operator, struct Command *c) switch(c->channel) { case Channel_Mono: - v1[offset] |= operator; - v2[offset] |= operator; + bopti_v1[offset] |= operator; + bopti_v2[offset] |= operator; break; case Channel_Light: - v1[offset] |= operator; + bopti_v1[offset] |= operator; break; case Channel_Dark: - v2[offset] |= operator; + bopti_v2[offset] |= operator; break; case Channel_FullAlpha: - v1[offset] &= ~operator; - v2[offset] &= ~operator; + bopti_v1[offset] &= ~operator; + bopti_v2[offset] &= ~operator; break; case Channel_LightAlpha: diff --git a/src/bopti/dimage.c b/src/bopti/dimage.c index 8c2f5f9..d4d300f 100644 --- a/src/bopti/dimage.c +++ b/src/bopti/dimage.c @@ -1,5 +1,5 @@ #include -#include +#include /* dimage() @@ -34,7 +34,7 @@ void dimage(struct Image *img, int x, int y) if(x >= 0) getMasks(x, x + actual_width - 1, command.masks); else getMasks(0, actual_width + x - 1, command.masks); - vram = display_getCurrentVRAM(); + bopti_vram = display_getCurrentVRAM(); while(format) { diff --git a/src/bopti/gimage.c b/src/bopti/gimage.c index 65e0ed3..27df32b 100644 --- a/src/bopti/gimage.c +++ b/src/bopti/gimage.c @@ -1,5 +1,5 @@ #include -#include +#include #include /* @@ -34,8 +34,8 @@ void gimage(struct Image *img, int x, int y) if(x >= 0) getMasks(x, x + actual_width - 1, command.masks); else getMasks(0, actual_width + x - 1, command.masks); - v1 = gray_lightVRAM(); - v2 = gray_darkVRAM(); + bopti_v1 = gray_lightVRAM(); + bopti_v2 = gray_darkVRAM(); while(format) { diff --git a/src/display/font_system.bmp b/src/display/font_system.bmp index e866558a1efb2b18fbaa6c2d36c784e0ee4d29c9..0f49d5b296a2fde8eed023b55d1695f0d747ad30 100644 GIT binary patch delta 124 zcmezMpYhj!#tpyyCZCPwnQYIeIB^31WCb44$rnPMfV9fw2?|1!7i5V}HYjwRIDri; zR1hRR`2i2xKZHpD<)ndF9f(DN+JGj3xW+(}0w*UViEe%nD9Sw9 QmWyYyg8=_#fzVf40JkPA!vFvP delta 126 zcmV-^0D=Gd{{i~{0kHc{lMoOUvk*_^1(QG=36o$88lVD;Mli&;nlaOK(lOPNalVBGHlaN*qlW<`SlfVuMlki6yli(^Ildx10 glf7#av5 #include #include +#include static int internal_vrams[3][256]; static const void *vrams[4]; @@ -151,6 +152,6 @@ void gray_init(void) vrams[2] = (const void *)internal_vrams[1]; vrams[3] = (const void *)internal_vrams[2]; - delays[0] = 993; + delays[0] = isSH3() ? 985 : 994; delays[1] = 1609; } diff --git a/src/rtc/rtc_interrupt.c b/src/rtc/rtc_interrupt.c index a606a45..96e66a3 100644 --- a/src/rtc/rtc_interrupt.c +++ b/src/rtc/rtc_interrupt.c @@ -14,7 +14,7 @@ static void (*rtc_callback)(void) = NULL; Sets the callback function for the real-time clock interrupt. If frequency is non-NULL, the clock frequency is set to the given value. */ -void gint_setRTCCallback(void (*callback)(void), enum RTCFrequency frequency) +void rtc_setCallback(void (*callback)(void), enum RTCFrequency frequency) { rtc_callback = callback; if(frequency < 1 || frequency > 7) return; @@ -30,7 +30,7 @@ void gint_setRTCCallback(void (*callback)(void), enum RTCFrequency frequency) Returns the callback function. If frequency is non-NULL, it is set to the current frequency value. */ -void (*gint_getRTCCallback(enum RTCFrequency *frequency))(void) +void (*rtc_getCallback(enum RTCFrequency *frequency))(void) { if(!frequency) return rtc_callback; diff --git a/src/setjmp/setjmp.s b/src/setjmp/setjmp.s index 81a053a..3b6f910 100644 --- a/src/setjmp/setjmp.s +++ b/src/setjmp/setjmp.s @@ -1,5 +1,5 @@ /* - gint standard module: setjmp + standard library module: setjmp Long jumps. The register contents are saved in a buffer when setjmp() is called and restored at any time when longjmp() performs the jump. diff --git a/src/stdio/snprintf.c b/src/stdio/snprintf.c new file mode 100644 index 0000000..eed74db --- /dev/null +++ b/src/stdio/snprintf.c @@ -0,0 +1,19 @@ +#include +#include +#include + +/* + snprintf() + Prints to a string with a size limit. +*/ +int snprintf(char *str, size_t size, const char *format, ...) +{ + va_list args; + va_start(args, format); + + int x = __printf(size, format, args); + strncpy(str, __stdio_buffer, size); + + va_end(args); + return x; +} diff --git a/src/stdio/sprintf.c b/src/stdio/sprintf.c new file mode 100644 index 0000000..a283635 --- /dev/null +++ b/src/stdio/sprintf.c @@ -0,0 +1,19 @@ +#include +#include +#include + +/* + sprintf() + Prints to a string. +*/ +int sprintf(char *str, const char *format, ...) +{ + va_list args; + va_start(args, format); + + int x = __printf(0, format, args); + strncpy(str, __stdio_buffer, __stdio_buffer_size); + + va_end(args); + return x; +} diff --git a/src/stdio/stdio_format.c b/src/stdio/stdio_format.c new file mode 100644 index 0000000..392ddc7 --- /dev/null +++ b/src/stdio/stdio_format.c @@ -0,0 +1,912 @@ +#include +#include + +#include +#include +#include + +/* + Internal buffer. + + Using a buffer *really* simplifies everything. But it also has + disadvantages, such a memory loss and limited output size. + + So, in case we find a possibility to get rid of this buffer, we will + just have to change function character(), which is for now the only + function that directly accesses the buffer. +*/ +char __stdio_buffer[__stdio_buffer_size]; + + + +/* + Format composed types. + + Format structure handles everything in a format, from data type to + given value, including alternative forms, alignment and digit numbers. + + A format is made of a data type, which can be altered by a size option, + a number of integer and decimal digits, and additional flags. + + The FormatFlags enumeration handles the various flags that can be added + to a printf()-family format. +*/ + +enum FormatFlags +{ + // Option '#' specifies alternatives forms, mainly '0' and '0x' + // prefixes in integer display. + Alternative = 1, + // Under specific conditions, zero-padding may be used instead of + // whitespace-padding. + ZeroPadded = 2, + // Left alignment specifies that additional spaces should be added + // after the value. + LeftAlign = 4, + // In numeric display, this forces a blank sign to be written before + // positive values. + BlankSign = 8, + // In numeric display, this forces an explicit sign in all cases. This + // option overrides BlankSign (see __printf() description for further + // information on option precedence and influence). + ForceSign = 16 +}; + +struct Format +{ + // Format type, one of 'diouxXcs' ('eEfFgGaApnm' still to add). + char type; + // Format size, one of 'l', 'h', 'i' ('i' means 'hh'). + char size; + + // Number of characters printed. + int characters; + // Number of digits after the dot. + int precision; + + // Various flags. + enum FormatFlags flags; + + // Value to output. + union + { + // Signed int with formats %c, %d and %i. + signed int _int; + // Insigned int with formats %o, %u, %x and %X. + unsigned int _unsigned; + // Double with formats %f, %F, %e, %E, %g and %G. +// double _double; + // String pointer with format %s. + const char *_pointer; + }; +}; + + + +//--- +// Static declarations. +//--- + +// Outputs a character in the buffer. Updates counters. +static void character(int c); +// Outputs n timers the given character. +static void character_n(int c, int n); +// Reads a format from the given string pointer address (must begin with '%'). +static struct Format get_format(const char **pointer); +// Computes the number of spaces and zeros to add to the bare output. +static void get_spacing(struct Format format, int *begin_spaces, int *sign, + int *zeros, int length, int *end_spaces); + +static void format_di (struct Format format); +static void format_u (struct Format format); +static void format_oxX (struct Format format); +// static void format_e (struct Format format); +static void format_c (struct Format format); +static void format_s (struct Format format); +static void format_p (struct Format format); + +#define abs(x) ((x) < 0 ? -(x) : (x)) + +// Number of characters currently written. +static size_t written = 0; +// Total number of function calls (characters theoretically written). +static size_t total = 0; +// Maximum number of characters to output. +static size_t max = 0; + + + +/* + character() + Outputs a character to the buffer. This function centralizes all the + buffer interface, so that if we come to remove it for property reasons, + we would just have to edit this function. + + Static variables written and total are both needed, because the + terminating NUL character may be written after the maximum has been + reached. + In other words, when the function ends, we need to have a variable + counting the current position in the buffer (written), and one other + containing the total number of theoretic characters (total) because + these two values may be different. + + Of course the three variables need to be initialized before using this + function. +*/ +static void character(int c) +{ + // If there is space left in the buffer. + if(written < max - 1) __stdio_buffer[written++] = c; + total++; +} + +/* + character_n() + Outputs n times the same character. Thought to be used to output spaces + or zeros without heavy loops. +*/ +static void character_n(int c, int n) +{ + int i = 0; + while(i++ < n) character(c); +} + +/* + get_format() + Reads the format from the given string pointer and returns a + corresponding Format structure. The string pointer points to is also + modified, so that is points to the first character after the format. + This function expects **pointer == '%'. +*/ +static struct Format get_format(const char **pointer) +{ + const char *convspec = "diouxXeEfFgGaAcspnm"; + struct Format format; + + const char *string = *pointer, *ptr; + int c, i; + char precision[10]; + + // Moving the string pointer after the '%' character. + string++; + + // Initializing structure. + format.type = 0; + format.size = 0; + format.flags = 0; + // Initializing digit counts. + format.characters = -1; + format.precision = -1; + + // Parsing the format string. Testing each character until a + // conversion specifier is found. + while((c = *string)) + { + // Looking for a conversion specifier. + ptr = strchr(convspec, c); + if(ptr) + { + format.type = *ptr; + break; + } + + // Looking for a left precision string (number of digits before + // the dot), introduced by a non-null digit. + if(c >= '1' && c <= '9') + { + format.characters = 0; + for(i = 0; i < 9 && isdigit(*string); string++) + { + format.characters *= 10; + format.characters += *string - '0'; + } + + // As pointer is now pointing to the next character, + // we want to try tests again from the beginning. + continue; + } + + // Looking for a right precision string (number of digits after + // the dot), introduced by a point. + if(c == '.') + { + string++; + if(!isdigit(*string)) continue; + + format.precision = 0; + for(i = 0; i < 9 && isdigit(*string); string++) + { + format.precision *= 10; + format.precision += *string - '0'; + } + + // As pointer is now pointing on the next character, + // we want to try tests again from the beginning. + continue; + } + + // Handling predefined characters. + switch(*string) + { + // Length modifiers. + case 'h': + format.size = 'h' + (format.size == 'h'); + break; + case 'l': + case 'L': + case 'z': + case 't': + format.size = *string; + break; + + // Flags. + case '#': + format.flags |= Alternative; + break; + case '0': + format.flags |= ZeroPadded; + break; + case '-': + format.flags |= LeftAlign; + break; + case ' ': + format.flags |= BlankSign; + break; + case '+': + format.flags |= ForceSign; + break; + } + + string++; + } + + // If the format hasn't ended, the type attribute is left to zero and + // the main loop will handle failure and break. Nothing has to be done + // here. + + *pointer = string + 1; + return format; +} + +/* + get_spacing() + Computes the arrangement of beginning spaces, sign, zeros, pure value + and ending spaces in formats. + This formatting follows a recurrent model which is centralized in this + function. Note that you can't have `begin_spaces` and `end_spaces` + both non-zero: at least one is null. +*/ +static void get_spacing(struct Format format, int *begin_spaces, int *sign, + int *zeros, int length, int *end_spaces) +{ + // Using a list of types involving a sign. + const char *signed_types = "dieEfFgGaA"; + int spaces; + // Digits represents pure output + zeros (don't mix up with the *real* + // displayed digits). + int digits; + int left = format.flags & LeftAlign; + + // Getting the total number of digits. + switch(format.type) + { + // In integer display, the number of digits output is specified in the + // precision. + case 'd': + case 'i': + case 'u': + digits = format.precision; + if(digits < length) digits = length; + break; + + // Binary display has prefixes such as '0' and '0x'. + case 'o': + case 'x': + case 'X': + digits = format.precision; + if(digits == -1) digits = length; + + if(format.flags & Alternative) + { + int hexa = (format.type == 'x' || format.type == 'X'); + digits += 1 + hexa; + length += 1 + hexa; + } + if(digits < length) digits = length; + break; + + // Other formats do not have additional zeros. + default: + digits = length; + break; + } + + if(sign) + { + if(strchr(signed_types, format.type)) + { + if(format.flags & BlankSign) *sign = ' '; + // Option '+' overrides option ' '. + if(format.flags & ForceSign) *sign = '+'; + // And of course negative sign overrides everything! + if(format.type == 'd' || format.type == 'i') + { + if(format._int < 0) *sign = '-'; + } +// else if(format._double < 0) *sign = '-'; + + } + else *sign = 0; + } + + // Computing the number of spaces. + spaces = format.characters - digits; + // Computing the number of zeros. + *zeros = digits - length; + + // Removing a space when a sign appears. + if(sign && *sign) spaces--; + + // Option '0' translates spaces to zeros, but only if no precision is + // specified; additionally, left alignment overrides zero-padding. + if(!left && format.precision == -1 && format.flags & ZeroPadded) + { + *zeros += spaces; + spaces = 0; + } + + // Setting the correct spaces number to the computed value, depending + // on the left alignment parameter. + *begin_spaces = left ? 0 : spaces; + *end_spaces = left ? spaces : 0; +} + +/* + __printf() + + Basic buffered formatted printing function. Fully-featured, so that + ant call to a printf()-family function can be translated into a + __printf() call. + + It always returns the number of characters of the theoretic formatted + output. The real output may be limited in size by the given size + argument when working with nprintf()-family functions, or the internal + buffer itself. + + The Flags structure isn't necessary, but it simplifies a lot format + argument handling (because flag effects depend on format type, which + is unknown when the flags are read). Also, length modifiers 'hh' is + stored as 'i' to simplify structure handling. 'll' is not supported. + Format '%LF' is allowed by C99 and therefore supported. + + Generic information on options precedence and influence. + - Influences of integer part and mantissa digit numbers depend on + the type of data that is being displayed. + - Option '#' doesn't contend with any other. + - Option '+' overrides options ' '. + - In integer display, option '0' translates spaces to zeros, but + only if no decimal digit number is specified. + The option '-' also overrides it, forcing whitespaces to be + written at the end of the format. + + Limit of function. + - Internal buffer size (should be customizable with a -D option + when compiling). + - Precision values (format %a.b) are written on 8 bits, therefore + limited to 127. + + Unsupported features. + - Flag character ''' (single quote) for thousands grouping + - Flag character 'I', that outputs locale's digits (glibc 2.2) + - Length modifiers 'll' and 'q' (libc 5 and 4.4 BSD) + - This is not really a feature but incorrect characters in + formats are ignored and don't invalidate the format. +*/ +int __printf(size_t size, const char *string, va_list args) +{ + struct Format format; + + // Avoiding overflow by adjusting the size argument. + if(!size || size > __stdio_buffer_size) + size = __stdio_buffer_size; + + // Initializing character() working values. + written = 0; + total = 0; + max = size; + + // Parsing the format string. At each iteration, a literal character, a + // '%%' identifier or a format is parsed. + while(*string) + { + // Literal text. + if(*string != '%') + { + character(*string++); + continue; + } + + // Literal '%'. + if(string[1] == '%') + { + string += 2; + character('%'); + continue; + } + + // Getting the format. + format = get_format(&string); + if(!format.type) break; + +/* + // Displaying an information message. + printf( + "Format found :%s%c%c, options %d, and %d.%d " + "digits\n", + format.size ? " " : "", + format.size ? format.size : ' ', + format.type, + format.flags, + format.digits, + format.mantissa + ); +*/ + + switch(format.type) + { + // Signed integers. + case 'd': + case 'i': + format._int = va_arg(args, signed int); + + // Reducing value depending on format size. + switch(format.size) + { + case 'h': + format._int &= 0x0000ffff; + break; + case 'i': + format._int &= 0x000000ff; + break; + } + + format_di(format); + break; + + // Unsigned integers. + case 'u': + format._unsigned = va_arg(args, unsigned int); + format_u(format); + break; + case 'o': + case 'x': + case 'X': + format._unsigned = va_arg(args, unsigned int); + format_oxX(format); + break; + +/* // Exponent notation. + case 'e': + case 'E': + format._double = va_arg(args, double); + format_e(format); + break; +*/ + // Characters. + case 'c': + format._int = va_arg(args, signed int) & 0xff; + format_c(format); + break; + + // Strings. + case 's': + format._pointer = va_arg(args, const char *); + format_s(format); + break; + + // Pointers. + case 'p': + format._unsigned = va_arg(args, unsigned int); + format_p(format); + break; + + // Character counter. + case 'n': + *va_arg(args, int *) = written; + break; + } + } + + // Adding a terminating NUL character. Function character() should have + // left an empty byte for that. + __stdio_buffer[written] = 0; + return total; +} + +/* + format_di() + + Subroutine itoa(). Writes the given signed integer to the internal + buffer, trough function character(). + It is used by conversion specifiers 'd' and 'i'. + Options '#' and '0' have no effect. +*/ +static void format_di(struct Format format) +{ + // In integer display, character number includes pure digits and + // additional zeros and spacing. + // The precision represents the number of digits (pure digits and + // zeros) to print. + // For example: ' 0004', pure digits: 1, digits: 4, characters: 5. + + int sign = 0; + signed int x = format._int; + // Using integers to store the number pure digits and additional spaces + // and zeros. + int bspaces, zeros, digits = 0, espaces; + // Using a multiplier to output digit in the correct order. + int multiplier = 1; + + // Returning if the argument is null with an explicit precision of + // zero, but only if there are no spaces. + if(!x && format.characters == -1 && !format.precision) return; + + + + //--- + // Computations. + //--- + + // Computing the number of digits and the multiplier. + x = abs(format._int); + if(!x) digits = 1; + else while(x) + { + digits++; + x /= 10; + if(x) multiplier *= 10; + } + + // Getting the corresponding spacing. + get_spacing(format, &bspaces, &sign, &zeros, digits, &espaces); + + + + //--- + // Output. + //--- + + character_n(' ', bspaces); + if(sign) character(sign); + character_n('0', zeros); + + x = abs(format._int); + // Writing the pure digits, except if the value is null with an + // explicit precision of zero. + if(x || format.precision) while(multiplier) + { + character((x / multiplier) % 10 + '0'); + multiplier /= 10; + } + + character_n(' ', espaces); +} + +/* + format_u() + Unsigned integers in base 10. Options ' ', '+' and '#' have no effect. +*/ +static void format_u(struct Format format) +{ + int bspaces, zeros, digits = 0, espaces; + int x = format._unsigned; + int multiplier = 1; + int c; + + // Computing number of digits. + if(!x) digits = 1; + else while(x) + { + digits++; + x /= 10; + if(x) multiplier *= 10; + } + + get_spacing(format, &bspaces, NULL, &zeros, digits, &espaces); + + //--- + // Output. + //--- + + character_n(' ', bspaces); + character_n('0', zeros); + + x = format._unsigned; + while(multiplier) + { + character('0' + (x / multiplier) % 10); + multiplier /= 10; + } + + character_n(' ', espaces); +} + +/* + format_oxX() + Unsigned integers in base 8 or 16. + Since the argument is unsigned, options ' ' and '+' have no effect. + Option '#' adds prefix '0' in octal or '0x' in hexadecimal. +*/ +static void format_oxX(struct Format format) +{ + // In unsigned display, the digit number specifies the minimal number + // of characters that should be output. If the prefix (alternative + // form) is present, it is part of this count. + // Integer part and decimal part digit numbers behave the same way as + // in signed integer display. + + // Using integers to store the number of digits, zeros and spaces. + int bspaces, zeros, digits = 0, espaces; + unsigned int x = format._unsigned; + int multiplier = 0, shift, mask; + int c, disp; + + + + //--- + // Computations. + //--- + + shift = (format.type == 'o') ? (3) : (4); + mask = (1 << shift) - 1; + disp = (format.type == 'x') ? (39) : (7); + + // Computing number of digits. + if(!x) digits = 1; + else while(x) + { + digits++; + x >>= shift; + if(x) multiplier += shift; + } + + // Getting the spacing distribution. + get_spacing(format, &bspaces, NULL, &zeros, digits, &espaces); + + + + //--- + // Output. + //--- + + character_n(' ', bspaces); + x = format._unsigned; + + // Writing the alternative form prefix. + if(format.flags & Alternative && x) + { + character('0'); + if(format.type != 'o') character(format.type); + } + + character_n('0', zeros); + + // Extracting the digits. + while(multiplier >= 0) + { + c = (x >> multiplier) & mask; + c += '0' + (c > 9) * disp; + + character(c); + multiplier -= shift; + } + + character_n(' ', espaces); +} + +/* + format_e() + Exponent notation. Option '#' has no effect. + +static void format_e(struct Format format) +{ + // In exponent display, the precision is the number of digits after the + // dot. + + // Using an integer to store the number exponent. + int exponent = 0; + // Using a double value for temporary computations, and another to + // store the format parameter. + double tmp = 1, x = format._double; + // Using spacing variables. Default length is for '0.e+00'; + int bspaces, zeros, sign, length = 6, espaces; + // Using an iterator and a multiplier. + int i, mul; + + + + //--- + // Computations. + //--- + + // Computing the exponent. For positive exponents, increasing until + // the temporary value gets greater than x. + if(x > 1) + { + // Looping until we haven't reached a greater exponent. + while(tmp < x) + { + // Incrementing the exponent. + exponent++; + // Multiplying the test value. + tmp *= 10; + } + // Removing an additional incrementation. + exponent--; + } + // For negative exponents, decreasing until it's lower. + else while(tmp > x) + { + // Decrementing the exponent. + exponent--; + // Dividing the test value. + tmp *= 0.1; + } + + // Adding a character if the exponent is greater that 100. + if(exponent >= 100) length++; + // Adding another one if it's greater than 1000. + if(exponent >= 1000) length++; + + // Adjusting the format precision, defaulting to 6. + if(format.precision == -1) format.precision = 6; + // Adding the decimal digits. + length += format.precision; + + // Getting the space repartition. + get_spacing(format, &bspaces, &sign, &zeros, length, &espaces); + + + + //--- + // Output. + //--- + + // Writing the beginning whitespaces. + character_n(' ', bspaces); + // Writing the sign if existing. + if(sign) character(sign); + // Writing the zeros. + character_n('0', zeros); + + // Initializing x. + x = abs(format._double) / tmp; + // Writing the first digit. + character(x + '0'); + character('.'); + + // Writing the decimal digits. + for(i = 0; i < format.precision; i++) + { + // Multiplying x by 10 and getting rid of the previous digit. + x = (x - (int)x) * 10; + // Writing the current digit. + character(x + '0'); + } + + // Writing the exponent letter and its sign. + character(format.type); + character(exponent < 0 ? '-' : '+'); + + // Getting a positive exponent. + exponent = abs(exponent); + + // Using a multiplier for the exponent. + if(exponent >= 1000) mul = 1000; + else if(exponent >= 100) mul = 100; + else mul = 10; + + // Writing the exponent characters. + while(mul) + { + // Writing the next character. + character((exponent / mul) % 10 + '0'); + // Dividing the multiplier. + mul *= 0.1; + } + + // Writing the ending whitespaces if left-aligned. + character_n(' ', espaces); +} +*/ + +/* + format_c() + Character output. Only handles left alignment and spacing. + Options '#', '0', ' ' and '+', as well as mantissa digit number, have + no effect. +*/ +static void format_c(struct Format format) +{ + // In character display, the digit number represents the number of + // characters written, including the argument and additional + // whitespaces. + + int spaces = format.characters - 1; + int left = format.flags & LeftAlign; + + if(!left) character_n(' ', spaces); + character(format._int & 0xff); + if(left) character_n(' ', spaces); +} + +/* + format_s() + String output. Spaces if needed. +*/ +void format_s(struct Format format) +{ + // In string display, the character number specify the minimum size of + // output (padded with whitespaces if needed) and the precision + // specify the maximum number of string characters output. + + int string = format.precision; + int spaces; + + const char *str = format._pointer; + int length, i; + int left = format.flags & LeftAlign; + + // Computing length of string and number of whitespaces. + length = strlen(str); + if(string > length || string == -1) string = length; + spaces = format.characters - string; + + if(!left) character_n(' ', spaces); + for(i = 0; i < string; i++) character(str[i]); + if(left) character_n(' ', spaces); +} + +/* + format_p() + Pointer output. Simple hexadecimal dump. Prints "(nil)" if pointer is + NULL. +*/ +void format_p(struct Format format) +{ + // Pointer display falls back to %#08x in the pointer is non-null, + // "(nil)" otherwise. + + unsigned int x = format._unsigned; + int bspaces, zeros, digits = 0, espaces; + int c; + + digits = x ? 10 : 5; + get_spacing(format, &bspaces, NULL, &zeros, digits, &espaces); + + character_n(' ', bspaces); + character_n('0', zeros); + + if(x) + { + character('0'); + character('x'); + while(x) + { + c = x >> 28; + c += '0' + 39 * (c > 9); + character(c); + x <<= 4; + } + } + else + { + character('('); + character('n'); + character('i'); + character('l'); + character(')'); + } + + character_n(' ', espaces); +} diff --git a/src/stdio/vsnprintf.c b/src/stdio/vsnprintf.c new file mode 100644 index 0000000..5cc13e3 --- /dev/null +++ b/src/stdio/vsnprintf.c @@ -0,0 +1,15 @@ +#include +#include +#include + +/* + vsnprintf() + The most generic formatted printing function around there. +*/ +int vsnprintf(char *str, size_t size, const char *format, va_list args) +{ + int x = __printf(size, format, args); + strncpy(str, __stdio_buffer, size); + + return x; +} diff --git a/src/stdio/vsprintf.c b/src/stdio/vsprintf.c new file mode 100644 index 0000000..448c9da --- /dev/null +++ b/src/stdio/vsprintf.c @@ -0,0 +1,15 @@ +#include +#include +#include + +/* + vsprintf() + Prints to a string from an argument list. +*/ +int vsprintf(char *str, const char *format, va_list args) +{ + int x = __printf(0, format, args); + strncpy(str, __stdio_buffer, __stdio_buffer_size); + + return x; +} diff --git a/src/string/strchr.c b/src/string/strchr.c new file mode 100644 index 0000000..c90725d --- /dev/null +++ b/src/string/strchr.c @@ -0,0 +1,11 @@ +#include + +/* + strchr + Searches a character in a string. +*/ +const char *strchr(const char *str, int value) +{ + while(*str && *str != value) *str++; + return *str ? str : NULL; +} diff --git a/src/string/strcpy.c b/src/string/strcpy.c new file mode 100644 index 0000000..7659120 --- /dev/null +++ b/src/string/strcpy.c @@ -0,0 +1,11 @@ +#include + +/* + strcpy() + Copies a string to another. +*/ +char *strcpy(char *destination, const char *source) +{ + size_t length = strlen(source); + return memcpy(destination, source, length); +} diff --git a/src/string/strncpy.c b/src/string/strncpy.c new file mode 100644 index 0000000..98422fa --- /dev/null +++ b/src/string/strncpy.c @@ -0,0 +1,20 @@ +#include + +/* + strncpy() + Copies part of a string to another. +*/ +char *strncpy(char *destination, const char *source, size_t size) +{ + size_t length = strlen(source); + + if(length >= size) + { + return memcpy(destination, source, size); + } + else + { + memset(destination + length, 0, size - length); + return memcpy(destination, source, length); + } +} diff --git a/src/tales/dprint.c b/src/tales/dprint.c new file mode 100644 index 0000000..5547c52 --- /dev/null +++ b/src/tales/dprint.c @@ -0,0 +1,18 @@ +#include +#include +#include + +/* + dprint() + Prints a formatted string. Works the same as printf(). +*/ +void dprint(int x, int y, const char *format, ...) +{ + va_list args; + + va_start(args, format); + __printf(0, format, args); + va_end(args); + + dtext(__stdio_buffer, x, y); +} diff --git a/src/tales/gprint.c b/src/tales/gprint.c new file mode 100644 index 0000000..37e6862 --- /dev/null +++ b/src/tales/gprint.c @@ -0,0 +1,18 @@ +#include +#include +#include + +/* + gprint() + Prints a formatted string. Works the same as printf(). +*/ +void gprint(int x, int y, const char *format, ...) +{ + va_list args; + + va_start(args, format); + __printf(0, format, args); + va_end(args); + + gtext(__stdio_buffer, x, y); +}