From aa0f4b7285cdf4002dda2e3d28e685d874def92f Mon Sep 17 00:00:00 2001 From: lephe Date: Fri, 20 May 2016 22:04:15 +0200 Subject: [PATCH] First gray tests. Added text module, 'tales'. --- Makefile | 15 +- TODO | 16 +- ginttest.c | 318 ++++++++++++++++--------------------- ginttest.g1a | Bin 14328 -> 18760 bytes include/ctype.h | 27 ++++ include/display.h | 15 +- include/gray.h | 22 +++ include/keyboard.h | 6 +- include/stdlib.h | 39 +++++ include/tales.h | 105 ++++++++++++ include/timer.h | 10 ++ libc.a | Bin 1770 -> 1770 bytes libgint.a | Bin 25286 -> 27912 bytes resources/font.bmp | Bin 0 -> 24698 bytes resources/illustration.bmp | Bin 0 -> 32906 bytes resources/swords.bmp | Bin 5770 -> 5770 bytes src/bopti.c | 2 + src/gint_7305.c | 1 + src/gint_7705.c | 1 + src/gray.c | 44 ++++- src/keyboard.c | 5 + src/syscalls.s | 22 ++- src/tales.c | 292 ++++++++++++++++++++++++++++++++++ src/timer.c | 23 +++ 24 files changed, 765 insertions(+), 198 deletions(-) create mode 100644 include/ctype.h create mode 100644 include/tales.h create mode 100644 resources/font.bmp create mode 100644 resources/illustration.bmp create mode 100644 src/tales.c diff --git a/Makefile b/Makefile index e368635..6ed5617 100644 --- a/Makefile +++ b/Makefile @@ -37,23 +37,25 @@ lib = -lgcc -L. -lgint -lc # 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 bopti.c gray.c timer.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 + mpu.h keyboard.h screen.h display.h gray.h timer.h tales.h obj-lib = $(addprefix build/, $(addsuffix .o, $(src-lib))) hdr-lib = $(addprefix include/, $(hea-lib)) # Standard library. src-std = setjmp.s string.c -hea-std = setjmp.h string.h +hea-std = setjmp.h string.h ctype.h obj-std = $(addprefix build/, $(addsuffix .o, $(src-std))) hdr-std = $(addprefix include/, $(hea-std)) # Test application. src-app = ginttest.c -img-app = bitmap_opt.bmp swords.bmp sprites.bmp symbol.bmp symbol2.bmp -res-app = $(addprefix build/, $(addsuffix .o, $(img-app))) +img-app = bitmap_opt.bmp swords.bmp sprites.bmp symbol.bmp symbol2.bmp \ + illustration.bmp +res-app = build/font.o $(addprefix build/, $(addsuffix .o, $(img-app))) # @@ -97,6 +99,9 @@ build/%.s.o: src/%.s build/%.bmp.o: resources/%.bmp fxconv $^ -o $@ +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) diff --git a/TODO b/TODO index 8b252f5..304e43c 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,15 @@ +@ vram overflow +@ keyboard interface + +- upgraded blending modes +- blending modes for text +- information masks for text +- test all font encodings +- font clipping + +- bitmap parts +- bitmap clipping + - multi-getkey repeats (if possible, which doesn't seem likely) - it appears that multi-getkey does not always trigger rectangle effects on sh7305 @@ -11,5 +23,5 @@ - check possible bug for optimization of __attribute__((interrupt_handler)) -_ 7305.h -_ libc +- 7305.h +- libc diff --git a/ginttest.c b/ginttest.c index f918f8c..a1ef815 100644 --- a/ginttest.c +++ b/ginttest.c @@ -4,6 +4,11 @@ #include #include #include +#include +#include + +#include +#include <7305.h> extern unsigned int bgint, egint; @@ -11,17 +16,9 @@ extern unsigned int bgint, egint; // A few procedures for displaying text in the system's vram. //--- -extern void __Print(const char *msg, int x, int y); - -void print_clear(void) -{ - char *empty_line = " "; - int i = 0; - while(i < 8) __Print(empty_line, 0, i++); -} void print(const char *str, int x, int y) { - __Print(str, x, y); + print_raw(str, x, y); } void print_hex(unsigned int n, int x, int y) { @@ -34,7 +31,7 @@ void print_hex(unsigned int n, int x, int y) n >>= 4; } ch[10] = 0; - __Print(ch, x, y); + print(ch, x, y); } void print_bin(unsigned char n, int x, int y) { @@ -47,7 +44,7 @@ void print_bin(unsigned char n, int x, int y) n >>= 1; } ch[8] = 0; - __Print(ch, x, y); + print(ch, x, y); } void print_hexa(unsigned int n, int digits, int x, int y) { @@ -61,31 +58,48 @@ void print_hexa(unsigned int n, int digits, int x, int y) } ch[digits] = 0; - __Print(ch, x, y); + print(ch, x, y); } -/* - Keyboard tests. - The user timer reproduces the parameters of the keyboard timer. -*/ + +//--- +// Test applications. +//--- + +/* + 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(); - print_bin(state[0], 0, 1); - print_bin(state[1], 0, 2); - print_bin(state[2], 0, 3); - print_bin(state[3], 0, 4); - print_bin(state[4], 0, 5); + dclear_area(5, 10, 71, 34); - print_bin(state[5], 9, 1); - print_bin(state[6], 9, 2); - print_bin(state[7], 9, 3); - print_bin(state[8], 9, 4); - print_bin(state[9], 9, 5); + print_bin(state[0], 5, 10); + print_bin(state[1], 5, 16); + print_bin(state[2], 5, 22); + print_bin(state[3], 5, 28); + print_bin(state[4], 5, 34); + + print_bin(state[5], 40, 10); + print_bin(state[6], 40, 16); + print_bin(state[7], 40, 22); + print_bin(state[8], 40, 28); + print_bin(state[9], 40, 34); + + dupdate(); } +/* + keyboard_test() + Displays a multi-getkey test as well as the keyboard state in real + time. +*/ void keyboard_test(void) { int x = 0; @@ -95,37 +109,40 @@ void keyboard_test(void) timer_start(TIMER_USER, 1700, TIMER_Po_256, keyboard_test_timer, 0); - print_clear(); - print("Keyboard state:", 0, 0); - print("multi-getkey ^^", 6, 7); - while(1) { multigetkey(keys, 4, 0); - if(keys[0] == KEY_EXIT && keys[1] == KEY_NONE) break; + dclear(); + print("Keyboard state:", 0, 0); + print("multi-getkey ^^", 50, 55); + #define hexa(h) ('0' + (h) + 39 * ((h) > 9)) x = (x + 1) & 15; str[0] = hexa(x); str[1] = 0; - print(str, 20, 0); + print(str, 100, 0); for(i = 0; i < 4; i++) { str[0] = hexa((keys[i] >> 4) & 0x0f); str[1] = hexa(keys[i] & 0x0f); str[2] = 0; - print(str, 19, i + 3); + print(str, 100, 16 + 10 * i); } #undef hexa + + dupdate(); } timer_stop(TIMER_USER); } + + /* const unsigned char data[1024] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -180,114 +197,16 @@ const unsigned char data[1024] = { 255, 15, 31, 252, 31 }; */ - /* -static const unsigned char icon[76] = { -0, 0, 0, 0, 51, 156, 10, 68, 74, 82, 11, 68, 74, 82, 234, 196, 122, 82, 10, -68, 75, 156, 10, 68, 0, 0, 0, 4, 0, 254, 0, 4, 0, 130, 124, 4, 0, 130, 68, 4, -0, 2, 4, 4, 3, 238, 196, 4, 2, 170, 93, 252, 0, 254, 65, 252, 7, 40, 65, 252, -5, 232, 65, 252, 7, 15, 193, 252, 0, 0, 1, 252, 127, 255, 255, 252 }; - -char *ML_vram_adress(void) -{ - return display_getVRAM(); -} - -void ML_bmp_or_cl(const unsigned char *bmp, int x, int y, int width, int height) -{ - unsigned short line; - char shift, *screen, *p; - int i, j, real_width, begin_x, end_x, begin_y, end_y; - char bool1=1, bool2=1, bool3; - if(!bmp || x<1-width || x>127 || y<1-height || y>63 || height<1 || width<1) return; - p = (char*)&line; - real_width = (width-1>>3<<3)+8; - if(y < 0) begin_y = -y; - else begin_y = 0; - if(y+height > 64) end_y = 64-y; - else end_y = height; - shift = 8-(x&7); - if(x<0) - { - begin_x = -x>>3; - if(shift != 8) bool1 = 0; - } else begin_x = 0; - if(x+real_width > 128) end_x = 15-(x>>3), bool2 = 0; - else end_x = real_width-1>>3; - bool3 = (end_x == real_width-1>>3); - screen = ML_vram_adress()+(y+begin_y<<4)+(x>>3); - - for(i=begin_y ; i>3)+begin_x] << shift; - if(bool1) screen[begin_x] |= *p; - if(shift!=8) screen[begin_x+1] |= *(p+1); - for(j=begin_x+1 ; j>3)+j] << shift; - screen[j] |= *p; - if(shift!=8) screen[j+1] |= *(p+1); - } - } - line = bmp[i*(real_width>>3)+end_x]; - if(bool3) line &= -1< -#include <7305.h> - -/* -unsigned int exec(void (*f)(void)) -{ - int t, s, dt, ds; - - t = (int)RTC.R64CNT; - s = 10 * (RTC.RSECCNT.TENS) + RTC.RSECCNT.ONES; - - (*f)(); - - dt = (int)RTC.R64CNT - t; - ds = (10 * (RTC.RSECCNT.TENS) + RTC.RSECCNT.ONES) - s; - if(dt < 0) ds--, dt += 64; - - return (ds << 8) | dt; -} - -void btest_ml_icon(void) -{ - int i; - for(i = 0; i < 5000; i++) - { - ML_bmp_or_cl(icon, 0, 30, 30, 19); - } -} -void btest_gint_icon(void) -{ - extern Image binary_icon_start; - - int i; - for(i = 0; i < 5000; i++) - { - dimage(&binary_icon_start, 0, 0, Blend_Or); - } -} -*/ - void bitmap_test(void) { extern Image binary_resources_bitmap_opt_start; extern Image binary_resources_symbol_start; extern Image binary_resources_symbol2_start; extern Image binary_resources_sprites_start; - extern Image binary_resources_swords_start; Image *opt = &binary_resources_bitmap_opt_start; Image *sprites = &binary_resources_sprites_start; @@ -324,64 +243,78 @@ void bitmap_test(void) } return; +} - dclear(); - dreverse_area(0, 0, 127, 30); - dimage(sybl, 0, 0, Blend_Or); - dimage(sybl, 20, 0, Blend_And); - dimage(sybl, 40, 0, Blend_Or | Blend_And); - dimage(sybl, 90, 0, Blend_Or | Blend_Invert); - dimage(sybl2, 0, 20, Blend_Or); - dimage(sybl2, 20, 20, Blend_And); - dimage(sybl2, 28, 20, Blend_And); - dimage(sybl2, 40, 20, Blend_Or | Blend_And); - dimage(sybl2, 90, 20, Blend_Or | Blend_Invert); - - dreverse_area(35, 31, 127, 63); - dimage(&binary_resources_sprites_start, 50, 31, Blend_And); - - dupdate(); /* - do key = getkey(); - while(key != KEY_EXE && key != KEY_EXIT); - if(key == KEY_EXIT) return 0; - - print("h'sszz 64z=1s", 0, 0); - print("ML", 14, 0); - print("gint", 17, 0); - print("---------------------", 0, 1); - - print("30*19 icon", 0, 2); - print(wait, 12, 2); - print_hexa(exec(btest_ml_icon), 4, 12, 2); - print(wait, 17, 2); - print_hexa(exec(btest_gint_icon), 4, 17, 2); + text_test() + Renders text. */ - while(getkey() != KEY_EXE); + +void text_test(void) +{ + extern Font binary_resources_font_start; + Font *font = &binary_resources_font_start; + + print_configure(font, Blend_Or); dclear(); - dimage(&binary_resources_swords_start, 20, 20, Blend_Or); + + print(" !\"#$%&'()*+,-./", 10, 10); + print("0123456789:;<=>?", 10, 16); + print("@ABCDEFGHIJKLMNO", 10, 22); + print("PQRSTUVWXYZ[\\]^_", 10, 28); + print("`abcdefghijklmno", 10, 34); + print("pqrstuvwxyz{|}~", 10, 40); + dupdate(); - while(getkey() != KEY_EXE); + while(getkey() != KEY_EXIT); } -void test(void) + + +/* + gray_test() + Runs the gray engine. +*/ + +void gray_test(void) { - static int x = 0; - x++; + extern Image binary_resources_illustration_start; + Image *illustration = &binary_resources_illustration_start; - print_hex(x, 0, 0); + int light, dark; + int key; + + gray_getDelays(&light, &dark); + gray_start(); + dimage(illustration, 0, 0, Blend_Or); + + while(1) + { + key = getkey(); + if(key == KEY_EXIT) break; + + if(key == KEY_F1) gray_setDelays(--light, dark); + if(key == KEY_F2) gray_setDelays(++light, dark); + + if(key == KEY_F5) gray_setDelays(light, --dark); + if(key == KEY_F6) gray_setDelays(light, ++dark); + } + + gray_stop(); } +/* + main_menu() + Displays the main menu and returns user's choice. + + @return User choice. 0 means EXIT, other numbers are applications. +*/ int main_menu(void) { - /* - Main menu. - */ - const char *mpu_names[] = { "MPU_Unkown", "MPU_SH7337", @@ -392,18 +325,22 @@ int main_menu(void) }; int key; - print_clear(); + dclear(); - print("gint test application", 0, 0); - print("---------------------", 0, 1); + print("gint test application", 19, 1); + dline(19, 8, 107, 8, Color_Black); - print("[1] Keyboard test", 2, 3); - print("[2] Drawing test", 2, 4); + print("[1] Keyboard", 10, 17); + print("[2] Bitmap drawing", 10, 24); + print("[3] Text rendering", 10, 31); + print("[4] Gray engine", 10, 38); - print("mpu type:", 0, 6); - print(mpu_names[MPU_CURRENT < 5 ? MPU_CURRENT : 5], 11, 6); - print("gint size:", 0, 7); - print_hex(&egint - &bgint, 11, 7); + print("mpu type:", 2, 49); + print(mpu_names[MPU_CURRENT < 5 ? MPU_CURRENT : 5], 50, 48); + print("gint size:", 2, 56); + print_hex(&egint - &bgint, 50, 56); + + dupdate(); while(1) { @@ -412,13 +349,26 @@ int main_menu(void) if(key == KEY_1) return 1; if(key == KEY_2) return 2; + if(key == KEY_3) return 3; + if(key == KEY_4) return 4; } return 0; } +/* + main() + Handles application calls. + + @return 0. +*/ int main(void) { + extern Font binary_resources_font_start; + Font *font = &binary_resources_font_start; + + print_configure(font, Blend_Or); + int app; while(1) @@ -428,6 +378,8 @@ int main(void) if(app == 1) keyboard_test(); if(app == 2) bitmap_test(); + if(app == 3) text_test(); + if(app == 4) gray_test(); } return 0; diff --git a/ginttest.g1a b/ginttest.g1a index 076483fed459a670ee8cefec74dfcecda9e0c6e6..78b5a4e904db4db9bbb3a118fb7e7d416b3d0abf 100644 GIT binary patch delta 6653 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 SuDK&$59L2jkvU90Q2!s5nfeg` delta 2734 zcmZuzeN0=|6~FJp&(ARo`#o?CCHM`!Y?k0_Ww<}sC?MO>&oA$dm ze$DYmcIb2N^Ju9Sq{Y_Zi6t)39A^cd0j9ij;$(aL~4_xjuJvXL38d@oqA$SX+>1h}E}XAtqc8IEFXQ9Zim?=Q*Vd zmdR0dll-tnHwDajg+a%KiXLP(1-kof#aGYTw*xSaC;GMWVpa^r3jZ9E;78N2sbg@ zATfbNzmn{dnkAYzN1scbEqVY|b$^bqz`EG3D`(u4it-?WRD^ve?KHm1{efOIo>I$U z|7yX_8kDeQ;eGlyV}F%oCz|^L^nnZ|xet6Cc#>%97VVKIl!2OI^_&11FCX=6s$ipx zekD8V-zTP}HmqZo*9~YD>gz13FEiuLCY+`#TohYTos%sUPod4gP30QVsxA}F`8BLl zM6(ZJohP^TePIQ>ak}hs>&CEBIAg(nk#!TcIfS}c=#VTnXgc6>*dyx%q80x?T5}W8j1Y{eUl%f@&kfb*9|-~TCYQgKJio&0N*6#9 z)P=l+Ko8)Rm6xTBDK6Lu9*FR-w790?I?Wd_fpDkkTG^W>IG?4LXx1URRd&>cyEURI z6TTd@o)A_->eR;G^#l%k=$z%3rM>yQz}2c*U!!*G)c+8;Q>{I8-g>2`sTY$5*XbI* zhRFlo4YykeuqP!yWfIdKb=;OeiupHR|PIG88>h?P&f*C@Co1}z#jk~j;r6MfKSjDq3R)Wmj@BmV7Zo2JuvJ60?X^AEd7Td{wTjLYb4UU4O`y3Hm%r0teK&F0=HsmM zxI_^Us>JA@U-@942d)?I98i*m>?iq(w-cY*J$wUGK>I-8hrPrM5UnDWf*ao7n6(kj zW=}k?I>{ZjIg9+ob?_ZhST{Iv?F#O#AMpX~2+f1XjMM4rD&FR#H>=;s^Ozcu@8_j3pYW>`g4}{~5<#t%M%3FDIN1H-{Fx>jrr-p1520 zn2%Q8mn|aHdH=HSTIS!r4}71TJ>mQPd!p~bPfqzBPmK6-KRw^)9`{GLt_H?$zEcvO z3C#qWA3B_JxO!I1kc_N(XZ;xtuM_S=QuR=9%Cr0rs$Q2biC2T`Wy2+|hL9TLX4_-@ zEqBP1wCF9j-pYun7Qfk{qz^SmgrM2s8F)4}Gy3J3MC4|b=7=!x z4AHR}-yPHlnA@LHe?xgk#-i2V`Xa+GeV!4S-HKWB*i1$QWyRqd{nB?QuZ*T0`rbbB zF}@s)Y_#_}6cD^rTwMBO;2CDF25uZTWUO)pcn3C03I-YD(fNoFXzcTX42Gw2Mdw4% zSbiCFY9NiD!sI1&AuWa#Ob0RdTd}kS9CWAohXNFwm+3#8qudI8+jZ2i5`Tk;iPeTG zUQ#t2UAoig{;~T)jQnL@=K_scf-$+XDPti9DQ$G|R##fGx`8|p&0fV9(LeYDE(4V; zI=}A&gG{HJoK$QMbv1wA2NZtPdfNHsnO_V~h0jHt7tWl&fLPmUXZN}A&)=CG+k@zD zo3D$Pjodxjp-qcJ7UdpY)W*1ZTHg96?k;@FX1xI5}~w`x_2e(@78Sf`5zT yZj7u##>sq)JihO{wrbRkp(~IhS*+0|db!6YS&}$QG~V-JDP|e|GFlcf+y4bc^B0i- diff --git a/include/ctype.h b/include/ctype.h new file mode 100644 index 0000000..0a716be --- /dev/null +++ b/include/ctype.h @@ -0,0 +1,27 @@ +#ifndef _CTYPE_H +#define _CTYPE_H 1 + +// Character definition macros. +#define isalnum(c) (isdigit(c) || isalpha(c)) +#define isalpha(c) (islower(c) || isupper(c)) + +#define iscntrl(c) ((c) <= 0x1f || (c) == 0x7f) +#define isdigit(c) ((c) >= '0' && (c) <= '9') +#define isgraph(c) ((c) > ' ' && (c) < 0x7f) +#define islower(c) ((c) >= 'a' && (c) <= 'z') +#define isprint(c) ((c) >= ' ' && (c) < 0x7f) +#define ispunct(c) (((c) >= '!' && (c) <= '/') || \ + ((c) >= ':' && (c) <= '@') || \ + ((c) >= '[' && (c) <= '`') || \ + ((c) >= '{' && (c) <= '~')) +#define isspace(c) (((c) >= '\t' && (c) <= '\r') || (c) == ' ') +#define isupper(c) ((c) >= 'A' && (c) <= 'Z') +#define isxdigit(c) (((c) >= '0' && (c) <= '9') || \ + ((c) >= 'A' && (c) <= 'F') || \ + ((c) >= 'a' && (c) <= 'f')) + +// Character manipulation macros. +#define tolower(c) (isupper(c) ? (c)|32 : (c)) +#define toupper(c) (islower(c) ? (c)&~32 : (c)) + +#endif // _CTYPE_H diff --git a/include/display.h b/include/display.h index 00b4042..58a111e 100644 --- a/include/display.h +++ b/include/display.h @@ -1,6 +1,14 @@ #ifndef _DISPLAY_H #define _DISPLAY_H 1 +//--- +// Included submodules. +//--- + +#include + + + //--- // Types and constants. //--- @@ -60,13 +68,12 @@ enum ImageFormat */ struct Image { + unsigned char magic; + unsigned char width; unsigned char height; unsigned char format; - // Ensures data is 4-aligned. - unsigned char gap; - const unsigned char __attribute__((aligned(4))) data[]; } __attribute__((aligned(4))); @@ -205,4 +212,6 @@ void dline(int x1, int y1, int x2, int y2, enum Color color); */ void dimage(struct Image *image, int x, int y, enum BlendingMode mode); + + #endif // _DISPLAY_H diff --git a/include/gray.h b/include/gray.h index c91b0e5..c685fd1 100644 --- a/include/gray.h +++ b/include/gray.h @@ -31,6 +31,28 @@ void *gray_lightVRAM(void); */ void *gray_darkVRAM(void); +/* + gray_getDelays() + Returns the gray engine delays. + + @arg light Will be set if non-NULL. + @arg dark Will be set if non-NULL. +*/ +void gray_getDelays(int *light, int *dark); + +/* + gray_setDelays() + Changes the gray engine delays. Usually you don't need to call this, + because the engine has its default values. + Finding values that give proper grays is quite the hard part of the + gray engine. Usual values are about 1000, with light being between 75 + and 90% of dark. + + @arg light Light gray duration (the lower). + @arg dark Dark gray duration (the higher). +*/ +void gray_setDelays(int light, int dark); + //--- // Internal API. // Referenced here for documentation purposes only. Do not call. diff --git a/include/keyboard.h b/include/keyboard.h index b8aa1c7..ce22954 100644 --- a/include/keyboard.h +++ b/include/keyboard.h @@ -148,6 +148,7 @@ enum GetkeyOpt non-NULL, it is set to the number of repetitions. @arg repeat_count + @return Key matrix code. */ int keylast(int *repeat_count); @@ -223,6 +224,7 @@ enum KeyType Ignores modifiers. @arg key + @return Modified keycode. */ int keyid(int key); @@ -233,7 +235,8 @@ int keyid(int key); other keys. @arg key - @return Key character. + + @return Associated character. */ int keychar(int key); @@ -242,6 +245,7 @@ int keychar(int key); Returns a key's type. Ignores modifiers. @arg key + @return Key type. */ enum KeyType keytype(int key); diff --git a/include/stdlib.h b/include/stdlib.h index 66f7396..8d0fb91 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -28,4 +28,43 @@ void abort(void); */ void exit(int status); + + +//--- +// Dynamic storage allocation. +//--- + +/* + malloc() + Allocs 'size' bytes and returns a pointer to a free memory area. + Returns NULL on error. + + @arg size Size to allocate, in bytes. + + @return Memory area address, or NULL. +*/ +void *malloc(size_t size); + +/* + calloc() + Allocs 'n' elements of size 'size' and wipes the memory area. Returns + NULL on error. + + @arg n Element number. + @arg size Element size. + + @return Memory area address, or NULL. +*/ +void *calloc(size_t n, size_t size); + +/* + free() + Frees a memory block allocated with malloc(). + + @arg ptr Pointer to free. +*/ +void free(void *ptr); + + + #endif // _STDLIB_H diff --git a/include/tales.h b/include/tales.h new file mode 100644 index 0000000..14e6646 --- /dev/null +++ b/include/tales.h @@ -0,0 +1,105 @@ +#ifndef _TALES_H +#define _TALES_H 1 + +#include +#include + +//--- +// Types and constants. +//--- + +enum BlendingMode; + +/* + enum ImageFormat + This type holds information about the characters in the font. Each bit + represents various characters, and the type itself is a combination of + several of those bits. + Bits represent the following characters (lsb right): + -- -- -- non-print | special capitals lower numbers +*/ +enum FontFormat +{ + FontFormat_Unknown = 0x00, + FontFormat_Numeric = 0x01, + FontFormat_LowerCase = 0x02, + FontFormat_UpperCase = 0x04, + FontFormat_Letters = 0x06, + FontFormat_Common = 0x07, + FontFormat_Print = 0x0f, + FontFormat_Ascii = 0x1f, +}; + +/* + struct FontGlyph + Holds a glyph's data. The width is used for spacing, and the raw data + is encoded line after line, from to to bottom, by appending bits + without consideration of the byte boundaries. + This structure is actually never used, because data is read directly + as a longword array (hence the 4-byte alignment). +*/ +struct FontGlyph +{ + unsigned char width; + + const unsigned char data[]; +} __attribute__((aligned(4))); + +/* + struct Font + Holds a font's data. Data is accessed using longword operations, hence + the 4-alignment attributes. The line height is the one given in the + font image header line, which may be used by applications that write + strings on several lines. The data height is the height of the biggest + glyph. Every glyph is encoded on 'data_height' lines, for optimization + considerations. + The index field is used to reduce character access time. + The name field may not be NUL-terminated when the name contains 28 + characters. When the name is shorter, the field is padded with zeros. +*/ +struct Font +{ + unsigned char magic; + + unsigned char format; + unsigned char line_height; + unsigned char data_height; + + // Warning : this field may not be NUL-terminated. + char name[28]; + + uint16_t index[16]; + + __attribute__((aligned(4))) const struct FontGlyph glyphs[]; + +} __attribute__((aligned(4))); +// Useful shorthand for user code. +typedef struct Font Font; + + + + +//--- +// Generic functions. +//--- + +/* + print_configure() + Sets the font and mode to use for the following print operations. + + @arg font + @arg mode +*/ +void print_configure(struct Font *font, enum BlendingMode mode); + +/* + print_raw() + Prints the given string, without any analysis. + + @arg str + @arg x + @arg y +*/ +void print_raw(const char *str, int x, int y); + +#endif // _TALES_H diff --git a/include/timer.h b/include/timer.h index 84b6dde..3d475bc 100644 --- a/include/timer.h +++ b/include/timer.h @@ -56,6 +56,16 @@ void timer_start(int timer, int delay, int prescaler, void (*callback)(void), */ void timer_stop(int timer); +/* + timer_reload() + Reloads the given timer with the given constant. Starts the timer if + it was stopped. + + @arg timer Timer identifier. + @arg new_delay +*/ +void timer_reload(int timer, int new_delay); + //--- diff --git a/libc.a b/libc.a index fdab1e246183244671ddee5bbd54e90723472ab9..79d61d81aea241964cf75ba93c101d51f7c4ee42 100644 GIT binary patch delta 39 kcmaFG`-*phG@G%xxv{C)M8zB^Yvbf1CMa_=H}idF0Oe^4;s5{u delta 39 kcmaFG`-*phG@Fr`p{bd{M8zB^Yvbf1CMa_=H}idF0OJ7)!2kdN diff --git a/libgint.a b/libgint.a index d03f064616a774dc5e983730ff2174dc4c35340e..cf2e8b91dfd6bfdfc67b3eb222e72148aa7938ec 100644 GIT binary patch delta 4160 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 T0x3G(hD|+dF1$8ylMVb0+askH literal 0 HcmV?d00001 diff --git a/resources/illustration.bmp b/resources/illustration.bmp new file mode 100644 index 0000000000000000000000000000000000000000..ca8755ad1f4de5b1c1e1d53199583e333d5d2a36 GIT binary patch literal 32906 zcmeIxJ#u5|4TWLZ4jp;}UW#iHM^0QdD{<;z;#o>>vaOe%#|3|NsTMCukl0&JDOGGR%&MZF+Z+gx1cKO9FecL-9rR&e<&E`txtl6;gr$6^FcXO-R^_Rv!cN^v{8pc00 z|IRB z&e?N5zM3_6Zx6kFYtdu68Qg5^ovj(0&3ti8A6M9{z32S6y`A=nZO!&0Os!c~emf8^ zpN%^V5A2@Wdv9sGsgG%I^;LYGGauGF)3>9rY2R}Paht=N>1*CJS35DEnc~hS*?I^Q z54)xZ{O2_Osn6wxm#1$%hG(CXnP+|+)tE0#9GBW~d1ANJ=F$Vb_s#0IYUe!qHya(U zpDhk`d$r#7aOjA#b@|ItX`Z$uQi%nj$ zhWXy&-xHhf?WtdD@abLL{`gbRn7X-_$thkvTdusxeXSj5{ppc?>05Z}Rll?Uc;$F2 z-*@dCZ`Jq4tpwMcEp9Vyy;E#!C*_7uPP}5XR^HYdd$BmZp~w77-zs1I>>Zc5c`xPP zJDn-z<*xEwtB)1Ggy@9g!xUH$Cq(zj;5IpV}`j{KQh&PR&( z_x4bo`R2ZwA%E+WUyhrm;W+ttajM(fbM@y0=j^*a;OFWlUhdj+KD^vZIVb}DXY-5Ay@-V+e4OgkEP?|ZWz2P~dTxb89EdpYZQep_|L zo5yYB@ZB&RHghJH-Dg*8ja<6Cd&rzA{!4GBui2*^6%)Tl@Au@?`>M@mPxWB-*$*sD zVEOF$gxED#f>@xm@?u~43WzRdZ<;`3%d^p3| zr^mj?pE`F>-!PkwR=_Xp6Tx8mTWgHUra7NW7+fbo0$45{0y40`EU8HoO6%! zo$xK0`O~(0nA&_d?6wJCuKO1Y%b(xOgTvxd7e>VIp}p}Dy8h=~uCZ6H{3Om9gU|WG zws1K!jxWr;(sJPGgl{&u8hqZGoY^y8t$O*l)c7yedwb{|d%0Fmu4&iX^t1QMi=~t4 zXX7cBP1YFv*|h%mXgk}hdvn%K-=4yft^VY^rPaG3p2^v*e8tyXST*wG=pSEkF}Zpu z=PQX_uG&t1r0uml9QMPf;d^u(?vkD8Eu5e2J$5nmGd64F;!69>R{rlr>}l0@PS1F| zS^aDGg|GMABON}m-U$yYmZ;sr%S&*w)zIb1#d|9Jo&K?xsqeK4`)>d4za92Nb#SeY|4cL1xb)UpN#lpkf>6G;P$35lCqr=I(H6HcF4teYb+S8;9FR+Lq28$-G+1v z_ked>_mx)+CO-Z0aHW%KVA+#{KlQ2T`12tfuy?oYPGO0d+qrW%EDfJFK0I>N=8K(- z2fB2I1bty^7x1TxDD97ySYtzy|Wv_)4pO8 zH$gmNIEzh8?x7#E0XOd^B-_2*6$V$g`sL4bh;luLhZ$@2M_94%=f$rkdom;JXy>C9u z-K)uVa~yF`+gpczz72Gz^;Uc_clR4ei#3sa_KZE>#79SS1M_z9^?q{J|L1F-`a^%M o4Y)sTy48mt`fF|A_<#Pj?s-geY~a|yv4LX)#|DlKe98^{2Z{t)MgRZ+ literal 0 HcmV?d00001 diff --git a/resources/swords.bmp b/resources/swords.bmp index 695bc8d8093ea873847080f9dcc406fb1a4a743c..8aa6416275a5725e7cf1e5efc4d602c0c54acc27 100644 GIT binary patch delta 26 gcmeCu?b6+Fh?Dg{0}xD>XH%a1k6m!{Z_a)m0Csi=!~g&Q delta 26 fcmeCu?b6+Fh?A881SZR~DNp{#F1YzOXFm@BWQYgF diff --git a/src/bopti.c b/src/bopti.c index 81a3794..aaa6998 100644 --- a/src/bopti.c +++ b/src/bopti.c @@ -286,6 +286,8 @@ void dimage(struct Image *image, int x, int y, enum BlendingMode mode) int height = image->height; const unsigned char *data = (const unsigned char *)&(image->data); + if(image->magic != 0xb7) return; + // Computing the layer size. int columns = image->width >> 5; int rest = image->width & 31; diff --git a/src/gint_7305.c b/src/gint_7305.c index bbdc22c..12f310e 100644 --- a/src/gint_7305.c +++ b/src/gint_7305.c @@ -93,6 +93,7 @@ static void kdelay(void) more details. @arg row Row to check (0 <= row <= 9). + @return Bit-based representation of pressed keys in the checked row. */ static int krow(int row) diff --git a/src/gint_7705.c b/src/gint_7705.c index 4a08601..253a174 100644 --- a/src/gint_7705.c +++ b/src/gint_7705.c @@ -100,6 +100,7 @@ static void kdelay(void) Reads a keyboard row. @arg row Row to check (0 <= row <= 9). + @return Bit-based representation of pressed keys in the checked row. */ static int krow(int row) diff --git a/src/gray.c b/src/gray.c index 53bcb56..8687df9 100644 --- a/src/gray.c +++ b/src/gray.c @@ -1,11 +1,15 @@ #include #include #include +#include static int internal_vrams[3][256]; const void *vrams[4]; static int current = 0; +static int delays[2]; + +#define GRAY_PRESCALER TIMER_Po_64 /* gray_start() @@ -14,6 +18,7 @@ static int current = 0; */ void gray_start(void) { + timer_start(TIMER_GRAY, delays[0], GRAY_PRESCALER, gray_interrupt, 0); } /* @@ -23,6 +28,7 @@ void gray_start(void) */ void gray_stop(void) { + timer_stop(TIMER_GRAY); display_useVRAM(display_getLocalVRAM()); } @@ -44,6 +50,38 @@ void *gray_darkVRAM(void) return (void *)vrams[current + 1]; } +/* + gray_getDelays() + Returns the gray engine delays. + + @arg light Will be set if non-NULL. + @arg dark Will be set if non-NULL. +*/ +void gray_getDelays(int *light, int *dark) +{ + if(light) *light = delays[0]; + if(dark) *dark = delays[1]; +} + +/* + gray_setDelays() + Changes the gray engine delays. + + @arg light Light gray duration (the lower). + @arg dark Dark gray duration (the higher). +*/ +void gray_setDelays(int light, int dark) +{ + delays[0] = light; + delays[1] = dark; +} + + + +//--- +// Internal API. +//--- + /* gray_swap() Swaps the vram buffers. @@ -55,10 +93,11 @@ void gray_swap(void) /* gray_interrupt() - Answers a timer interrupt. Swaps the two buffers. + Answers a timer interrupt. Swaps the buffers. */ void gray_interrupt(void) { + timer_reload(TIMER_GRAY, delays[current & 1]); screen_display(vrams[current]); current ^= 1; } @@ -73,4 +112,7 @@ void gray_init(void) vrams[1] = (const void *)internal_vrams[0]; vrams[2] = (const void *)internal_vrams[1]; vrams[3] = (const void *)internal_vrams[2]; + + delays[0] = 3269; + delays[1] = 6987; } diff --git a/src/keyboard.c b/src/keyboard.c index 1f44d74..f3a8c2c 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -201,6 +201,7 @@ void keyboard_setRepeatRate(int first, int next) non-NULL, it is set to the number of repetitions. @arg repeat_count + @return Key matrix code. */ int keylast(int *repeat_count) @@ -426,6 +427,7 @@ void multigetkey(int *keys, int count, int max_cycles) Ignores modifiers. @arg key + @return Modified keycode. */ int keyid(int key) @@ -445,6 +447,8 @@ int keyid(int key) keys. @arg key + + @return Associated character. */ int keychar(int key) { @@ -482,6 +486,7 @@ int keychar(int key) Returns a key's type. Ignores modifiers. @arg key + @return Key type. */ enum KeyType keytype(int key) diff --git a/src/syscalls.s b/src/syscalls.s index c76d3e3..c2a3e1c 100644 --- a/src/syscalls.s +++ b/src/syscalls.s @@ -5,7 +5,9 @@ .global ___Hmem_SetMMU .global ___GLibAddinAplExecutionCheck - .global ___Print + .global _malloc + .global _calloc + .global _free @@ -22,12 +24,26 @@ ___GLibAddinAplExecutionCheck: jmp @r2 nop -___Print: +_malloc: mov.l syscall_table, r2 mov.l 1f, r0 jmp @r2 nop -1: .long 0x15d +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 + jmp @r2 + nop +1: .long 0xacc diff --git a/src/tales.c b/src/tales.c new file mode 100644 index 0000000..fa564a2 --- /dev/null +++ b/src/tales.c @@ -0,0 +1,292 @@ +#include +#include +#include +#include + +#include + +static struct Font *font; +static enum BlendingMode mode; + +//--- +// Local functions. +//--- + +/* + getCharacterIndex() + Returns the index of a character in a font data area depending on the + font format and the size of the characters. + + @arg character + + @return Index in data area (as long array). Returns -1 when the + character does not belong to the font format set. +*/ +static int getCharacterIndex(int c) +{ + const char *data = (const char *)&font->glyphs; + int index, current; + int offset; + int width, bits; + + c &= 0x7f; + + + + // Getting the character index in the glyph array. + + if(font->format == FontFormat_Ascii) index = c; + else if(font->format == FontFormat_Print) index = c - 32; + + else switch(font->format) + { + case FontFormat_Numeric: + if(!isdigit(c)) return -1; + index = c - '0'; + break; + case FontFormat_LowerCase: + if(!islower(c)) return -1; + index = c - 'a'; + break; + case FontFormat_UpperCase: + if(!isupper(c)) return -1; + index = c - 'A'; + break; + case FontFormat_Letters: + if(!isalpha(c)) return -1; + index = c - 'A' - ('a' - 'z') * (c >= 'a'); + break; + case FontFormat_Common: + if(!isalnum(c)) return -1; + index = c - '0' - ('A' - '9') * (c >= 'A') - + ('a' - 'z') * (c >= 'a'); + break; + case FontFormat_Unknown: + default: + return -1; + } + + + + // Reaching the character offset. + + current = index & ~7; + offset = font->index[current >> 3]; + + while(current < index) + { + width = data[offset << 2]; + bits = font->data_height * width + 8; + + offset += (bits + 31) >> 5; + current++; + } + + return offset; +} + +/* + operate() + Operates on the vram using the given operators. The x-coordinate should + be a multiple of 32. + + @arg operators Operator array. + @arg height Number of operators (height of text). + @arg x + @arg y +*/ +static void operate(uint32_t *operators, int height, int x, int y) +{ + int *vram = display_getCurrentVRAM(); + int vram_offset = (x >> 5) + (y << 2); + int i; + + for(i = 0; i < height; i++) + { + // TODO BLENDING MODES // + vram[vram_offset] |= operators[i]; + + vram_offset += 4; + } +} + +/* + update() + Updates the operators using the given glyph. The operation will not be + complete if there are not enough bits available in the operator data. + In this case the offset will become negative, which means that the + calling procedure has to call operate() and re-call update(). + + @arg operators Operator array. + @arg height Number of operators. + @arg available Number of free bits in the operators (lower + bits). + @arg glyph Glyph data, including meta-data. + + @return Number of bits available after the operation. May be negative: + in this case, call operate() and update() again. +*/ +static int update(uint32_t *operators, int height, int available, + uint32_t *glyph) +{ + // Glyph width. + int width = glyph[0] >> 24; + int i; + + // The glyph mask extracts 'width' bits at the left. The partial mask + // is used when there are less than 'width' bits available in the + // current data longword. + uint32_t glyph_mask = 0xffffffff << (32 - width); + uint32_t partial_mask; + + int shift; + uint32_t line; + + // Current data longword, next data array index, and number of bits + // still available in 'data'. + uint32_t data = glyph[0] << 8; + int data_index = 1; + int bits_available = 24; + + for(i = 0; i < height; i++) + { + shift = 32 - available; + + // Getting the next 'width' bits. In some cases these bits will + // intersect two different longs. + line = data & glyph_mask; + line = (shift >= 0) ? (line >> shift) : (line << -shift); + operators[i] |= line; + + data <<= width; + bits_available -= width; + + // Continue until they do. + if(bits_available >= 0) continue; + + // Computing a special mask that extracts just the number of + // bits missing, and loading a new data longword. + partial_mask = 0xffffffff << (32 + bits_available); + data = glyph[data_index++]; + shift += width + bits_available; + + if(shift <= 31) + { + line = data & partial_mask; + line = (shift >= 0) ? (line >> shift) : + (line << -shift); + operators[i] |= line; + } + + data <<= -bits_available; + bits_available += 32; + } + + return available - width; +} + + + +//--- +// Public API. +//--- + +/* + print_configure() + Sets the font and mode to use for the following print operations. + + @arg font + @arg mode +*/ +void print_configure(struct Font *next_font, enum BlendingMode next_mode) +{ + font = next_font; + mode = next_mode; +} + +/* + print_raw() + Prints the given string, without any analysis. + + @arg str + @arg x + @arg y +*/ +void print_raw(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; + + + + 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 = calloc(height, sizeof(uint32_t)); + 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/timer.c b/src/timer.c index 77c9a9d..5988b8e 100644 --- a/src/timer.c +++ b/src/timer.c @@ -176,3 +176,26 @@ void timer_stop(int timer) // Stopping the timer. *tstr &= ~byte; } + +/* + timer_reload() + Reloads the given timer with the given constant. Starts the timer if + it was stopped. + + @arg timer Timer identifier. + @arg new_delay +*/ +void timer_reload(int timer, int new_delay) +{ + struct mod_tmu *tmu; + unsigned char *tstr; + int byte = (1 << timer); + timer_get(timer, &tmu, &tstr); + + // Setting the constant and the delay. + (*tmu).TCOR = new_delay; + (*tmu).TCNT = new_delay; + + // Starting the timer. + *tstr |= byte; +}