Merge pull request #76 from alanswx/master
Screenshot using Alt-Print Screen
This commit is contained in:
5
Makefile
5
Makefile
@@ -29,12 +29,13 @@ ST_SRC = $(wildcard ./support/st/*.cpp)
|
||||
X86_SRC = $(wildcard ./support/x86/*.cpp)
|
||||
SNES_SRC = $(wildcard ./support/snes/*.cpp)
|
||||
LIBCO_SRC = lib/libco/arm.c
|
||||
LODEPNG_SRC = lib/lodepng/lodepng.cpp
|
||||
MINIZ_SRC = $(wildcard ./lib/miniz/*.c)
|
||||
|
||||
VPATH = ./:./support/minimig:./support/sharpmz:./support/archie:./support/st:./support/x86:./support/snes
|
||||
|
||||
OBJ = $(SRC:.c=.c.o) $(SRC2:.cpp=.cpp.o) $(MINIMIG_SRC:.cpp=.cpp.o) $(SHARPMZ_SRC:.cpp=.cpp.o) $(ARCHIE_SRC:.cpp=.cpp.o) $(ST_SRC:.cpp=.cpp.o) $(X86_SRC:.cpp=.cpp.o) $(SNES_SRC:.cpp=.cpp.o) $(LIBCO_SRC:.c=.c.o) $(MINIZ_SRC:.c=.c.o)
|
||||
DEP = $(SRC:.c=.cpp.d) $(SRC2:.cpp=.cpp.d) $(MINIMIG_SRC:.cpp=.cpp.d) $(SHARPMZ_SRC:.cpp=.cpp.d) $(ARCHIE_SRC:.cpp=.cpp.d) $(ST_SRC:.cpp=.cpp.d) $(X86_SRC:.cpp=.cpp.d) $(SNES_SRC:.cpp=.cpp.d) $(LIBCO_SRC:.c=.c.d) $(MINIZ_SRC:.c=.c.d)
|
||||
OBJ = $(SRC:.c=.c.o) $(SRC2:.cpp=.cpp.o) $(MINIMIG_SRC:.cpp=.cpp.o) $(SHARPMZ_SRC:.cpp=.cpp.o) $(ARCHIE_SRC:.cpp=.cpp.o) $(ST_SRC:.cpp=.cpp.o) $(X86_SRC:.cpp=.cpp.o) $(SNES_SRC:.cpp=.cpp.o) $(LIBCO_SRC:.c=.c.o) $(MINIZ_SRC:.c=.c.o) $(LODEPNG_SRC:.cpp=.cpp.o)
|
||||
DEP = $(SRC:.c=.cpp.d) $(SRC2:.cpp=.cpp.d) $(MINIMIG_SRC:.cpp=.cpp.d) $(SHARPMZ_SRC:.cpp=.cpp.d) $(ARCHIE_SRC:.cpp=.cpp.d) $(ST_SRC:.cpp=.cpp.d) $(X86_SRC:.cpp=.cpp.d) $(SNES_SRC:.cpp=.cpp.d) $(LIBCO_SRC:.c=.c.d) $(MINIZ_SRC:.c=.c.d) $(LODEPNG_SRC:.cpp=.cpp.d)
|
||||
|
||||
DFLAGS = $(INCLUDE) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE -DVDATE=\"`date +"%y%m%d"`\"
|
||||
CFLAGS = $(DFLAGS) -Wall -Wextra -Wno-strict-aliasing -c -O3
|
||||
|
||||
46
file_io.cpp
46
file_io.cpp
@@ -71,7 +71,7 @@ static char* make_fullpath(const char *path, int mode = 0)
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(full_path, path);
|
||||
sprintf(full_path, "%s",path);
|
||||
}
|
||||
|
||||
return full_path;
|
||||
@@ -587,6 +587,50 @@ int FileCanWrite(const char *name)
|
||||
return ((st.st_mode & S_IWUSR) != 0);
|
||||
}
|
||||
|
||||
|
||||
//http://nion.modprobe.de/blog/archives/357-Recursive-directory-creation.html
|
||||
static void mkdirs(const char *dir) {
|
||||
char tmp[256];
|
||||
char *p = NULL;
|
||||
size_t len;
|
||||
|
||||
snprintf(tmp, sizeof(tmp),"%s",dir);
|
||||
len = strlen(tmp);
|
||||
if(tmp[len - 1] == '/')
|
||||
tmp[len - 1] = 0;
|
||||
for(p = tmp + 1; *p; p++)
|
||||
if(*p == '/') {
|
||||
*p = 0;
|
||||
mkdir(tmp, S_IRWXU);
|
||||
*p = '/';
|
||||
}
|
||||
mkdir(tmp, S_IRWXU);
|
||||
}
|
||||
|
||||
void FileGenerateScreenshotName(const char *path, const char *postfix,char *buffer, int buflen)
|
||||
{
|
||||
int curnum=1;
|
||||
int done=false;
|
||||
// create the full path, ie: /media/fat/screenshot/NES/
|
||||
mkdirs(getFullPath(path));
|
||||
// create
|
||||
do
|
||||
{
|
||||
snprintf(buffer,buflen,"%s/%s_%04d.png",path,postfix,curnum);
|
||||
if (getFileType(buffer)==0)
|
||||
{
|
||||
done=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
curnum++;
|
||||
}
|
||||
|
||||
|
||||
} while(curnum<10000 && done==false);
|
||||
}
|
||||
|
||||
|
||||
void FileGenerateSavePath(const char *name, char* out_name)
|
||||
{
|
||||
make_fullpath(SAVE_DIR);
|
||||
|
||||
@@ -66,6 +66,8 @@ int FileCanWrite(const char *name);
|
||||
#define SAVE_DIR "saves"
|
||||
void FileGenerateSavePath(const char *name, char* out_name);
|
||||
|
||||
void FileGenerateScreenshotName(const char *path, const char *postfix,char *buffer, int buflen);
|
||||
|
||||
int FileSave(const char *name, void *pBuffer, int size);
|
||||
int FileLoad(const char *name, void *pBuffer, int size); // supply pBuffer = 0 to get the file size without loading
|
||||
|
||||
|
||||
5992
lib/lodepng/lodepng.cpp
Normal file
5992
lib/lodepng/lodepng.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1930
lib/lodepng/lodepng.h
Normal file
1930
lib/lodepng/lodepng.h
Normal file
File diff suppressed because it is too large
Load Diff
130
scaler.cpp
Normal file
130
scaler.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
Copyright 2019 alanswx
|
||||
with help from the MiSTer contributors including Grabulosaure
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sched.h>
|
||||
#include <inttypes.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <err.h>
|
||||
|
||||
|
||||
|
||||
#include "scaler.h"
|
||||
|
||||
|
||||
|
||||
mister_scaler * mister_scaler_init()
|
||||
{
|
||||
mister_scaler *ms =(mister_scaler *) calloc(sizeof(mister_scaler),1);
|
||||
int pagesize = sysconf(_SC_PAGE_SIZE);
|
||||
if (pagesize==0) pagesize=4096;
|
||||
int offset = MISTER_SCALAR_BASEADDR;
|
||||
int map_start = offset & ~(pagesize - 1);
|
||||
ms->map_off = offset - map_start;
|
||||
ms->num_bytes=MISTER_SCALAR_BUFFERSIZE;
|
||||
//printf("map_start = %d map_off=%d offset=%d\n",map_start,ms->map_off,offset);
|
||||
|
||||
unsigned char *buffer;
|
||||
ms->fd=open("/dev/mem", O_RDONLY, S_IRUSR | S_IWUSR);
|
||||
ms->map=(char *)mmap(NULL, ms->num_bytes+ms->map_off,PROT_READ, MAP_SHARED, ms->fd, map_start);
|
||||
if (ms->map==MAP_FAILED)
|
||||
{
|
||||
printf("problem MAP_FAILED\n");
|
||||
mister_scaler_free(ms);
|
||||
return NULL;
|
||||
}
|
||||
buffer = (unsigned char *)(ms->map+ms->map_off);
|
||||
printf (" 1: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
||||
buffer[0],buffer[1],buffer[2],buffer[3],buffer[4],buffer[5],buffer[6],buffer[7],
|
||||
buffer[8],buffer[9],buffer[10],buffer[11],buffer[12],buffer[13],buffer[14],buffer[15]);
|
||||
if (buffer[0]!=1 || buffer[1]!=1) {
|
||||
printf("problem\n");
|
||||
mister_scaler_free(ms);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ms->header=buffer[2]<<8 | buffer[3];
|
||||
ms->width =buffer[6]<<8 | buffer[7];
|
||||
ms->height=buffer[8]<<8 | buffer[9];
|
||||
ms->line =buffer[10]<<8 | buffer[11];
|
||||
|
||||
printf ("Image: Width=%i Height=%i Line=%i Header=%i\n",ms->width,ms->height,ms->line,ms->header);
|
||||
/*
|
||||
printf (" 1: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
||||
buffer[0],buffer[1],buffer[2],buffer[3],buffer[4],buffer[5],buffer[6],buffer[7],
|
||||
buffer[8],buffer[9],buffer[10],buffer[11],buffer[12],buffer[13],buffer[14],buffer[15]);
|
||||
*/
|
||||
|
||||
return ms;
|
||||
|
||||
}
|
||||
void mister_scaler_free(mister_scaler *ms)
|
||||
{
|
||||
munmap(ms->map,ms->num_bytes+ms->map_off);
|
||||
close(ms->fd);
|
||||
free(ms);
|
||||
}
|
||||
|
||||
int mister_scaler_read_yuv(mister_scaler *ms,int lineY,unsigned char *bufY, int lineU, unsigned char *bufU, int lineV, unsigned char *bufV) {
|
||||
unsigned char *buffer;
|
||||
buffer = (unsigned char *)(ms->map+ms->map_off);
|
||||
|
||||
// do this slow way for now..
|
||||
unsigned char *pixbuf;
|
||||
unsigned char *outbufy;
|
||||
unsigned char *outbufU;
|
||||
unsigned char *outbufV;
|
||||
for (int y=0; y< ms->height ; y++) {
|
||||
pixbuf=&buffer[ms->header + y*ms->line];
|
||||
outbufy=&bufY[y*(lineY)];
|
||||
outbufU=&bufU[y*(lineU)];
|
||||
outbufV=&bufV[y*(lineV)];
|
||||
for (int x = 0; x < ms->width ; x++) {
|
||||
int R,G,B;
|
||||
R = *pixbuf++;
|
||||
G = *pixbuf++;
|
||||
B = *pixbuf++;
|
||||
int Y = (0.257 * R) + (0.504 * G) + (0.098 * B) + 16;
|
||||
int U = -(0.148 * R) - (0.291 * G) + (0.439 * B) + 128;
|
||||
int V = (0.439 * R) - (0.368 * G) - (0.071 * B) + 128;
|
||||
|
||||
*outbufy++ = Y;
|
||||
*outbufU++ = U;
|
||||
*outbufV++ = V;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int mister_scaler_read(mister_scaler *ms,unsigned char *gbuf)
|
||||
{
|
||||
unsigned char *buffer;
|
||||
buffer = (unsigned char *)(ms->map+ms->map_off);
|
||||
|
||||
// do this slow way for now.. - could use a memcpy?
|
||||
unsigned char *pixbuf;
|
||||
unsigned char *outbuf;
|
||||
for (int y=0; y< ms->height ; y++) {
|
||||
pixbuf=&buffer[ms->header + y*ms->line];
|
||||
outbuf=&gbuf[y*(ms->width*3)];
|
||||
for (int x = 0; x < ms->width ; x++) {
|
||||
*outbuf++ = *pixbuf++;
|
||||
*outbuf++ = *pixbuf++;
|
||||
*outbuf++ = *pixbuf++;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
27
scaler.h
Normal file
27
scaler.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright 2019 alanswx
|
||||
with help from the MiSTer contributors including Grabulosaure
|
||||
*/
|
||||
|
||||
|
||||
typedef struct {
|
||||
int header;
|
||||
int width;
|
||||
int height;
|
||||
int line;
|
||||
|
||||
char *map;
|
||||
int num_bytes;
|
||||
int map_off;
|
||||
int fd;
|
||||
} mister_scaler;
|
||||
|
||||
|
||||
#define MISTER_SCALAR_BASEADDR 536870912
|
||||
#define MISTER_SCALAR_BUFFERSIZE 2048*3*1024
|
||||
|
||||
|
||||
mister_scaler *mister_scaler_init();
|
||||
int mister_scaler_read(mister_scaler *,unsigned char *buffer);
|
||||
int mister_scaler_read_yuv(mister_scaler *ms,int,unsigned char *y,int, unsigned char *U,int, unsigned char *V);
|
||||
void mister_scaler_free(mister_scaler *);
|
||||
40
user_io.cpp
40
user_io.cpp
@@ -10,6 +10,8 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statvfs.h>
|
||||
|
||||
#include "lib/lodepng/lodepng.h"
|
||||
|
||||
#include "hardware.h"
|
||||
#include "osd.h"
|
||||
#include "user_io.h"
|
||||
@@ -26,6 +28,7 @@
|
||||
#include "tzx2wav.h"
|
||||
#include "bootcore.h"
|
||||
#include "charrom.h"
|
||||
#include "scaler.h"
|
||||
|
||||
#include "support.h"
|
||||
|
||||
@@ -2479,6 +2482,43 @@ void user_io_kbd(uint16_t key, int press)
|
||||
{
|
||||
if(is_menu_core()) spi_uio_cmd(UIO_KEYBOARD); //ping the Menu core to wakeup
|
||||
|
||||
// ALT - Print Screen - screen shot
|
||||
if (key==0x63 && (get_key_mod() & (LALT | RALT | RGUI | LGUI)))
|
||||
{
|
||||
if (press==1)
|
||||
{
|
||||
printf("print key pressed - do screen shot\n");
|
||||
mister_scaler *ms=mister_scaler_init();
|
||||
if (ms==NULL)
|
||||
{
|
||||
printf("problem with scaler, maybe not a new enough version\n");
|
||||
Info("Scaler not compatible");
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned char *outputbuf = (unsigned char *)calloc(ms->width*ms->height*3,1);
|
||||
mister_scaler_read(ms,outputbuf);
|
||||
char path[1024];
|
||||
char filename[1024];
|
||||
//user_io_get_core_name()
|
||||
snprintf(path,1024,"screenshot/%s",HomeDir);
|
||||
FileGenerateScreenshotName(path,"shot",filename,1024);
|
||||
unsigned error = lodepng_encode24_file(getFullPath(filename), outputbuf, ms->width, ms->height);
|
||||
if(error) {
|
||||
printf("error %u: %s\n", error, lodepng_error_text(error));
|
||||
printf("%s", filename);
|
||||
Info("error in saving png");
|
||||
}
|
||||
free(outputbuf);
|
||||
mister_scaler_free(ms);
|
||||
char msg[1024];
|
||||
snprintf(msg,1024,"Saving screen shot\n %s\n",filename+strlen("screenshot/"));
|
||||
Info(msg);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
if (key == KEY_MUTE)
|
||||
{
|
||||
if (press == 1 && hasAPI1_5()) set_volume(0);
|
||||
|
||||
Reference in New Issue
Block a user