aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2022-10-12 10:48:58 +0200
committerBad Diode <bd@badd10de.dev>2022-10-12 10:48:58 +0200
commite146eb61450f5c09ed81fe421eb6b8f1ca153296 (patch)
treee8dbf7458f5806a66072f4b48d4ba306968bed1c
parent0e7a4d7ab72237fcc1c88565d4ff14b14171ad1b (diff)
downloaduxnfb-e146eb61450f5c09ed81fe421eb6b8f1ca153296.tar.gz
uxnfb-e146eb61450f5c09ed81fe421eb6b8f1ca153296.zip
[WIP] Add some changes for 16bpp fb running on NST
-rw-r--r--Makefile4
-rw-r--r--src/main.c132
-rw-r--r--src/ppu.c82
3 files changed, 182 insertions, 36 deletions
diff --git a/Makefile b/Makefile
index 37b3802..1faa069 100644
--- a/Makefile
+++ b/Makefile
@@ -12,8 +12,8 @@ KBD_PATH ?= /dev/input/event1
12MOUSE_PATH ?= /dev/input/mice 12MOUSE_PATH ?= /dev/input/mice
13C_DEFINES := -DKBD_PATH=\"$(KBD_PATH)\" -DMOUSE_PATH=\"$(MOUSE_PATH)\" 13C_DEFINES := -DKBD_PATH=\"$(KBD_PATH)\" -DMOUSE_PATH=\"$(MOUSE_PATH)\"
14 14
15CC ?= cc 15CC := ../ndk/bin/arm-linux-androideabi-gcc
16CFLAGS := -Wall -Wextra -pedantic -static 16CFLAGS := -Wall -Wextra -std=c99
17 17
18REL_FLAGS := -DNDEBUG -O2 18REL_FLAGS := -DNDEBUG -O2
19DEB_FLAGS := -DDEBUG -O0 -g 19DEB_FLAGS := -DDEBUG -O0 -g
diff --git a/src/main.c b/src/main.c
index 8d19d95..53aa5c3 100644
--- a/src/main.c
+++ b/src/main.c
@@ -80,14 +80,14 @@ init_input(void) {
80 if (in.kbd_fd == -1) { 80 if (in.kbd_fd == -1) {
81 // NOTE: Some applications may not require a keyboard so this is 81 // NOTE: Some applications may not require a keyboard so this is
82 // optional, but we are still displaying an error. 82 // optional, but we are still displaying an error.
83 fprintf(stderr, "error: no couldn't open keyboard %s: %s.\n", KBD_PATH, strerror(errno)); 83 // fprintf(stderr, "error: couldn't open keyboard %s: %s.\n", KBD_PATH, strerror(errno));
84 } 84 }
85 85
86 in.mouse_fd = open(MOUSE_PATH, O_RDONLY | O_NONBLOCK); 86 in.mouse_fd = open(MOUSE_PATH, O_RDONLY | O_NONBLOCK);
87 if (in.mouse_fd == -1) { 87 if (in.mouse_fd == -1) {
88 // NOTE: Some applications may not require a mouse so this is 88 // NOTE: Some applications may not require a mouse so this is
89 // optional, but we are still displaying an error. 89 // optional, but we are still displaying an error.
90 fprintf(stderr, "error: no couldn't open mouse %s: %s.\n", MOUSE_PATH, strerror(errno)); 90 // fprintf(stderr, "error: couldn't open mouse %s: %s.\n", MOUSE_PATH, strerror(errno));
91 } 91 }
92} 92}
93 93
@@ -367,6 +367,20 @@ screen_dei(Device *d, u8 port) {
367void 367void
368screen_deo(Device *d, u8 port) { 368screen_deo(Device *d, u8 port) {
369 switch(port) { 369 switch(port) {
370 // case 0x3:
371 // if(!FIXED_SIZE) {
372 // Uint16 w;
373 // DEVPEEK16(w, 0x2);
374 // screen_resize(&uxn_screen, clamp(w, 1, 1024), uxn_screen.height);
375 // }
376 // break;
377 // case 0x5:
378 // if(!FIXED_SIZE) {
379 // Uint16 h;
380 // DEVPEEK16(h, 0x4);
381 // screen_resize(&uxn_screen, uxn_screen.width, clamp(h, 1, 1024));
382 // }
383 // break;
370 case 0xe: { 384 case 0xe: {
371 u16 x, y; 385 u16 x, y;
372 u8 layer = d->dat[0xe] & 0x40; 386 u8 layer = d->dat[0xe] & 0x40;
@@ -509,6 +523,7 @@ main(int argc, char *argv[]) {
509 523
510 // Main loop. 524 // Main loop.
511 Time frame_time = time_now(); 525 Time frame_time = time_now();
526 size_t frames = 0;
512 while (true) { 527 while (true) {
513 poll_input(); 528 poll_input();
514 size_t elapsed = time_elapsed(frame_time); 529 size_t elapsed = time_elapsed(frame_time);
@@ -520,9 +535,122 @@ main(int argc, char *argv[]) {
520 535
521 // Blit ppu.pixels to the framebuffer. 536 // Blit ppu.pixels to the framebuffer.
522 blit_framebuffer(); 537 blit_framebuffer();
538 if (++frames > 5) {
539 // memset(framebuffer, 0xFF, screen_width * screen_height * bpp);
540 // system("echo 0 > /dev/graphics/fb0");
541 // redraw_screen();
542 // blit_framebuffer();
543
544 // FIXME: Thre HAS to be a better way to refresh the display lol.
545 system("echo 0 > /dev/graphics/fb0");
546
547 // Time t = time_now();
548 // while (time_elapsed(t) < 16666666 * 2) {
549 // // nop wait X frames for the refresh?
550 // }
551 // wait(ret);
552 // memset(framebuffer, 0xFF, screen_width * screen_height * bpp);
553 // redraw_screen();
554 // memset(framebuffer, 0x00, screen_width * screen_height * bpp);
555 // redraw_screen();
556
557 frames = 0;
558 }
523 frame_time = time_now(); 559 frame_time = time_now();
524 } 560 }
525 } 561 }
526 562
527 return 0; 563 return 0;
528} 564}
565
566// int
567// main(int argc, char *argv[]) {
568// // FIXME: Experimental
569// int fb = open("/dev/graphics/fb0", O_RDWR);
570// if (fb <= 0) {
571// fprintf(stderr, "error: couldn't open the framebuffer\n");
572// exit(EXIT_FAILURE);
573// }
574// struct fb_var_screeninfo info;
575// if (ioctl(fb, FBIOGET_VSCREENINFO, &info) != 0) {
576// fprintf(stderr, "error: couldn't get the framebuffer size\n");
577// exit(EXIT_FAILURE);
578// }
579// size_t screen_width = info.xres;
580// size_t screen_height = info.yres;
581// size_t bpp = info.bits_per_pixel / 8;
582// size_t len = bpp * screen_width * screen_height;
583// u8 *framebuffer = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0);
584// if (framebuffer == MAP_FAILED) {
585// fprintf(stderr, "error: couldn't mmap the framebuffer\n");
586// exit(EXIT_FAILURE);
587// }
588
589// // Print all relevant elements from the fb_var_screeninfo struct
590// printf("> xres: %d\n"
591// "> yres: %d\n"
592// "> xres_virtual: %d\n"
593// "> yres_virtual: %d\n"
594// "> xoffset: %d\n"
595// "> yoffset: %d\n"
596// "> bits_per_pixel: %d\n"
597// "> grayscale: %d\n"
598// "> activate: %d\n"
599// "> height: %d\n"
600// "> width: %d\n"
601// "> hsync_len: %d\n"
602// "> vsync_len: %d\n"
603// "> sync: %d\n"
604// "> vmode: %d\n"
605// "> rotate: %d\n"
606// "> len: %d\n",
607// info.xres,
608// info.yres,
609// info.xres_virtual,
610// info.yres_virtual,
611// info.xoffset,
612// info.yoffset,
613// info.bits_per_pixel,
614// info.grayscale,
615// info.activate,
616// info.height,
617// info.width,
618// info.hsync_len,
619// info.vsync_len,
620// info.sync,
621// info.vmode,
622// info.rotate,
623// len);
624
625
626// // Clean screen
627// // memset(framebuffer, 0x00, screen_width * screen_height * 2); // black
628// memset(framebuffer, 0xFF, len); // white
629// for (size_t i = 0, k = 0; i < (screen_width * screen_height) / 2; i++) {
630// for (size_t b = 0; b < bpp; b++) {
631// framebuffer[k++] = 0xF0;
632// }
633// // p[i] = 0xF0F0;
634// // framebuffer[k++] = 0xFF;
635// // framebuffer[k++] = 0x00;
636// }
637
638// // Main loop.
639// Time frame_time = time_now();
640// size_t frames = 0;
641// while (true) {
642// size_t elapsed = time_elapsed(frame_time);
643// if (elapsed >= 16666666) {
644
645// // FIXME: Thre HAS to be a better way lol.
646// frame_time = time_now();
647// frames++;
648// if (frames > 10) {
649// system("echo 0 > /dev/graphics/fb0");
650// frames = 0;
651// }
652// }
653// }
654
655// return 0;
656// }
diff --git a/src/ppu.c b/src/ppu.c
index aa99ed8..175b2a7 100644
--- a/src/ppu.c
+++ b/src/ppu.c
@@ -4,7 +4,7 @@
4 4
5#include <linux/fb.h> 5#include <linux/fb.h>
6#include <sys/ioctl.h> 6#include <sys/ioctl.h>
7#include <sys/kd.h> 7// #include <sys/kd.h>
8#include <sys/mman.h> 8#include <sys/mman.h>
9 9
10#include "ppu.h" 10#include "ppu.h"
@@ -24,8 +24,9 @@
24 24
25static size_t screen_width = 0; 25static size_t screen_width = 0;
26static size_t screen_height = 0; 26static size_t screen_height = 0;
27static size_t bpp = 0;
27 28
28static u32 *framebuffer = 0; 29static u8 *framebuffer = 0;
29 30
30static u32 palette[16]; 31static u32 palette[16];
31static u8 *pixels_fg; 32static u8 *pixels_fg;
@@ -42,6 +43,14 @@ static u8 blending[5][16] = {
42 {2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2}, 43 {2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2},
43 {1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0}}; 44 {1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0}};
44 45
46u16
47rgb565(u32 rgba) {
48 u16 r = rgba >> 16 & 0xFF;
49 u16 g = rgba >> 8 & 0xFF;
50 u16 b = rgba >> 0 & 0xFF;
51 return (r << 8) | (g << 3) | (b >> 3);
52}
53
45void 54void
46ppu_pixel(u8 *layer, u16 x, u16 y, u8 color) { 55ppu_pixel(u8 *layer, u16 x, u16 y, u8 color) {
47 if(x < screen_width && y < screen_height) { 56 if(x < screen_width && y < screen_height) {
@@ -101,39 +110,39 @@ set_tty(bool graphics) {
101 exit(EXIT_FAILURE); 110 exit(EXIT_FAILURE);
102 } 111 }
103 112
104 if (graphics) { 113 // if (graphics) {
105 if (ioctl(tty, KDSETMODE, KD_GRAPHICS)) { 114 // if (ioctl(tty, KDSETMODE, KD_GRAPHICS)) {
106 fprintf(stderr,"error: setting graphics mode failed\n"); 115 // fprintf(stderr,"error: setting graphics mode failed\n");
107 exit(EXIT_FAILURE); 116 // exit(EXIT_FAILURE);
108 } 117 // }
109 struct termios t; 118 // struct termios t;
110 if (tcgetattr(STDIN_FILENO, &t)) { 119 // if (tcgetattr(STDIN_FILENO, &t)) {
111 fprintf(stderr, "error: couldn't disable terminal echo\n"); 120 // fprintf(stderr, "error: couldn't disable terminal echo\n");
112 exit(EXIT_FAILURE); 121 // exit(EXIT_FAILURE);
113 } 122 // }
114 prev_t = t; 123 // prev_t = t;
115 t.c_lflag &= ~((tcflag_t) ECHO); 124 // t.c_lflag &= ~((tcflag_t) ECHO);
116 if (tcsetattr(STDIN_FILENO, TCSANOW, &t)) { 125 // if (tcsetattr(STDIN_FILENO, TCSANOW, &t)) {
117 fprintf(stderr, "error: couldn't disable terminal echo\n"); 126 // fprintf(stderr, "error: couldn't disable terminal echo\n");
118 exit(EXIT_FAILURE); 127 // exit(EXIT_FAILURE);
119 } 128 // }
120 } else { 129 // } else {
121 if (ioctl(tty, KDSETMODE, KD_TEXT)) { 130 // if (ioctl(tty, KDSETMODE, KD_TEXT)) {
122 fprintf(stderr,"error: setting text mode failed\n"); 131 // fprintf(stderr,"error: setting text mode failed\n");
123 exit(EXIT_FAILURE); 132 // exit(EXIT_FAILURE);
124 } 133 // }
125 if (tcsetattr(STDIN_FILENO, TCSANOW, &prev_t)) { 134 // if (tcsetattr(STDIN_FILENO, TCSANOW, &prev_t)) {
126 fprintf(stderr, "error: couldn't restore terminal attributes\n"); 135 // fprintf(stderr, "error: couldn't restore terminal attributes\n");
127 exit(EXIT_FAILURE); 136 // exit(EXIT_FAILURE);
128 } 137 // }
129 } 138 // }
130 close(tty); 139 close(tty);
131} 140}
132 141
133int 142int
134ppu_init(void) { 143ppu_init(void) {
135 // Open frambuffer and get the size. 144 // Open frambuffer and get the size.
136 int fb = open("/dev/fb0", O_RDWR); 145 int fb = open("/dev/graphics/fb0", O_RDWR);
137 if (fb <= 0) { 146 if (fb <= 0) {
138 fprintf(stderr, "error: couldn't open the framebuffer\n"); 147 fprintf(stderr, "error: couldn't open the framebuffer\n");
139 exit(EXIT_FAILURE); 148 exit(EXIT_FAILURE);
@@ -147,7 +156,8 @@ ppu_init(void) {
147 // Mmap the framebuffer to a buffer object. 156 // Mmap the framebuffer to a buffer object.
148 screen_width = info.xres; 157 screen_width = info.xres;
149 screen_height = info.yres; 158 screen_height = info.yres;
150 size_t len = 4 * screen_width * screen_height; 159 bpp = info.bits_per_pixel / 8;
160 size_t len = bpp * screen_width * screen_height;
151 framebuffer = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0); 161 framebuffer = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0);
152 if (framebuffer == MAP_FAILED) { 162 if (framebuffer == MAP_FAILED) {
153 fprintf(stderr, "error: couldn't mmap the framebuffer\n"); 163 fprintf(stderr, "error: couldn't mmap the framebuffer\n");
@@ -164,7 +174,7 @@ ppu_init(void) {
164 } 174 }
165 175
166 // Prepare TTY for graphics mode. 176 // Prepare TTY for graphics mode.
167 set_tty(true); 177 // set_tty(true);
168 178
169 // Initialize default palette. 179 // Initialize default palette.
170 palette[0] = 0x444444; 180 palette[0] = 0x444444;
@@ -177,6 +187,9 @@ ppu_init(void) {
177 memset(pixels_bg, 0, screen_width * screen_height); 187 memset(pixels_bg, 0, screen_width * screen_height);
178 memset(dirty_lines, 1, screen_height); 188 memset(dirty_lines, 1, screen_height);
179 189
190 // Clear framebuffer.
191 memset(framebuffer, 0xFF, len);
192
180 // Make sure we perform an initial screen drawing. 193 // Make sure we perform an initial screen drawing.
181 reqdraw = 1; 194 reqdraw = 1;
182 redraw_screen(); 195 redraw_screen();
@@ -189,11 +202,16 @@ blit_framebuffer(void) {
189 if (reqdraw == 0) { 202 if (reqdraw == 0) {
190 return; 203 return;
191 } 204 }
205 // TODO: add some parameter to account for zoom? for example we may want to
206 // have an internal resolution smaller than the screen!
192 for (size_t j = 0; j < screen_height; j++) { 207 for (size_t j = 0; j < screen_height; j++) {
193 if (dirty_lines[j] != 0) { 208 if (dirty_lines[j] != 0) {
194 for (size_t i = 0; i < screen_width; i++) { 209 for (size_t i = 0; i < screen_width; i++) {
195 size_t idx = i + j * screen_width; 210 size_t idx = i + j * screen_width;
196 framebuffer[idx] = palette[pixels_fg[idx] << 2 | pixels_bg[idx]]; 211 u16 *p = framebuffer;
212 p[idx] = rgb565(palette[pixels_fg[idx] << 2 | pixels_bg[idx]]);
213 // FIXME: can we generalize this to use bpp instead of having
214 // a version for 32/16 bit color?
197 } 215 }
198 } 216 }
199 dirty_lines[j] = 0; 217 dirty_lines[j] = 0;