Bootcore feature

[MiSTer]
; lastcore - Autoboot the last loaded core (corename autosaved in CONFIG/lastcore.dat) first found on the SD/USB
; lastexactcore - Autoboot the last loaded exact core (corename_yyyymmdd.rbf autosaved in CONFIG/lastcore.dat) first found on the SD/USB
; corename - Autoboot first corename_*.rbf found on the SD/USB
; corename_yyyymmdd.rbf - Autoboot first corename_yyyymmdd.rbf found on the SD/USB
;bootcore=lastcore    ; uncomment to autoboot a core, as the last loaded core.
bootcore_timeout=10  ; 10-30 timeout before autoboot, comment for autoboot without timeout.
This commit is contained in:
Aitor Gómez
2019-03-13 06:04:26 +01:00
committed by GitHub
parent 9c7f1a8780
commit ee250685e1
15 changed files with 389 additions and 9 deletions

View File

@@ -17,6 +17,13 @@ vscale_border=0 ; set vertical border for TVs cutting the upper/bottom pa
rbf_hide_datecode=0 ; 1 - hides datecodes from rbf file names. Press F2 for quick temporary toggle
menu_pal=0 ; 1 - PAL mode for menu core
; lastcore - Autoboot the last loaded core (corename autosaved in CONFIG/lastcore.dat) first found on the SD/USB
; lastexactcore - Autoboot the last loaded exact core (corename_yyyymmdd.rbf autosaved in CONFIG/lastcore.dat) first found on the SD/USB
; corename - Autoboot first corename_*.rbf found on the SD/USB
; corename_yyyymmdd.rbf - Autoboot first corename_yyyymmdd.rbf found on the SD/USB
;bootcore=lastcore ; uncomment to autoboot a core, as the last loaded core.
bootcore_timeout=10 ; 10-30 timeout before autoboot, comment for autoboot without timeout.
; USER button emulation by keybaord. Usually it's reset button.
; 0 - lctrl+lalt+ralt (lctrl+lgui+rgui on keyrah)
; 1 - lctrl+lgui+rgui

View File

@@ -49,6 +49,7 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="battery.cpp" />
<ClCompile Include="bootcore.cpp" />
<ClCompile Include="brightness.cpp" />
<ClCompile Include="cfg.cpp" />
<ClCompile Include="DiskImage.cpp" />
@@ -84,6 +85,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="battery.h" />
<ClInclude Include="bootcore.h" />
<ClInclude Include="brightness.h" />
<ClInclude Include="cfg.h" />
<ClInclude Include="charrom.h" />

View File

@@ -127,6 +127,9 @@
<ClCompile Include="lib\miniz\miniz_zip.c">
<Filter>Source Files\miniz</Filter>
</ClCompile>
<ClCompile Include="bootcore.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="battery.h">
@@ -258,5 +261,8 @@
<ClInclude Include="lib\miniz\miniz_zip.h">
<Filter>Header Files\miniz</Filter>
</ClInclude>
<ClInclude Include="bootcore.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

240
bootcore.cpp Normal file
View File

