aboutsummaryrefslogtreecommitdiffstats
path: root/src/text/text.h
blob: ab525d4e2c8ee7e1c39a7d11bafb1dcd032fd1e4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#ifndef TEXT_H
#define TEXT_H

#include "posprintf.h"

typedef void (*TxtDrawc)(char c, size_t x, size_t y, u8 clr);
typedef struct TextEngine {
    // Cursor for tiled text mode The X and Y positions correspond to the tile
    // X and Y starting from the top left of the screen. For a 240x160 screen,
    // we have 30x20 tiles available.
    size_t cursor_x;
    size_t cursor_y;

    u8 buffer[30 * 20];
    u8 spacing;
    u8 color;
    TxtDrawc drawc;
} TextEngine;

static TextEngine text_engine = {0};

// Initializes the text engine.
static inline
void
txt_init(TxtDrawc drawc) {
    // Initialize remaining variables.
    text_engine.spacing = 8;
    text_engine.color = 1;
    text_engine.drawc = drawc;
}

// Writes a message to the tile text background.
static inline
void
txt_puts(char *msg) {
    while (*msg) {
        char c = *msg++;
        if (c == '\0') {
            continue;
        }
        if (c == '\n') {
            text_engine.cursor_x = 0;
            text_engine.cursor_y++;
        } else {
            int x = text_engine.cursor_x;
            int y = text_engine.cursor_y;
            text_engine.buffer[x + 30 * y] = c;
            text_engine.cursor_x += 1;
            if (text_engine.cursor_x >= 30) {
                text_engine.cursor_x = 0;
                text_engine.cursor_y++;
            }
        }
        if (text_engine.cursor_y >= 20) {
            text_engine.cursor_y = 0;
        }
    }
}

// Clears the current line on the tile text mode.
static inline
void
txt_clear_line(void) {
    dma_fill(text_engine.buffer, 0, sizeof(text_engine.buffer), 3);
    text_engine.cursor_x = 0;
    text_engine.cursor_y = 0;
}

// Clears the screen on the tile text mode.
static inline
void
txt_clear(void) {
    for (size_t j = 0; j < 20; ++j) {
        text_engine.cursor_y = j;
        txt_clear_line();
    }
    text_engine.cursor_x = 0;
    text_engine.cursor_y = 0;
}

// Moves the tile mode cursor to the specified position.
static inline
void
txt_position(size_t tile_x, size_t tile_y) {
    text_engine.cursor_x = tile_x;
    text_engine.cursor_y = tile_y;
}

static inline
void
txt_color(u8 clr) {
    text_engine.color = clr;
}

static inline
void
txt_spacing(u8 spacing) {
    text_engine.spacing = spacing;
}

// Renders the contents of the scrollback buffer to the screen.
void
txt_render(void) {
    for (size_t y = 0; y < 20; y++) {
        for (size_t x = 0; x < 30; x++) {
            size_t pos = x + y * 30;
            if (text_engine.buffer[pos] == 0) {
                continue;
            }
            text_engine.drawc(
                    text_engine.buffer[pos],
                    x * text_engine.spacing,
                    y * text_engine.spacing,
                    text_engine.color);
        }
    }
}

// Draws a message where the first character's top-left corner begins at the
// given x and y position. The character spacing can be adjusted, but beware of
// color merging issues.
static inline
void
txt_draws(char *msg, size_t x, size_t y, u8 clr) {
    size_t i = 0;
    while (*msg) {
        char c = *msg++;
        text_engine.drawc(c, x + i++ * text_engine.spacing, y, clr);
    }
}

// Print text to the screen with formatting.
#define txt_printf(msg, ...) \
	{ \
		char buf[256] = {0}; \
		posprintf(buf, msg, ##__VA_ARGS__); \
		txt_puts(buf); \
	}

// Draws text to the screen with formatting starting on the x and y position and
// with custom character spacing.
#define txt_drawf(msg, x, y, c, ...) \
	{ \
		char buf[256] = {0}; \
		posprintf(buf, msg, ##__VA_ARGS__); \
		txt_draws(buf, x, y, c); \
	}

#endif // TEXT_H