From c63d7b812e45c93ed011134ffc1d54387ee6b61d Mon Sep 17 00:00:00 2001 From: lephe Date: Thu, 28 Jul 2016 18:12:07 +0200 Subject: [PATCH] Added bitmap part rendering and text colors, proper gray text. Enhanced demo app (wip). --- Makefile | 11 +- TODO | 12 +- demo/gintdemo.c | 347 +++----------------------- demo/gintdemo.h | 114 +++++++++ demo/resources/bitmap_opt.bmp | Bin 2810 -> 0 bytes demo/resources/bopti_thumbs.bmp | Bin 0 -> 1250 bytes demo/resources/font_modern.bmp | Bin 24698 -> 24698 bytes demo/resources/isometric.bmp | Bin 0 -> 4134 bytes demo/resources/items.bmp | Bin 92378 -> 99322 bytes demo/resources/opt_bitmap.bmp | Bin 0 -> 3194 bytes demo/resources/opt_tales.bmp | Bin 0 -> 3194 bytes demo/resources/symbol.bmp | Bin 554 -> 0 bytes demo/resources/symbol2.bmp | Bin 242 -> 0 bytes demo/resources/zelda.bmp | Bin 0 -> 72922 bytes demo/test_bopti.c | 222 ++++++++++++++++ demo/test_gray.c | 93 +++++++ demo/test_keyboard.c | 82 ++++++ demo/test_tales.c | 158 ++++++++++++ doc/bopti.md | 2 +- gintdemo.g1a | Bin 30046 -> 37666 bytes include/display.h | 16 +- include/gint.h | 2 +- include/gray.h | 11 +- include/internals/bopti.h | 12 +- include/internals/tales.h | 19 +- include/keyboard.h | 52 ++-- include/stdlib.h | 14 ++ include/tales.h | 17 +- libc.a | Bin 12430 -> 12430 bytes libgint.a | Bin 68010 -> 72922 bytes src/bopti/bopti_internals.c | 26 +- src/bopti/dimage.c | 2 +- src/bopti/dimage_part.c | 65 +++++ src/bopti/gimage.c | 4 +- src/bopti/gimage_part.c | 85 +++++++ src/core/gint.c | 8 +- src/core/syscalls.s | 7 - src/display/font_system.bmp | Bin 32762 -> 32762 bytes src/gray/gline.c | 6 +- src/keyboard/keyboard_sh7305.c | 13 +- src/keyboard/keyboard_sh7705.c | 2 - src/mpu/gint_sh7305.c | 6 +- src/stdio/stdio_format.c | 2 - src/stdlib/abs.c | 7 + src/stdlib/calloc.c | 12 + src/string/strchr.c | 2 +- src/tales/dtext.c | 92 ------- src/tales/gprint.c | 14 -- src/tales/gtext.c | 14 -- src/tales/tales_configuration.c | 16 +- src/tales/tales_internals.c | 160 +++++++++++- src/tales/{dprint.c => tales_print.c} | 17 +- src/tales/tales_text.c | 23 ++ 53 files changed, 1227 insertions(+), 540 deletions(-) create mode 100644 demo/gintdemo.h delete mode 100644 demo/resources/bitmap_opt.bmp create mode 100644 demo/resources/bopti_thumbs.bmp create mode 100644 demo/resources/isometric.bmp create mode 100644 demo/resources/opt_bitmap.bmp create mode 100644 demo/resources/opt_tales.bmp delete mode 100644 demo/resources/symbol.bmp delete mode 100644 demo/resources/symbol2.bmp create mode 100644 demo/resources/zelda.bmp create mode 100644 demo/test_bopti.c create mode 100644 demo/test_gray.c create mode 100644 demo/test_keyboard.c create mode 100644 demo/test_tales.c create mode 100644 src/bopti/dimage_part.c create mode 100644 src/bopti/gimage_part.c create mode 100644 src/stdlib/abs.c create mode 100644 src/stdlib/calloc.c delete mode 100644 src/tales/dtext.c delete mode 100644 src/tales/gtext.c rename src/tales/{dprint.c => tales_print.c} (51%) create mode 100644 src/tales/tales_text.c diff --git a/Makefile b/Makefile index e358b80..0607f44 100644 --- a/Makefile +++ b/Makefile @@ -29,10 +29,12 @@ ob = sh3eb-elf-objcopy wr = g1a-wrapper # Flags -cflags = -m3 -mb -nostdlib -I include -ffreestanding -std=c11 -Os +cflags = -m3 -mb -nostdlib -I include -ffreestanding -std=c11 -Os \ +-W -Wall -Wextra -pedantic # Demo application (could be done better) demo-src = $(notdir $(wildcard demo/*.[cs])) +demo-dep = $(wildcard demo/*.h) demo-ld = demo/gintdemo.ld demo-icon = demo/icon.bmp demo-res = $(notdir $(wildcard demo/resources/*)) @@ -83,8 +85,9 @@ hdr-dep = $(wildcard include/*.h include/internals/*.h) # C source file template: # $1 module name # $2 filename +# $3 dependencies define rule-c-source -build/$1_$2.o: src/$1/$2 $(hdr-dep) +build/$1_$2.o: src/$1/$2 $3 $(cc) -c $$< -o $$@ $(cflags) -I src/$1 endef @@ -128,7 +131,7 @@ $(target-g1a): $(target-std) $(target-lib) $(demo-obj) $(foreach mod,$(modules), \ $(foreach source,$(mod-$(mod)-c), $(eval \ - $(call rule-c-source,$(mod),$(source)))) \ + $(call rule-c-source,$(mod),$(source),$(hdr-dep)))) \ $(foreach source,$(mod-$(mod)-asm), $(eval \ $(call rule-asm-source,$(mod),$(source)))) \ ) @@ -145,7 +148,7 @@ build/display_font_system.bmp.o: src/display/font_system.bmp # Demo application -build/demo_%.c.o: demo/%.c +build/demo_%.c.o: demo/%.c $(hdr-dep) $(demo-dep) $(cc) -c $< -o $@ $(cflags) build/demo_font_%.bmp.o: demo/resources/font_%.bmp diff --git a/TODO b/TODO index e2f2ba8..f830f93 100644 --- a/TODO +++ b/TODO @@ -9,21 +9,15 @@ ~ needs investigation -@ vram overflow -@ keyboard test threaded interface +@ possibility of vram overflow with text ++ bitmap blending modes + have timers use structures from 7705.h and 7305.h -+ full and partial transparency ++ partial transparency + gint vs. ML with 248x124 at (-60, -28) + call exit handlers + compute frequencies -+ gray text -+ upgraded blending modes -+ blending modes for text -+ information masks for text + test all font encodings -+ font clipping -+ bitmap parts - improve exception handler debugging information (if possible) - full rtc driver (time) diff --git a/demo/gintdemo.c b/demo/gintdemo.c index 4f14e51..19f097b 100644 --- a/demo/gintdemo.c +++ b/demo/gintdemo.c @@ -1,17 +1,11 @@ -#include -#include +#include "gintdemo.h" #include #include #include #include -#include #include -#include -#include -#include <7305.h> - #include @@ -21,207 +15,28 @@ // Not really beautiful... but this will do. //--- -void print(int x, int y, const char *format, ...) +void locate(int x, int y, const char *str) { if(x < 1 || x > 21 || y < 1 || y > 8) return; + if(gray_runs()) gtext(x * 6 - 5, y * 8 - 8, str); + else dtext(x * 6 - 5, y * 8 - 8, str); +} +void print(int x, int y, const char *format, ...) +{ 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); + locate(x, y, __stdio_buffer); } -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 - 8); - else dtext(str, x * 6 - 5, y * 8 - 8); -} - - - -//--- -// 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 - there is a timer artifact. The keyboard state timer uses the same - period as the (internal) keyboard analysis timer, but there is a time - gap between a keyboard analysis and an update on the screen. -*/ -void keyboard_test_timer(void) -{ - volatile unsigned char *state = keystate(); - - dclear_area(5, 10, 71, 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); - - 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(); -} - -/* - keyboard_test() - Displays a multi-getkey test as well as the keyboard state in real - time. -*/ -void keyboard_test(void) -{ - int x = 0; - char str[3]; - int keys[4] = { 0 }; - int i; - - timer_start(TIMER_USER, 1700, TIMER_Po_256, keyboard_test_timer, 0); - - dclear(); - locate("Keyboard state:", 0, 0); - locate("multi-getkey ^^", 50, 55); - dupdate(); - - 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; - locate(str, 100, 0); - - for(i = 0; i < 4; i++) - { - str[0] = hexa((keys[i] >> 4) & 0x0f); - str[1] = hexa(keys[i] & 0x0f); - str[2] = 0; - locate(str, 100, 16 + 10 * i); - } - - #undef hexa - - dupdate(); - } - - timer_stop(TIMER_USER); -} - - -/* - bitmap_test() - Displays various bitmaps to ensure bopti is working correctly. -*/ -/* -void bitmap_test(void) -{ - extern Image res_bitmap_opt_start; - extern Image res_symbol_start; - extern Image res_symbol2_start; - extern Image res_sprites_start; - extern Image res_swords_start; - extern Image res_items_start; - - Image *opt = &res_bitmap_opt_start; - Image *sybl = &res_symbol_start; - Image *sybl2 = &res_symbol2_start; - Image *sprites = &res_sprites_start; - Image *swords = &res_swords_start; - Image *items = &res_items_start; - - uint32_t a32 = 0xffffffff; - int black_bg = 0, gray = 0; - int key; - int x = 20, y = 10; - - while(1) - { - if(gray) - { - gray_start(); - gclear(); - - if(black_bg) greverse_area(0, 0, 127, 63); - gimage(swords, 0, 57); - - gimage(items, x, y); - - gupdate(); - } - else - { - gray_stop(); - dclear(); - - if(black_bg) dreverse_area(0, 0, 127, 63); - dimage(opt, 0, 57); - - dimage(sybl, 30 & a32, 40); - dimage(sybl2, 62 & a32, 40); - - dupdate(); - - } - - key = getkey(); - if(key == KEY_EXIT) break; - - if(key == KEY_F1) gray = !gray; - if(key == KEY_F2) a32 ^= 31; - if(key == KEY_F3) black_bg = !black_bg; - - if(key == KEY_UP) y--; - if(key == KEY_DOWN) y++; - if(key == KEY_LEFT) x--; - if(key == KEY_RIGHT) x++; - } - - gray_stop(); - return; -} -*/ - - /* text_test() Renders text. -*/ + void text_test(void) { extern Font res_font_modern_start; @@ -242,115 +57,27 @@ void text_test(void) while(getkey() != KEY_EXIT); } - - - -/* - gray_test() - Runs the gray engine. */ -void gray_test(void) -{ - extern Image res_opt_gray_start; - - int *v1, *v2; - - int delays[2]; // { light, dark } - int key, changed = 1, i; - int selected = 0; - - gray_getDelays(delays, delays + 1); - gray_start(); - - while(1) - { - if(changed) - { - gray_setDelays(delays[0], delays[1]); - gclear(); - - v1 = gray_lightVRAM(); - v2 = gray_darkVRAM(); - - for(i = 0; i < 63; i++) - { - v1[(i << 2)] = v1[(i << 2) + 1] = - -((i & 31) < 16); - v2[(i << 2)] = v2[(i << 2) + 1] = - -(i < 32); - } - - locate("light", 15, 2); - print(15, 3, "%d", delays[0]); - - locate("dark", 15, 5); - print(15, 6, "%d", delays[1]); - - locate("\x02", 14, selected ? 6 : 3); - - gimage(&res_opt_gray_start, 0, 56); - gupdate(); - } - - changed = 0; - - key = getkey_opt(Getkey_RepeatArrowKeys, 1); - if(key == KEY_EXIT) break; - - changed = 1; - - switch(key) - { - case KEY_F1: - selected = !selected; - break; - case KEY_F2: - delays[0] = isSH3() ? 985 : 994; - delays[1] = 1609; - break; - case KEY_F3: - delays[0] = 860; - delays[1] = 1298; - break; - case KEY_UP: - delays[selected] += 10; - break; - case KEY_DOWN: - if(delays[selected] >= 110) delays[selected] -= 10; - break; - case KEY_RIGHT: - delays[selected]++; - break; - case KEY_LEFT: - if(delays[selected] >= 101) delays[selected]--; - break; - default: - changed = 0; - break; - } - } - - gray_stop(); -} /* printf_test() Tests formatting functions. -*/ + void printf_test(void) { dclear(); - locate("Formatted printing", 1, 1); + locate(1, 1, "Formatted printing"); 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); + print(2, 7, "%%6p NULL :\"%6p\"", NULL); dupdate(); while(getkey() != KEY_EXIT); } +*/ /* static const unsigned char screen[1024] = { @@ -504,7 +231,7 @@ void debug(void) tlb_debug() Displays the TLB contents and some information. Only available for SH7705, because the SH7305's TLB is much more complicated. -*/ + void tlb_debug(void) { // Entry address address (pointer in the address array), entry data @@ -573,6 +300,7 @@ void tlb_debug(void) key = getkey(); } } +*/ /* main_menu() @@ -615,8 +343,8 @@ void main_menu(int *category, int *app) "View TLB (SH3 only)", NULL }; - const char **list; - int list_len; + const char **list = NULL; + int list_len = 0; extern unsigned int bgint, egint; extern unsigned int romdata; @@ -630,7 +358,7 @@ void main_menu(int *category, int *app) int i; mpu = mpu_names[MPU_CURRENT < 5 ? MPU_CURRENT : 5]; - text_configure_default(); + text_configure(NULL, Color_Black); while(1) { @@ -644,7 +372,7 @@ void main_menu(int *category, int *app) switch(tab) { case 0: - locate("Demo application", 1, 1); + locate(1, 1, "Demo application"); print(2, 3, "gint version: %5s", GINT_VERSION_STR); print(2, 4, "handler size: %5d", gint_size); print(2, 5, "mpu type: %7s", mpu); @@ -654,17 +382,17 @@ void main_menu(int *category, int *app) break; case 1: - locate("Test list", 1, 1); + locate(1, 1, "Test list"); list = list_tests; break; case 2: - locate("Performance", 1, 1); + locate(1, 1, "Performance"); list = list_perfs; break; case 3: - locate("Debug", 1, 1); + locate(1, 1, "Debug"); list = list_debug; break; @@ -672,7 +400,7 @@ void main_menu(int *category, int *app) print(1, 1, "Tab %d", tab); break; } - dimage(&res_opt_menu_start, 0, 56); + dimage(0, 56, &res_opt_menu_start); if(list) { @@ -680,10 +408,10 @@ void main_menu(int *category, int *app) while(list[list_len]) list_len++; for(i = scroll; list[i] && i < scroll + 6; i++) - locate(list[i], 2, i - scroll + 2); + locate(2, i - scroll + 2, list[i]); - if(scroll > 0) locate("\x0d", 20, 2); - if(scroll + 6 < list_len) locate("\x0e", 20, 7); + if(scroll > 0) locate(20, 2, "\x0d"); + if(scroll + 6 < list_len) locate(20, 7, "\x0e"); dreverse_area(0, 8 * (index - scroll) + 8, 127, 8 * (index - scroll) + 15); @@ -794,26 +522,33 @@ int main(void) switch((category << 8) | app) { case 0x0101: - keyboard_test(); + test_keyboard(); break; case 0x0102: - gray_test(); + test_gray(); break; case 0x0103: -// bitmap_test(); + test_bopti(); break; case 0x0104: - text_test(); + test_tales(); break; case 0x0105: -// rtc_test(); +// test_rtc(); break; case 0x0106: - printf_test(); +// test_printf(); + break; + + case 0x0201: +// perf_bopti(); + break; + case 0x0202: +// perf_tales(); break; case 0x0301: - if(isSH3()) tlb_debug(); +// if(isSH3()) debug_tlb(); break; } } diff --git a/demo/gintdemo.h b/demo/gintdemo.h new file mode 100644 index 0000000..a7805a3 --- /dev/null +++ b/demo/gintdemo.h @@ -0,0 +1,114 @@ +//--- +// +// gint demo application +// +// Displays some tests cases for many features of the library. +// +//--- + +#ifndef _GINTDEMO_H +#define _GINTDEMO_H + +//--- +// Main routines and common functions. +//--- + +/* + main() + No need for description. +*/ +int main(void); + +/* + main_menu() + Displays the main menu and returns user's choice by setting the + category and application. Category is 0 when the user leaves the + application. +*/ +void main_menu(int *category, int *app); + +/* + locate() + Displays text using a system-like monospaced font on a 21*8 grid. +*/ +void locate(int x, int y, const char *str); + +/* + print() + Locates a string using formatted printing. +*/ +void print(int x, int y, const char *format, ...); + + + +//--- +// Test applications. +//--- + +/* + test_keyboard() + Displays a real-time multigetkey() and the keyboard state. +*/ +void test_keyboard(void); + +/* + test_gray() + Lets the user set the gray delays and see the results. +*/ +void test_gray(void); + +/* + test_bopti() + Displays and moves many kinds of bitmaps. +*/ +void test_bopti(void); + +/* + test_tales() + Displays some text using different modes and clipping options. +*/ +void test_tales(void); + +/* + test_rtc() + Just a clock. +*/ +void test_rtc(void); + +/* + test_printf() + Some text formatting. +*/ +void test_printf(void); + + + +//--- +// Performance applications. +//--- + +/* + perf_bopti() + Compares bopti and MonochromeLib. +*/ +void perf_bopti(void); + +/* + perf_tales() + Compares tales and the system's text rendering functions. +*/ +void perf_tales(void); + + + +//--- +// Debug applications. +//--- + +/* + debug_tlb() + On SH7705, displays the TLB contents. Does nothing on SH7305. +*/ +void debug_tlb(void); + +#endif // _GINTDEMO_H diff --git a/demo/resources/bitmap_opt.bmp b/demo/resources/bitmap_opt.bmp deleted file mode 100644 index dd8d1230bc3e54e185fee97df6ce19b30d414975..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2810 zcmeH^u@1s83`Bti2}TyarwbDc-@(Sl#0U0^Sjwpxp>Beqryix0^E}&iH;ha`y>@=5l*{b?NUe7~4gwv$Y7&8ld}S0%zx+0u7NyCFxIJ zkF|2@k7hRX=@Ae|E@q^0#0mue3QZ4%j!3#K5LhxR)!Bo4 zIPVIC;a#d7(wGSZVrRt~2y7S=aVQDpUC@KfSm$0&%@WrH27(vDFm@Deq6hLzV(6iy SBzV>n0nxj#6MoE_(`y>Pd7r2hQmnFy}^;r(;QfBoJsgqO8IvqoS3kw3kD^}p;B zz}n!X0X?76RXvBVp0n$>{~!9Qj3cT;dJ*)?!&Ix7#AlVM)y1sn0m>>P89u!-m5(wc z%+~(HFl5Tl6sFu{nL-*jfsGLeAOR_9qG1H4n8$NbGUZkv*xElPSzdj3fFVDQBdJgG zzLi^J?aKQKsy>Q#BBVZ~Vd4{j#(>${pNUj)wrd)4!${#<{y5(*_Dl5*>Ft-Hxb2Z0efo@49?)P2(ME{{uKGKfqamp z90_IaTw)Y+*segSP1W0kEm*CvyqoV|bdcz8s!8}uS>!W{74lRRYlf})fp0&<_f(N* zmB5B?6~g;!aZtxkSYB~VQU-q*{rm8%J_~9S&G-cCdyb2tK{8}0Q~pQhG6SzU;v<0| oR(o$~0iz`mAu)_@7~0n_^*b7)BYgG^Y_CP+9YR$fLHs!W1xkZwnE(I) delta 278 zcmXYsv1-Cl6o!%Fg$seikkbalMxh|JmS%}U?O@_AE#0KUoxAAbcBj`@wY9|R zSz?}Wszq2m2;>Wi|IVh+Z*{_fnKMOtTXh~Mgm@xQCbA+j8Nmh;(X|6F@-Ld0T<`}W g?32Kh8M-fD^*Vkc2=O~2s9~GIdra%^z34MN0X<=4O#lD@ diff --git a/demo/resources/isometric.bmp b/demo/resources/isometric.bmp new file mode 100644 index 0000000000000000000000000000000000000000..5241b601dab9bab756a145bb1902c33287acb879 GIT binary patch literal 4134 zcmd5%J5EGF3>%=N0Ev=@1`e_f6%ALR3Y)uyC&`jxW(2t6qBaw>JFL!&;#YRGYpZO6BUH4GQz?sK+ap#_J)xbXU z3oL1HtX%|W-ujN(S%SCVB3~}%)tl^7O>$K`-;+RmQ^q-?k1}O_*Xwe(v;>D#HKZ z!17Ek?|J7;K83tDI?fYXUCC99cUm>wHJdvRj*oQpKHGO^ac@Rx`pj$*tC<>MJ1ls2 z-!A&jXpQbD%j$h*wunWhEl=R61>U0dkT&$7e+}YUI4dUiq1gan28DUg@^v=iH;lUy z{XWvwJND4UjPe_>T)eC0);()r4nAh_3ydb@q#YVs%{%hh?EyGi%{wFTN$uEsw@gw| z*}ERX$?J+=mt!IkD+^9$W}8qdwBi>Wdl54Nao;l8iH8UE`SILyC#HR;=N3J_ReiW8 WfrjgO6XmSq9zSx=8ek&U^ZNqrBFN|f literal 0 HcmV?d00001 diff --git a/demo/resources/items.bmp b/demo/resources/items.bmp index ec6a4197916d61a3c6d3d2aa355301e987407267..c57f9345638707c12ffc0d6b4cba05269bbbc3db 100644 GIT binary patch delta 5408 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 literal 0 HcmV?d00001 diff --git a/demo/resources/opt_tales.bmp b/demo/resources/opt_tales.bmp new file mode 100644 index 0000000000000000000000000000000000000000..8f34e47611f921da87495803af7ba6fc505c87c6 GIT binary patch literal 3194 zcmd6ju};H45JU}CBS5mev*tB@ie;4o$T01KIztTv$L}!AK%Z< z)9*Q}e(HYf9&{h3S5+PLU!HtTOw;l0*XKij({$ zPVzn6^S9nhvo^fPMWQk2t((c?h928&3HwQaMsI&pQLrdB*nP9GCV7m0`@K)M32KB0I8OOmEo^x$1QvS literal 0 HcmV?d00001 diff --git a/demo/resources/symbol.bmp b/demo/resources/symbol.bmp deleted file mode 100644 index 74772f7625f807e0c91e1478a922af205d623c10..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 554 zcma)$F%Ez*3)cs6C;E;WY9*Tr zzmnP5vkE}V%XT#V_gjAx;&(gXkimUJX4+8A3o`Go+VC|J!g>I?uG$>-`28U)i(G>g dJ{*$Dlk+9)B5x>*LR~zJfYYMzT}cRPxDWe9w_E@K diff --git a/demo/resources/symbol2.bmp b/demo/resources/symbol2.bmp deleted file mode 100644 index be7ac38829e7e0f9666885700224813c2d84abd8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 242 zcmZ?r{lowPRX{2Sh}oc+kwF41Q2``{xgi)V03@8;gNk8nVreF<3jhEAk17rqfHT1I Ua2}X}%7Yt#Ll`IzmtkN401OEta{vGU diff --git a/demo/resources/zelda.bmp b/demo/resources/zelda.bmp new file mode 100644 index 0000000000000000000000000000000000000000..03440dd6ce9cb1a51f34232d1d2270348f3be255 GIT binary patch literal 72922 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 literal 0 HcmV?d00001 diff --git a/demo/test_bopti.c b/demo/test_bopti.c new file mode 100644 index 0000000..3b9ee45 --- /dev/null +++ b/demo/test_bopti.c @@ -0,0 +1,222 @@ +#include "gintdemo.h" +#include +#include +#include + +#include + +#include + +/* + test_bopti() + Displays and moves many kinds of bitmaps. Here are the images used: + + Name Size Color Alpha + --------------------------------------------------------- + items.bmp 266 * 124 Gray - + sprites.bmp 66 * 33 Gray - + swords.bmp 88 * 16 Gray Full + --------------------------------------------------------- + zelda.bmp 86 * 280 Mono - + isometric.bmp 37 * 27 Mono Full + Mono Greater + --------------------------------------------------------- +*/ + +static void getwh(Image *img, int *width, int *height) +{ + const unsigned char *data; + + if(!img) + { + *width = 0; + *height = 0; + return; + } + *width = img->width; + *height = img->height; + if(*width && *height) return; + + data = img->data; + *width = (data[0] << 8) | data[1]; + *height = (data[2] << 8) | data[3]; +} + +static void getxy(Image *img, int *x, int *y) +{ + int width, height; + + getwh(img, &width, &height); + *x = 64 - (width >> 1); + *y = 28 - (height >> 1); +} + +static Image *select(Image *current) +{ + extern Image res_bopti_thumbs_start; + extern Image + res_items_start, + res_sprites_start, + res_swords_start, + res_zelda_start, + res_isometric_start; + + struct { + Image *img; + const char *name; + const char *info; + } images[] = { + { &res_items_start, "Items", "Gray" }, + { &res_sprites_start, "Sprites", "Gray" }, + { &res_swords_start, "Swords", "Gray Alpha" }, + { &res_zelda_start, "Zelda", "Mono" }, + { &res_isometric_start, "Isometric", "Mono Alpha" }, + { NULL, NULL, NULL } + }; + + Image *thumbs = &res_bopti_thumbs_start; + int items = 0; + static int row = 0; + int leave = 1, i; + + while(images[items].img) items++; + + gray_start(); + + while(1) + { + gclear(); + locate(1, 1, "Select an image:"); + + for(i = 0; i < items && i < 7; i++) + { + locate(2, 2 + i + (i > row), images[i].name); + gimage_part(100, 8 + 8 * (i + (i > row)), thumbs, 0, + 8 * i, 7, 7); + if(i == row) + { + int width, height; + getwh(images[i].img, &width, &height); + print(2, 2 + i + 1, "%d\x04%d", width, height); + locate(10, 2 + i + 1, images[i].info); + } + } + + greverse_area(0, 8 * row + 8, 128, 8 * row + 23); + gupdate(); + + do + { + leave = 1; + + switch(getkey()) + { + case KEY_UP: + row = (row + items - 1) % items; + break; + case KEY_DOWN: + row = (row + 1) % items; + break; + case KEY_EXE: + return images[row].img; + case KEY_EXIT: + return current; + default: + leave = 0; + break; + } + } + while(!leave); + } + + gray_stop(); +} + +void test_bopti(void) +{ + extern Image res_opt_bitmap_start; + Image *img = NULL; + + int leave = 1; + int black_bg = 0; + int x = 0, y = 0; + + while(1) + { + if(img && (img->format & Channel_Light)) + { + gray_start(); + gclear(); + + if(black_bg) greverse_area(0, 0, 127, 63); + if(img) gimage(x, y, img); + + gclear_area(0, 55, 127, 63); + gimage(0, 56, &res_opt_bitmap_start); + gupdate(); + } + else if(img) + { + gray_stop(); + dclear(); + + if(black_bg) dreverse_area(0, 0, 127, 63); + if(img) dimage(x, y, img); + + dclear_area(0, 55, 127, 63); + dimage(0, 56, &res_opt_bitmap_start); + dupdate(); + } + else + { + gray_stop(); + + dclear(); + locate(3, 3, "No image selected"); + + dimage(0, 56, &res_opt_bitmap_start); + dupdate(); + } + + leave = 1; + do + { + leave = 1; + + switch(getkey()) + { + case KEY_EXIT: + gray_stop(); + return; + + case KEY_F1: + img = select(img); + getxy(img, &x, &y); + break; + case KEY_F5: + black_bg = !black_bg; + break; + + case KEY_UP: + y--; + break; + case KEY_DOWN: + y++; + break; + case KEY_LEFT: + x--; + break; + case KEY_RIGHT: + x++; + break; + + default: + leave = 0; + } + } + while(!leave); + } + + gray_stop(); + return; +} diff --git a/demo/test_gray.c b/demo/test_gray.c new file mode 100644 index 0000000..55c23ef --- /dev/null +++ b/demo/test_gray.c @@ -0,0 +1,93 @@ +#include "gintdemo.h" +#include +#include +#include + +/* + test_gray() + Lets the user set the gray delays and see the results. +*/ + +static void draw(int delay1, int delay2, int selected) +{ + extern Image res_opt_gray_start; + int *vl = gray_lightVRAM(); + int *vd = gray_darkVRAM(); + + gclear(); + + for(int i = 0; i < 63; i++) + { + int o = (i << 2) + 2; + vl[o] = vl[o + 1] = -((i & 31) < 16); + vd[o] = vd[o + 1] = -(i < 32); + } + + locate(3, 2, "light"); + print(3, 3, "%d", delay1); + + locate(3, 5, "dark"); + print(3, 6, "%d", delay2); + + locate(2, selected ? 6 : 3, "\x02"); + + gimage(0, 56, &res_opt_gray_start); + gupdate(); +} + +void test_gray(void) +{ + int delays[2]; // { light, dark } + int key, changed = 1; + int selected = 0; + + gray_getDelays(delays, delays + 1); + gray_start(); + + while(1) + { + if(changed) + { + gray_setDelays(delays[0], delays[1]); + draw(delays[0], delays[1], selected); + } + changed = 0; + + key = getkey_opt(Getkey_RepeatArrowKeys, 1); + if(key == KEY_EXIT) break; + + changed = 1; + + switch(key) + { + case KEY_F1: + selected = !selected; + break; + case KEY_F2: + delays[0] = isSH3() ? 985 : 994; + delays[1] = 1609; + break; + case KEY_F3: + delays[0] = 860; + delays[1] = 1298; + break; + case KEY_UP: + delays[selected] += 10; + break; + case KEY_DOWN: + if(delays[selected] >= 110) delays[selected] -= 10; + break; + case KEY_RIGHT: + delays[selected]++; + break; + case KEY_LEFT: + if(delays[selected] >= 101) delays[selected]--; + break; + default: + changed = 0; + break; + } + } + + gray_stop(); +} diff --git a/demo/test_keyboard.c b/demo/test_keyboard.c new file mode 100644 index 0000000..a10a78d --- /dev/null +++ b/demo/test_keyboard.c @@ -0,0 +1,82 @@ +#include "gintdemo.h" +#include +#include +#include + +/* + test_keyboard() + Displays a real-time multigetkey() and the keyboard state. +*/ + +static void draw(volatile unsigned char *state) +{ + int i, j, k, l; + int x, y; + + for(i = 0; i < 10; i++) for(j = 1; j < 8; j++) + { + // Eliminating keys that do not exist. + if(!i && j != 7) continue; + if(i && j == 7) continue; + if(i <= 4 && j == 6) continue; + if(i == 4 && j == 5) continue; + + x = 5 * j + 1; + y = 61 - 5 * i; + // Moving the [AC/ON] key. + if(!i) x = 5 * (5) + 1, y = 61 - 5 * (4); + + // Drawing a filled shape when the key is pressed. + if(state[i] & (128 >> j)) + { + for(k = -2; k <= 2; k++) for(l = -2; l <= 2; l++) + if(abs(k) + abs(l) <= 2) + dpixel(x + k, y + l, Color_Black); + } + // Drawing a square border otherwise. + else + { + for(k = -1; k <= 1; k++) for(l = -1; l <= 1; l++) + if(k || l) dpixel(x + k, y + l, Color_Black); + } + } +} + +void test_keyboard(void) +{ + const char *key_names[] = { + "F1", "F2", "F3", "F4", "F5", "F6", + "SHIFT", "OPTN", "VARS", "MENU", "Left", "Up", + "ALPHA", "x^2", "^", "EXIT", "Down", "Right", + "X,\x1d,T", "log", "ln", "sin", "cos", "tan", + "[frac]", "F\x0f\x09" "D", "(", ")", ",", "\x09", + "7", "8", "9", "DEL", "AC/ON", NULL, + "4", "5", "6", "\x04", "\x05", NULL, + "1", "2", "3", "+", "-", NULL, + "0", ".", "\x08", "(-)", "EXE", NULL + }; + + volatile unsigned char *state = keystate(); + int keys[4] = { 0 }; + int i; + + while(1) + { + multigetkey(keys, 4, 1); + if(keys[0] == KEY_EXIT && keys[1] == KEY_NONE) break; + + dclear(); + locate(1, 1, "Keyboard driver"); + locate(8, 3, "Pressed keys:"); + draw(state); + + if(keys[0] == KEY_NONE) locate(9, 4, ":None"); + else for(i = 0; i < 4 && keys[i] != KEY_NONE; i++) + { + locate( 9, i + 4, ":"); + locate(10, i + 4, key_names[keyid(keys[i])]); + } + + dupdate(); + } +} diff --git a/demo/test_tales.c b/demo/test_tales.c new file mode 100644 index 0000000..5a94190 --- /dev/null +++ b/demo/test_tales.c @@ -0,0 +1,158 @@ +#include "gintdemo.h" +#include +#include +#include + +#include + +/* + test_tales() + Displays some text using different modes and clipping options. +*/ + +static Font *select(Font *current) +{ + extern Font res_font_modern_start; + struct { + Font *font; + const char *name; + } fonts[] = { + { NULL, "gint default" }, + { &res_font_modern_start, "Modern" }, + }; + int font_number = 2; + + static int row = 0; + int i, leave; + + while(1) + { + text_configure(NULL, Color_Black); + + dclear(); + locate(1, 1, "Select a font:"); + + for(i = 0; i < font_number && i < 6; i++) + { + if(fonts[i].font) + { + int height = fonts[i].font->line_height; + int y = (i + 2) * 8 - 8 + ((7 - height) >> 1); + + text_configure(fonts[i].font, Color_Black); + dtext(7, y, fonts[i].name); + } + else + { + text_configure(NULL, Color_Black); + locate(2, i + 2, fonts[i].name); + } + + } + + dreverse_area(0, 8 * row + 8, 128, 8 * row + 15); + dupdate(); + + do + { + leave = 1; + + switch(getkey()) + { + case KEY_UP: + row = (row + font_number - 1) % font_number; + break; + case KEY_DOWN: + row = (row + 1) % font_number; + break; + case KEY_EXE: + return fonts[row].font; + case KEY_EXIT: + return current; + default: + leave = 0; + break; + } + } + while(!leave); + } +} + +void test_tales(void) +{ + enum Color colors[] = { Color_Black, Color_Dark, Color_Light, + Color_White, Color_Invert }; + extern Image res_opt_tales_start; + Font *font = NULL; + + int black_bg = 0; + int color = 0; + int i, x, height; + int leave; + + gray_start(); + while(1) + { + gclear(); + if(black_bg) greverse_area(0, 0, 127, 54); + + if(font) + { + text_configure(font, colors[color]); + height = font->line_height + 1; + } + else + { + text_configure(NULL, colors[color]); + height = 8; + } + + for(i = 0; i < 6 && 2 + (i + 1) * height < 56; i++) + { + char str[17]; + for(int j = 0; j < 16; j++) str[j] = 32 + (i << 4) + j; + str[16] = 0; + + gtext(2, 2 + i * height, str); + } + + gimage(0, 56, &res_opt_tales_start); + + x = 45 + 8 * color; + gline(x, 57, x + 5, 57, Color_Black); + gline(x, 57, x, 62, Color_Black); + gline(x + 5, 57, x + 5, 62, Color_Black); + gline(x, 62, x + 5, 62, Color_Black); + + gupdate(); + + do + { + leave = 1; + + switch(getkey()) + { + case KEY_F1: + gray_stop(); + font = select(font); + gray_start(); + break; + case KEY_F2: + color = (color + 1) % 5; + break; + case KEY_F5: + black_bg = !black_bg; + break; + + case KEY_EXIT: + gray_stop(); + text_configure(NULL, Color_Black); + return; + default: + leave = 0; + break; + } + } + while (!leave); + } +} diff --git a/doc/bopti.md b/doc/bopti.md index 4cb6b2b..b460253 100644 --- a/doc/bopti.md +++ b/doc/bopti.md @@ -187,7 +187,7 @@ using the operation functions. 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). +means that it indicates which pixels are not transparent). * Non-transparent gray images also have two layers: one for each [gray buffer](gray-engine). Both are for the `draw` operation. * Transparent gray images have three layers. Two of them constitute the two-bit diff --git a/gintdemo.g1a b/gintdemo.g1a index 10aa989fd952a1d114b5bd08b27235bcf2306b2e..6c2964ec9ba281226d817f4a1339312627a1ad4e 100644 GIT binary patch delta 20561 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 delta 11640 zcmeHtdw5gVmG9c;=xGUCl8qlATgUPn1CnjP<}E)0hB(-~f|C%g41NM3#u#u2i4MUf zCd4t~^rpTUrqLvPDaqs;oSLs;I-QPExGAKxwZI{yrMYeJ)%$=Q|Uoh{Tl_#07dy{gTz3RECGg*k7TU|)ElhfoUXY56C3Vq~^b|MXuGv_Bd z6B)@_a5~bKmkC3tzedhE)xe9uNpj9rA(b6_HkUdMwS*im55!g4^Wz)Wdd8bdJFRtF z+Cl@`qWI2)0aIUe-gtei!{Rb{hN#czGLU{iqfe+msGhb=C+T*7)vpWayV$(#0bMcb zJgUmfrY{=5AcIFmdUDP@N6wUfoyiQvrH$mYxg3W!uXViK5~{Qh#O23(#ygXm);3NI zcsQ1i;3)a?5g=RJ#cGvgG0BtCe@{-3D(%;`p4;+R&82M@)#>K$pD?8k67(E)Mt0RTxsVs2}q6N4g1H^$nxQ+V#AQSRvux)Y=xn= zqW!>#P-|Ra7-sFyjffMugCic*M7DiIJ(2s?2n*+;+7C^1iE4j-qDxeJ$4I0{RQur( z^>7qK8v|;-M8&xgg)C>tIUQCKPm?pb%yDSM2f=(X*KJn_Z$FSdQL^@}Dr zP2(4u6WmNQ;5JF{Y4IjGt^2vz$XSOK@+6lbgUZ+Mt ze`>j5IBLYy9~VyJ`(wkYwcip>?fvF(n%!^WX&~k*lp%dN&{25gt9!m8VZgZ^5d~~6 zjN4BhXWb{rjFYq81f&B{gezrP=Q#8UIbL?W;rKzNJy7i#tGl&Z#oaIP@GGx}6q~3Wigm@h8@8;R`q(|HIlBt?xwq)|%uRF0 z>h~1xd)U3ju*V&1*i&li`dthA_<<4O*AMhR06&ds_D5k%3M9oXCxP~9VDU&%|Kei!N&x?%$|B`x)cmX>hs9fX>X^+uz)p2#PYdJ@ zvKq_IP+sN{!8_9@pmv7Ca_Tu{G|J{_A$`rkVqM<&X3O>3{K6w&w1iGIrrHCET%Jc) znR%Zbp>hj@VHN;wZ8P^G~2Q^q0&=7FldoSY4#NUH!CeOezmA4br! zImu}zoyi1;NO{o{NN^mQFnjz6yBgmQ(+{&7>MK)+#d3Jojm#@?!>Vv@`W4Htn&&<; z4{NT#^r)pPreQ75{bl1%dRPpR1Od+Mv; zt`Ve;!p_|T;=+W(ErDXbz5~gg`3arEfUQQ^DO@XS=(U-Lnd8`%(h3aX?sX;F#2w1- zRGY6~7xKIF3p-a1+LmN>E+0Su*nGVt`SJq0A+R7Vw;|s?{R#W>q)SCxF1s(6CSA~# z>Lp!TPN#agez`vD_X9?sdU-N>=(2K`Cob1rno*iqs;hf_h}k^C?$DLo5`!bZ>ht~? zlCF!@zuuq2=j6VOD8U9y7mRu1+LR&nm5d5Q-Rthlm|KLiRL?%aeZ50E z!k%V-piAZwL(}y>GoSCN!ySbl>Fa?3hZ@e1+T-MmIbU%vD%8Vy8jLW-RiyHyIU=WC zL*nN|bPFJDD1>@AQT;UlPS>yqDR;P=iY!j`{H@1Vb8F|!5094^YGW@Q=V@!=M0)Mg z@yo|;nS*4@y7V^%*_ZytHpgurR68@f1eY$TcIhZ3@SWdw|E9axU{n99dle?}5YX`2 zfLIvcSunzWDroly6m8ltQx%m}UG?@K<7WKGiw*1LUbx}*hGEr}qv7no4y&)c#B(3L z1a}SRdE-6qU<;%XVgMRh>4(glO%bbYtt(IH{;-b432O1jD7Ud1? z0JdBMWNmdJ{Sj~x;N~6zZsHuk{RR{ILskREYZ%j&nqYIM6^$+H0*I}Zb_6G(A9P@t zMVL{}C!8q-MAVc7#7GV4@2^uXnilFIKB1MIaXpiFiBNLtImKj7U{y-C`GwT2Z*yA3 zX9Y?oLugfGc2q&mDMwMJTsCLxs&Lbfn_kgkVq9u`2M)2Dir=y}eCNX$Dn*Vhb{K-O zC0OB0`aZ@}qNtx=(oE)~w_Oq^^HCR3tM3iQE@gRc2s?+#x-ot&uo0*R)}d@1lTrb? zJ~m9Q+@W|LNtLRpYgh0V8~Yf+kNDK7mZ#tN7jE&5HG1A#aV0De(yEpH3A>UeRI#7q z0{H+ySQSN=m?>;^DbB=rp>C#9p7=dAjAp4)ZYN$Y-giRH;?Z&s(s@XCB27fvinIu6 zGtvsAEl9T`eG=*WNOzowz0-%ZP0>yBJh1PCj^J2fDO?(t!liL3TpE|crEw`-8kfSQ z?Lf+u6wUT#|Jcw_692-&N&yImdcc5U*UZZB>$ zx({CXUmfhohCp7iq3%}Q=K~1)Th?|~791}%cU7$Z414(P<>s#CgG(1=b(Sgalnk~& zIh3+MIhT^|!IA&_rFBUht{tFgY|MX0gnt{M-8)mXXG3^GZZl_r}jb^7j5C#yX;6gkZjf0N`g z++=~oRG}}CNBTgb@`0^1byA(`h&r4Rgw;U=Ng0D$x0RXFORIAB^J@5uQHCJ`>g%-G z;#C)$?D<{eEh_GWjKcfZc%MW218{D)B~s4wsU?xT(ww?4>YhmDcB(y!Kc-lWHV zNOqqhrR8fP>_iz)D>VCcCe=CYa_s6PC-N7SvUJB{KWCv>LPRKQPk=$Z!MvKcyf?7Q z9}wLZKzjkl1r$x;y@5WZCp|$O$z4pJzU*8;a9chQprpW+R9)oW!Re&q{q0-$gFs+$ zrM<@D8QpO!HLp&M3v2xy)Vv`skqYW%e}vrIdQ5;cVT(5+yk& z)pOahEN5BL9%`sKJ4+OaIv+HAM`~#-oF-oHHJTnZQD{|s1@sb>s~K6)GB?8 z4ctK{i)xjcgO!<+PYIJxPTV-w9{xzl9p#>NO`}S8#vdOa<$eN>-i0l;1p}7$nag#Y zn`5xG17EGM79B6w)$~4SE;0^MC)>#eSh1;7za_0y=Pqb?u7!#JkoI(T{;At-ru*qE z-#yk7ia+aziYE73^b8Xo2g(4rXIhVvn2@cE=Khi0RDv^?2xwSZ z1+;Y=YAkcCH6=bxMp8gkrict-u5JT-Cfw{1G*V3r zm~?l*@DA%8n$^ODjEhROV~-}og4m!_`W-J%W}BU_L}g-X}kL zH)~1|O5-REbMql(|J>O^Zg%h6bMu)dALr&)sds4JV=M_ROhZ7hzP`SJoVnRx2E2M^ zZ*|cvfmcTapz1|nW28wzTyO2d6lR&c&wqi}^8tImy{L?Nx))a3|Jwr3SRiHcS*zxA zY>gRfJ}XX4&CQcLr{+E1sn0ulEGJLuG`6rjDKPbL!l@giKWsQAq0BJIP6ZK&Og^v| z{KxtRVtg9@Kl12vI1re^x!S3pb0W?kY$8voOvN-Tm5GeILll-p1E_GMtKsEZzNRU*Qd{J-W{@f)N z-~qu-PPZFnqwg|V3%90u8C3AVdMXDVe7J?$=B}X!c{#t%X!1^Ws8?p6(X4d()ccUG zIO+8+dcAR}pn6v`w%_YrFwMN5$n1(>>Qh8hi;1QK=4ZU#mjAGJ_WxCFN*l&_Ac7Q( zYeGJZGOxGUy8NZG;EC0BrW32zvjlI&z-@DxInMlmB`&&b@UPd;{44$cdi{<6F@Mx- zDs!1lu3~cvz*AFM$$+h>#Or-BmAzC(g13x}rZUn+uOl;CN7K#QX;E|;HDl%7UT;ki)&YM4_~XY900*#%hc%7{f}lV~=P)|O4t<}$JZMd&mk z*_I>XhP?#Kc}>JjCK993n3*UBofacM8}(HH)R;b(t04fY@0O7oIwwJzJ!KtjG_Rv( z=-iB_@OMx@2*5At6QCI?rE>pD#zf=LsR$FbM zb<=!u(lT;G8$UBe%c3uZqFvL;AnWA>iji%QwFr^Y(@ay*>aL(kfkZ~?AuEld)fsA# z=gpD~}U82sd>qe(;T~OoHxin6_UkqxXjS4dt zz25bnAQdr*$_0tgo|$yAAel+!vcp1US~GQMUn7%HOFl81TYQd`a8A&llY`?6S6-~ikl7B`&lQ*H^nAf|`6Ag7Na9}(Bm*F7j zpx3Z@&j}JMZ-vRu%L}9c&2b&0eEA_%KTgT=pJ<`{3)&^i@VL9zJvlnafo;h?-$Z3! zN^Ko+uEnOSa*DK`nq7AP0@>j=`XBMn3w}?|4SGuD$J}RWvvgMw%)(?Q3Ejeo`V--Y z+Gg<@8x{7mYqVFqOp@JiF4D>NNDJcFho#_gv9)G;crdB z%*v;n&WCqP&HMk&>D>FSDfr-HvB6n?a60FGe_?a-5IVH+j$UttN5)o{V}Mv6QM`+2 zkzb%kTqF9<`(I1GfO*t->8GFQR0Rd0zW>=$w;u&jDTa*aTn7qPrn52>gpOIAl zWYWti>@rK&zQNANRIosDw>W4$txd<30slGjy_JBrQRGrX*AAe!g6IPjg25oaj`mg!lA1;U`fhRl7w}>*8E$Q=F`orjizl zLB;znEheY>ima*_c0;hRWFbRfTSN`Lj$L@2RR9-h16`%Pz-$s^(^ZC(y^ z0DQ3|fM2rL>qz~kN*AvLMuDK>U7g_d#bx+$!>_&x^xT*CA@2r!UT<2m6B*u<7X$&G zZw6cdhRjOl1$@{sKnIur32*^uP&n0(%p_#w!|-|!{D-9K{}ZzR3?b8lki~+KC4k(_ z1W&2L^1AOQWb0Az3h*KDLtrV;hS)v~{DQ~$`w5vaLC6GfD>VpN6xdH3kd00glD|&K z1duQ_V!8pH=1vf@W^{lW_XwF9giH%=H67A2LC7jV$f}@o6$qIZjb8&!04IUFglrlJ zSrR%)AY}O*qFB^5Y{ ziss7(YDL`m20~`X*$sLN9kMXnRpf(27js6-_=SR^{js1&I(aHhkz+{O!J`3 zB5bHO>>VGh=E4arqnjE>eH1|$a(_V>CuHwa0Rl)R2w67>**hv7dkusv-5}}CN4a7_ z$ShJk&2+_4HdZDF(iUK1_YpER2$|ZiFV{=@a-BOWdy1qTHTqR1qhFAqf?rLDjrS8W zH=R`ZnNyFYi^Um`2@6$dL3LGcfH+lvNL7RCI?2sCND|MHUpwcU2w9`x7LTg@0^~4X zEJX()$6X=Dux|BU)}uO4ZlMTrx^bfSkx9JBJV&+Z-$=-2$W-+ZQP0y7t4at89kYGv zj>n~_@;6*@>VVzFP?3QKyx{~PO8^y{ z29EzGRj}8on=NBbRw1~B#8xczKgtW-3Z?sBrb4-r3{*;S^1C!cUPWtV86J1{;)E<7 z8wxg|$YV_Ad?!_W;BM=V^Jh3emgC)(wAr8OUnm#2bpAHi5@|$U;Pd=Me)=yFvP@N@ z@TjIwJk5H9?QA8?JYSkp1FbSO15OvsK>COH2^ z!A-9UZsr6b8?}(=@#kZ~DzIxB;paX0A2At^Sd$kgWU8K>chqM$rHICD28y>;(|%a{S|KzX=qHuUJ6bSGOZjVX=IDrPI3M`n(r^5wXRuI z5ByS&jebS^fqs#&Y09Yhlz@Pz2B(hl2`A%%>c2q9BqOO^Qwa}X>_e8Wd5e9jU&nTt zPYRjVe(lWIn-tQXrZ==5Y|vJ&^?b)#rTsb~n~va@3PQFlXrZs%x$=k7JlWz>%d=fE z@)~fj@6mj=jCLYC1$k(QA`vm=8wgoBDmWoa0U^V0P0!gVO86xwWWH%sCC#Oi9v3Vx zR|yL1QCr2TX(R->psy3M;XfStmm6<({Wi_4=`NYAl|aafRUNA5#AdBZD2~wyCDA5z zd%P4OWL8-%C6n6qjfCt^AY`fRy7&*wDrB^s>Cq%alLV9b`;tsmK4`FB?P^ z)AZii_Lv|>SDSjRPs+>_8V}tGjpF}-&=@cpIvWb!5y#%U6B|7EUE6zFlg%GPp;4P0 z8q4yB#w}nDuO9w-vp7zn;9o<;* z9n-itPNUj!HWu@5&)w06XiNkSj^hXK@#b6qH164QJv2sVL(O#X4t}8+FQ%Ark!)AB zv=rld{0xt(A}uA{2W{jDE=Ac=3K?w_vW6&>9HMubMsxG@_N%9_JrI1C8I4~$kMuQF zJ!pDn^dpMy`6}2cz3KjE(|;fRC!1Eg_K~&g9>7U*@ACfb6y?Sr1@@2rCqHxt#u3NiQU^O4_uE zq*QxadPZhecFv64nX_i|pY+I?mtQbv?!3aH`3n{DX>ZL_i!->s8MU)AxWi=Fokh@VK?V|PZdshM3x&U;k^wL|fzawyQ%zV9CUNO61cip`_;e z&a38Gfd#xgumGPAPN|JmMqWsX8!-=SYhwe>a7Ero62DUtkDwxH_%T$Zg)6c~Qo|K1 zk4%e0b}=f#-%tgtBRS!Uwj(KzBFifb;U4CZys+T#=azwJUUupZmF?C8^`7iGOs_``MB2Ft1Pje>hhgpKIs;^SRbZ|CzaZy~mY~ zt}XhT9rST6kf_}5%Hki@67H^=@RA1a@5z1dt?NySe17@sRi4|geEZ{vY$eBzRec_) za9*^r)YQSy&V8wp@rjo}W$p>%swb z!#j%-ye(O8c23KhUUzox#u3r8?D4FvxjP%YS#PF3orAB_(2N!TyrHi?VZfjIRO+@_ zCU-C*!Z)4tALixmoO`j}J9py^arxt!Z>DZb-52TQ?rS*9+s&fAUqZq&TY?Q-!u-^y zXX7)+{Vb4PW2&*18yuF+?AH5@3f{N^2rTMrARvA+Iy~`%E(y^?_Clq+`eggQmvhLWXsK_T2;TLH? pI#%f5Z_v--wLO1 - enum Color { Color_White = 0, @@ -26,6 +24,9 @@ enum Color Color_Invert = 5, }; +// This header needs enum Color to be defined. +#include + /* struct Image This structure holds information about a bitmap encoded with fxconv. @@ -146,6 +147,15 @@ void dline(int x1, int y1, int x2, int y2, enum Color color); Displays a monochrome image in the vram. Does a real lot of optimization. */ -void dimage(struct Image *image, int x, int y); +void dimage(int x, int y, struct Image *image); + +/* + dimage_part() + Draws a portion of an image, defined by its bounding rectangle. + Point (left, top) is included, but (left + width, top + height) is + excluded. +*/ +void dimage_part(int x, int y, struct Image *img, int left, int top, + int width, int height); #endif // _DISPLAY_H diff --git a/include/gint.h b/include/gint.h index 8e7fa35..098f9da 100644 --- a/include/gint.h +++ b/include/gint.h @@ -122,7 +122,7 @@ void gint_stop_7305(void); 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); +const char *gint_strerror_7305(void); //--- diff --git a/include/gray.h b/include/gray.h index de14fba..c77cf83 100644 --- a/include/gray.h +++ b/include/gray.h @@ -127,7 +127,16 @@ void gline(int x1, int y1, int x2, int y2, enum Color color); gimage() Displays a gray image in the vram. */ -void gimage(struct Image *image, int x, int y); +void gimage(int x, int y, struct Image *image); + +/* + gimage_part() + Draws a portion of a gray image, defined by its bounding rectangle. + Point (left, top) is included, but (left + width, top + height) is + excluded. +*/ +void gimage_part(int x, int y, struct Image *image, int left, int top, + int width, int height); diff --git a/include/internals/bopti.h b/include/internals/bopti.h index 3ed11cb..7e0009c 100644 --- a/include/internals/bopti.h +++ b/include/internals/bopti.h @@ -27,13 +27,13 @@ */ enum Channel { - Channel_Mono = 0x01, - Channel_Light = 0x02, - Channel_Dark = 0x04, + Channel_FullAlpha = 0x01, + Channel_LightAlpha = 0x02, + Channel_DarkAlpha = 0x04, - Channel_FullAlpha = 0x08, - Channel_LightAlpha = 0x10, - Channel_DarkAlpha = 0x20, + Channel_Mono = 0x08, + Channel_Light = 0x10, + Channel_Dark = 0x20, }; /* diff --git a/include/internals/tales.h b/include/internals/tales.h index 5e101cd..7f5dd26 100644 --- a/include/internals/tales.h +++ b/include/internals/tales.h @@ -13,7 +13,16 @@ #include #include +#define OPERATE_ARGS uint32_t *operators, int height, int x, int y + extern struct Font *font; +extern enum Color color; + +/* + tales_init() + Configures tales with the default font (which is part of gint). +*/ +void tales_init(void) __attribute__((constructor)); /* getCharacterIndex() @@ -29,7 +38,8 @@ int getCharacterIndex(int c); Operates on the vram using the given operators. The x-coordinate should be a multiple of 32. There should be `height` operators. */ -void operate(uint32_t *operators, int height, int x, int y); +void operate_mono(OPERATE_ARGS); +void operate_gray(OPERATE_ARGS); /* update() @@ -44,4 +54,11 @@ void operate(uint32_t *operators, int height, int x, int y); */ int update(uint32_t *operators, int height, int available, uint32_t *glyph); +/* + render() + Renders text without any formatting analysis, using the given operation + function. +*/ +void render(int x, int y, const char *str, void (*op)(OPERATE_ARGS)); + #endif // _INTERNALS_TALES_H diff --git a/include/keyboard.h b/include/keyboard.h index b622a6e..7b57390 100644 --- a/include/keyboard.h +++ b/include/keyboard.h @@ -171,38 +171,52 @@ volatile unsigned char *keystate(void); /* getkey() Blocking function with auto-repeat and SHIFT modifying functionalities. - Reproduces the behavior of the system's GetKey(). - - @return Pressed key matrix code. + Reproduces the behavior of the system's GetKey(). Returns the matrix + code with a possible MOD_SHIFT bit. */ int getkey(void); /* getkey_opt() - Enhances getkey() with most general functionalities. + Enhances getkey() with most general functionalities. An OR-combination + of options may be given as second argument. 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. + As getkey(), returns the pressed key matrix code, possibly with + modifiers depending on the options. */ 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 + Listens the keyboard for simultaneous key hits. This functions fills + array `keys` with `count` keycodes, adding KEY_NONE at the end if + more than `count` keys are pressed. + If `max_cycles` is non-zero and nothing happens after `max_cycles` + cycles, this function returns an array of KEY_NONE. + + WARNING: + Because of hardware limitations, this function generally yields poor + results. Rectangle and column effects make it read unpressed keys as + pressed (see documentation for more information). The more pressed + keys, the more errors. + + The results are guaranteed to be exact if two keys or less are pressed. + With three keys or more, column effects (on SH4) and rectangle effects + (on both platforms) mess up the results by making this function think + that some keys that are actually unpressed, are pressed. + + This function is designed to make combinations of one or two arrow keys + with another key as viable as possible. On SH4, this works pretty well + even if combinations like Left + Down + SHIFT trigger ALPHA sometimes. + On SH3, rectangle effects are *always* present, making it impossible to + use Left + Down or Up + Right with any other key in their rows without + having this function return junk. + + Any other combination of keys may quite randomly result in variably + incorrect results. Please do not expect multigetkey() to work as an + ideal multi-key analyzer. */ void multigetkey(int *keys, int count, int max_cycles); diff --git a/include/stdlib.h b/include/stdlib.h index 0eb5591..e77a140 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -63,4 +63,18 @@ void free(void *ptr); +//--- +// Integer arithmetic. +//--- + +/* + abs() + Returns the absolute value of an integer. +*/ +int abs(int x); +// Use a macro instead, when possible. +#define abs(x) ((x) < 0 ? -(x) : (x)) + + + #endif // _STDLIB_H diff --git a/include/tales.h b/include/tales.h index 5d5c25f..e1304c3 100644 --- a/include/tales.h +++ b/include/tales.h @@ -77,7 +77,7 @@ struct Font uint16_t index[16]; - __attribute__((aligned(4))) const struct FontGlyph glyphs[]; + __attribute__((aligned(4))) const uint32_t glyphs[]; } __attribute__((aligned(4))); // Useful shorthand for user code. @@ -91,27 +91,22 @@ typedef struct Font Font; /* text_configure() - Sets the font and mode to use for the following print operations. + Sets the font and color to use for subsequent text operations. Pass + font = NULL to use the default font. */ -void text_configure(struct Font *font); - -/* - text_configure_default() - Configures tales with the default font (which is part of gint). -*/ -void text_configure_default(void) __attribute__((constructor)); +void text_configure(struct Font *font, enum Color color); /* dtext() Prints the given string, without any analysis. */ -void dtext(const char *str, int x, int y); +void dtext(int x, int y, const char *str); /* gtext() Prints the given raw string. */ -void gtext(const char *str, int x, int y); +void gtext(int x, int y, const char *str); /* dprint() diff --git a/libc.a b/libc.a index ddbff9ece00dd69298253749f656d551b7a75216..c7e02abb4ba3f0129ce97a9dcfcc19916c50204e 100644 GIT binary patch delta 379 zcmeB6>`R;=!)9(|XkuhGQOQ=;je$WRiGe}r9Rq_{7z2akF$M-%JqXr3H?c;GDWhoO z0%^hGyn>?4yplAA_+kiS;!gF6zdI+tX5^Y&&1gUQ7o*zbos623Wth~UhEG1gBDOh> zDTWEk-+X{Yiy6lLz`R;=!)9V`VQFDLQOQ>J5(9%k90P;!F$h*jV_;A|#lWBz#lWC>YGRERS3xC1 zd~r!pPHNudhvHHbpNg>odC3_?6Ay|`{M|WuI-}X-FN_-8MVWc&Aay{Q$p;vXCo3>1 zv6+}!8k!hSzQ85EIi4w+32dvG!R7-jTFfx^2liWV@dRFG=E?57!caM&K8ej!1frQH zCkw#E9!Q37ju-yPBw=W(fCLOp%q&5EGB=rgfJJO`oNN(~gs~-(0tF-$1!Cfx|7)5s zOB$LPU{eBg;svg9CP_nctR?`Z3&bLrB`mSZnwxBXAnDIM*;p6iW()JlAp4SawV44+ C^kQTH diff --git a/libgint.a b/libgint.a index 895e9b7e0aa7431398456c0b443402a7bfe1f16b..a2df03caa0932906d809ec77923a699940f0a8b9 100644 GIT binary patch delta 8524 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 { - case Channel_Mono: - bopti_vram[offset] |= operator; - break; - case Channel_FullAlpha: bopti_vram[offset] &= ~operator; break; + case Channel_Mono: + bopti_vram[offset] |= operator; + break; + default: break; } @@ -36,6 +36,15 @@ void bopti_op_gray(int offset, uint32_t operator, struct Command *c) switch(c->channel) { + case Channel_FullAlpha: + bopti_v1[offset] &= ~operator; + bopti_v2[offset] &= ~operator; + break; + + case Channel_LightAlpha: + case Channel_DarkAlpha: + break; + case Channel_Mono: bopti_v1[offset] |= operator; bopti_v2[offset] |= operator; @@ -48,15 +57,6 @@ void bopti_op_gray(int offset, uint32_t operator, struct Command *c) case Channel_Dark: bopti_v2[offset] |= operator; break; - - case Channel_FullAlpha: - bopti_v1[offset] &= ~operator; - bopti_v2[offset] &= ~operator; - break; - - case Channel_LightAlpha: - case Channel_DarkAlpha: - break; } } diff --git a/src/bopti/dimage.c b/src/bopti/dimage.c index d4d300f..9f28532 100644 --- a/src/bopti/dimage.c +++ b/src/bopti/dimage.c @@ -5,7 +5,7 @@ dimage() Displays a monochrome image in the video ram. */ -void dimage(struct Image *img, int x, int y) +void dimage(int x, int y, struct Image *img) { if(img->magic != 0xb7) return; diff --git a/src/bopti/dimage_part.c b/src/bopti/dimage_part.c new file mode 100644 index 0000000..d4ce26d --- /dev/null +++ b/src/bopti/dimage_part.c @@ -0,0 +1,65 @@ +#include +#include + +/* + dimage_part() + Draws a portion of an image, defined by its bounding rectangle. + Point (left, top) is included, but (left + width, top + height) is + excluded. +*/ +void dimage_part(int x, int y, struct Image *img, int left, int top, + int width, int height) +{ + if(img->magic != 0xb7) return; + + struct Structure s; + struct Command command; + int actual_width; + int format = img->format, i = 0; + + if(format != Format_Mono && format != Format_MonoAlpha) return; + getStructure(img, &s); + + //--- + // Adjusting the bounding rectangle. + //--- + + // This is what happens when the bounding rectangle overflows from the + // image... + if(left < 0) left = 0; + if(top < 0) top = 0; + if(left + width > s.width) width = s.width - left; + if(top + height > s.height) height = s.height - top; + + if(x + left + width <= 0 || x > 127 || y + top + height <= 0 || y > 63) + return; + + command.top = (y < 0) ? (top - y) : top; + command.bottom = top + ((y + height > 64) ? (64 - y) : height); + command.left = ((x < 0) ? (left - x) : left) >> 5; + actual_width = (x + width > 128) ? (128 - x) : width; + command.right = left + ((actual_width + 31) >> 5) - 1; + + command.op = bopti_op_mono; + + if(x >= 0) getMasks(x, x + actual_width - 1, command.masks); + else getMasks(0, actual_width + x - 1, command.masks); + + bopti_vram = display_getCurrentVRAM(); + + while(format) + { + if(format & 1) + { + command.x = x - left; + command.y = y - top; + command.channel = (1 << i); + + bopti(s.data, &s, &command); + s.data += s.layer_size; + } + + format >>= 1; + i++; + } +} diff --git a/src/bopti/gimage.c b/src/bopti/gimage.c index 27df32b..e7499f4 100644 --- a/src/bopti/gimage.c +++ b/src/bopti/gimage.c @@ -6,7 +6,7 @@ gimage() Displays a gray image in the video ram. */ -void gimage(struct Image *img, int x, int y) +void gimage(int x, int y, struct Image *img) { if(img->magic != 0xb7) return; @@ -21,7 +21,7 @@ void gimage(struct Image *img, int x, int y) // Adjusting image parameters. //--- - if(x + s.width < 0 || x > 127 || y + s.height < 0 || y > 63) return; + if(x + s.width <= 0 || x > 127 || y + s.height <= 0 || y > 63) return; command.top = (y < 0) ? (-y) : (0); command.bottom = (y + s.height > 64) ? (64 - y) : (s.height); diff --git a/src/bopti/gimage_part.c b/src/bopti/gimage_part.c new file mode 100644 index 0000000..391c43b --- /dev/null +++ b/src/bopti/gimage_part.c @@ -0,0 +1,85 @@ +#include +#include +#include + +/* +#define min(a, b) ((a) < (b) ? (a) : (b)) +#define max(a, b) ((a) > (b) ? (a) : (b)) + +struct Rect +{ + int top, bottom; + int left, right; +}; +struct Rect intersect(struct Rect r1, struct Rect r2) +{ + struct Rect result; + result.top = max(r1.top, r2.top); + result.bottom = min(r1.bottom, r2.bottom); + result.left = max(r1.left, r2.left); + result.right = min(r1.right, r2.right); +} +*/ + +/* + gimage_part() + Draws a portion of a gray image, defined by its bounding rectangle. + Point (left, top) is included, but (left + width, top + height) is + excluded. +*/ +void gimage_part(int x, int y, struct Image *img, int left, int top, + int width, int height) +{ + if(img->magic != 0xb7) return; + + struct Structure s; + struct Command command; + int actual_width; + int format = img->format, i = 0; + + getStructure(img, &s); + + //--- + // Adjusting the bounding rectangle. + //--- + + // This is what happens when the bounding rectangle overflows from the + // image... + if(left < 0) left = 0; + if(top < 0) top = 0; + if(left + width > s.width) width = s.width - left; + if(top + height > s.height) height = s.height - top; + + if(x + left + width <= 0 || x > 127 || y + top + height <= 0 || y > 63) + return; + + command.top = (y < 0) ? (top - y) : top; + command.bottom = top + ((y + height > 64) ? (64 - y) : height); + command.left = ((x < 0) ? (left - x) : left) >> 5; + actual_width = (x + width > 128) ? (128 - x) : width; + command.right = left + ((actual_width + 31) >> 5) - 1; + + command.op = bopti_op_gray; + + if(x >= 0) getMasks(x, x + actual_width - 1, command.masks); + else getMasks(0, actual_width + x - 1, command.masks); + + bopti_v1 = gray_lightVRAM(); + bopti_v2 = gray_darkVRAM(); + + while(format) + { + if(format & 1) + { + command.x = x - left; + command.y = y - top; + command.channel = (1 << i); + + bopti(s.data, &s, &command); + s.data += s.layer_size; + } + + format >>= 1; + i++; + } +} diff --git a/src/core/gint.c b/src/core/gint.c index ec5f526..ec3a2cb 100644 --- a/src/core/gint.c +++ b/src/core/gint.c @@ -110,7 +110,7 @@ void gint_quit(void) //--- #include -#define print(str, x, y) dtext(str, 6 * (x) - 5, 8 * (y) - 7) +#define print(str, x, y) dtext(6 * (x) - 5, 8 * (y) - 7, str) #define hexdigit(n) ((n) + '0' + 39 * ((n) > 9)) void hex(unsigned int x, int digits, char *str) @@ -138,7 +138,7 @@ void gint_exc(void) unsigned int spc; char str[11]; - text_configure_default(); + text_configure(NULL, Color_Black); __asm__("\tstc spc, %0" : "=r"(spc)); @@ -175,7 +175,7 @@ void gint_tlb(void) unsigned int spc; char str[11]; - text_configure_default(); + text_configure(NULL, Color_Black); __asm__("\tstc spc, %0" : "=r"(spc)); @@ -242,5 +242,5 @@ const char *gint_strerror(int is_tlb) if(isSH3()) return gint_strerror_7705(is_tlb); else - return gint_strerror_7305(is_tlb); + return gint_strerror_7305(); } diff --git a/src/core/syscalls.s b/src/core/syscalls.s index ca5397f..621a84a 100644 --- a/src/core/syscalls.s +++ b/src/core/syscalls.s @@ -25,13 +25,6 @@ _malloc: nop 1: .long 0xacd -_calloc: - mov.l syscall_table, r2 - mov.l 1f, r0 - jmp @r2 - nop -1: .long 0xe6b - _free: mov.l syscall_table, r2 mov.l 1f, r0 diff --git a/src/display/font_system.bmp b/src/display/font_system.bmp index 0f49d5b296a2fde8eed023b55d1695f0d747ad30..5e7a0a7aa2caac33bedba8ed0199a32f3fe9da01 100644 GIT binary patch delta 1236 zcma)6L2J}N7-dm|vDqe$gpIDIEdp91WM;niecyZU%gmzGkJxZ7oA^3sBe4z0zV~XodR}0#79c9PNDmo^?wY6+ z45VWg$`@=zdj%5f``=g7;~o;vMQ_gRRQh-22xp-;a(Xk?g>%wmywUk!_vLWR^U%BO zBM}QM(8Sbf$qL=g75o9dj`GTQEFVA)x@b8?bo)(2D;{A>8`9dL`Bj7#9nm%d%yI$1~5+Jj`0e^MB5$4+V{=iJY~!>q{@Pm(VA*;f8!da+Zsb z_gyY(sWiL(5$ORF&cT3U8J(|lvpJ;nK$~@R8-6U!?HHxkx0@kXmv;r6JbP3%>DmH) zRa3S-dbdg=`F>q?ahEF4%nhX@lg5LDHov%FXu z>#OwSG<{bqZ4zo_dHw)8c>~T<@<^*DAqlzbudjM2b84d->XRkh68KhgSq?|%iitD# zEDYoY()(__HuT@6eIB)RCjDb*5MIg9C)Vf5OMNEuMAoFHCnzC0z-G>|v3wCzljAy5 mYpKGg8iaC|Sqpn2mX|o7G~x=y8s2pA=bcE#t&aKd$L`->1Hvr; delta 1099 zcmZWoO-~b16ip+J4jntSWYWP(ZIgz^MnZ$8gwRN>5O4t$wJeInv1}B-hLt3WsVlc{ zIR1eC153t@B*ZS>@L&(=vM~uOXZNT1CQ7H;E?HVc@ zMMvD{=fgcwI1@mul?*o-KPVu%s9@@G2JhphJF;{$#4aR>$t#QIP_Mx>I@Kj&8nB}p zyNRKZjG;NKcPVwAP7t3Jw#ljt{MiMTtiY-p@K)YRZ)CaCAcDNf)A=5#>00-WLtVwD z&L1_mQ)M^aoQCNsRZ{GUchvnX0rA4%l|#kU;MMjqzGUEBG}$-19cC7@Ze-IhPXjgPTaZZ!7px(7H^0g=Cx4d(bA8G1WjJ z6-1KsA$!WdJfF?rd#lU=p@nt18QnGXfEs?W(VSo&N)!Z;zJ% diff --git a/src/gray/gline.c b/src/gray/gline.c index bd7cadd..9b31480 100644 --- a/src/gray/gline.c +++ b/src/gray/gline.c @@ -11,7 +11,11 @@ void gline(int x1, int y1, int x2, int y2, enum Color color) if(color == Color_None) return; else if(color == Color_Invert) c1 = c2 = Color_Invert; - else c1 = color & 1, c2 = color >> 1; + else + { + c1 = 3 * (color & 1); + c2 = 3 * (color >> 1); + } display_useVRAM(gray_lightVRAM()); dline(x1, y1, x2, y2, c1); diff --git a/src/keyboard/keyboard_sh7305.c b/src/keyboard/keyboard_sh7305.c index 2df0ec6..09ef109 100644 --- a/src/keyboard/keyboard_sh7305.c +++ b/src/keyboard/keyboard_sh7305.c @@ -22,7 +22,7 @@ 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 ! + overclock). Take care of the effect of overclock! Column effects May have something to do with register HIZCRB not being used here. When @@ -48,9 +48,7 @@ static void kdelay(void) __asm__ ( - r4("nop\n\t") - r4("nop\n\t") - r4("nop\n\t") + "nop\n\t" ); #undef r4 @@ -142,5 +140,10 @@ void keyboard_updateState_7305(volatile unsigned char *keyboard_state) { int i; - for(i = 0; i < 10; i++) keyboard_state[i] = krow(i); + keyboard_state[8] = krow(8); + for(i = 0; i < 10; i++) + { + if(i != 7 && i != 8) keyboard_state[i] = krow(i); + } + keyboard_state[7] = krow(7); } diff --git a/src/keyboard/keyboard_sh7705.c b/src/keyboard/keyboard_sh7705.c index 4f3b27a..7f0c75c 100644 --- a/src/keyboard/keyboard_sh7705.c +++ b/src/keyboard/keyboard_sh7705.c @@ -30,8 +30,6 @@ static void kdelay(void) __asm__ ( r4("nop\n\t") - r4("nop\n\t") - r4("nop\n\t") ); #undef r4 diff --git a/src/mpu/gint_sh7305.c b/src/mpu/gint_sh7305.c index 03570b3..5a27924 100644 --- a/src/mpu/gint_sh7305.c +++ b/src/mpu/gint_sh7305.c @@ -83,12 +83,8 @@ volatile void *gint_reg_7305(enum Register reg) gint_strerror() Returns a string that describe the error set in EXPEVT. This string is not platform-dependent. - Some exception codes represent different errors when invoked inside the - general exception handler and the TLB error handler. Parameter 'is_tlb' - should be set to zero for general exception meanings, and anything non- - zero for TLB error meanings. */ -const char *gint_strerror_7305(int is_tlb) +const char *gint_strerror_7305(void) { volatile unsigned int *expevt = gint_reg_7305(Register_EXPEVT); diff --git a/src/stdio/stdio_format.c b/src/stdio/stdio_format.c index 392ddc7..d1f10c7 100644 --- a/src/stdio/stdio_format.c +++ b/src/stdio/stdio_format.c @@ -165,7 +165,6 @@ static struct Format get_format(const char **pointer) const char *string = *pointer, *ptr; int c, i; - char precision[10]; // Moving the string pointer after the '%' character. string++; @@ -601,7 +600,6 @@ 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; diff --git a/src/stdlib/abs.c b/src/stdlib/abs.c new file mode 100644 index 0000000..3a10e8f --- /dev/null +++ b/src/stdlib/abs.c @@ -0,0 +1,7 @@ +#include +#undef abs + +int abs(int x) +{ + return (x < 0) ? (-x) : (x); +} diff --git a/src/stdlib/calloc.c b/src/stdlib/calloc.c new file mode 100644 index 0000000..9c8421a --- /dev/null +++ b/src/stdlib/calloc.c @@ -0,0 +1,12 @@ +#include + +/* + calloc() + Allocates 'n' elements of size 'size' and wipes the memory area. + Returns NULL on error. +*/ +void *calloc(size_t n, size_t size) +{ + void *ptr = malloc(n * size); + return ptr ? memset(ptr, 0, n * size) : NULL; +} diff --git a/src/string/strchr.c b/src/string/strchr.c index c90725d..7954fcf 100644 --- a/src/string/strchr.c +++ b/src/string/strchr.c @@ -6,6 +6,6 @@ */ const char *strchr(const char *str, int value) { - while(*str && *str != value) *str++; + while(*str && *str != value) str++; return *str ? str : NULL; } diff --git a/src/tales/dtext.c b/src/tales/dtext.c deleted file mode 100644 index 6d44e2b..0000000 --- a/src/tales/dtext.c +++ /dev/null @@ -1,92 +0,0 @@ -#include -#include - -#include -#include -#include - -/* - dtext() - Prints the given string, without any analysis. -*/ -void dtext(const char *str, int x, int y) -{ - // Operator data, and number of available bits in the operators (which - // is the same for all operators, since they are treated equally). - uint32_t *operators; - int available; - - // Raw glyph data, each glyph being represented by one or several - // longwords, and an index in this array. - uint32_t *data = (uint32_t *)font->glyphs; - int index; - - // Height of each glyph. This value is constant because the storage - // format requires it: it allows greater optimization. - int height; - - int i; - - - - if(!font) return; - - // Allocating data. There will be one operator for each line. - height = font->data_height; - if(x > 127 || y > 63 || y <= -height) return; - - operators = alloca(height * sizeof(uint32_t)); - for(i = 0; i < height; i++) operators[i] = 0; - if(!operators) return; - - // Computing the initial operator offset to have 32-aligned operators. - // This allows to write directly video ram longs instead of having to - // shift operators, and do all the vram operation twice. - available = 32 - (x & 31); - x &= ~31; - - // Displaying character after another. - while(*str) - { - index = getCharacterIndex(*str++); - if(index < 0) continue; - - // Updating the operators. - available = update(operators, height, available, data + index); - - // Continue until operators are full (this includes an - // additional bit to add a space between each character). - if(available > 1) - { - available--; - continue; - } - - // When operators are full, updating the video ram and - // preparing the operators for another row. - - operate(operators, height, x, y); - x += 32; - if(x > 96) break; - - memset(operators, 0, height << 2); - if(available >= 0) - { - available = 31 + available; - continue; - } - - // Finishing update, in case it has been only partially done, - // because there was not enough bits available to fit all the - // information. Also adding a space, assuming that characters - // aren't more than 30 bits wide. - available += 32 + (data[index] >> 24); - available = update(operators, height, available, data + index); - available--; - } - - // Final operation. - if(x <= 96 && available < 32) operate(operators, height, x, y); - -// free(operators); -} diff --git a/src/tales/gprint.c b/src/tales/gprint.c index 37e6862..f67f3c1 100644 --- a/src/tales/gprint.c +++ b/src/tales/gprint.c @@ -2,17 +2,3 @@ #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); -} diff --git a/src/tales/gtext.c b/src/tales/gtext.c deleted file mode 100644 index b12d483..0000000 --- a/src/tales/gtext.c +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include - -/* - gtext() - Prints the given raw string. -*/ -void gtext(const char *str, int x, int y) -{ - display_useVRAM(gray_lightVRAM()); - dtext(str, x, y); - display_useVRAM(gray_darkVRAM()); - dtext(str, x, y); -} diff --git a/src/tales/tales_configuration.c b/src/tales/tales_configuration.c index 394dd0f..916b761 100644 --- a/src/tales/tales_configuration.c +++ b/src/tales/tales_configuration.c @@ -5,17 +5,11 @@ text_configure() Sets the font and mode to use for the following print operations. */ -void text_configure(struct Font *next_font) -{ - font = next_font; -} - -/* - text_configure_default() - Configures tales with the default font (which is part of gint). -*/ -void text_configure_default(void) +void text_configure(struct Font *next_font, enum Color next_color) { extern Font gint_font_system_start; - text_configure(&gint_font_system_start); + if(next_font) font = next_font; + else font = &gint_font_system_start; + + color = next_color; } diff --git a/src/tales/tales_internals.c b/src/tales/tales_internals.c index 7e29d3f..a92ccac 100644 --- a/src/tales/tales_internals.c +++ b/src/tales/tales_internals.c @@ -1,7 +1,20 @@ #include +#include +#include #include +#include struct Font *font; +enum Color color; + +/* + tales_init() + Configures tales with the default font (which is part of gint). +*/ +void tales_init(void) +{ + text_configure(NULL, Color_Black); +} /* getCharacterIndex() @@ -78,16 +91,72 @@ int getCharacterIndex(int c) Operates on the vram using the given operators. The x-coordinate should be a multiple of 32. There should be `height` operators. */ -void operate(uint32_t *operators, int height, int x, int y) +void operate_mono(OPERATE_ARGS) { int *vram = display_getCurrentVRAM(); int vram_offset = (x >> 5) + (y << 2); + uint32_t op; int i; for(i = 0; i < height; i++) { - // TODO BLENDING MODES // - vram[vram_offset] |= operators[i]; + op = operators[i]; + + switch(color) + { + case Color_White: + vram[vram_offset] &= ~op; + break; + case Color_Black: + vram[vram_offset] |= op; + break; + case Color_Invert: + vram[vram_offset] ^= op; + break; + default: + break; + } + + vram_offset += 4; + } +} +void operate_gray(OPERATE_ARGS) +{ + int *vl = gray_lightVRAM(); + int *vd = gray_darkVRAM(); + int vram_offset = (x >> 5) + (y << 2); + uint32_t op; + int i; + + for(i = 0; i < height; i++) + { + op = operators[i]; + + switch(color) + { + case Color_White: + vl[vram_offset] &= ~op; + vd[vram_offset] &= ~op; + break; + case Color_Light: + vl[vram_offset] |= op; + vd[vram_offset] &= ~op; + break; + case Color_Dark: + vl[vram_offset] &= ~op; + vd[vram_offset] |= op; + break; + case Color_Black: + vl[vram_offset] |= op; + vd[vram_offset] |= op; + break; + case Color_Invert: + vl[vram_offset] ^= op; + vd[vram_offset] ^= op; + break; + default: + break; + } vram_offset += 4; } @@ -162,3 +231,88 @@ int update(uint32_t *operators, int height, int available, return available - width; } + +/* + render() + Renders text without any formatting analysis, using the given operation + function. +*/ +void render(int x, int y, const char *str, void (*op)(OPERATE_ARGS)) +{ + // Operator data, and number of available bits in the operators (which + // is the same for all operators, since they are treated equally). + uint32_t *operators; + int available; + + // Raw glyph data, each glyph being represented by one or several + // longwords, and an index in this array. + uint32_t *data = (uint32_t *)font->glyphs; + int index; + + // Height of each glyph. This value is constant because the storage + // format requires it: it allows greater optimization. + int height; + + int i; + + + + if(!font) return; + + // Allocating data. There will be one operator for each line. + height = font->data_height; + if(x > 127 || y > 63 || y <= -height) return; + + operators = alloca(height * sizeof(uint32_t)); + for(i = 0; i < height; i++) operators[i] = 0; + if(!operators) return; + + // Computing the initial operator offset to have 32-aligned operators. + // This allows to write directly video ram longs instead of having to + // shift operators, and do all the vram operation twice. + available = 32 - (x & 31); + x &= ~31; + + // Displaying character after another. + while(*str) + { + index = getCharacterIndex(*str++); + if(index < 0) continue; + + // Updating the operators. + available = update(operators, height, available, data + index); + + // Continue until operators are full (this includes an + // additional bit to add a space between each character). + if(available > 1) + { + available--; + continue; + } + + // When operators are full, updating the video ram and + // preparing the operators for another row. + + (*op)(operators, height, x, y); + x += 32; + if(x > 96) break; + + memset(operators, 0, height << 2); + if(available >= 0) + { + available = 31 + available; + continue; + } + + // Finishing update, in case it has been only partially done, + // because there was not enough bits available to fit all the + // information. Also adding a space, assuming that characters + // aren't more than 30 bits wide. + available += 32 + (data[index] >> 24); + available = update(operators, height, available, data + index); + available--; + } + + // Final operation. + if(x <= 96 && available < 32) (*op)(operators, height, x, y); +} diff --git a/src/tales/dprint.c b/src/tales/tales_print.c similarity index 51% rename from src/tales/dprint.c rename to src/tales/tales_print.c index 5547c52..be3d107 100644 --- a/src/tales/dprint.c +++ b/src/tales/tales_print.c @@ -14,5 +14,20 @@ void dprint(int x, int y, const char *format, ...) __printf(0, format, args); va_end(args); - dtext(__stdio_buffer, x, y); + dtext(x, y, __stdio_buffer); +} + +/* + 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(x, y, __stdio_buffer); } diff --git a/src/tales/tales_text.c b/src/tales/tales_text.c new file mode 100644 index 0000000..8b7977c --- /dev/null +++ b/src/tales/tales_text.c @@ -0,0 +1,23 @@ +#include +#include + +#include +#include + +/* + dtext() + Prints the given string, without any analysis. +*/ +void dtext(int x, int y, const char *str) +{ + render(x, y, str, operate_mono); +} + +/* + gtext() + Prints the given raw string. +*/ +void gtext(int x, int y, const char *str) +{ + render(x, y, str, operate_gray); +}