Almost ended quality review, and fixed tales-related vram overflows.

This commit is contained in:
lephe 2017-04-19 19:57:31 +02:00
parent 6c0ae34708
commit 3214f6b797
33 changed files with 327 additions and 183 deletions

View file

@ -30,7 +30,7 @@ wr = g1a-wrapper
# Flags for gint # Flags for gint
lib-cflags = -m3 -mb -nostdlib -I include -ffreestanding -std=c11 -Os \ lib-cflags = -m3 -mb -nostdlib -I include -ffreestanding -std=c11 -Os \
-Wall -Wextra @gcc.cfg -Wall -Wextra @gcc.cfg -g0
# Demo application (could be done better) # Demo application (could be done better)
demo-src = $(notdir $(wildcard demo/*.[cs])) demo-src = $(notdir $(wildcard demo/*.[cs]))

9
TODO
View file

@ -3,14 +3,11 @@ Bugs to fix:
- Lost keyboard control at startup (could not reproduce) - Lost keyboard control at startup (could not reproduce)
- Alignment of ALL .data / .rodata files is required to ensure converted data - Alignment of ALL .data / .rodata files is required to ensure converted data
is properly aligned is properly aligned
- Reported video ram overflow when rendering text at borderline positions
Things to do before 1.0: Things to do before 1.0:
- bopti: Test partial transparency - bopti: Test partial transparency
* core: Allow return to menu * core: Allow return to menu
- demo: Try 284x124 at (-60, -28) (all disadvantages) - demo: Try 284x124 at (-60, -28) (all disadvantages)
- display: Implement rectangle-based drawing functions
- project: Add a real build-based version system
- project: Check size of *all* library structures - project: Check size of *all* library structures
- project: Clean headers that have some internal definitions - project: Clean headers that have some internal definitions
- project: Unify this hellish mess of register access! - project: Unify this hellish mess of register access!
@ -24,7 +21,13 @@ Things to do later:
- core: Review interrupt system (again) - this one is too slow - core: Review interrupt system (again) - this one is too slow
- errno: Introduce errno and use it more or less everywhere - errno: Introduce errno and use it more or less everywhere
- esper: Cleaner playback, synthesizing - esper: Cleaner playback, synthesizing
- events: Allow customization of keyboard event system (option to return
| events with modifiers, etc)
- events: Generate keyboard events on-the-fly by reading state arrays,
| allowing both a faster interrupt and avoiding supressing other
| events inside getkey() and multigetkey()
- serial: Implement a driver - serial: Implement a driver
- stdio: More serious formatted printing functions
- string: Use cmp/str to implement memchr() (assembler examples) - string: Use cmp/str to implement memchr() (assembler examples)
- string: Do some tests for memcmp() and memcpy() - string: Do some tests for memcmp() and memcpy()
- usb: Implement a driver - usb: Implement a driver

56
demo/asm_syscalls.s Normal file
View file

@ -0,0 +1,56 @@
# int BFile_Remove(const uint16_t *file)
.global _BFile_Remove
_BFile_Remove:
mov.l 1f, r0
mov.l 2f, r1
jmp @r1
mov #0, r5
1: .long 0x0439
# int BFile_Create(const uint16_t *file, enum { file = 1, folder = 5 },
# int *size)
.global _BFile_Create
_BFile_Create:
mov.l 1f, r0
mov.l 2f, r1
jmp @r1
nop
1: .long 0x0434
# int BFile_Open(const uint16_t *file, int mode)
.global _BFile_Open
_BFile_Open:
mov.l 1f, r0
mov.l 2f, r1
jmp @r1
mov #0, r6
1: .long 0x042c
# int BFile_Close(int handle)
.global _BFile_Close
_BFile_Close:
mov.l 1f, r0
mov.l 2f, r1
jmp @r1
nop
1: .long 0x042d
# int BFile_Write(int handle, void *ram_buffer, int even_size)
.global _BFile_Write
_BFile_Write:
mov.l 1f, r0
mov.l 2f, r1
jmp @r1
nop
1: .long 0x0435
.align 4
# Syscall branch address
2: .long 0x80010070

View file

@ -434,6 +434,10 @@ void main_menu(int *category, int *app)
index = 0; index = 0;
scroll = 0; scroll = 0;
break; break;
case KEY_F6:;
void screen(void);
screen();
break;
case KEY_UP: case KEY_UP:
if(list && list_len > 1) if(list && list_len > 1)
@ -533,3 +537,48 @@ void crash(void)
"trapa #1 " "trapa #1 "
); );
} }
void screen(void)
{
enum { File = 1, Folder = 5 };
enum { Read = 0x01, Write = 0x02, ReadWrite = Read | Write };
int BFile_Remove(const uint16_t *file);
int BFile_Create(const uint16_t *file, int type, int *size);
int BFile_Open(const uint16_t *file, int mode);
int BFile_Close(int handle);
int BFile_Write(int handle, const void *ram_buffer, int even_size);
const uint8_t bmp_header[0x7e] = {
0x42, 0x4d, 0x7e, 0x04, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x6c, 0x00,
0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x40, 0x00,
0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x13, 0x0b,
0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x42, 0x47,
0x52, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0xff, 0xff, 0x00,
};
const uint16_t file[] = { '\\', '\\', 'f', 'l', 's', '0', '\\', 'g',
's', 'c', 'r', 'e', 'e', 'n', '.', 'b', 'm', 'p', 0x00 };
int size = 0x7e + 1024;
BFile_Remove(file);
BFile_Create(file, File, &size);
int handle = BFile_Open(file, Write);
BFile_Write(handle, bmp_header, 0x7e);
void *vram = (void *)display_getCurrentVRAM() + 1024;
for(int i = 1; i <= 64; i++)
{
BFile_Write(handle, vram - 16 * i, 16);
}
BFile_Close(handle);
}

View file

@ -53,14 +53,15 @@ static void draw_keyboard(volatile uint8_t *state)
typedef struct { typedef struct {
event_type_t type; event_type_t type;
int key; uint32_t key;
int repeats; int repeats;
} enhanced_event_t; } enhanced_event_t;
static void push_history(enhanced_event_t *history, int size, event_t event) static void push_history(enhanced_event_t *history, int size, event_t event)
{ {
#define event_eq(x, y) ((x).type == (y).type && (x).key == (y).key) #define event_eq(x, y) \
((x).type == (y).type && (x).key == (y).key.code)
// Determining where the history ends. // Determining where the history ends.
int length = 0; int length = 0;
@ -82,7 +83,7 @@ static void push_history(enhanced_event_t *history, int size, event_t event)
// Adding a new entry to the history. // Adding a new entry to the history.
history[length].type = event.type; history[length].type = event.type;
history[length].key = event.key; history[length].key = event.key.code;
history[length].repeats = 1; history[length].repeats = 1;
#undef event_eq #undef event_eq
@ -135,7 +136,7 @@ void test_keyboard_events(void)
dupdate(); dupdate();
event = waitevent(); event = waitevent();
if(event.type == event_key_press && event.key == KEY_EXIT) if(event.type == event_key_press && event.key.code == KEY_EXIT)
break; break;
push_history(history, history_size, event); push_history(history, history_size, event);
} }

View file

@ -10,11 +10,11 @@
Displays some text using different modes and clipping options. Displays some text using different modes and clipping options.
*/ */
static Font *select(Font *current) static font_t *select(font_t *current)
{ {
extern Font res_font_modern; extern font_t res_font_modern;
struct { struct {
Font *font; font_t *font;
const char *name; const char *name;
} fonts[] = { } fonts[] = {
{ NULL, "gint default" }, { NULL, "gint default" },
@ -83,7 +83,7 @@ void test_tales(void)
color_t colors[] = { color_black, color_dark, color_light, color_white, color_t colors[] = { color_black, color_dark, color_light, color_white,
color_invert }; color_invert };
extern image_t res_opt_tales; extern image_t res_opt_tales;
Font *font = NULL; font_t *font = NULL;
int black_bg = 0; int black_bg = 0;
int color = 0; int color = 0;
@ -113,10 +113,8 @@ void test_tales(void)
for(int j = 0; j < 16; j++) str[j] = 32 + (i << 4) + j; for(int j = 0; j < 16; j++) str[j] = 32 + (i << 4) + j;
str[16] = 0; str[16] = 0;
gtext(-3, -3 + i * height, str); gtext(1, 1 + i * height, str);
} }
gtext(120, 60, "Hello, World!");
gtext(-40, 2, "Try");
gimage(0, 56, &res_opt_tales); gimage(0, 56, &res_opt_tales);

View file

@ -41,6 +41,23 @@ typedef enum
} event_type_t; } event_type_t;
/*
key_event_t
Keyboard events. "I think the user wants something."
*/
typedef struct
{
// This is the key code as defined in <keyboard.h> (a matrix code), and
// probably what you need.
uint32_t code;
// This is a "compact id" which can be used for array subscript. There
// are only a few holes in the "compact id" numbering.
uint32_t id;
// Character associated with the event key.
int character;
} key_event_t;
/* /*
event_t event_t
Wake up, something's going on. The union member that holds information Wake up, something's going on. The union member that holds information
@ -55,7 +72,7 @@ typedef struct
// For event_user. // For event_user.
void *data; void *data;
// For event_key_press, event_key_repeat and event_key_release. // For event_key_press, event_key_repeat and event_key_release.
int key; key_event_t key;
// For event_timer_underflow. // For event_timer_underflow.
timer_t *timer; timer_t *timer;
}; };

View file

@ -23,6 +23,7 @@ __attribute__((always_inline)) static inline uint32_t swap32(uint32_t longw)
"swap.b r0, %0 \n\t" "swap.b r0, %0 \n\t"
: "=r"(result) : "=r"(result)
: "r"(longw) : "r"(longw)
: "r0"
); );
return result; return result;
} }

View file

@ -15,11 +15,16 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
// This one is defined by the linked and consists in four fields: // The version symbol is defined through the linker and consists of four
// fields:
// - Version type, an ascii char ('a'lpha, 'b'eta, 'd'ev, 'r'elease), 8 bits // - Version type, an ascii char ('a'lpha, 'b'eta, 'd'ev, 'r'elease), 8 bits
// - Major version number, 4 bits // - Major version number, 4 bits
// - Minor version numer, 4 bits // - Minor version number, 4 bits
// - Build number, 16 bits // - Build number, 16 bits
// Please note that the version number is the *ADDRESS* of GINT_VERSION, which
// you definitely want to cast to uint32_t. Evaluating GINT_VERSION is illegal
// (dereferencing a pointer which is actually a four-field version number just
// cannot work) and will certainly crash your program.
extern uint32_t GINT_VERSION; extern uint32_t GINT_VERSION;
//--- //---

View file

@ -1,12 +1,3 @@
//---
//
// standard library module: stdio
//
// Handles most input/output for the program. This module does not
// interact with the file system directly.
//
//---
#ifndef _INTERNALS_STDIO_H #ifndef _INTERNALS_STDIO_H
#define _INTERNALS_STDIO_H #define _INTERNALS_STDIO_H

View file

@ -3,10 +3,11 @@
#include <tales.h> #include <tales.h>
#include <stdint.h> #include <stdint.h>
#include <stddef.h>
#define OPERATE_ARGS uint32_t *operators, int height, int x, int y #define OPERATE_ARGS uint32_t *operators, int height, int x, int y
extern struct Font *font; extern font_t *font;
extern color_t operator; extern color_t operator;
/* /*

View file

@ -3,14 +3,14 @@
#include <stdint.h> #include <stdint.h>
// Padding is just empty space, we don't want to give it a name. There's also // Padding is just empty space, we don't want to give it a type. There's also
// some subtle preprocessor trick to automatically add a (supposedly) unique // some subtle preprocessor trick to automatically add a (supposedly) unique
// name to each padding member. For instance the substitution may operate as: // name to each padding member. For instance the substitution may operate as:
// name(__LINE__) -> namesub(78) -> _##78 -> _78 // name(__LINE__) -> namesub(78) -> _##78 -> _78
#define namesub(x) _##x #define namesub(x) _##x
#define name(x) namesub(x) #define name(x) namesub(x)
#define pad(bytes) \ #define pad(bytes) \
uint8_t name(__LINE__)[bytes] \ uint8_t name(__LINE__)[bytes]
// Fixed-width types for bit field are totally meaningless. // Fixed-width types for bit field are totally meaningless.
typedef unsigned uint; typedef unsigned uint;

View file

@ -7,7 +7,7 @@
// which is stored in a global variable MPU_CURRENT and determined at // which is stored in a global variable MPU_CURRENT and determined at
// startup. // startup.
// //
// If you need to do MPU-dependant jobs, use isSH3() or (possibly) isSH4() // If you need to do MPU-dependent jobs, use isSH3() or (possibly) isSH4()
// instead of testing the value of MPU_CURRENT because these macros take // instead of testing the value of MPU_CURRENT because these macros take
// care of assuming unknown MPUs are SH4, which is the more reasonable // care of assuming unknown MPUs are SH4, which is the more reasonable
// option. // option.

View file

@ -10,9 +10,11 @@
#ifndef _SETJMP_H #ifndef _SETJMP_H
#define _SETJMP_H #define _SETJMP_H
#include <stdint.h>
// There are 16 CPU registers that *must* be saved to ensure a basically // There are 16 CPU registers that *must* be saved to ensure a basically
// safe jump. // safe jump.
typedef unsigned int jmp_buf[16]; typedef uint32_t jmp_buf[16];

View file

@ -19,42 +19,43 @@
//--- //---
/* /*
enum ImageFormat font_format_t
This type holds information about the characters in the font. Each bit This type holds information about the characters in the font. Each bit
represents various characters, and the type itself is a combination of represents various characters, and the type itself is a combination of
several of those bits. several of those bits.
Bits represent the following characters (lsb right): Bits represent the following characters (lsb right):
-- -- -- non-print | special capitals lower numbers -- -- -- non-print | special capitals lower numbers
*/ */
enum FontFormat typedef enum
{ {
FontFormat_Unknown = 0x00, font_format_unknown = 0x00,
FontFormat_Numeric = 0x01, font_format_numeric = 0x01,
FontFormat_LowerCase = 0x02, font_format_lower = 0x02,
FontFormat_UpperCase = 0x04, font_format_upper = 0x04,
FontFormat_Letters = 0x06, font_format_letters = 0x06,
FontFormat_Common = 0x07, font_format_common = 0x07,
FontFormat_Print = 0x0f, font_format_print = 0x0f,
FontFormat_Ascii = 0x1f, font_format_ascii = 0x1f,
};
} font_format_t;
/* /*
struct FontGlyph font_glyph_t
Holds a glyph's data. The width is used for spacing, and the raw data 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 is encoded line after line, from to to bottom, by appending bits
without consideration of the byte boundaries. without consideration of the byte boundaries.
This structure is actually never used, because data is read directly This structure is actually never used, because data is read directly
as a longword array (hence the 4-byte alignment). as a longword array (hence the 4-byte alignment).
*/ */
struct FontGlyph typedef struct
{ {
unsigned char width; uint8_t width;
const uint8_t data[];
const unsigned char data[]; } __attribute__((packed, aligned(4))) font_glyph_t;
} __attribute__((aligned(4)));
/* /*
struct Font font_t
Holds a font's data. Data is accessed using longword operations, hence 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 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 font image header line, which may be used by applications that write
@ -65,13 +66,12 @@ struct FontGlyph
The name field may not be NUL-terminated when the name contains 28 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. characters. When the name is shorter, the field is padded with zeros.
*/ */
struct Font typedef struct
{ {
unsigned char magic; uint8_t magic;
uint8_t format;
unsigned char format; uint8_t line_height;
unsigned char line_height; uint8_t data_height;
unsigned char data_height;
// Warning : this field may not be NUL-terminated. // Warning : this field may not be NUL-terminated.
char name[28]; char name[28];
@ -80,9 +80,7 @@ struct Font
__attribute__((aligned(4))) const uint32_t glyphs[]; __attribute__((aligned(4))) const uint32_t glyphs[];
} __attribute__((aligned(4))); } __attribute__((packed, aligned(4))) font_t;
// Useful shorthand for user code.
typedef struct Font Font;
@ -95,7 +93,7 @@ typedef struct Font Font;
Sets the font and color to use for subsequent text operations. Pass Sets the font and color to use for subsequent text operations. Pass
font = NULL to use the default font. font = NULL to use the default font.
*/ */
void text_configure(struct Font *font, color_t operator); void text_configure(font_t *font, color_t operator);
/* /*
text_length() text_length()

View file

@ -36,7 +36,7 @@ struct tm
clock_t clock_t
Only used by clock(). Only used by clock().
*/ */
typedef signed int clock_t; typedef signed int clock_t;
/* /*
time_t time_t

View file

@ -11,14 +11,18 @@
#include <timer.h> #include <timer.h>
#include <mpu.h> #include <mpu.h>
// Additional video rams used by the gray engine.
static uint32_t internal_vrams[3][256]; static uint32_t internal_vrams[3][256];
static uint32_t *vrams[4]; static uint32_t *vrams[4];
// Current vram set (0 or 1), delays of the light and dark frames respectively.
static int current = 0; static int current = 0;
static int delays[2]; static int delays[2];
// Is the engine currently running?
static int runs = 0; static int runs = 0;
// Hardware timer used to run the engine.
static timer_t *gray_timer = NULL; static timer_t *gray_timer = NULL;
@ -87,6 +91,9 @@ void gray_stop(void)
timer_stop(gray_timer); timer_stop(gray_timer);
runs = 0; runs = 0;
/* TODO This may not be very wise considering the fact that the user
may have specified another monochrome vram address. This raises again
the idea of a parameter stack. */
display_useVRAM(display_getLocalVRAM()); display_useVRAM(display_getLocalVRAM());
} }

