Merge pull request #76 from alanswx/master

Screenshot using Alt-Print Screen
This commit is contained in:
sorgelig
2019-05-09 08:15:56 +08:00
committed by GitHub
8 changed files with 8169 additions and 3 deletions

View File

@@ -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

View File

@@ -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);

View File

@@ -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

File diff suppressed because it is too large Load Diff

1930
lib/lodepng/lodepng.h Normal file

File diff suppressed because it is too large Load Diff

130
scaler.cpp Normal file
View 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
View 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 *);

View File

@@ -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);