First gray tests. Added text module, 'tales'.

This commit is contained in:
lephe 2016-05-20 22:04:15 +02:00
parent f27ba1129a
commit aa0f4b7285
24 changed files with 765 additions and 198 deletions

View file

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

16
TODO
View file

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

View file

@ -4,6 +4,11 @@
#include <keyboard.h>
#include <display.h>
#include <timer.h>
#include <gray.h>
#include <tales.h>
#include <stdint.h>
#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<end_y ; i++)
{
if(begin_x < end_x)
{
line = bmp[i*(real_width>>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<end_x ; j++)
{
line = bmp[i*(real_width>>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<<real_width-width;
line <<= shift;
if(begin_x < end_x || bool1) screen[end_x] |= *p;
if(bool2) screen[end_x+1] |= *(p+1);
screen += 16;
}
}
bitmap_test()
Displays various bitmaps to ensure bopti is working correctly.
*/
#include <stdint.h>
#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;

Binary file not shown.

27
include/ctype.h Normal file
View file

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

View file

@ -1,6 +1,14 @@
#ifndef _DISPLAY_H
#define _DISPLAY_H 1
//---
// Included submodules.
//---
#include <tales.h>
//---
// 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

View file

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

View file

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

View file

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

105
include/tales.h Normal file
View file

@ -0,0 +1,105 @@
#ifndef _TALES_H
#define _TALES_H 1
#include <display.h>
#include <stdint.h>
//---
// 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

View file

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

BIN
libc.a

Binary file not shown.

BIN
libgint.a

Binary file not shown.

BIN
resources/font.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
resources/illustration.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View file

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

View file

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

View file

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

View file

@ -1,11 +1,15 @@
#include <display.h>
#include <gray.h>
#include <screen.h>
#include <timer.h>
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;
}

View file

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

View file

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

292
src/tales.c Normal file
View file

@ -0,0 +1,292 @@
#include <stdint.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <tales.h>
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);
}

View file

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