mirror of
https://github.com/joel16/VitaShell.git
synced 2024-11-23 11:49:40 +00:00
Added config parser. Changed language file format.
This commit is contained in:
parent
608102ad51
commit
b20212177d
4
Makefile
4
Makefile
@ -1,13 +1,13 @@
|
||||
TITLE_ID = VITASHELL
|
||||
TARGET = VitaShell
|
||||
OBJS = main.o init.o io_process.o package_installer.o archive.o photo.o file.o text.o hex.o \
|
||||
uncommon_dialog.o message_dialog.o ime_dialog.o language.o utils.o sha1.o \
|
||||
uncommon_dialog.o message_dialog.o ime_dialog.o config.o language.o utils.o sha1.o \
|
||||
audioplayer.o minizip/unzip.o minizip/ioapi.o
|
||||
|
||||
RESOURCES_PNG = resources/ftp.png resources/battery.png resources/battery_bar_green.png resources/battery_bar_red.png \
|
||||
resources/headphone.png resources/audio_previous.png resources/audio_pause.png resources/audio_play.png \
|
||||
resources/audio_next.png
|
||||
RESOURCES_TXT = resources/english_us_translation.txt
|
||||
RESOURCES_TXT = resources/english_us.txt
|
||||
OBJS += $(RESOURCES_PNG:.png=.o) $(RESOURCES_TXT:.txt=.o)
|
||||
|
||||
LIBS = -lftpvita -lvita2d -lpng -ljpeg -lz -lm -lc \
|
||||
|
225
config.c
Normal file
225
config.c
Normal file
@ -0,0 +1,225 @@
|
||||
/*
|
||||
VitaShell
|
||||
Copyright (C) 2015-2016, TheFloW
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "main.h"
|
||||
#include "config.h"
|
||||
|
||||
void trim(char *str) {
|
||||
int len = strlen(str);
|
||||
int i;
|
||||
|
||||
for (i = len - 1; i >= 0; i--) {
|
||||
if (str[i] == 0x20 || str[i] == '\t') {
|
||||
str[i] = 0;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int GetLine(char *buf, int size, char *str) {
|
||||
uint8_t ch = 0;
|
||||
int n = 0;
|
||||
int i = 0;
|
||||
uint8_t *s = (uint8_t *)str;
|
||||
|
||||
while (1) {
|
||||
if (i >= size)
|
||||
break;
|
||||
|
||||
ch = ((uint8_t *)buf)[i];
|
||||
|
||||
if (ch < 0x20 && ch != '\t') {
|
||||
if (n != 0) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
*str++ = ch;
|
||||
n++;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
trim((char *)s);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
int getDecimal(char *str) {
|
||||
return strtol(str, NULL, 0);
|
||||
}
|
||||
|
||||
int getHexdecimal(char *str) {
|
||||
return strtoul(str, NULL, 16);
|
||||
}
|
||||
|
||||
int getBoolean(char *str) {
|
||||
if (strcasecmp(str, "false") == 0 || strcasecmp(str, "off") == 0 || strcasecmp(str, "no") == 0)
|
||||
return 0;
|
||||
|
||||
if (strcasecmp(str, "true") == 0 || strcasecmp(str, "on") == 0 || strcasecmp(str, "yes") == 0)
|
||||
return 1;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *getString(char *str) {
|
||||
if (str[0] != '"')
|
||||
return NULL;
|
||||
|
||||
char *p = strchr(str + 1, '"');
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
int len = p - (str + 1);
|
||||
|
||||
char *out = malloc(len + 1);
|
||||
strncpy(out, str + 1, len);
|
||||
out[len] = '\0';
|
||||
|
||||
int i;
|
||||
for (i = 0; i < strlen(out); i++) {
|
||||
if (out[i] == '\\')
|
||||
out[i] = '\n';
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
int readEntry(char *line, ConfigEntry *entries, int n_entries) {
|
||||
// Trim at beginning
|
||||
while (*line == ' ' || *line == '\t')
|
||||
line++;
|
||||
|
||||
// Ignore comments #1
|
||||
if (line[0] == '#') {
|
||||
// debugPrintf("IGNORE %s\n", line);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Ignore comments #2
|
||||
char *p = strchr(line, '#');
|
||||
if (p) {
|
||||
// debugPrintf("IGNORE %s\n", p);
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
// Get token
|
||||
p = strchr(line, '=');
|
||||
if (!p)
|
||||
return -1;
|
||||
|
||||
// Name of entry
|
||||
char name[MAX_NAME_LENGTH];
|
||||
strncpy(name, line, p - line);
|
||||
name[p - line] = '\0';
|
||||
|
||||
trim(name);
|
||||
|
||||
// debugPrintf("NAME: %s\n", name);
|
||||
|
||||
// String of entry
|
||||
char *string = p + 1;
|
||||
|
||||
// Trim at beginning
|
||||
while (*string == ' ' || *string == '\t')
|
||||
string++;
|
||||
|
||||
// Trim at end
|
||||
trim(string);
|
||||
|
||||
// debugPrintf("STRING: %s\n", string);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < n_entries; i++) {
|
||||
if (strcasecmp(name, entries[i].name) == 0) {
|
||||
switch (entries[i].type) {
|
||||
case CONFIG_TYPE_DECIMAL:
|
||||
*(uint32_t *)entries[i].value = getDecimal(string);
|
||||
// debugPrintf("VALUE DECIMAL: %d\n", *(uint32_t *)entries[i].value);
|
||||
break;
|
||||
|
||||
case CONFIG_TYPE_HEXDECIMAL:
|
||||
*(uint32_t *)entries[i].value = getHexdecimal(string);
|
||||
// debugPrintf("VALUE HEXDECIMAL: 0x%X\n", *(uint32_t *)entries[i].value);
|
||||
break;
|
||||
|
||||
case CONFIG_TYPE_BOOLEAN:
|
||||
*(uint32_t *)entries[i].value = getBoolean(string);
|
||||
// debugPrintf("VALUE BOOLEAN: %d\n", *(uint32_t *)entries[i].value);
|
||||
break;
|
||||
|
||||
case CONFIG_TYPE_STRING:
|
||||
*(uint32_t *)entries[i].value = (uint32_t)getString(string);
|
||||
// debugPrintf("VALUE STRING: %s\n", *(uint32_t *)entries[i].value);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int readConfigBuffer(void *buffer, int size, ConfigEntry *entries, int n_entries) {
|
||||
int res = 0;
|
||||
char line[MAX_LINE_LENGTH];
|
||||
char *p = buffer;
|
||||
|
||||
// Skip UTF-8 bom
|
||||
uint32_t bom = 0xBFBBEF;
|
||||
if (memcmp(p, &bom, 3) == 0) {
|
||||
p += 3;
|
||||
size -= 3;
|
||||
}
|
||||
|
||||
do {
|
||||
memset(line, 0, sizeof(line));
|
||||
res = GetLine(p, size, line);
|
||||
|
||||
if (res > 0) {
|
||||
readEntry(line, entries, n_entries);
|
||||
size -= res;
|
||||
p += res;
|
||||
}
|
||||
} while (res > 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int readConfig(char *path, ConfigEntry *entries, int n_entries) {
|
||||
SceUID fd = sceIoOpen(path, SCE_O_RDONLY, 0);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
int size = sceIoLseek32(fd, 0, SCE_SEEK_END);
|
||||
sceIoLseek32(fd, 0, SCE_SEEK_SET);
|
||||
|
||||
void *buffer = malloc(size);
|
||||
sceIoRead(fd, buffer, size);
|
||||
sceIoClose(fd);
|
||||
|
||||
readConfigBuffer(buffer, size, entries, n_entries);
|
||||
|
||||
free(buffer);
|
||||
|
||||
return 0;
|
||||
}
|
42
config.h
Normal file
42
config.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
VitaShell
|
||||
Copyright (C) 2015-2016, TheFloW
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __CONFIG_H__
|
||||
#define __CONFIG_H__
|
||||
|
||||
#define MAX_NAME_LENGTH 128
|
||||
#define MAX_STRING_LENGTH 512
|
||||
#define MAX_LINE_LENGTH 1024
|
||||
|
||||
enum ConfigTypes {
|
||||
CONFIG_TYPE_DECIMAL,
|
||||
CONFIG_TYPE_HEXDECIMAL,
|
||||
CONFIG_TYPE_BOOLEAN,
|
||||
CONFIG_TYPE_STRING,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
int type;
|
||||
void *value;
|
||||
} ConfigEntry;
|
||||
|
||||
int readConfigBuffer(void *buffer, int size, ConfigEntry *entries, int n_entries);
|
||||
int readConfig(char *path, ConfigEntry *entries, int n_entries);
|
||||
|
||||
#endif
|
135
language.c
135
language.c
@ -17,10 +17,11 @@
|
||||
*/
|
||||
|
||||
#include "main.h"
|
||||
#include "config.h"
|
||||
#include "language.h"
|
||||
|
||||
extern unsigned char _binary_resources_english_us_translation_txt_start;
|
||||
extern unsigned char _binary_resources_english_us_translation_txt_size;
|
||||
extern unsigned char _binary_resources_english_us_txt_start;
|
||||
extern unsigned char _binary_resources_english_us_txt_size;
|
||||
|
||||
static char *lang[] ={
|
||||
"japanese",
|
||||
@ -46,49 +47,6 @@ static char *lang[] ={
|
||||
|
||||
char *language_container[LANGUAGE_CONTRAINER_SIZE];
|
||||
|
||||
void trim(char *str) {
|
||||
int len = strlen(str);
|
||||
int i;
|
||||
|
||||
for (i = len - 1; i >= 0; i--) {
|
||||
if (str[i] == 0x20 || str[i] == '\t') {
|
||||
str[i] = 0;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int GetLine(char *buf, int size, char *str) {
|
||||
unsigned char ch = 0;
|
||||
int n = 0;
|
||||
int i = 0;
|
||||
unsigned char *s = (unsigned char *)str;
|
||||
|
||||
while (1) {
|
||||
if (i >= size)
|
||||
break;
|
||||
|
||||
ch = ((unsigned char *)buf)[i];
|
||||
|
||||
if (ch < 0x20 && ch != '\t') {
|
||||
if (n != 0) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
*str++ = ch;
|
||||
n++;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
trim((char *)s);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void freeLanguageContainer() {
|
||||
int i;
|
||||
for (i = 0; i < LANGUAGE_CONTRAINER_SIZE; i++) {
|
||||
@ -99,57 +57,50 @@ void freeLanguageContainer() {
|
||||
}
|
||||
}
|
||||
|
||||
int loadLanguageContainer(void *buffer, int size) {
|
||||
int res;
|
||||
int i = 0;
|
||||
char *p = buffer;
|
||||
char line[512];
|
||||
|
||||
freeLanguageContainer();
|
||||
|
||||
do {
|
||||
memset(line, 0, sizeof(line));
|
||||
|
||||
if ((res = GetLine(p, size, line)) > 0) {
|
||||
int j;
|
||||
for (j = 0; j < strlen(line); j++) {
|
||||
if (line[j] == '\\')
|
||||
line[j] = '\n';
|
||||
}
|
||||
|
||||
language_container[i] = malloc(strlen(line) + 1);
|
||||
strcpy(language_container[i], line);
|
||||
i++;
|
||||
}
|
||||
|
||||
size -= res;
|
||||
p += res;
|
||||
} while (res > 0 && i < LANGUAGE_CONTRAINER_SIZE);
|
||||
|
||||
return i == LANGUAGE_CONTRAINER_SIZE;
|
||||
}
|
||||
|
||||
void loadLanguage(int id) {
|
||||
int loaded = 0;
|
||||
freeLanguageContainer();
|
||||
|
||||
#define LANGUAGE_ENTRY(name) { #name, CONFIG_TYPE_STRING, &language_container[name] }
|
||||
ConfigEntry language_entries[] = {
|
||||
LANGUAGE_ENTRY(ERROR),
|
||||
LANGUAGE_ENTRY(OK),
|
||||
LANGUAGE_ENTRY(YES),
|
||||
LANGUAGE_ENTRY(NO),
|
||||
LANGUAGE_ENTRY(CANCEL),
|
||||
LANGUAGE_ENTRY(OFFSET),
|
||||
LANGUAGE_ENTRY(MARK_ALL),
|
||||
LANGUAGE_ENTRY(UNMARK_ALL),
|
||||
LANGUAGE_ENTRY(MOVE),
|
||||
LANGUAGE_ENTRY(COPY),
|
||||
LANGUAGE_ENTRY(PASTE),
|
||||
LANGUAGE_ENTRY(DELETE),
|
||||
LANGUAGE_ENTRY(RENAME),
|
||||
LANGUAGE_ENTRY(NEW_FOLDER),
|
||||
LANGUAGE_ENTRY(FOLDER),
|
||||
LANGUAGE_ENTRY(COPIED_FILE),
|
||||
LANGUAGE_ENTRY(COPIED_FOLDER),
|
||||
LANGUAGE_ENTRY(COPIED_FILES_FOLDERS),
|
||||
LANGUAGE_ENTRY(MOVING),
|
||||
LANGUAGE_ENTRY(COPYING),
|
||||
LANGUAGE_ENTRY(DELETING),
|
||||
LANGUAGE_ENTRY(INSTALLING),
|
||||
LANGUAGE_ENTRY(DELETE_FILE_QUESTION),
|
||||
LANGUAGE_ENTRY(DELETE_FOLDER_QUESTION),
|
||||
LANGUAGE_ENTRY(DELETE_FILES_FOLDERS_QUESTION),
|
||||
LANGUAGE_ENTRY(INSTALL_QUESTION),
|
||||
LANGUAGE_ENTRY(WIFI_ERROR),
|
||||
LANGUAGE_ENTRY(FTP_SERVER),
|
||||
};
|
||||
|
||||
int loaded = -1;
|
||||
|
||||
if (id >= 0 && id < (sizeof(lang) / sizeof(char *))) {
|
||||
char path[128];
|
||||
sprintf(path, "cache0:VitaShell/%s_translation.txt", lang[id]);
|
||||
|
||||
SceUID fd = sceIoOpen(path, SCE_O_RDONLY, 0);
|
||||
if (fd >= 0) {
|
||||
int size = sceIoLseek(fd, 0, SCE_SEEK_END);
|
||||
sceIoLseek(fd, 0, SCE_SEEK_SET);
|
||||
|
||||
void *buffer = malloc(size);
|
||||
sceIoRead(fd, buffer, size);
|
||||
|
||||
loaded = loadLanguageContainer(buffer, size);
|
||||
|
||||
free(buffer);
|
||||
}
|
||||
sprintf(path, "ux0:VitaShell/language/%s.txt", lang[id]);
|
||||
loaded = readConfig(path, language_entries, sizeof(language_entries) / sizeof(ConfigEntry));
|
||||
}
|
||||
|
||||
if (!loaded)
|
||||
loadLanguageContainer(&_binary_resources_english_us_translation_txt_start, (int)&_binary_resources_english_us_translation_txt_size);
|
||||
}
|
||||
if (loaded < 0)
|
||||
readConfigBuffer(&_binary_resources_english_us_txt_start, (int)&_binary_resources_english_us_txt_size, language_entries, sizeof(language_entries) / sizeof(ConfigEntry));
|
||||
}
|
@ -24,20 +24,6 @@ static int message_dialog_type = -1;
|
||||
|
||||
static char message_string[1024];
|
||||
|
||||
void ansi_to_utf8(uint8_t *src, uint8_t *dst) {
|
||||
int i;
|
||||
for (i = 0; src[i]; i++) {
|
||||
if (src[i] < 0x80) {
|
||||
*(dst++) = src[i];
|
||||
} else {
|
||||
*(dst++) = 0xC0 | (src[i] & 0xC0) >> 6;
|
||||
*(dst++) = 0x80 | (src[i] & 0x3F);
|
||||
}
|
||||
}
|
||||
|
||||
*dst = '\0';
|
||||
}
|
||||
|
||||
int initMessageDialog(int type, char *msg, ...) {
|
||||
if (message_dialog_running)
|
||||
return -1;
|
||||
@ -49,7 +35,7 @@ int initMessageDialog(int type, char *msg, ...) {
|
||||
vsprintf(string, msg, list);
|
||||
va_end(list);
|
||||
|
||||
ansi_to_utf8((uint8_t *)string, (uint8_t *)message_string);
|
||||
strcpy(message_string, string);
|
||||
|
||||
SceMsgDialogParam param;
|
||||
sceMsgDialogParamInit(¶m);
|
||||
|
30
resources/english_us.txt
Normal file
30
resources/english_us.txt
Normal file
@ -0,0 +1,30 @@
|
||||
# VitaShell language config file
|
||||
|
||||
ERROR = "Error 0x%08X."
|
||||
OK = "OK"
|
||||
YES = "Yes"
|
||||
NO = "No"
|
||||
CANCEL = "Cancel"
|
||||
OFFSET = "Offset"
|
||||
MARK_ALL = "Mark all"
|
||||
UNMARK_ALL = "Unmark all"
|
||||
MOVE = "Move"
|
||||
COPY = "Copy"
|
||||
PASTE = "Paste"
|
||||
DELETE = "Delete"
|
||||
RENAME = "Rename"
|
||||
NEW_FOLDER = "New folder"
|
||||
FOLDER = "Folder"
|
||||
COPIED_FILE = "Copied %d file."
|
||||
COPIED_FOLDER = "Copied %d folder."
|
||||
COPIED_FILES_FOLDERS = "Copied %d files/folders."
|
||||
MOVING = "Moving..."
|
||||
COPYING = "Copying..."
|
||||
DELETING = "Deleting..."
|
||||
INSTALLING = "Installing..."
|
||||
DELETE_FILE_QUESTION = "Are you sure you want to delete this file?"
|
||||
DELETE_FOLDER_QUESTION = "Are you sure you want to delete this folder?"
|
||||
DELETE_FILES_FOLDERS_QUESTION = "Are you sure you want to delete these files/folders?"
|
||||
INSTALL_QUESTION = "Do you want to install this package?"
|
||||
WIFI_ERROR = "You must use Wi-Fi to do this."
|
||||
FTP_SERVER = "FTP server is now running at\ftp://%s:%i\\Press 'OK' to keep it in background.\Press 'Cancel' to disconnect."
|
@ -1,28 +0,0 @@
|
||||
Error 0x%08X.
|
||||
OK
|
||||
Yes
|
||||
No
|
||||
Cancel
|
||||
Offset
|
||||
Mark all
|
||||
Unmark all
|
||||
Move
|
||||
Copy
|
||||
Paste
|
||||
Delete
|
||||
Rename
|
||||
New folder
|
||||
Folder
|
||||
Copied %d file.
|
||||
Copied %d folder.
|
||||
Copied %d files/folders.
|
||||
Moving...
|
||||
Copying...
|
||||
Deleting...
|
||||
Installing...
|
||||
Are you sure you want to delete this file?
|
||||
Are you sure you want to delete this folder?
|
||||
Are you sure you want to delete these files/folders?
|
||||
Do you want to install this package?
|
||||
You must use Wi-Fi to do this.
|
||||
FTP server is now running at\ftp://%s:%i\\Press 'OK' to keep it in background.\Press 'Cancel' to disconnect.
|
Loading…
Reference in New Issue
Block a user