Update screenshot code.
This commit is contained in:
@@ -30,7 +30,7 @@
|
||||
<NMakeOutput>MiSTer</NMakeOutput>
|
||||
<NMakeCleanCommandLine>git.lnk ./clean.sh</NMakeCleanCommandLine>
|
||||
<NMakePreprocessorDefinitions>__arm__;__GNUC__;__USE_GNU ;_GNU_SOURCE;VDATE="000000";_FILE_OFFSET_BITS=64;_LARGEFILE64_SOURCE;$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
|
||||
<NMakeIncludeSearchPath>c:\Work\Git\opt\gcc54\arm-linux-gnueabihf\libc\usr\include;c:\Work\Git\opt\gcc54\lib\gcc\arm-linux-gnueabihf\5.4.1\include;c:\Work\Git\opt\gcc54\arm-linux-gnueabihf\include\c++\5.4.1;$(NMakeIncludeSearchPath);lib\libco;lib\miniz</NMakeIncludeSearchPath>
|
||||
<NMakeIncludeSearchPath>c:\Work\Git\opt\gcc54\arm-linux-gnueabihf\libc\usr\include;c:\Work\Git\opt\gcc54\lib\gcc\arm-linux-gnueabihf\5.4.1\include;c:\Work\Git\opt\gcc54\arm-linux-gnueabihf\include\c++\5.4.1;$(NMakeIncludeSearchPath);lib\libco;lib\miniz;lib\lodepng</NMakeIncludeSearchPath>
|
||||
<OutDir>$(TEMP)</OutDir>
|
||||
<IntDir>$(TEMP)</IntDir>
|
||||
<AdditionalOptions>
|
||||
@@ -62,6 +62,7 @@
|
||||
<ClCompile Include="input.cpp" />
|
||||
<ClCompile Include="lib\libco\arm.c" />
|
||||
<ClCompile Include="lib\libco\libco.c" />
|
||||
<ClCompile Include="lib\lodepng\lodepng.cpp" />
|
||||
<ClCompile Include="lib\miniz\miniz.c" />
|
||||
<ClCompile Include="lib\miniz\miniz_tdef.c" />
|
||||
<ClCompile Include="lib\miniz\miniz_tinfl.c" />
|
||||
@@ -69,6 +70,7 @@
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="menu.cpp" />
|
||||
<ClCompile Include="osd.cpp" />
|
||||
<ClCompile Include="scaler.cpp" />
|
||||
<ClCompile Include="scheduler.cpp" />
|
||||
<ClCompile Include="spi.cpp" />
|
||||
<ClCompile Include="support\archie\archie.cpp" />
|
||||
@@ -106,6 +108,7 @@
|
||||
<ClInclude Include="input.h" />
|
||||
<ClInclude Include="lib\libco\libco.h" />
|
||||
<ClInclude Include="lib\libco\settings.h" />
|
||||
<ClInclude Include="lib\lodepng\lodepng.h" />
|
||||
<ClInclude Include="lib\miniz\miniz.h" />
|
||||
<ClInclude Include="lib\miniz\miniz_common.h" />
|
||||
<ClInclude Include="lib\miniz\miniz_tdef.h" />
|
||||
@@ -114,6 +117,7 @@
|
||||
<ClInclude Include="logo.h" />
|
||||
<ClInclude Include="menu.h" />
|
||||
<ClInclude Include="osd.h" />
|
||||
<ClInclude Include="scaler.h" />
|
||||
<ClInclude Include="scheduler.h" />
|
||||
<ClInclude Include="spi.h" />
|
||||
<ClInclude Include="support.h" />
|
||||
|
||||
@@ -136,6 +136,12 @@
|
||||
<ClCompile Include="cheats.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="lib\lodepng\lodepng.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="scaler.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="battery.h">
|
||||
@@ -273,5 +279,11 @@
|
||||
<ClInclude Include="cheats.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="lib\lodepng\lodepng.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="scaler.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
73
file_io.cpp
73
file_io.cpp
@@ -587,57 +587,40 @@ 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)
|
||||
static void create_path(const char *base_dir, const char* sub_dir)
|
||||
{
|
||||
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);
|
||||
make_fullpath(base_dir);
|
||||
mkdir(full_path, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
strcat(full_path, "/");
|
||||
strcat(full_path, sub_dir);
|
||||
mkdir(full_path, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
}
|
||||
|
||||
void FileGenerateScreenshotName(const char *name, char *out_name, int buflen)
|
||||
{
|
||||
create_path(SCREENSHOT_DIR, HomeDir);
|
||||
|
||||
time_t t = time(NULL);
|
||||
struct tm tm = *localtime(&t);
|
||||
char datecode[32] = {};
|
||||
if (tm.tm_year >= 119) // 2019 or up considered valid time
|
||||
{
|
||||
strftime(datecode, 31, "%Y%m%d_%H%M%S", &tm);
|
||||
snprintf(out_name, buflen, "%s/%s/%s-%s.png", SCREENSHOT_DIR, HomeDir, datecode, name[0] ? name : SCREENSHOT_DEFAULT);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 1; i < 10000; i++)
|
||||
{
|
||||
snprintf(out_name, buflen, "%s/%s/NODATE-%s_%04d.png", SCREENSHOT_DIR, HomeDir, name[0] ? name : SCREENSHOT_DEFAULT, i);
|
||||
if (!getFileType(out_name)) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FileGenerateSavePath(const char *name, char* out_name)
|
||||
{
|
||||
make_fullpath(SAVE_DIR);
|
||||
mkdir(full_path, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
strcat(full_path, "/");
|
||||
strcat(full_path, HomeDir);
|
||||
mkdir(full_path, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
create_path(SAVE_DIR, HomeDir);
|
||||
|
||||
sprintf(out_name, "%s/%s/", SAVE_DIR, HomeDir);
|
||||
char *fname = out_name + strlen(out_name);
|
||||
|
||||
@@ -66,7 +66,9 @@ 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);
|
||||
#define SCREENSHOT_DIR "screenshots"
|
||||
#define SCREENSHOT_DEFAULT "screen"
|
||||
void FileGenerateScreenshotName(const char *name, char *out_name, 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
|
||||
|
||||
1
menu.cpp
1
menu.cpp
@@ -1411,6 +1411,7 @@ void HandleUI(void)
|
||||
|
||||
case MENU_8BIT_MAIN_FILE_SELECTED:
|
||||
printf("File selected: %s\n", SelectedPath);
|
||||
user_io_store_filename(SelectedPath);
|
||||
user_io_file_tx(SelectedPath, user_io_ext_idx(SelectedPath, fs_pFileExt) << 6 | (menusub + 1), opensave);
|
||||
cheats_init(SelectedPath);
|
||||
menustate = MENU_NONE1;
|
||||
|
||||
48
scaler.cpp
48
scaler.cpp
@@ -17,21 +17,18 @@ with help from the MiSTer contributors including Grabulosaure
|
||||
#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 offset = MISTER_SCALER_BASEADDR;
|
||||
int map_start = offset & ~(pagesize - 1);
|
||||
ms->map_off = offset - map_start;
|
||||
ms->num_bytes=MISTER_SCALAR_BUFFERSIZE;
|
||||
ms->num_bytes=MISTER_SCALER_BUFFERSIZE;
|
||||
//printf("map_start = %d map_off=%d offset=%d\n",map_start,ms->map_off,offset);
|
||||
|
||||
unsigned char *buffer;
|
||||
@@ -68,6 +65,7 @@ mister_scaler * mister_scaler_init()
|
||||
return ms;
|
||||
|
||||
}
|
||||
|
||||
void mister_scaler_free(mister_scaler *ms)
|
||||
{
|
||||
munmap(ms->map,ms->num_bytes+ms->map_off);
|
||||
@@ -75,7 +73,8 @@ void mister_scaler_free(mister_scaler *ms)
|
||||
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) {
|
||||
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);
|
||||
|
||||
@@ -84,28 +83,29 @@ int mister_scaler_read_yuv(mister_scaler *ms,int lineY,unsigned char *bufY, int
|
||||
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;
|
||||
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;
|
||||
}
|
||||
*outbufy++ = Y;
|
||||
*outbufU++ = U;
|
||||
*outbufV++ = V;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int mister_scaler_read(mister_scaler *ms,unsigned char *gbuf)
|
||||
|
||||
10
scaler.h
10
scaler.h
@@ -3,6 +3,8 @@ Copyright 2019 alanswx
|
||||
with help from the MiSTer contributors including Grabulosaure
|
||||
*/
|
||||
|
||||
#ifndef SCALER_H
|
||||
#define SCALER_H
|
||||
|
||||
typedef struct {
|
||||
int header;
|
||||
@@ -16,12 +18,12 @@ typedef struct {
|
||||
int fd;
|
||||
} mister_scaler;
|
||||
|
||||
|
||||
#define MISTER_SCALAR_BASEADDR 536870912
|
||||
#define MISTER_SCALAR_BUFFERSIZE 2048*3*1024
|
||||
|
||||
#define MISTER_SCALER_BASEADDR 0x20000000
|
||||
#define MISTER_SCALER_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 *);
|
||||
|
||||
#endif
|
||||
|
||||
71
user_io.cpp
71
user_io.cpp
@@ -69,6 +69,17 @@ static bool scrl_status = 0;
|
||||
|
||||
static char minimig_adjust = 0;
|
||||
|
||||
static char last_filename[1024] = {};
|
||||
void user_io_store_filename(char *filename)
|
||||
{
|
||||
char *p = strrchr(filename, '/');
|
||||
if (p) strcpy(last_filename, p + 1);
|
||||
else strcpy(last_filename, filename);
|
||||
|
||||
p = strrchr(last_filename, '.');
|
||||
if (p) *p = 0;
|
||||
}
|
||||
|
||||
const char *get_image_name(int i)
|
||||
{
|
||||
if (!sd_image[i].size) return NULL;
|
||||
@@ -2482,42 +2493,39 @@ 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)
|
||||
// Win+PrnScr or Alt/Win+ScrLk - screen shot
|
||||
if ((key == KEY_SYSRQ && (get_key_mod() & (RGUI | LGUI))) || (key == KEY_SCROLLLOCK && (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");
|
||||
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");
|
||||
unsigned char *outputbuf = (unsigned char *)calloc(ms->width*ms->height * 3, 1);
|
||||
mister_scaler_read(ms, outputbuf);
|
||||
static char filename[1024];
|
||||
FileGenerateScreenshotName(last_filename, 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, "Screen saved to\n%s", filename + strlen(SCREENSHOT_DIR"/"));
|
||||
Info(msg);
|
||||
}
|
||||
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)
|
||||
{
|
||||
@@ -2550,11 +2558,6 @@ void user_io_kbd(uint16_t key, int press)
|
||||
PrintDirectory();
|
||||
}
|
||||
else
|
||||
if ((core_type == CORE_TYPE_MINIMIG2) ||
|
||||
(core_type == CORE_TYPE_MIST) ||
|
||||
(core_type == CORE_TYPE_ARCHIE) ||
|
||||
(core_type == CORE_TYPE_SHARPMZ) ||
|
||||
(core_type == CORE_TYPE_8BIT))
|
||||
{
|
||||
if (key)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user