Implement a console which is fed by the _write() syscall (and thus e.g. stdout) and redirect locate() to the console

This commit is contained in:
Memallox 2018-08-31 18:04:44 +02:00
parent c81076ab88
commit c40e651d90
6 changed files with 260 additions and 4 deletions

View File

@ -8,7 +8,7 @@ AM_CCASFLAGS = $(INCLUDES) $(CFLAGS)
noinst_LIBRARIES = lib.a
lib_a_SOURCES = syscalls.c trap.S creat.c ftruncate.c truncate.c calloc.c free.c malloc.c memcmp.c memcpy.c memmove.c memset.c realloc.c strcat.c strchr.c strcmp.c strlen.c strncat.c strncmp.c strncpy.c strrchr.c strstr.c casio_syscalls.c
lib_a_SOURCES = syscalls.c trap.S creat.c ftruncate.c truncate.c calloc.c free.c malloc.c memcmp.c memcpy.c memmove.c memset.c realloc.c strcat.c strchr.c strcmp.c strlen.c strncat.c strncmp.c strncpy.c strrchr.c strstr.c casio_syscalls.c console.c
lib_a_CCASFLAGS = $(AM_CCASFLAGS)
lib_a_CFLAGS = $(AM_CFLAGS)

View File

@ -80,7 +80,7 @@ am_lib_a_OBJECTS = lib_a-syscalls.$(OBJEXT) lib_a-trap.$(OBJEXT) \
lib_a-strlen.$(OBJEXT) lib_a-strncat.$(OBJEXT) \
lib_a-strncmp.$(OBJEXT) lib_a-strncpy.$(OBJEXT) \
lib_a-strrchr.$(OBJEXT) lib_a-strstr.$(OBJEXT) \
lib_a-casio_syscalls.$(OBJEXT)
lib_a-casio_syscalls.$(OBJEXT) lib_a-console.$(OBJEXT)
lib_a_OBJECTS = $(am_lib_a_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp =
@ -207,7 +207,7 @@ AUTOMAKE_OPTIONS = cygnus
INCLUDES = $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS)
AM_CCASFLAGS = $(INCLUDES) $(CFLAGS)
noinst_LIBRARIES = lib.a
lib_a_SOURCES = syscalls.c trap.S creat.c ftruncate.c truncate.c calloc.c free.c malloc.c memcmp.c memcpy.c memmove.c memset.c realloc.c strcat.c strchr.c strcmp.c strlen.c strncat.c strncmp.c strncpy.c strrchr.c strstr.c casio_syscalls.c
lib_a_SOURCES = syscalls.c trap.S creat.c ftruncate.c truncate.c calloc.c free.c malloc.c memcmp.c memcpy.c memmove.c memset.c realloc.c strcat.c strchr.c strcmp.c strlen.c strncat.c strncmp.c strncpy.c strrchr.c strstr.c casio_syscalls.c console.c
lib_a_CCASFLAGS = $(AM_CCASFLAGS)
lib_a_CFLAGS = $(AM_CFLAGS)
ACLOCAL_AMFLAGS = -I ../../.. -I ../../../..
@ -414,6 +414,12 @@ lib_a-casio_syscalls.o: casio_syscalls.c
lib_a-casio_syscalls.obj: casio_syscalls.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-casio_syscalls.obj `if test -f 'casio_syscalls.c'; then $(CYGPATH_W) 'casio_syscalls.c'; else $(CYGPATH_W) '$(srcdir)/casio_syscalls.c'; fi`
lib_a-console.o: console.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-console.o `test -f 'console.c' || echo '$(srcdir)/'`console.c
lib_a-console.obj: console.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-console.obj `if test -f 'console.c'; then $(CYGPATH_W) 'console.c'; else $(CYGPATH_W) '$(srcdir)/console.c'; fi`
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \

View File