@@ -0,0 +1,240 @@
// bootcore.cpp
// 2019, Aitor Gomez Garcia (spark2k06@gmail.com)
// Thanks to Sorgelig and BBond007 for their help and advice in the development of this feature.
#include "file_io.h"
#include "cfg.h"
#include "fpga_io.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
int16_t btimeout;
char bootcoretype[64];
bool isExactcoreName(char *path)
{
char *spl = strrchr(path, '.');
return (spl && !strcmp(spl, ".rbf"));
}
char *getcoreName(char *path)
{
char *spl = strrchr(path, '.');
if (spl && !strcmp(spl, ".rbf"))
{
*spl = '\0';
}
else
{
return NULL;
}
if ((spl = strrchr(path, '/')) != NULL)
{
path = spl + 1;
}
if ((spl = strrchr(path, '_')) != NULL)
{
*spl = 0;
}
return path;
}
char *getcoreExactName(char *path)
{
char *spl;
if ((spl = strrchr(path, '/')) != NULL)
{
path = spl + 1;
}
return path;
}
char *replaceStr(const char *str, const char *oldstr, const char *newstr)
{
char *result;
int i, cnt = 0;
int newstrlen = strlen(newstr);
int oldstrlen = strlen(oldstr);
for (i = 0; str[i] != '\0'; i++)
{
if (strstr(&str[i], oldstr) == &str[i])
{
cnt++;
i += oldstrlen - 1;
}
}
result = new char[i + cnt * (newstrlen - oldstrlen) + 1];
i = 0;
while (*str)
{
if (strstr(str, oldstr) == str)
{
strcpy(&result[i], newstr);
i += newstrlen;
str += oldstrlen;
}
else
result[i++] = *str++;
}
result[i] = '\0';
return result;
}
char* loadLastcore()
{
char full_path[2100];
char path[256] = { CONFIG_DIR"/" };
strcat(path, "lastcore.dat");
sprintf(full_path, "%s/%s", getRootDir(), path);
FILE *fd = fopen(full_path, "r");
if (!fd)
{
return NULL;
}
fseek(fd, 0L, SEEK_END);
long size = ftell(fd);
fseek(fd, 0L, SEEK_SET);
char *lastcore = new char[size + 1];
int ret = fread(lastcore, sizeof(char), size, fd);
fclose(fd);
if (ret == size)
{
return lastcore;
}
delete[] lastcore;
return NULL;
}
char *findCore(const char *name, char *coreName, int indent)
{
char *spl;
DIR *dir;
struct dirent *entry;
if (!(dir = opendir(name)))
{
return NULL;
}
char *indir;
char* path = new char[256];
while ((entry = readdir(dir)) != NULL) {
if (entry->d_type == DT_DIR) {
if (entry->d_name[0] != '_')
continue;
snprintf(path, 256, "%s/%s", name, entry->d_name);
indir = findCore(path, coreName, indent + 2);
if (indir != NULL)
{
closedir(dir);
delete[] path;
return indir;
}
}
else {
snprintf(path, 256, "%s/%s", name, entry->d_name);
if (strstr(path, coreName) != NULL) {
spl = strrchr(path, '.');
if (spl && !strcmp(spl, ".rbf"))
{
closedir(dir);
return path;
}
}
}
}
closedir(dir);
delete[] path;
return NULL;
}
void bootcore_init(const char *path)
{
MiSTer_ini_parse();
if (cfg.bootcore[0] == '\0')
{
return;
}
char *auxpointer;
char auxstr[256];
char bootcore[256];
bool is_lastcore;
const char *rootdir = getRootDir();
cfg.bootcore_timeout = cfg.bootcore_timeout * 10;
btimeout = cfg.bootcore_timeout;
strcpy(bootcore, cfg.bootcore);
is_lastcore = (!strcmp(cfg.bootcore, "lastcore") || !strcmp(cfg.bootcore, "lastexactcore"));
if (is_lastcore)
{
strcpy(bootcoretype, cfg.bootcore);
auxpointer = loadLastcore();
if (auxpointer != NULL)
{
strcpy(bootcore, auxpointer);
delete[] auxpointer;
}
}
else
{
strcpy(bootcoretype, isExactcoreName(cfg.bootcore) ? "exactcorename" : "corename");
}
auxpointer = findCore(rootdir, bootcore, 0);
if (auxpointer != NULL)
{
strcpy(bootcore, auxpointer);
delete[] auxpointer;
sprintf(auxstr, "%s/", rootdir);
auxpointer = replaceStr(bootcore, auxstr, "");
if (auxpointer != NULL)
{
strcpy(bootcore, auxpointer);
delete[] auxpointer;
if (path[0] == '\0')
{
if (!cfg.bootcore_timeout)
{
fpga_load_rbf(bootcore);
}
strcpy(cfg.bootcore, strcmp(bootcore, "menu.rbf") ? bootcore : "");
return;
}
}
}
if (is_lastcore && path[0] != '\0')
{
strcpy(auxstr, path);
auxpointer = !strcmp(cfg.bootcore, "lastexactcore") ? getcoreExactName(auxstr) : getcoreName(auxstr);
if (auxpointer != NULL)
{
if (strcmp(bootcore, auxpointer))
{
FileSaveConfig("lastcore.dat", (char*)auxpointer, strlen(auxpointer));
}
}
}
strcpy(cfg.bootcore, "");
}

18
bootcore.h Normal file
View File

@@ -0,0 +1,18 @@
// bootcore.h
// 2019, Aitor Gomez Garcia (spark2k06@gmail.com)
// Thanks to Sorgelig and BBond007 for their help and advice in the development of this feature.
#ifndef __BOOTCORE_H__
#define __BOOTCORE_H__
char *getcoreName(char *path);
char *getcoreExactName(char *path);
char *replaceStr(const char *str, const char *oldstr, const char *newstr);
char *loadLastcore();
char *findCore(const char *name, char *coreName, int indent);
void bootcore_init(const char *path);
extern char bootcoretype[64];
extern int16_t btimeout;
#endif // __BOOTCORE_H__

