diff options
author | Bad Diode <bd@badd10de.dev> | 2022-10-12 10:48:58 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2022-10-12 10:48:58 +0200 |
commit | e146eb61450f5c09ed81fe421eb6b8f1ca153296 (patch) | |
tree | e8dbf7458f5806a66072f4b48d4ba306968bed1c | |
parent | 0e7a4d7ab72237fcc1c88565d4ff14b14171ad1b (diff) | |
download | uxnfb-e146eb61450f5c09ed81fe421eb6b8f1ca153296.tar.gz uxnfb-e146eb61450f5c09ed81fe421eb6b8f1ca153296.zip |
[WIP] Add some changes for 16bpp fb running on NST
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | src/main.c | 132 | ||||
-rw-r--r-- | src/ppu.c | 82 |
3 files changed, 182 insertions, 36 deletions
@@ -12,8 +12,8 @@ KBD_PATH ?= /dev/input/event1 | |||
12 | MOUSE_PATH ?= /dev/input/mice | 12 | MOUSE_PATH ?= /dev/input/mice |
13 | C_DEFINES := -DKBD_PATH=\"$(KBD_PATH)\" -DMOUSE_PATH=\"$(MOUSE_PATH)\" | 13 | C_DEFINES := -DKBD_PATH=\"$(KBD_PATH)\" -DMOUSE_PATH=\"$(MOUSE_PATH)\" |
14 | 14 | ||
15 | CC ?= cc | 15 | CC := ../ndk/bin/arm-linux-androideabi-gcc |
16 | CFLAGS := -Wall -Wextra -pedantic -static | 16 | CFLAGS := -Wall -Wextra -std=c99 |
17 | 17 | ||
18 | REL_FLAGS := -DNDEBUG -O2 | 18 | REL_FLAGS := -DNDEBUG -O2 |
19 | DEB_FLAGS := -DDEBUG -O0 -g | 19 | DEB_FLAGS := -DDEBUG -O0 -g |
@@ -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) { | |||
367 | void | 367 | void |
368 | screen_deo(Device *d, u8 port) { | 368 | screen_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 | // } | ||
@@ -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 | ||
25 | static size_t screen_width = 0; | 25 | static size_t screen_width = 0; |
26 | static size_t screen_height = 0; | 26 | static size_t screen_height = 0; |
27 | static size_t bpp = 0; | ||
27 | 28 | ||
28 | static u32 *framebuffer = 0; | 29 | static u8 *framebuffer = 0; |
29 | 30 | ||
30 | static u32 palette[16]; | 31 | static u32 palette[16]; |
31 | static u8 *pixels_fg; | 32 | static 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 | ||
46 | u16 | ||
47 | rgb565(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 | |||
45 | void | 54 | void |
46 | ppu_pixel(u8 *layer, u16 x, u16 y, u8 color) { | 55 | ppu_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 | ||
133 | int | 142 | int |
134 | ppu_init(void) { | 143 | ppu_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; |