View file

@ -1,24 +0,0 @@
#include <internals/keyboard.h>
/*
getPressedKey()
Finds a pressed key in the keyboard state and returns it.
*/
int getPressedKey(volatile uint8_t *keyboard_state)
{
int row = 1, column = 0;
int state;
if(keyboard_state[0] & 1) return KEY_AC_ON;
while(row <= 9 && !keyboard_state[row]) row++;
if(row > 9) return KEY_NONE;
state = keyboard_state[row];
while(!(state & 1))
{
state >>= 1;
column++;
}
return (column << 4) | row;
}

View file

@ -53,7 +53,7 @@ int getkey_opt(getkey_option_t options, int delay_ms)
break; break;
case event_key_press: case event_key_press:
key = event.key; key = event.key.code;
if(options & getkey_manage_backlight && key == KEY_OPTN if(options & getkey_manage_backlight && key == KEY_OPTN
&& (modifier & MOD_SHIFT)) && (modifier & MOD_SHIFT))
@ -79,7 +79,7 @@ int getkey_opt(getkey_option_t options, int delay_ms)
return key | modifier; return key | modifier;
case event_key_repeat: case event_key_repeat:
key = event.key; key = event.key.code;
if(key != last_key) continue; if(key != last_key) continue;
// Checking that this type of repetition is allowed. // Checking that this type of repetition is allowed.
@ -98,7 +98,7 @@ int getkey_opt(getkey_option_t options, int delay_ms)
break; break;
case event_key_release: case event_key_release:
if(event.key != last_key) break; if((int)event.key.code != last_key) break;
last_key = KEY_NONE; last_key = KEY_NONE;
last_repeats = 0; last_repeats = 0;
last_time = 0; last_time = 0;