View File

@@ -46,6 +46,8 @@ const ini_var_t ini_vars[] = {
{ "VSCALE_BORDER", (void*)(&(cfg.vscale_border)), UINT8, 0, 100, 1 },
{ "RBF_HIDE_DATECODE", (void*)(&(cfg.rbf_hide_datecode)), UINT8, 0, 1, 1 },
{ "MENU_PAL", (void*)(&(cfg.menu_pal)), UINT8, 0, 1, 1 },
{ "BOOTCORE", (void*)(&(cfg.bootcore)), STRING, 0, sizeof(cfg.bootcore) - 1, 1 },
{ "BOOTCORE_TIMEOUT", (void*)(&(cfg.bootcore_timeout)), INT8, 10, 30, 1 },
};
// mist ini config

2
cfg.h
View File

@@ -32,6 +32,8 @@ typedef struct {
uint8_t vscale_border;
uint8_t rbf_hide_datecode;
uint8_t menu_pal;
int16_t bootcore_timeout;
char bootcore[256];
char video_conf[1024];
char video_conf_pal[1024];
char video_conf_ntsc[1024];

View File

@@ -737,7 +737,6 @@ void FindStorage(void)
{
int saveddev = device;
device = 0;
MiSTer_ini_parse();
device = saveddev;
parse_video_mode();
user_io_send_buttons(1);

View File

@@ -516,7 +516,7 @@ int fpga_load_rbf(const char *name, const char *cfg)
}
}
close(rbf);
app_restart(!strcasecmp(name, "menu.rbf") ? NULL : path);
app_restart(!strcasecmp(name, "menu.rbf") ? "menu.rbf" : path);
return ret;
}

View File

@@ -31,6 +31,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "input.h"
#include "fpga_io.h"
#include "scheduler.h"
#include "bootcore.h"
const char *version = "$VER:HPS" VDATE;
@@ -65,6 +66,7 @@ int main(int argc, char *argv[])
}
FindStorage();
bootcore_init(argc > 1 ? argv[1] : "");
user_io_init((argc > 1) ? argv[1] : "");
scheduler_init();

103
menu.cpp
View File

