From e146eb61450f5c09ed81fe421eb6b8f1ca153296 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Wed, 12 Oct 2022 10:48:58 +0200 Subject: [WIP] Add some changes for 16bpp fb running on NST --- Makefile | 4 +- src/main.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/ppu.c | 82 +++++++++++++++++++++++--------------- 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 MOUSE_PATH ?= /dev/input/mice C_DEFINES := -DKBD_PATH=\"$(KBD_PATH)\" -DMOUSE_PATH=\"$(MOUSE_PATH)\" -CC ?= cc -CFLAGS := -Wall -Wextra -pedantic -static +CC := ../ndk/bin/arm-linux-androideabi-gcc +CFLAGS := -Wall -Wextra -std=c99 REL_FLAGS := -DNDEBUG -O2 DEB_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) { if (in.kbd_fd == -1) { // NOTE: Some applications may not require a keyboard so this is // optional, but we are still displaying an error. - fprintf(stderr, "error: no couldn't open keyboard %s: %s.\n", KBD_PATH, strerror(errno)); + // fprintf(stderr, "error: couldn't open keyboard %s: %s.\n", KBD_PATH, strerror(errno)); } in.mouse_fd = open(MOUSE_PATH, O_RDONLY | O_NONBLOCK); if (in.mouse_fd == -1) { // NOTE: Some applications may not require a mouse so this is // optional, but we are still displaying an error. - fprintf(stderr, "error: no couldn't open mouse %s: %s.\n", MOUSE_PATH, strerror(errno)); + // fprintf(stderr, "error: couldn't open mouse %s: %s.\n", MOUSE_PATH, strerror(errno)); } } @@ -367,6 +367,20 @@ screen_dei(Device *d, u8 port) { void screen_deo(Device *d, u8 port) { switch(port) { + // case 0x3: + // if(!FIXED_SIZE) { + // Uint16 w; + // DEVPEEK16(w, 0x2); + // screen_resize(&uxn_screen, clamp(w, 1, 1024), uxn_screen.height); + // } + // break; + // case 0x5: + // if(!FIXED_SIZE) { + // Uint16 h; + // DEVPEEK16(h, 0x4); + // screen_resize(&uxn_screen, uxn_screen.width, clamp(h, 1, 1024)); + // } + // break; case 0xe: { u16 x, y; u8 layer = d->dat[0xe] & 0x40; @@ -509,6 +523,7 @@ main(int argc, char *argv[]) { // Main loop. Time frame_time = time_now(); + size_t frames = 0; while (true) { poll_input(); size_t elapsed = time_elapsed(frame_time); @@ -520,9 +535,122 @@ main(int argc, char *argv[]) { // Blit ppu.pixels to the framebuffer. blit_framebuffer(); + if (++frames > 5) { + // memset(framebuffer, 0xFF, screen_width * screen_height * bpp); + // system("echo 0 > /dev/graphics/fb0"); + // redraw_screen(); + // blit_framebuffer(); + + // FIXME: Thre HAS to be a better way to refresh the display lol. + system("echo 0 > /dev/graphics/fb0"); + + // Time t = time_now(); + // while (time_elapsed(t) < 16666666 * 2) { + // // nop wait X frames for the refresh? + // } + // wait(ret); + // memset(framebuffer, 0xFF, screen_width * screen_height * bpp); + // redraw_screen(); + // memset(framebuffer, 0x00, screen_width * screen_height * bpp); + // redraw_screen(); + + frames = 0; + } frame_time = time_now(); } } return 0; } + +// int +// main(int argc, char *argv[]) { +// // FIXME: Experimental +// int fb = open("/dev/graphics/fb0", O_RDWR); +// if (fb <= 0) { +// fprintf(stderr, "error: couldn't open the framebuffer\n"); +// exit(EXIT_FAILURE); +// } +// struct fb_var_screeninfo info; +// if (ioctl(fb, FBIOGET_VSCREENINFO, &info) != 0) { +// fprintf(stderr, "error: couldn't get the framebuffer size\n"); +// exit(EXIT_FAILURE); +// } +// size_t screen_width = info.xres; +// size_t screen_height = info.yres; +// size_t bpp = info.bits_per_pixel / 8; +// size_t len = bpp * screen_width * screen_height; +// u8 *framebuffer = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0); +// if (framebuffer == MAP_FAILED) { +// fprintf(stderr, "error: couldn't mmap the framebuffer\n"); +// exit(EXIT_FAILURE); +// } + +// // Print all relevant elements from the fb_var_screeninfo struct +// printf("> xres: %d\n" +// "> yres: %d\n" +// "> xres_virtual: %d\n" +// "> yres_virtual: %d\n" +// "> xoffset: %d\n" +// "> yoffset: %d\n" +// "> bits_per_pixel: %d\n" +// "> grayscale: %d\n" +// "> activate: %d\n" +// "> height: %d\n" +// "> width: %d\n" +// "> hsync_len: %d\n" +// "> vsync_len: %d\n" +// "> sync: %d\n" +// "> vmode: %d\n" +// "> rotate: %d\n" +// "> len: %d\n", +// info.xres, +// info.yres, +// info.xres_virtual, +// info.yres_virtual, +// info.xoffset, +// info.yoffset, +// info.bits_per_pixel, +// info.grayscale, +// info.activate, +// info.height, +// info.width, +// info.hsync_len, +// info.vsync_len, +// info.sync, +// info.vmode, +// info.rotate, +// len); + + +// // Clean screen +// // memset(framebuffer, 0x00, screen_width * screen_height * 2); // black +// memset(framebuffer, 0xFF, len); // white +// for (size_t i = 0, k = 0; i < (screen_width * screen_height) / 2; i++) { +// for (size_t b = 0; b < bpp; b++) { +// framebuffer[k++] = 0xF0; +// } +// // p[i] = 0xF0F0; +// // framebuffer[k++] = 0xFF; +// // framebuffer[k++] = 0x00; +// } + +// // Main loop. +// Time frame_time = time_now(); +// size_t frames = 0; +// while (true) { +// size_t elapsed = time_elapsed(frame_time); +// if (elapsed >= 16666666) { + +// // FIXME: Thre HAS to be a better way lol. +// frame_time = time_now(); +// frames++; +// if (frames > 10) { +// system("echo 0 > /dev/graphics/fb0"); +// frames = 0; +// } +// } +// } + +// return 0; +// } 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 @@ #include #include -#include +// #include #include #include "ppu.h" @@ -24,8 +24,9 @@ static size_t screen_width = 0; static size_t screen_height = 0; +static size_t bpp = 0; -static u32 *framebuffer = 0; +static u8 *framebuffer = 0; static u32 palette[16]; static u8 *pixels_fg; @@ -42,6 +43,14 @@ static u8 blending[5][16] = { {2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2}, {1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0}}; +u16 +rgb565(u32 rgba) { + u16 r = rgba >> 16 & 0xFF; + u16 g = rgba >> 8 & 0xFF; + u16 b = rgba >> 0 & 0xFF; + return (r << 8) | (g << 3) | (b >> 3); +} + void ppu_pixel(u8 *layer, u16 x, u16 y, u8 color) { if(x < screen_width && y < screen_height) { @@ -101,39 +110,39 @@ set_tty(bool graphics) { exit(EXIT_FAILURE); } - if (graphics) { - if (ioctl(tty, KDSETMODE, KD_GRAPHICS)) { - fprintf(stderr,"error: setting graphics mode failed\n"); - exit(EXIT_FAILURE); - } - struct termios t; - if (tcgetattr(STDIN_FILENO, &t)) { - fprintf(stderr, "error: couldn't disable terminal echo\n"); - exit(EXIT_FAILURE); - } - prev_t = t; - t.c_lflag &= ~((tcflag_t) ECHO); - if (tcsetattr(STDIN_FILENO, TCSANOW, &t)) { - fprintf(stderr, "error: couldn't disable terminal echo\n"); - exit(EXIT_FAILURE); - } - } else { - if (ioctl(tty, KDSETMODE, KD_TEXT)) { - fprintf(stderr,"error: setting text mode failed\n"); - exit(EXIT_FAILURE); - } - if (tcsetattr(STDIN_FILENO, TCSANOW, &prev_t)) { - fprintf(stderr, "error: couldn't restore terminal attributes\n"); - exit(EXIT_FAILURE); - } - } + // if (graphics) { + // if (ioctl(tty, KDSETMODE, KD_GRAPHICS)) { + // fprintf(stderr,"error: setting graphics mode failed\n"); + // exit(EXIT_FAILURE); + // } + // struct termios t; + // if (tcgetattr(STDIN_FILENO, &t)) { + // fprintf(stderr, "error: couldn't disable terminal echo\n"); + // exit(EXIT_FAILURE); + // } + // prev_t = t; + // t.c_lflag &= ~((tcflag_t) ECHO); + // if (tcsetattr(STDIN_FILENO, TCSANOW, &t)) { + // fprintf(stderr, "error: couldn't disable terminal echo\n"); + // exit(EXIT_FAILURE); + // } + // } else { + // if (ioctl(tty, KDSETMODE, KD_TEXT)) { + // fprintf(stderr,"error: setting text mode failed\n"); + // exit(EXIT_FAILURE); + // } + // if (tcsetattr(STDIN_FILENO, TCSANOW, &prev_t)) { + // fprintf(stderr, "error: couldn't restore terminal attributes\n"); + // exit(EXIT_FAILURE); + // } + // } close(tty); } int ppu_init(void) { // Open frambuffer and get the size. - int fb = open("/dev/fb0", O_RDWR); + int fb = open("/dev/graphics/fb0", O_RDWR); if (fb <= 0) { fprintf(stderr, "error: couldn't open the framebuffer\n"); exit(EXIT_FAILURE); @@ -147,7 +156,8 @@ ppu_init(void) { // Mmap the framebuffer to a buffer object. screen_width = info.xres; screen_height = info.yres; - size_t len = 4 * screen_width * screen_height; + bpp = info.bits_per_pixel / 8; + size_t len = bpp * screen_width * screen_height; framebuffer = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0); if (framebuffer == MAP_FAILED) { fprintf(stderr, "error: couldn't mmap the framebuffer\n"); @@ -164,7 +174,7 @@ ppu_init(void) { } // Prepare TTY for graphics mode. - set_tty(true); + // set_tty(true); // Initialize default palette. palette[0] = 0x444444; @@ -177,6 +187,9 @@ ppu_init(void) { memset(pixels_bg, 0, screen_width * screen_height); memset(dirty_lines, 1, screen_height); + // Clear framebuffer. + memset(framebuffer, 0xFF, len); + // Make sure we perform an initial screen drawing. reqdraw = 1; redraw_screen(); @@ -189,11 +202,16 @@ blit_framebuffer(void) { if (reqdraw == 0) { return; } + // TODO: add some parameter to account for zoom? for example we may want to + // have an internal resolution smaller than the screen! for (size_t j = 0; j < screen_height; j++) { if (dirty_lines[j] != 0) { for (size_t i = 0; i < screen_width; i++) { size_t idx = i + j * screen_width; - framebuffer[idx] = palette[pixels_fg[idx] << 2 | pixels_bg[idx]]; + u16 *p = framebuffer; + p[idx] = rgb565(palette[pixels_fg[idx] << 2 | pixels_bg[idx]]); + // FIXME: can we generalize this to use bpp instead of having + // a version for 32/16 bit color? } } dirty_lines[j] = 0; -- cgit v1.2.1