View file

@ -36,27 +36,39 @@ timer_t *vtimer = NULL;
static inline void push_press(int keycode) static inline void push_press(int keycode)
{ {
uint32_t id = key_id(keycode);
event_t event = { event_t event = {
.type = event_key_press, .type = event_key_press,
.key = keycode, .key.code = keycode,
.key.id = id,
.key.character = key_char(keycode),
}; };
event_push(event); event_push(event);
} }
static inline void push_repeat(int keycode) static inline void push_repeat(int keycode)
{ {
uint32_t id = key_id(keycode);
event_t event = { event_t event = {
.type = event_key_repeat, .type = event_key_repeat,
.key = keycode, .key.code = keycode,
.key.id = id,
.key.character = key_char(keycode),
}; };
event_push(event); event_push(event);
} }
static inline void push_release(int keycode) static inline void push_release(int keycode)
{ {
uint32_t id = key_id(keycode);
event_t event = { event_t event = {
.type = event_key_release, .type = event_key_release,
.key = keycode, .key.code = keycode,
.key.id = id,
.key.character = key_char(keycode),
}; };
event_push(event); event_push(event);
} }

View file

@ -30,8 +30,8 @@
many keys on the same column are pressed, other keys of the same column many keys on the same column are pressed, other keys of the same column
may be triggered. may be triggered.
(The following values do not apply to the latest tests, even if the (The following values do not apply to the latest tests, but the trend
trend remains the same.) remains the same.)
- Less Bad key detection. - Less Bad key detection.
- 8 Very few column effects. Most often, three keys may be pressed - 8 Very few column effects. Most often, three keys may be pressed
simultaneously. However, [UP] has latencies and is globally not simultaneously. However, [UP] has latencies and is globally not
@ -63,7 +63,7 @@ static void kdelay(void)
Reads a keyboard row. Works like krow() for SH7705; see source file Reads a keyboard row. Works like krow() for SH7705; see source file
keyboard_7705.c for more details. keyboard_7705.c for more details.
*/ */
static int krow(int row) static uint8_t krow(int row)
{ {
volatile uint16_t *injector1 = (void *)0xa4050116; volatile uint16_t *injector1 = (void *)0xa4050116;
volatile uint8_t *data1 = (void *)0xa4050136; volatile uint8_t *data1 = (void *)0xa4050136;
@ -79,9 +79,9 @@ static int krow(int row)
uint16_t smask; uint16_t smask;
uint8_t cmask; uint8_t cmask;
int result = 0; uint8_t result = 0;
if(row < 0 || row > 9) return 0; if(row < 0 || row > 9) return 0x00;
// Additional configuration for SH7305. // Additional configuration for SH7305.
*detector = 0xaaaa; *detector = 0xaaaa;

View file

@ -66,16 +66,16 @@ static void kdelay(void)
krow() krow()
Reads a keyboard row. Reads a keyboard row.
*/ */
static int krow(int row) static uint8_t krow(int row)
{ {
// '11' on the active row, '00' everywhere else. // '11' on the active row, '00' everywhere else.
unsigned short smask = 0x0003 << ((row % 8) * 2); uint16_t smask = 0x0003 << ((row % 8) * 2);
// '0' on the active row, '1' everywhere else. // '0' on the active row, '1' everywhere else.
unsigned char cmask = ~(1 << (row % 8)); uint8_t cmask = ~(1 << (row % 8));
// Line results. // Line results.
int result = 0; uint8_t result = 0;
if(row < 0 || row > 9) return 0; if(row < 0 || row > 9) return 0x00;
// Initial configuration. // Initial configuration.
PFC.PBCR.WORD = 0xaaaa; PFC.PBCR.WORD = 0xaaaa;

View file

@ -1,6 +1,5 @@
#include <internals/mmu.h> #include <internals/mmu.h>
#include <stdint.h>
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
/* /*
mmu_pseudoTLBInit() mmu_pseudoTLBInit()
@ -15,15 +14,16 @@
*/ */
void mmu_pseudoTLBInit(void) void mmu_pseudoTLBInit(void)
{ {
extern unsigned int romdata; extern uint32_t romdata;
unsigned int address = 0x00300000; uint32_t limit = (uint32_t)&romdata;
unsigned int x;
while(address <= (unsigned int)&romdata) uint32_t address = 0x00300000;
// Access every page to make the system load everything in the TLB (and
// just hope it works and the add-in fits in).
while(address <= limit)
{ {
x = *((volatile unsigned int *)address); *((volatile uint32_t *)address);
address += 0x1000; address += 0x1000;
} }
} }
#pragma GCC diagnostic pop

View file

@ -1,4 +1,5 @@
#include <screen.h> #include <screen.h>
#include <stdint.h>
#include <mpu.h> #include <mpu.h>
/* /*
@ -9,13 +10,13 @@ void screen_setBacklight(int on)
{ {
if(isSH3()) if(isSH3())
{ {
volatile unsigned char *PGDR = (void *)0xa400012c; volatile uint8_t *PGDR = (void *)0xa400012c;
if(on) *PGDR |= 0x80; if(on) *PGDR |= 0x80;
else *PGDR &= ~0x80; else *PGDR &= ~0x80;
} }
else else
{ {
volatile unsigned char *PNDR = (void *)0xa4050138; volatile uint8_t *PNDR = (void *)0xa4050138;
if(on) *PNDR |= 0x10; if(on) *PNDR |= 0x10;
else *PNDR &= ~0x10; else *PNDR &= ~0x10;
} }
@ -29,12 +30,12 @@ void screen_toggleBacklight(void)
{ {
if(isSH3()) if(isSH3())
{ {
volatile unsigned char *PGDR = (void *)0xa400012c; volatile uint8_t *PGDR = (void *)0xa400012c;
*PGDR ^= 0x80; *PGDR ^= 0x80;
} }
else else
{ {
volatile unsigned char *PNDR = (void *)0xa4050138; volatile uint8_t *PNDR = (void *)0xa4050138;
*PNDR ^= 0x10; *PNDR ^= 0x10;
} }
} }

View file

@ -1,4 +1,5 @@
#include <screen.h> #include <screen.h>
#include <stdint.h>
/* /*
screen_display() screen_display()
@ -9,12 +10,11 @@
*/ */
void screen_display(const void *ptr) void screen_display(const void *ptr)
{ {
const char *vram = (const char *)ptr; volatile uint8_t *selector = (void *)0xb4000000;
volatile char *selector = (char *)0xb4000000; volatile uint8_t *data = (void *)0xb4010000;
volatile char *data = (char *)0xb4010000; const uint8_t *vram = ptr;
int line, bytes;
for(line = 0; line < 64; line++) for(int line = 0; line < 64; line++)
{ {
// Setting the x-address register. // Setting the x-address register.
*selector = 4; *selector = 4;
@ -29,7 +29,27 @@ void screen_display(const void *ptr)
*data = 0; *data = 0;
// Selecting data write register 7 and sending a line's bytes. // Selecting data write register 7 and sending a line's bytes.
// We could loop but I suspect it will be faster to iterate.
*selector = 7; *selector = 7;
for(bytes = 0; bytes < 16; bytes++) *data = *vram++;
/* TODO Manually load the video-ram line into the cache? */
*data = *vram++;
*data = *vram++;
*data = *vram++;
*data = *vram++;
*data = *vram++;
*data = *vram++;
*data = *vram++;
*data = *vram++;
*data = *vram++;
*data = *vram++;
*data = *vram++;
*data = *vram++;
*data = *vram++;
*data = *vram++;
*data = *vram++;
*data = *vram++;
} }
} }

View file

@ -1,22 +1,19 @@
/*
standard library module: setjmp
Long jumps. The register contents are saved in a buffer when setjmp()
is called and restored at any time when longjmp() performs the jump.
This is based on a trick that uses pr ; the user program is resumed
after the setjmp() call when longjmp() is invoked but this is not
setjmp() that returns. longjmp() restores the pr value that was saved
by setjmp() and performs an rts instruction.
setjmp() returns 0 when called to set up the jump point and a non-zero
value when invoked through a long jump. If 0 is given as return value
to longjmp(), then 1 is returned.
*/
.global _setjmp .global _setjmp
.global _longjmp .global _longjmp
/*
setjmp()
This function is implemented using a trick that changes the value of
pr (so that it points just after the call to setjmp()) within the
longjmp() function, which lets the rts function perform the actual
jump. This value is obtained from the save buffer.
setjmp() returns 0 when called to set up the jump point and a non-zero
value when invoked through a long jump. If 0 is provided as argument to
longjmp(), 1 is returned instead.
*/
_setjmp: _setjmp:
/* Getting some free space. */ /* Getting some free space. */
add #64, r4 add #64, r4
@ -42,8 +39,8 @@ _setjmp:
sts.l pr, @-r4 sts.l pr, @-r4
/* This function always return 0. The cases where setjmp() seems to /* This function always return 0. The cases where setjmp() seems to
return non-zero values, when a long jump has just been performed, is return non-zero values, when a long jump has just been performed, are
actually handled by longjmp(). */ those when the longjmp() function returns. */
rts rts
mov #0, r0 mov #0, r0
@ -52,7 +49,7 @@ _setjmp:
_longjmp: _longjmp:
/* Restoring the system and control registers. Restoring pr is actually /* Restoring the system and control registers. Restoring pr is actually
what performs the jump -- and makes the user program think that what performs the jump -- and makes the user program think that
setjmp() has returned. */ setjmp() has just returned. */
lds.l @r4+, pr lds.l @r4+, pr
lds.l @r4+, macl lds.l @r4+, macl
lds.l @r4+, mach lds.l @r4+, mach

View file

@ -13,7 +13,6 @@ int snprintf(char *str, size_t size, const char *format, ...)
int x = __printf(size, format, args); int x = __printf(size, format, args);
memcpy(str, __stdio_buffer, x + 1); memcpy(str, __stdio_buffer, x + 1);
va_end(args); va_end(args);
return x; return x;

View file

@ -9,6 +9,7 @@ void srand(unsigned int new_seed)
int rand(void) int rand(void)
{ {
/* TODO Or maybe seed = (16807 * seed) % ((1 << 31) - 1); */
seed = seed * 1103515245 + 12345; seed = seed * 1103515245 + 12345;
return seed & 0x7fffffff; return seed & 0x7fffffff;
} }

View file

@ -5,9 +5,9 @@
text_configure() text_configure()
Sets the font and mode to use for the following print operations. Sets the font and mode to use for the following print operations.
*/ */
void text_configure(struct Font *next_font, color_t next_operator) void text_configure(font_t *next_font, color_t next_operator)
{ {
extern Font gint_font_system; extern font_t gint_font_system;
if(next_font) font = next_font; if(next_font) font = next_font;
else font = &gint_font_system; else font = &gint_font_system;

View file

@ -4,12 +4,15 @@
void operate_gray(OPERATE_ARGS) void operate_gray(OPERATE_ARGS)
{ {
size_t vram_offset = (x >> 5) + (y << 2); if(x < 0) return;
uint32_t *light = gray_lightVRAM() + vram_offset;
uint32_t *dark = gray_darkVRAM() + vram_offset; int start = (y < 0) ? (-y) : (0);
size_t vram_offset = (x >> 5) + ((y + start) << 2);
uint32_t *light = (uint32_t *)gray_lightVRAM() + vram_offset;
uint32_t *dark = (uint32_t *)gray_darkVRAM() + vram_offset;
uint32_t op, old_light; uint32_t op, old_light;
for(int i = 0; i < height; i++) for(int i = start; i < height; i++)
{ {
op = operators[i]; op = operators[i];

View file

@ -4,7 +4,7 @@
#include <ctype.h> #include <ctype.h>
#include <gray.h> #include <gray.h>
struct Font *font; font_t *font = NULL;
color_t operator; color_t operator;
/* /*
@ -27,8 +27,8 @@ int getCharacterIndex(int c)
{ {
const char *data = (const char *)&font->glyphs; const char *data = (const char *)&font->glyphs;
int index, current; int index, current;
int offset;
int width, bits; int width, bits;
size_t offset;
c &= 0x7f; c &= 0x7f;
@ -36,33 +36,33 @@ int getCharacterIndex(int c)
// Getting the character index in the glyph array. // Getting the character index in the glyph array.
if(font->format == FontFormat_Ascii) index = c; if(font->format == font_format_ascii) index = c;
else if(font->format == FontFormat_Print) index = c - 32; else if(font->format == font_format_print) index = c - 32;
else switch(font->format) else switch(font->format)
{ {
case FontFormat_Numeric: case font_format_numeric:
if(!isdigit(c)) return -1; if(!isdigit(c)) return -1;
index = c - '0'; index = c - '0';
break; break;
case FontFormat_LowerCase: case font_format_lower:
if(!islower(c)) return -1; if(!islower(c)) return -1;
index = c - 'a'; index = c - 'a';
break; break;
case FontFormat_UpperCase: case font_format_upper:
if(!isupper(c)) return -1; if(!isupper(c)) return -1;
index = c - 'A'; index = c - 'A';
break; break;
case FontFormat_Letters: case font_format_letters:
if(!isalpha(c)) return -1; if(!isalpha(c)) return -1;
index = c - 'A' - ('a' - 'Z') * (c >= 'a'); index = c - 'A' - ('a' - 'Z') * (c >= 'a');
break; break;
case FontFormat_Common: case font_format_common:
if(!isalnum(c)) return -1; if(!isalnum(c)) return -1;
index = c - '0' - ('A' - '9') * (c >= 'A') - index = c - '0' - ('A' - '9') * (c >= 'A') -
('a' - 'Z') * (c >= 'a'); ('a' - 'Z') * (c >= 'a');
break; break;
case FontFormat_Unknown: case font_format_unknown:
default: default:
return -1; return -1;
} }
@ -93,13 +93,16 @@ int getCharacterIndex(int c)
*/ */
void operate_mono(OPERATE_ARGS) void operate_mono(OPERATE_ARGS)
{ {
if(x < 0) return;
uint32_t *vram = display_getCurrentVRAM(); uint32_t *vram = display_getCurrentVRAM();
uint32_t *video = vram + (x >> 5) + (y << 2); int start = (y < 0) ? (-y) : (0);
uint32_t *video = vram + (x >> 5) + ((y + start) << 2);
switch(operator) switch(operator)
{ {
case color_white: case color_white:
for(int i = 0; i < height; i++) for(int i = start; i < height; i++)
{ {
*video &= ~operators[i]; *video &= ~operators[i];
video += 4; video += 4;
@ -107,7 +110,7 @@ void operate_mono(OPERATE_ARGS)
break; break;
case color_black: case color_black:
for(int i = 0; i < height; i++) for(int i = start; i < height; i++)
{ {
*video |= operators[i]; *video |= operators[i];
video += 4; video += 4;
@ -115,7 +118,7 @@ void operate_mono(OPERATE_ARGS)
break; break;
case color_invert: case color_invert:
for(int i = 0; i < height; i++) for(int i = start; i < height; i++)
{ {
*video ^= operators[i]; *video ^= operators[i];
video += 4; video += 4;
@ -163,7 +166,7 @@ int update(uint32_t *operators, int height, int available, uint32_t *glyph)
shift = 32 - available; shift = 32 - available;
// Getting the next 'width' bits. In some cases these bits will // Getting the next 'width' bits. In some cases these bits will
// intersect two different longs. // intersect two different longs...
line = data & glyph_mask; line = data & glyph_mask;
line = (shift >= 0) ? (line >> shift) : (line << -shift); line = (shift >= 0) ? (line >> shift) : (line << -shift);
operators[i] |= line; operators[i] |= line;
@ -171,7 +174,7 @@ int update(uint32_t *operators, int height, int available, uint32_t *glyph)
data <<= width; data <<= width;
bits_available -= width; bits_available -= width;
// Continue until they do. // ... continue looping until they do.
if(bits_available >= 0) continue; if(bits_available >= 0) continue;
// Computing a special mask that extracts just the number of // Computing a special mask that extracts just the number of
@ -180,6 +183,10 @@ int update(uint32_t *operators, int height, int available, uint32_t *glyph)
data = glyph[data_index++]; data = glyph[data_index++];
shift += width + bits_available; shift += width + bits_available;
// In case this condition is not verified, the program invokes
// undefined behavior because of the bit shift. Anyway, it
// means that the end of the end of the operators was reached,
// in which case the function should not continue writing.
if(shift <= 31) if(shift <= 31)
{ {
line = data & partial_mask; line = data & partial_mask;
@ -202,34 +209,32 @@ int update(uint32_t *operators, int height, int available, uint32_t *glyph)
*/ */
void render(int x, int y, const char *str, void (*op)(OPERATE_ARGS)) void render(int x, int y, const char *str, void (*op)(OPERATE_ARGS))
{ {
if(!font) return;
// Operator data, and number of available bits in the operators (which // Operator data, and number of available bits in the operators (which
// is the same for all operators, since they are treated equally). // is the same for all operators, since they are treated equally).
uint32_t *operators; uint32_t *operators;
int available; int available;
// Raw glyph data, each glyph being represented by one or several // Raw glyph data, each glyph being represented as one or several
// longwords, and an index in this array. // longwords, and an index in this array.
uint32_t *data = (uint32_t *)font->glyphs; uint32_t *data = (uint32_t *)font->glyphs;
int index; int index;
// Height of each glyph. This value is constant because the storage // Storage height of each glyph. This is a constant for all glyphs
// format requires it: it allows greater optimization. // because the format required it. It makes this routine consequently
int height; // faster.
int height = font->data_height;
int i;
if(!font) return;
// Allocating data. There will be one operator for each line. // Allocating data. There will be one operator for each line.
height = font->data_height;
if(x > 127 || y > 63 || y <= -height) return; if(x > 127 || y > 63 || y <= -height) return;
if(y + height > 64) height = 64 - y; if(y + height > 64) height = 64 - y;
operators = alloca(height * sizeof(uint32_t)); operators = alloca(height * sizeof(uint32_t));
for(i = 0; i < height; i++) operators[i] = 0;
if(!operators) return; if(!operators) return;
for(int i = 0; i < height; i++) operators[i] = 0;
// Computing the initial operator offset to have 32-aligned operators. // Computing the initial operator offset to have 32-aligned operators.
// This allows to write directly video ram longs instead of having to // This allows to write directly video ram longs instead of having to
@ -263,22 +268,23 @@ void render(int x, int y, const char *str, void (*op)(OPERATE_ARGS))
x += 32; x += 32;
if(x > 96) break; if(x > 96) break;
memset(operators, 0, height << 2); for(int i = 0; i < height; i++) operators[i] = 0;
if(available >= 0) if(available >= 0)
{ {
available = 31 + available; available += 31;
continue; continue;
} }
// Finishing update, in case it has been only partially done, // Finishing update, in cases where it has been only partially
// because there was not enough bits available to fit all the // done because there was not enough bits available to fit all
// information. Also adding a space, assuming that characters // the information. Also adding a space, assuming that
// aren't more than 30 bits wide. // characters aren't more than 30 bits wide. (=p)
available += 32 + (data[index] >> 24); available += 32 + (data[index] >> 24);
available = update(operators, height, available, data + index); available = update(operators, height, available, data + index);
available--; available--;
} }
// Final operation. // Final operation. This condition allows a single bit of the operators
if(x <= 96 && available < 32) (*op)(operators, height, x, y); // to be used - that's because the loop will add a final spacing pixel.
if(x <= 96 && available < 31) (*op)(operators, height, x, y);
} }

View file

@ -53,7 +53,7 @@ time_t mktime(struct tm *time)
time->tm_wday = (1 + days) % 7; time->tm_wday = (1 + days) % 7;
// This RTC does not seem to have any DST feature. // This RTC does not seem to have any DST feature.
time->tm_isdst = 0; time->tm_isdst = 0;
if(time->tm_year + 1900 < 1970) return (time_t)-1; if(time->tm_year + 1900 < 1970) return (time_t)-1;

View file

@ -1 +1 @@
beta-0.9-305 beta-0.9-349