@@ -47,6 +47,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "cfg.h"
#include "input.h"
#include "battery.h"
#include "bootcore.h"
#include "support.h"
@@ -643,6 +644,26 @@ static void MenuWrite(unsigned char n, const char *s, unsigned char invert, unsi
OsdWriteOffset(row, s, invert, stipple, 0, (row == 0 && firstmenu) ? 17 : (row == (OsdGetSize()-1) && !arrow) ? 16 : 0, 0);
}
const char* get_rbf_name_bootcore(char *str)
{
if (!strlen(cfg.bootcore)) return "";
char *p = strrchr(str, '/');
if (!p) return str;
char *spl = strrchr(p + 1, '.');
if (spl && !strcmp(spl, ".rbf"))
{
*spl = 0;
}
else
{
return NULL;
}
return p + 1;
}
void HandleUI(void)
{
switch (user_io_core_type())
@@ -689,6 +710,11 @@ void HandleUI(void)
plus = false;
minus = false;
if (c && c != KEY_F12 && cfg.bootcore[0] != '\0')
{
cfg.bootcore[0] = '\0';
}
switch (c)
{
case KEY_F12:
@@ -3556,8 +3582,35 @@ void HandleUI(void)
if (!rtc_timer || CheckTimer(rtc_timer))
{
rtc_timer = GetTimer(1000);
rtc_timer = GetTimer(cfg.bootcore[0] != '\0' ? 100 : 1000);
char str[64] = { 0 };
char straux[64];
if (cfg.bootcore[0] != '\0')
{
if (btimeout >= 10)
{
sprintf(str, " Bootcore -> %s", bootcoretype);
OsdWrite(13, str, 0, 0);
strcpy(straux, cfg.bootcore);
sprintf(str, " %s", get_rbf_name_bootcore(straux));
PrintFileName(str, 14, (32 * btimeout) / cfg.bootcore_timeout);
sprintf(str, " Press any key to cancel");
OsdWrite(15, str, 0, 0);
btimeout--;
if (btimeout < 10)
{
OsdWrite(13, "", 0, 0);
strcpy(straux, cfg.bootcore);
sprintf(str, " %s", get_rbf_name_bootcore(straux));
PrintFileName(str, 14, 0);
sprintf(str, " Loading...");
OsdWrite(15, str, 1, 0);
fpga_load_rbf(cfg.bootcore);
}
}
}
sprintf(str, " MiSTer ");
time_t t = time(NULL);
@@ -3624,6 +3677,54 @@ void ScrollLongName(void)
ScrollText(flist_iSelectedEntry()-flist_iFirstEntry(), flist_SelectedItem()->d_name, 2, len, max_len, 1);
}
void PrintFileName(char *name, int row, int maxinv)
{
int len;
char s[40];
s[32] = 0; // set temporary string length to OSD line length
len = strlen(name); // get name length
memset(s, ' ', 32); // clear line buffer
char *p = 0;
if ((fs_Options & SCANO_CORES) && len > 9 && !strncmp(name + len - 9, "_20", 3))
{
p = name + len - 6;
len -= 9;
}
if (len > 28)
{
len = 27; // trim display length if longer than 30 characters
s[28] = 22;
}
strncpy(s + 1, name, len); // display only name
if (!cfg.rbf_hide_datecode && (fs_Options & SCANO_CORES))
{
if (p)
{
int n = 19;
s[n++] = ' ';
s[n++] = p[0];
s[n++] = p[1];
s[n++] = '.';
s[n++] = p[2];
s[n++] = p[3];
s[n++] = '.';
s[n++] = p[4];
s[n++] = p[5];
}
else
{
strcpy(&s[19], " --.--.--");
}
}
OsdWrite(row, s, 1, 0, 0, maxinv);
}
// print directory contents
void PrintDirectory(void)
{

1
menu.h
View File

@@ -13,6 +13,7 @@ extern const char *config_chipset_msg[];
void HandleUI(void);
void menu_key_set(unsigned int c);
void PrintFileName(char *name, int row, int maxinv);
void PrintDirectory(void);
void ScrollLongName(void);

View File

@@ -200,13 +200,13 @@ void OsdSetArrow(int a)
arrow = a;
}
void OsdWrite(unsigned char n, const char *s, unsigned char invert, unsigned char stipple, char usebg)
void OsdWrite(unsigned char n, const char *s, unsigned char invert, unsigned char stipple, char usebg, int maxinv)
{
OsdWriteOffset(n, s, invert, stipple, 0, 0, usebg);
OsdWriteOffset(n, s, invert, stipple, 0, 0, usebg, maxinv);
}
// write a null-terminated string <s> to the OSD buffer starting at line <n>
void OsdWriteOffset(unsigned char n, const char *s, unsigned char invert, unsigned char stipple, char offset, char leftchar, char usebg)
void OsdWriteOffset(unsigned char n, const char *s, unsigned char invert, unsigned char stipple, char offset, char leftchar, char usebg, int maxinv)
{
//printf("OsdWriteOffset(%d)\n", n);
unsigned short i;
@@ -237,6 +237,7 @@ void OsdWriteOffset(unsigned char n, const char *s, unsigned char invert, unsign
// send all characters in string to OSD
while (1)
{
if (invert && i / 8 >= maxinv) invert = 0;
if (i == 0 && (n < osd_size))
{ // Render sidestripe
unsigned char j;

4
osd.h
View File

@@ -68,8 +68,8 @@
/*functions*/
void OsdSetTitle(const char *s, int arrow = 0); // arrow > 0 = display right arrow in bottom right, < 0 = display left arrow
void OsdSetArrow(int arrow);
void OsdWrite(unsigned char n, const char *s="", unsigned char inver=0, unsigned char stipple=0, char usebg = 0);
void OsdWriteOffset(unsigned char n, const char *s, unsigned char inver, unsigned char stipple, char offset, char leftchar, char usebg = 0); // Used for scrolling "Exit" text downwards...
void OsdWrite(unsigned char n, const char *s="", unsigned char inver=0, unsigned char stipple=0, char usebg = 0, int maxinv = 32);
void OsdWriteOffset(unsigned char n, const char *s, unsigned char inver, unsigned char stipple, char offset, char leftchar, char usebg = 0, int maxinv = 32); // Used for scrolling "Exit" text downwards...
void OsdClear(void);
void OsdEnable(unsigned char mode);
void InfoEnable(int x, int y, int width, int height);

View File

@@ -500,7 +500,6 @@ void user_io_init(const char *path)
user_io_8bit_set_status(UIO_STATUS_RESET, UIO_STATUS_RESET);
}
MiSTer_ini_parse();
parse_video_mode();
FileLoadConfig("Volume.dat", &vol_att, 1);
vol_att &= 0x1F;