@ -1,6 +1,7 @@
#include <stddef.h>
#include <sys/casio_syscalls.h>
#include <sys/console.h>
DEFINE_CASIO_SYSCALL_FN_PTR(GetKey, int, (unsigned int*), 0x90F)
DEFINE_CASIO_SYSCALL_FN_PTR(PutKey, int, (int keycode, int mode), 0x910)
@ -36,7 +37,18 @@ void Print(const unsigned char* str) {
}
void locate(int x, int y) {
/*
* This call could be omitted, but to keep compatibility with the fxlib functions:
* locate(x, y);
* Print(str);
*/
_locate_ptr(x, y);
/*
* For use with stdio functions like printf
*/
_console_set_cursor(&_console_ctx, x, y);
}
void wait_ms(unsigned int ms) { // TODO signature assumed

View File

@ -0,0 +1,167 @@
#include <sys/console.h>
#include <sys/casio_syscalls.h>
/*
* Console instance for printf etc.
*/
_console _console_ctx = {
.cursor_x = 0,
.cursor_y = 0,
.buf_strlen = 0,
.buf = {0},
};
/*
* Sets the internal cursor position on the console.
* Note that the Casio cursor position will not be set until
* the console is flushed (automatically or manually).
*/
void _console_set_cursor(_console *ctx, unsigned char x, unsigned char y) {
/*
* No need to flush here, because the buffer already was flushed
* at the end of the _console_write() function.
*/
if (x < _CONSOLE_WIDTH && y < _CONSOLE_HEIGHT) {
ctx->cursor_x = x;
ctx->cursor_y = y;
}
}
/*
* Writes the (potentially but not necessarily null-terminated)
* string *ptr to the internal buffer. May flush and invoke
* the Casio "locate" and "Print" syscalls.
*/
int _console_write (_console *ctx, int file, char *ptr, int len)
{
/*
* Start parsing
*/
while (len-- && *ptr) {
/*
* Filter out all control characters
*/
switch (*ptr) {
case '\a':
// ignore
ptr++;
continue;
case '\b':
// undo last char (if not first char in line)
// no wrapping
ctx->cursor_x -= !!ctx->cursor_x;
ctx->buf_strlen -= !!ctx->buf_strlen;
ctx->buf[ctx->buf_strlen] = '\0';
ptr++;
continue;
case '\f':
case '\v':
_console_flush(ctx);
ctx->cursor_y = (ctx->cursor_y + 1) % _CONSOLE_HEIGHT;
ptr++;
continue;
case '\n':
_console_flush(ctx);
ctx->cursor_x = 0;
ctx->cursor_y = (ctx->cursor_y + (ctx->cursor_x < _CONSOLE_WIDTH)) % _CONSOLE_HEIGHT;
ptr++;
continue;
case '\r':
_console_flush(ctx);
ctx->cursor_x = 0;
ptr++;
continue;
case '\t':
;
/*
* Go to next tab stop (or to the end of the line).
*/
/*
* Somehow the following statement (see int s) cannot be written directly inside
* the condition of the for loop (or the program will act strangely).
* Possibly due to signedness? TODO
*/
int s = _CONSOLE_TAB_LEN - (ctx->cursor_x % _CONSOLE_TAB_LEN);
for (int i = 0; i < s; i++) {
_console_write(ctx, file, " ", 1);
}
ptr++;
continue;
}
// Add char to the buffer (flushes before it overflows)
_console_putc(ctx, *ptr);
// Flush buffer if there is a line wrap
if (ctx->cursor_x == _CONSOLE_WIDTH - 1) {
/*
* Temporarily increment cursor_x (without wrapping)
* because _console_flush expects the cursor to point
* to the position of the next char.
*/
ctx->cursor_x++;
_console_flush(ctx);
ctx->cursor_x--;
}
// Move curser to the left (wrap if bounds are exceeded)
ctx->cursor_x = (ctx->cursor_x + 1) % _CONSOLE_WIDTH;
// Move curser down if (ctx->cursor_x == 0) (wrap if bounds are exceeded)
ctx->cursor_y = (ctx->cursor_y + !ctx->cursor_x) % _CONSOLE_HEIGHT;
ptr++;
}
// Always flush in the end
_console_flush(ctx);
return len;
}
/*
* Adds a character to the internal buffer.
* Does not take care of the cursor position.
* May invoke _console_flush() to print the contents of the internal buffer.
* Use _console_flush() to manually flush the contents to the console output.
* Does not change the position of the internal cursor.
*/
void _console_putc(_console *ctx, char c) {
if (ctx->buf_strlen == _CONSOLE_BUF_WIDTH - 1) {
_console_flush(ctx);
}
ctx->buf[ctx->buf_strlen++] = c;
ctx->buf[ctx->buf_strlen] = '\0';
}
/*
* Prints the buffer out to the console and invokes
* the Casio "locate" and "Print" syscalls.
* Resets the internal buffer to "".
* Does not change the position of the internal cursor.
*/
void _console_flush(_console *ctx) {
/*
* Local syscall to Casio's locate
* because Casio's syscall is overwritten by _casio_set_cursor()
*/
typedef void (*console_locate_type)(int, int);
static const unsigned int console_locate_address[] = { _CASIO_SYSCALLS_SCA, _CASIO_SYSCALLS_SCB,_CASIO_SYSCALLS_SCE, 0x807 };
static const console_locate_type console_locate_ptr = (console_locate_type) console_locate_address;
if (!ctx->buf_strlen) {
return;
}
// +1 because the CASIO cursor position is 1-based
console_locate_ptr(ctx->cursor_x - ctx->buf_strlen + 1, ctx->cursor_y + 1);
Print((unsigned char*) ctx->buf);
ctx->buf[0] = '\0';
ctx->buf_strlen = 0;
}

View File

@ -0,0 +1,69 @@
#ifdef _CONSOLE_H
#define _CONSOLE_H
#else
/* Width of display in characters */
#define _CONSOLE_WIDTH 21
/* Height of the display in lines */
#define _CONSOLE_HEIGHT 8
/*
* Size of the internal buffer in chars/bytes.
* Can be set arbitrarily (but must not be 0)
*/
#define _CONSOLE_BUF_WIDTH (_CONSOLE_WIDTH + 1)
/* Width of a tab (amount of spaces) */
#define _CONSOLE_TAB_LEN 4
/*
* Structure to store the state of the console.
* Contains the cursor position and an internal buffer.
*/
typedef struct {
/*
* Cursor position (column) of the next char to be written.
* Unlike the convention set by CASIO:
* the cursor position is 0-based!
* The actual Casio cursor will not be set until the
* consol is flushed!
*/
unsigned char cursor_x;
/*
* Cursor position (row) of the next char to be written.
* Unlike the convention set by CASIO:
* the cursor position is 0-based!
* The actual Casio cursor will not be set until the
* consol is flushed!
*/
unsigned char cursor_y;
/*
* Internal buffer of the console.
* All those characters will be consecutive and in the same line.
* If the cursor changes position, the buffer needs to be flushed.
*/
char buf[_CONSOLE_BUF_WIDTH];
/*
* Amount of characters in the internal buffer.
*/
unsigned char buf_strlen;
} _console;
/*
* Console instance for the stdio functions like printf etc.
*/
extern _console _console_ctx;
int _console_write(_console *ctx, int file, char *ptr, int len);
void _console_set_cursor(_console *ctx, unsigned char x, unsigned char y);
void _console_flush(_console *ctx);
void _console_putc(_console *ctx, char c);
#endif /* _CONSOLE_H */

View File

@ -3,6 +3,7 @@
#include <sys/stat.h>
#include <sys/time.h>
#include "sys/syscall.h"
#include "sys/console.h"
int errno;
/* This is used by _sbrk. */
@ -29,7 +30,8 @@ _write ( int file,
char *ptr,
int len)
{
return -1;
_console_write(&_console_ctx, file, ptr, len);
return len;
}
int