mirror of
https://github.com/xtreme8000/CavEX.git
synced 2025-01-22 09:11:55 -05:00
Screenshot feature
This commit is contained in:
parent
0ab2fe2a0f
commit
0da0139fce
8 changed files with 103 additions and 4 deletions
|
@ -21,6 +21,7 @@
|
|||
"gui_left": [2, 202],
|
||||
"gui_right": [3, 203],
|
||||
"gui_click": [4, 204],
|
||||
"gui_click_alt": [5, 205]
|
||||
"gui_click_alt": [5, 205],
|
||||
"screenshot": [7],
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"gui_left": [65],
|
||||
"gui_right": [68],
|
||||
"gui_click": [1000],
|
||||
"gui_click_alt": [1001]
|
||||
"gui_click_alt": [1001],
|
||||
"screenshot": [291]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef PLATFORM_WII
|
||||
#include <fat.h>
|
||||
|
@ -42,10 +43,9 @@
|
|||
|
||||
#include "cNBT/nbt.h"
|
||||
#include "cglm/cglm.h"
|
||||
#include "lodepng/lodepng.h"
|
||||
|
||||
int main(void) {
|
||||
time_reset();
|
||||
|
||||
gstate.quit = false;
|
||||
gstate.camera = (struct camera) {
|
||||
.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(),
|
||||
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();
|
||||
gfx_finish(true);
|
||||
}
|
||||
|
|
|
@ -54,6 +54,8 @@ void gfx_clear_buffers(uint8_t r, uint8_t g, uint8_t b);
|
|||
int gfx_width(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_modelview(mat4 mv);
|
||||
void gfx_matrix_texture(bool enable, mat4 tex);
|
||||
|
|
|
@ -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_CLICK: return "input.gui_click";
|
||||
case IB_GUI_CLICK_ALT: return "input.gui_click_alt";
|
||||
case IB_SCREENSHOT: return "input.screenshot";
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ enum input_button {
|
|||
IB_GUI_RIGHT,
|
||||
IB_GUI_CLICK,
|
||||
IB_GUI_CLICK_ALT,
|
||||
IB_SCREENSHOT,
|
||||
};
|
||||
|
||||
enum input_category {
|
||||
|
|
|
@ -206,6 +206,33 @@ void gfx_bind_texture(struct tex_gfx* tex) {
|
|||
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() {
|
||||
gfx_write_buffers(true, true, true);
|
||||
gfx_matrix_texture(false, NULL);
|
||||
|
|
|
@ -252,6 +252,55 @@ void gfx_bind_texture(struct tex_gfx* tex) {
|
|||
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() {
|
||||
gfx_write_buffers(true, true, true);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue