-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathdisplay.h
239 lines (197 loc) · 7.66 KB
/
display.h
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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
#include <gui/gui.h>
#include <furi_hal.h>
#include <u8g2_glue.h>
#include "constants.h"
#include "compiled/assets_icons.h"
#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))
static const uint8_t bit_mask[8] = { 128, 64, 32, 16, 8, 4, 2, 1 };
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
#define read_bit(b, n) b & pgm_read_byte(bit_mask + n) ? 1 : 0
//#define read_bit(byte, index) (((unsigned)(byte) >> (index)) & 1)
void drawVLine(uint8_t x, int8_t start_y, int8_t end_y, uint8_t intensity, Canvas* const canvas);
void drawPixel(int8_t x, int8_t y, bool color, bool raycasterViewport, Canvas* const canvas);
void drawSprite(int8_t x, int8_t y, const uint8_t *bitmap, const uint8_t *bitmap_mask, int16_t w, int16_t h, uint8_t sprite, double distance, Canvas* const canvas);
void drawBitmap(int16_t x, int16_t y, const Icon *i, int16_t w, int16_t h, uint16_t color, Canvas* const canvas);
void drawTextSpace(int8_t x, int8_t y, char *txt, uint8_t space, Canvas* const canvas);
void drawChar(int8_t x, int8_t y, char ch, Canvas* const canvas);
void clearRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, Canvas* const canvas);
void drawGun(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, Canvas* const canvas);
void drawRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, Canvas* const canvas);
void drawText(uint8_t x, uint8_t y, uint8_t num, Canvas* const canvas);
void fadeScreen(uint8_t intensity, bool color, Canvas* const canvas);
bool getGradientPixel(uint8_t x, uint8_t y, uint8_t i);
double getActualFps();
void fps();
void setupDisplay(Canvas* canvas);
uint8_t reverse_bits(uint8_t num);
// FPS control
double delta = 1;
uint32_t lastFrameTime = 0;
uint8_t zbuffer[128]; /// 128 = screen width & REMOVE WHEN DISPLAY.H IMPLEMENTED
uint8_t *display_buf = NULL;
void drawGun(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, Canvas* const canvas){
int16_t byteWidth = (w + 7) / 8;
uint8_t byte = 0;
for(int16_t j=0; j<h; j++, y++) {
for(int16_t i=0; i<w; i++) {
if(i & 7) byte <<= 1;
else byte = pgm_read_byte(&bitmap[j * byteWidth + i / 8]);
if(byte & 0x80) drawPixel(x+i, y, color,false, canvas);
}
}
}
void drawVLine(uint8_t x, int8_t start_y, int8_t end_y, uint8_t intensity, Canvas* const canvas){
uint8_t dots = end_y - start_y;
for(int i = 0; i < dots; i++){
canvas_draw_dot(canvas, x, start_y+i);
}
}
void setupDisplay(Canvas* canvas){
memset(zbuffer, 0xff, 128);
display_buf = (uint8_t*)canvas_get_buffer(canvas);
//display_buf = u8g2_GetBufferPtr(&canvas->fb);
}
void drawBitmap(int16_t x, int16_t y, const Icon *i, int16_t w, int16_t h, uint16_t color, Canvas* const canvas){
canvas_draw_icon_bitmap(canvas, x, y, w, h, i);
}
void drawText(uint8_t x, uint8_t y, uint8_t num, Canvas* const canvas){
char buf[4];
itoa(num, buf, 10);
drawTextSpace(x,y,buf,1,canvas);
}
void drawTextSpace(int8_t x, int8_t y, char *txt, uint8_t space, Canvas* const canvas){
uint8_t pos = x;
uint8_t i = 0;
char ch;
while ((ch = txt[i]) != '\0') {
drawChar(pos, y, ch, canvas);
i++;
pos += CHAR_WIDTH + space;
// shortcut on end of screen
if (pos > SCREEN_WIDTH) return;
}
}
// Custom drawBitmap method with scale support, mask, zindex and pattern filling
void drawSprite(int8_t x, int8_t y, const uint8_t *bitmap, const uint8_t *bitmap_mask, int16_t w, int16_t h, uint8_t sprite, double distance, Canvas* const canvas){
uint8_t tw = (double) w / distance;
uint8_t th = (double) h / distance;
uint8_t byte_width = w / 8;
uint8_t pixel_size = fmax(1, (double)1.0 / (double)distance);
uint16_t sprite_offset = byte_width * h * sprite;
bool pixel;
bool maskPixel;
// Don't draw the whole sprite if the anchor is hidden by z buffer
// Not checked per pixel for performance reasons
if (zbuffer[(int)(fmin(fmax(x, 0), ZBUFFER_SIZE - 1) / Z_RES_DIVIDER)] < distance * DISTANCE_MULTIPLIER) {
return;
}
for (uint8_t ty = 0; ty < th; ty += pixel_size) {
// Don't draw out of screen
if (y + ty < 0 || y + ty >= RENDER_HEIGHT) {
continue;
}
uint8_t sy = ty * distance; // The y from the sprite
for (uint8_t tx = 0; tx < tw; tx += pixel_size) {
uint8_t sx = tx * distance; // The x from the sprite
uint16_t byte_offset = sprite_offset + sy * byte_width + sx / 8;
// Don't draw out of screen
if (x + tx < 0 || x + tx >= SCREEN_WIDTH) {
continue;
}
maskPixel = read_bit(pgm_read_byte(bitmap_mask + byte_offset), sx % 8);
if (maskPixel) {
pixel = read_bit(pgm_read_byte(bitmap + byte_offset), sx % 8);
for (uint8_t ox = 0; ox < pixel_size; ox++) {
for (uint8_t oy = 0; oy < pixel_size; oy++) {
if(bitmap == imp_inv)
drawPixel(x + tx + ox, y + ty + oy, 1, true, canvas);
else
drawPixel(x + tx + ox, y + ty + oy, pixel, true, canvas);
}
}
}
}
}
}
void drawPixel(int8_t x, int8_t y, bool color, bool raycasterViewport, Canvas* const canvas) {
if (x < 0 || x >= SCREEN_WIDTH || y < 0 || y >= (raycasterViewport ? RENDER_HEIGHT : SCREEN_HEIGHT)){
return;
}
if(color)
canvas_draw_dot(canvas, x, y);
else{
canvas_invert_color(canvas);
canvas_draw_dot(canvas, x, y);
canvas_invert_color(canvas);
}
}
void drawChar(int8_t x, int8_t y, char ch, Canvas* const canvas){
uint8_t lsb;
uint8_t c = 0;
while (CHAR_MAP[c] != ch && CHAR_MAP[c] != '\0') c++;
for(uint8_t i = 0; i < 6; i++){
//lsb = (char_arr[c][i] >> 4);
lsb = reverse_bits(char_arr[c][i]);
for (uint8_t n = 0; n < 4; n++){
if(CHECK_BIT(lsb, n)){
drawPixel(x+n, y+i, true, false, canvas);
}
}
}
}
void clearRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, Canvas* const canvas){
canvas_invert_color(canvas);
for(int i = 0; i < w; i++){
for(int j = 0; j < h; j++){
canvas_draw_dot(canvas, x+i, y+j);
}
}
canvas_invert_color(canvas);
}
void drawRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, Canvas* const canvas){
for(int i = 0; i < w; i++){
for(int j = 0; j < h; j++){
canvas_draw_dot(canvas, x+i, y+j);
}
}
}
bool getGradientPixel(uint8_t x, uint8_t y, uint8_t i) {
if (i == 0) return 0;
if (i >= GRADIENT_COUNT - 1) return 1;
uint8_t index = fmax(0, fmin(GRADIENT_COUNT - 1, i)) * GRADIENT_WIDTH * GRADIENT_HEIGHT // gradient index
+ y * GRADIENT_WIDTH % (GRADIENT_WIDTH * GRADIENT_HEIGHT) // y byte offset
+ x / GRADIENT_HEIGHT % GRADIENT_WIDTH; // x byte offset
//uint8_t *gradient_data = NULL;
//furi_hal_compress_icon_decode(icon_get_data(&I_gradient_inv), &gradient_data);
// return the bit based on x
return read_bit(pgm_read_byte(gradient + index), x % 8);
}
void fadeScreen(uint8_t intensity, bool color, Canvas* const canvas) {
for (uint8_t x = 0; x < SCREEN_WIDTH; x++) {
for (uint8_t y = 0; y < SCREEN_HEIGHT; y++) {
if (getGradientPixel(x, y, intensity))
drawPixel(x, y, color, false, canvas);
}
}
}
// Adds a delay to limit play to specified fps
// Calculates also delta to keep movement consistent in lower framerates
void fps() {
while (furi_get_tick() - lastFrameTime < FRAME_TIME);
delta = (double)(furi_get_tick() - lastFrameTime) / (double)FRAME_TIME;
lastFrameTime = furi_get_tick();
}
double getActualFps() {
return 1000 / ((double)FRAME_TIME * (double)delta);
}
uint8_t reverse_bits(uint8_t num)
{
unsigned int NO_OF_BITS = sizeof(num) * 8;
uint8_t reverse_num = 0;
uint8_t i;
for (i = 0; i < NO_OF_BITS; i++) {
if ((num & (1 << i)))
reverse_num |= 1 << ((NO_OF_BITS - 1) - i);
}
return reverse_num;
}