TwlToolsRED/build/tools/sctools/common/src/text.c

468 lines
9.6 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <twl.h>
#include "text.h"
#define TAB_SIZE 8
#define Y_LINE_VIRTUAL_MAX (Y_LINE_MAX*10)
/*****************************************************/
static LINE_BUF *lb_free_ptr;
static int x_size = X_LINE_MAX;
static int y_size = Y_LINE_MAX;
void text_display_newline_on(TEXT_CTRL *tc)
{
tc->text_buf.display_newline = 1;
}
void text_display_newline_off(TEXT_CTRL *tc)
{
tc->text_buf.display_newline = 0;
}
void text_blink_current_line(TEXT_CTRL *tc)
{
tc->text_buf.cur->blink_flag = 1;
}
void text_blink_clear(TEXT_CTRL *tc)
{
LINE_BUF *lb;
lb = tc->text_buf.start;
while( lb != NULL ) {
lb->blink_flag = 0;
lb = lb->next;
}
}
static void link_line_buf(LINE_BUF *m,LINE_BUF *s)
{
if( m->next != NULL ) {
s->next = m->next;
(s->next)->prev = s;
}
else
s->next = NULL;
m->next = s;
s->prev = m;
}
static void unlink_line_buf(LINE_BUF *s)
{
if( (s->prev != NULL ) && (s->next != NULL) ) {
(s->prev)->next = s->next;
(s->next)->prev = s->prev;
s->next = NULL;
s->prev = NULL;
}
else if( s->next != NULL) {
s->prev = NULL;
(s->next)->prev = NULL;
s->next = NULL;
}
else if( s->prev != NULL ) {
s->next = NULL;
(s->prev)->next = NULL;
s->prev = NULL;
}
}
static LINE_BUF *alloc_line_buf(void)
{
LINE_BUF *tmp;
if( lb_free_ptr == NULL ) {
OS_TPrintf("Error: %s %d\n",__FUNCTION__,__LINE__);
return NULL;
}
if( lb_free_ptr->next == NULL ) {
OS_TPrintf("Error: %s %d\n",__FUNCTION__,__LINE__);
return NULL;
}
tmp = lb_free_ptr;
lb_free_ptr = lb_free_ptr->next;
unlink_line_buf(tmp);
tmp->last_count = 0;
tmp->cur_count = 0;
tmp->blink_flag = 0;
#if 0
for(i = 0 ; i < LINE_BUF_X_SIZE ; i++)
tmp->buf[i] = 0x20;
#endif
return(tmp);
}
static void free_line_buf(LINE_BUF *lb)
{
lb->next = lb_free_ptr;
lb->prev = NULL;
(lb->next)->prev = lb;
lb_free_ptr = lb;
}
static int init_lb_heap(void *heap_start, void *heap_end)
{
int i;
LINE_BUF *lb_heap=(LINE_BUF *)heap_start;
lb_free_ptr = (LINE_BUF *)heap_start;
lb_heap[0].prev = NULL;
i = 0;
while( (u32)&(lb_heap[i+1]) < (u32)heap_end ) {
link_line_buf(&(lb_heap[i]), &(lb_heap[i+1]));
i++;
}
lb_heap[i].next = NULL;
return i; /* num of line buffer */
#if 0
OS_Printf("text_heap s %08x\n",(u32)heap_start);
OS_Printf("text_heap e %08x\n",(u32)heap_end);
#endif
}
static void init_text_buf(TEXT_BUF *tb)
{
tb->num_y = &y_size;
tb->num_x = &x_size;
tb->virtual_x = LINE_BUF_X_SIZE - X_LINE_MAX - 1;
// tb->virtual_y = Y_LINE_MAX * 4;
tb->virtual_y = Y_LINE_VIRTUAL_MAX;
tb->start = tb->cur = alloc_line_buf();
tb->display_offset_y = 0;
tb->display_offset_x = 0;
}
void init_text(TEXT_CTRL *tc, u16 *screen, u16 *screen_bg1, u16 palette)
{
tc->screen = screen;
tc->screen_bg1 = screen_bg1;
tc->x_line = 0;
tc->y_line = 0;
tc->palette = palette;
init_text_buf(&(tc->text_buf));
}
/*
0 -> black
1 -> red
2 -> green
3 -> blue
4 -> yellow
5 -> purple
6 -> sky blue
7 -> red
8 -> green
9 -> blue
0xA -> yellow
0xB -> purple
0xC -> sky blue
0xD -> white
0xE -> white
0xF -> white
*/
void m_set_palette(TEXT_CTRL *tc, u16 num)
{
tc->palette = (u16)(0x0f & num);
}
u16 m_get_palette(TEXT_CTRL *tc)
{
return tc->palette;
}
void m_set_display_offset_x(TEXT_CTRL *tc, int offset)
{
TEXT_BUF *tb = &(tc->text_buf);
if( ( offset >= 0 ) && (offset < tb->virtual_x) ) {
tb->display_offset_x = offset;
}
}
int m_get_display_offset_x(TEXT_CTRL *tc)
{
TEXT_BUF *tb = &(tc->text_buf);
return tb->display_offset_x;
}
void m_set_display_offset_y(TEXT_CTRL *tc, int offset)
{
TEXT_BUF *tb = &(tc->text_buf);
LINE_BUF *lb = tb->cur;
int line_count = 0;
while( lb != NULL ) {
line_count++;
lb = lb->prev;
}
if( ( offset >= 0 ) && (offset < line_count - Y_LINE_MAX ) ) {
tb->display_offset_y = offset;
}
}
int m_get_display_offset_y(TEXT_CTRL *tc)
{
TEXT_BUF *tb = &(tc->text_buf);
return tb->display_offset_y;
}
static void clear_line(TEXT_CTRL *tc)
{
int i;
i = tc->x_line;
for( ; i < X_LINE_MAX ; i++)
tc->screen[(tc->y_line * X_LINE_MAX ) + i] = 0;
}
static void add_y_line(TEXT_CTRL *tc,u16 num)
{
tc->y_line += num;
if( tc->y_line > Y_LINE_MAX ) {
tc->y_line = 0;
}
}
static void add_x_line(TEXT_CTRL *tc,u16 num)
{
tc->x_line += num;
if( tc->x_line > X_LINE_MAX ) {
tc->x_line = 0;
tc->y_line++;
if( tc->y_line > Y_LINE_MAX ) {
tc->y_line = 0;
}
}
}
static void put_char_vram(TEXT_CTRL *tc, int c, u16 col)
{
switch( c ) {
case '\0':
break;
case '\n':
clear_line(tc);
tc->x_line = 0;
add_y_line(tc, 1 );
break;
case '\r':
tc->x_line = 0;
break;
case '\t':
add_x_line(tc, TAB_SIZE );
break;
case '\f':
tc->x_line = 0;
tc->y_line = 0;
clear_line(tc);
break;
case '\b': /* Back Space */
case '\v': /* Vertical Tab */
break;
default:
if( ( c < 0x20 ) || ( 0x7f < c ) )
c = 0x20; /* white space */
tc->screen[(tc->y_line * X_LINE_MAX ) + tc->x_line] = (u16)((col << 12) | (0x00ff & c));
add_x_line(tc, 1 );
}
}
/**********************/
void m_putchar(TEXT_CTRL *tc, int c)
{
int i;
LINE_BUF *tmp;
TEXT_BUF *tb = &(tc->text_buf);
switch( c ) {
case '\0':
break;
case '\n':
if( tb->cur->next == NULL ) {
tmp = tb->cur; /* <20>\<5C><><EFBFBD>J<EFBFBD>n<EFBFBD>o<EFBFBD>b<EFBFBD>t<EFBFBD>@<40><><EFBFBD>Čv<C48C>Z */
for(i = 0 ; (i < *(tb->num_y)-1) && (i < LINE_BUF_Y_SIZE) ; i++) {
if( tmp->prev == NULL )
break;
tmp = tmp->prev;
}
tb->start = tmp; /* <20>\<5C><><EFBFBD>J<EFBFBD>n<EFBFBD>o<EFBFBD>b<EFBFBD>t<EFBFBD>@ */
/* <20><><EFBFBD><EFBFBD><EFBFBD>Ȃ<EFBFBD><C882>o<EFBFBD>b<EFBFBD>t<EFBFBD>@<40><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>A<EFBFBD><41><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ۑ<EFBFBD><DB91>p<EFBFBD>o<EFBFBD>[<5B>`<60><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͎c<CD8E><63> */
i = 0;
while(tmp->prev != NULL) {
tmp = tmp->prev;
i++;
if( i > tb->virtual_y-1 ) {
unlink_line_buf( tmp );
free_line_buf( tmp );
}
}
tmp = alloc_line_buf(); /* <20>o<EFBFBD>b<EFBFBD>t<EFBFBD>@<40><><EFBFBD>P<EFBFBD>Ž擾 */
if( tmp == NULL ) {
/* <20><><EFBFBD>C<EFBFBD><43><EFBFBD>o<EFBFBD>b<EFBFBD>t<EFBFBD>@<40><><EFBFBD>Ȃ<EFBFBD> */
OS_TPrintf("Free line buffer shortage!!\n");
return;
}
link_line_buf(tb->cur, tmp); /* <20><EFBFBD><E693BE><EFBFBD><EFBFBD><EFBFBD>o<EFBFBD>b<EFBFBD>t<EFBFBD>@<40><><EFBFBD>J<EFBFBD><4A><EFBFBD><EFBFBD><EFBFBD>g
<20>o<EFBFBD>b<EFBFBD>t<EFBFBD>@<40>̎<EFBFBD><CC8E>Ƀ<EFBFBD><C983><EFBFBD><EFBFBD>N */
tb->cur = tmp; /* <20>J<EFBFBD><4A><EFBFBD><EFBFBD><EFBFBD>g<EFBFBD>o<EFBFBD>b<EFBFBD>t<EFBFBD>@<40><><EFBFBD>X<EFBFBD>V */
tb->cur->cur_count = 0;
tb->cur->last_count = 0;
}
else {
tb->cur = tb->cur->next;
tb->cur->cur_count = 0;
tb->cur->last_count = 0;
}
break;
case '\r':
tb->cur->cur_count = 0;
break;
case '\t':
tb->cur->cur_count += TAB_SIZE;
if( tb->cur->cur_count > LINE_BUF_X_SIZE )
tb->cur->cur_count = LINE_BUF_X_SIZE;
if( tb->cur->cur_count > tb->cur->last_count )
tb->cur->last_count = tb->cur->cur_count;
break;
case '\f':
tb->cur = tb->start;
tb->cur->cur_count = 0;
tb->cur->last_count = 0;
break;
case '\a': /* BELL */
break;
case '\b': /* Back Space */
if( tb->cur->cur_count > 0 )
tb->cur->cur_count--;
break;
case '\v': /* Vertical Tab */
break;
default:
if( tb->cur->cur_count >= LINE_BUF_X_SIZE ) {
/* add 2008.08.14 */
/* <20><><EFBFBD>C<EFBFBD><43><EFBFBD>o<EFBFBD>b<EFBFBD>t<EFBFBD>@<40><><EFBFBD>I<EFBFBD>[<5B>o<EFBFBD>[<5B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̋<EFBFBD><CC8B><EFBFBD> */
if( tb->display_newline == 0 ) {
/* <20>\<5C><><EFBFBD><EFBFBD><EFBFBD>Ȃ<EFBFBD> */
break;
}
else {
/* <20><><EFBFBD>s<EFBFBD><73><EFBFBD>ĕ\<5C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
m_putchar(tc, '\n');
}
}
tb->cur->buf[tb->cur->cur_count] = c;
tb->cur->col[tb->cur->cur_count] = tc->palette;
tb->cur->cur_count++;
if( tb->cur->cur_count > LINE_BUF_X_SIZE ) {
tb->cur->cur_count = LINE_BUF_X_SIZE;
break;
}
if( tb->cur->cur_count > tb->cur->last_count )
tb->cur->last_count = tb->cur->cur_count;
break;
}
}
int init_text_buf_sys(void *heap_start, void *heap_end)
{
return init_lb_heap(heap_start, heap_end);
}
static int blink_counter = 0;
static int blink_flag = 0;
void text_buf_to_vram(TEXT_CTRL *tc)
{
int x_line,line_no;
int c;
u16 col;
int i;
LINE_BUF *lb;
TEXT_BUF *tb = &(tc->text_buf);
blink_counter++;
/* blink interval */
if( blink_flag == 1 ) {
if( blink_counter > 100 ) {
blink_counter = 0;
blink_flag ^= 1;
}
}
else {
if( blink_counter > 20 ) {
blink_counter = 0;
blink_flag ^= 1;
}
}
lb = tb->start;
i = 0;
while( i < tb->display_offset_y ) {
if( lb->prev == NULL ) {
break;
}
lb = lb->prev;
i++;
}
put_char_vram(tc, '\f', (u16)0);
for(line_no = 0 ; line_no < *tb->num_y ; line_no++ ){
//miya x_line = 0;
x_line = tb->display_offset_x;
if( lb == NULL)
break;
while( x_line < lb->last_count ) {
//miya 2008.09.10
// if( x_line >= (*tb->num_x + 1)) {
if( x_line >= (*tb->num_x + 1 + tb->display_offset_x)) {
break;
}
else {
if( lb->blink_flag ) {
if( blink_flag == 0 ) {
c = 0;
col = 0;
}
else {
c = lb->buf[x_line];
col = lb->col[x_line];
}
}
else {
c = lb->buf[x_line];
col = lb->col[x_line];
}
put_char_vram(tc, c, col);
}
x_line++;
}
//miya 2008.09.10
// if( x_line <= *tb->num_x ) {
if( x_line <= *tb->num_x + tb->display_offset_x ) {
put_char_vram(tc, '\n', (u16)0);
}
lb = lb->next;
}
for( ; line_no < *tb->num_y ; line_no++ ) {
put_char_vram(tc, '\n', (u16)0);
}
}