Screenshot feature

This commit is contained in:
xtreme8000 2023-09-24 15:48:47 +02:00
parent 0ab2fe2a0f
commit 0da0139fce
8 changed files with 103 additions and 4 deletions

View file

@ -21,6 +21,7 @@
"gui_left": [2, 202], "gui_left": [2, 202],
"gui_right": [3, 203], "gui_right": [3, 203],
"gui_click": [4, 204], "gui_click": [4, 204],
"gui_click_alt": [5, 205] "gui_click_alt": [5, 205],
"screenshot": [7],
} }
} }

View file

@ -21,6 +21,7 @@
"gui_left": [65], "gui_left": [65],
"gui_right": [68], "gui_right": [68],
"gui_click": [1000], "gui_click": [1000],
"gui_click_alt": [1001] "gui_click_alt": [1001],
"screenshot": [291]
} }
} }

View file

@ -22,6 +22,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h>
#ifdef PLATFORM_WII #ifdef PLATFORM_WII
#include <fat.h> #include <fat.h>
@ -42,10 +43,9 @@
#include "cNBT/nbt.h" #include "cNBT/nbt.h"
#include "cglm/cglm.h" #include "cglm/cglm.h"
#include "lodepng/lodepng.h"
int main(void) { int main(void) {
time_reset();
gstate.quit = false; gstate.quit = false;
gstate.camera = (struct camera) { gstate.camera = (struct camera) {
.x = 0, .y = 0, .z = 0, .rx = 0, .ry = 0, .controller = {0, 0, 0}}; .x = 0, .y = 0, .z = 0, .rx = 0, .ry = 0, .controller = {0, 0, 0}};
@ -183,6 +183,23 @@ int main(void) {
gstate.current_screen->render2D(gstate.current_screen, gfx_width(), gstate.current_screen->render2D(gstate.current_screen, gfx_width(),
gfx_height()); gfx_height());
if(input_pressed(IB_SCREENSHOT)) {
size_t width, height;
gfx_copy_framebuffer(NULL, &width, &height);
void* image = malloc(width * height * 4);
if(image) {
gfx_copy_framebuffer(image, &width, &height);
char name[64];
snprintf(name, sizeof(name), "%ld.png", (long)time(NULL));
lodepng_encode32_file(name, image, width, height);
free(image);
}
}
input_poll(); input_poll();
gfx_finish(true); gfx_finish(true);
} }

View file

@ -54,6 +54,8 @@ void gfx_clear_buffers(uint8_t r, uint8_t g, uint8_t b);
int gfx_width(void); int gfx_width(void);
int gfx_height(void); int gfx_height(void);
void gfx_copy_framebuffer(uint8_t* dest, size_t* width, size_t* height);
void gfx_matrix_projection(mat4 proj, bool is_perspective); void gfx_matrix_projection(mat4 proj, bool is_perspective);
void gfx_matrix_modelview(mat4 mv); void gfx_matrix_modelview(mat4 mv);
void gfx_matrix_texture(bool enable, mat4 tex); void gfx_matrix_texture(bool enable, mat4 tex);

View file

@ -303,6 +303,7 @@ static const char* input_config_translate(enum input_button key) {
case IB_GUI_RIGHT: return "input.gui_right"; case IB_GUI_RIGHT: return "input.gui_right";
case IB_GUI_CLICK: return "input.gui_click"; case IB_GUI_CLICK: return "input.gui_click";
case IB_GUI_CLICK_ALT: return "input.gui_click_alt"; case IB_GUI_CLICK_ALT: return "input.gui_click_alt";
case IB_SCREENSHOT: return "input.screenshot";
default: return NULL; default: return NULL;
} }
} }

View file

@ -41,6 +41,7 @@ enum input_button {
IB_GUI_RIGHT, IB_GUI_RIGHT,
IB_GUI_CLICK, IB_GUI_CLICK,
IB_GUI_CLICK_ALT, IB_GUI_CLICK_ALT,
IB_SCREENSHOT,
}; };
enum input_category { enum input_category {

View file

@ -206,6 +206,33 @@ void gfx_bind_texture(struct tex_gfx* tex) {
tex_gfx_bind(tex, 0); tex_gfx_bind(tex, 0);
} }
void gfx_copy_framebuffer(uint8_t* dest, size_t* width, size_t* height) {
assert(width && height);
*width = gfx_width();
*height = gfx_height();
if(!dest)
return;
void* tmp = malloc(*width * 4);
if(!tmp)
return;
glReadPixels(0, 0, *width, *height, GL_RGBA, GL_UNSIGNED_BYTE, dest);
// flip image
for(size_t y = 0; y < *height / 2; y++) {
memcpy(tmp, dest + y * (*width) * 4, *width * 4);
memcpy(dest + y * (*width) * 4, dest + (*height - 1 - y) * (*width) * 4,
*width * 4);
memcpy(dest + (*height - 1 - y) * (*width) * 4, tmp, *width * 4);
}
free(tmp);
}
void gfx_mode_world() { void gfx_mode_world() {
gfx_write_buffers(true, true, true); gfx_write_buffers(true, true, true);
gfx_matrix_texture(false, NULL); gfx_matrix_texture(false, NULL);

View file

@ -252,6 +252,55 @@ void gfx_bind_texture(struct tex_gfx* tex) {
tex_gfx_bind(tex, GX_TEXMAP0); tex_gfx_bind(tex, GX_TEXMAP0);
} }
void gfx_copy_framebuffer(uint8_t* dest, size_t* width, size_t* height) {
assert(width && height);
*width = screenMode->fbWidth;
*height = screenMode->efbHeight;
if(!dest)
return;
size_t length
= GX_GetTexBufferSize(*width, *height, GX_TF_RGBA8, GX_FALSE, 0);
uint8_t* buffer = memalign(32, length);
if(!buffer)
return;
GX_SetTexCopySrc(0, 0, *width, *height);
GX_SetTexCopyDst(*width, *height, GX_TF_RGBA8, GX_FALSE);
GX_CopyTex(buffer, GX_FALSE);
GX_PixModeSync();
GX_SetDrawDone();
DCInvalidateRange(buffer, length);
GX_WaitDrawDone();
uint8_t* src = buffer;
for(size_t y = 0; y < *height; y += 4) {
for(size_t x = 0; x < *width; x += 4) {
for(size_t by = 0; by < 4; by++) {
for(size_t bx = 0; bx < 4; bx++) {
uint8_t* col = dest + (x + bx + (y + by) * (*width)) * 4;
col[3] = *(src++);
col[0] = *(src++);
}
}
for(size_t by = 0; by < 4; by++) {
for(size_t bx = 0; bx < 4; bx++) {
uint8_t* col = dest + (x + bx + (y + by) * (*width)) * 4;
col[1] = *(src++);
col[2] = *(src++);
}
}
}
}
free(buffer);
}
void gfx_mode_world() { void gfx_mode_world() {
gfx_write_buffers(true, true, true); gfx_write_buffers(true, true, true);
} }