cr+lf -> lf

This commit is contained in:
TheFloW 2018-08-27 10:05:53 +02:00
parent 57d1f62368
commit dd98fa3f97
29 changed files with 5509 additions and 5509 deletions

View File

@ -1,479 +1,479 @@
/*
VitaShell
Copyright (C) 2015-2018, 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 "archive.h"
#include "audioplayer.h"
#include "file.h"
#include "theme.h"
#include "language.h"
#include "utils.h"
#include "audio/lrcparse.h"
#include "audio/player.h"
static struct fileInfo *fileinfo = NULL;
static vita2d_texture *tex = NULL;
/**
* Calculate the x-axis position if draw text in center
* @param[in] sx start x-axis
* @param[in] ex end x-axis
* @param[in] text
* @return x-axis position
*/
float getCenteroffset(float sx,float ex,char* string){
if(!string||(string[0] == '\0'))
return sx;
float drawWidthSpace = ex - sx;
uint16_t stringWidth = pgf_text_width(string);
return stringWidth > drawWidthSpace ? sx : sx + (drawWidthSpace - stringWidth) / 2 ;
}
/**
* Try to load lrc file from audio path
* @param[in] path audio path
* @param[out] totalms set 0
* @param[out] lyricsIndex set 0
* @return Lyrics pointer , NULL is fail
*/
Lyrics* loadLyricsFile(const char *path, uint64_t *totalms, uint32_t *lyricsIndex){
size_t pathlength = strlen(path);
*totalms = *lyricsIndex = 0;
while(pathlength > 0){
if(path[pathlength] == '.'){
break;
}
pathlength--;
}
if(pathlength < 0)
return NULL;
char lrcPath[pathlength + 5 * sizeof(char)];
memccpy(lrcPath,path,sizeof(char),pathlength);//copy path string except filename extension
strcpy(lrcPath+pathlength,".lrc");
return lrcParseLoadWithFile(lrcPath);
}
/**
* Draw the lyrics from the designated area
* @param[in] lyrics Lyrics pointer
* @param[in] cur_time_string Playing time string
* @param[out] totalms Playing time (millisecond)
* @param[out] lyricsIndex Index of lyrics
* @param[in] lrcSpaceX Designated area starting point x
* @param[in] lrcSpaceX Designated area starting point y
*/
void drawLyrics(Lyrics* lyrics, const char *cur_time_string, uint64_t* totalms, uint32_t* lyricsIndex, float lrcSpaceX, float lrcSpaceY){
if(!lyrics)
return;
char hourString[3];
char minuteString[3];
char secondString[3];
strncpy(hourString,cur_time_string,sizeof(hourString));
strncpy(minuteString,cur_time_string + 3,sizeof(minuteString));
strncpy(secondString,cur_time_string + 6,sizeof(secondString));
*totalms = (((atoi(hourString) * 60) + atoi(minuteString)) * 60 + atoi(secondString)) * 1000;
uint32_t m_index = *lyricsIndex >= 1 ? (*lyricsIndex - 1) : *lyricsIndex;
float right_max_x = SCREEN_WIDTH - SHELL_MARGIN_X;
//draw current lyrics
pgf_draw_textf(getCenteroffset(lrcSpaceX,right_max_x,lyrics->lrclines[m_index].word),lrcSpaceY, AUDIO_INFO_ASSIGN, "%s",lyrics->lrclines[m_index].word);
int i;
for (i = 1;i < 7; i++){//draw 6 line lyrics for preview
int n_index = m_index + i;
if(n_index + 1 > lyrics->lyricscount)
break;
pgf_draw_textf(getCenteroffset(lrcSpaceX,right_max_x,lyrics->lrclines[n_index].word),lrcSpaceY + FONT_Y_SPACE * i, AUDIO_INFO, "%s",lyrics->lrclines[n_index].word);
}
if (*totalms >= (lyrics->lrclines[*lyricsIndex].totalms) ){
*lyricsIndex = *lyricsIndex + 1;
} else if (( *lyricsIndex >= 1 ) & ( *totalms < (lyrics->lrclines[*lyricsIndex - 1].totalms ))) {
*lyricsIndex = *lyricsIndex - 1;
}
}
void shortenString(char *out, const char *in, int width) {
strcpy(out, in);
int i;
for (i = strlen(out)-1; i > 0; i--) {
if (pgf_text_width(out) < width)
break;
out[i] = '\0';
}
}
vita2d_texture *getAlternativeCoverImage(const char *file) {
char path[MAX_PATH_LENGTH];
char *p = strrchr(file, '/');
if (p) {
*p = '\0';
snprintf(path, MAX_PATH_LENGTH - 1, "%s/cover.jpg", file);
if (checkFileExist(path)) {
*p = '/';
return vita2d_load_JPEG_file(path);
}
snprintf(path, MAX_PATH_LENGTH - 1, "%s/folder.jpg", file);
if (checkFileExist(path)) {
*p = '/';
return vita2d_load_JPEG_file(path);
}
*p = '/';
}
return NULL;
}
void getAudioInfo(const char *file) {
char *buffer = NULL;
fileinfo = getInfoFunct();
if (tex) {
vita2d_wait_rendering_done();
vita2d_free_texture(tex);
tex = NULL;
}
switch (fileinfo->encapsulatedPictureType) {
case JPEG_IMAGE:
case PNG_IMAGE:
{
SceUID fd = sceIoOpen(file, SCE_O_RDONLY, 0);
if (fd >= 0) {
char *buffer = malloc(fileinfo->encapsulatedPictureLength);
if (buffer) {
sceIoLseek32(fd, fileinfo->encapsulatedPictureOffset, SCE_SEEK_SET);
sceIoRead(fd, buffer, fileinfo->encapsulatedPictureLength);
sceIoClose(fd);
if (fileinfo->encapsulatedPictureType == JPEG_IMAGE)
tex = vita2d_load_JPEG_buffer(buffer, fileinfo->encapsulatedPictureLength);
if (fileinfo->encapsulatedPictureType == PNG_IMAGE)
tex = vita2d_load_PNG_buffer(buffer);
if (tex)
vita2d_texture_set_filters(tex, SCE_GXM_TEXTURE_FILTER_LINEAR, SCE_GXM_TEXTURE_FILTER_LINEAR);
free(buffer);
}
break;
}
}
}
if (!tex)
tex = getAlternativeCoverImage(file);
}
int audioPlayer(const char *file, int type, FileList *list, FileListEntry *entry, int *base_pos, int *rel_pos) {
static int speed_list[] = { -7, -3, -1, 0, 1, 3, 7 };
#define N_SPEED (sizeof(speed_list) / sizeof(int))
sceAppMgrAcquireBgmPort();
powerLock();
setAudioFunctions(type);
initFunct(0);
loadFunct((char *)file);
playFunct();
getAudioInfo(file);
uint64_t totalms = 0;
uint32_t lyricsIndex = 0;
Lyrics* lyrics = loadLyricsFile(file,&totalms,&lyricsIndex);
int scroll_count = 0;
float scroll_x = 0.0f;
while (1) {
char cur_time_string[12];
getTimeStringFunct(cur_time_string);
readPad();
// Cancel
if (pressed_pad[PAD_CANCEL]) {
break;
}
// Display off
if (pressed_pad[PAD_TRIANGLE]) {
scePowerRequestDisplayOff();
}
// Toggle play/pause
if (pressed_pad[PAD_ENTER]) {
if (isPlayingFunct() && getPlayingSpeedFunct() == 0) {
pauseFunct();
} else {
setPlayingSpeedFunct(0);
playFunct();
}
}
if (pressed_pad[PAD_LEFT] || pressed_pad[PAD_RIGHT]) {
int speed = getPlayingSpeedFunct();
if (pressed_pad[PAD_LEFT]) {
int i;
for (i = 0; i < N_SPEED; i++) {
if (speed_list[i] == speed) {
if (i > 0)
speed = speed_list[i-1];
break;
}
}
}
if (pressed_pad[PAD_RIGHT]) {
int i;
for (i = 0; i < N_SPEED; i++) {
if (speed_list[i] == speed) {
if (i < N_SPEED - 1)
speed = speed_list[i + 1];
break;
}
}
}
setPlayingSpeedFunct(speed);
playFunct();
}
// Previous/next song.
if (getPercentageFunct() == 100.0f || endOfStreamFunct() ||
pressed_pad[PAD_LTRIGGER] || pressed_pad[PAD_RTRIGGER]) {
int previous = pressed_pad[PAD_LTRIGGER];
if (previous && strcmp(cur_time_string, "00:00:00") != 0) {
lrcParseClose(lyrics);
endFunct();
initFunct(0);
loadFunct((char *)file);
playFunct();
getAudioInfo(file);
lyrics = loadLyricsFile(file,&totalms,&lyricsIndex);
} else {
int available = 0;
int old_base_pos = *base_pos;
int old_rel_pos = *rel_pos;
FileListEntry *old_entry = entry;
if (getPercentageFunct() == 100.0f && !endOfStreamFunct())
previous = 1;
if (endOfStreamFunct())
previous = 0;
while (previous ? entry->previous : entry->next) {
entry = previous ? entry->previous : entry->next;
if (previous) {
if (*rel_pos > 0) {
(*rel_pos)--;
} else if (*base_pos > 0) {
(*base_pos)--;
}
} else {
if ((*rel_pos + 1) < list->length) {
if ((*rel_pos + 1) < MAX_POSITION) {
(*rel_pos)++;
} else if ((*base_pos+*rel_pos + 1) < list->length) {
(*base_pos)++;
}
}
}
if (!entry->is_folder) {
char path[MAX_PATH_LENGTH];
snprintf(path, MAX_PATH_LENGTH - 1, "%s%s", list->path, entry->name);
int type = getFileType(path);
if (type == FILE_TYPE_MP3 || type == FILE_TYPE_OGG) {
file = path;
lrcParseClose(lyrics);
endFunct();
setAudioFunctions(type);
initFunct(0);
loadFunct((char *)file);
playFunct();
getAudioInfo(file);
lyrics = loadLyricsFile(file,&totalms,&lyricsIndex);
available = 1;
break;
}
}
}
if (!available) {
*base_pos = old_base_pos;
*rel_pos = old_rel_pos;
entry = old_entry;
break;
}
}
}
// Start drawing
startDrawing(bg_audio_image);
// Draw shell info
drawShellInfo(file);
float cover_size = MAX_ENTRIES * FONT_Y_SPACE;
// Cover
if (tex) {
vita2d_draw_texture_scale(tex, SHELL_MARGIN_X, START_Y, cover_size / vita2d_texture_get_width(tex), cover_size / vita2d_texture_get_height(tex));
} else {
vita2d_draw_texture(cover_image, SHELL_MARGIN_X, START_Y);
}
// Info
float x = 2.0f * SHELL_MARGIN_X + cover_size;
pgf_draw_text(x, START_Y + (0 * FONT_Y_SPACE), AUDIO_INFO_ASSIGN, language_container[TITLE]);
pgf_draw_text(x, START_Y + (1 * FONT_Y_SPACE), AUDIO_INFO_ASSIGN, language_container[ALBUM]);
pgf_draw_text(x, START_Y + (2 * FONT_Y_SPACE), AUDIO_INFO_ASSIGN, language_container[ARTIST]);
pgf_draw_text(x, START_Y + (3 * FONT_Y_SPACE), AUDIO_INFO_ASSIGN, language_container[GENRE]);
pgf_draw_text(x, START_Y + (4 * FONT_Y_SPACE), AUDIO_INFO_ASSIGN, language_container[YEAR]);
x += 120.0f;
vita2d_enable_clipping();
vita2d_set_clip_rectangle(x + 1.0f, START_Y, x + 1.0f + 390.0f, START_Y + (5 * FONT_Y_SPACE));
float title_x = x;
uint32_t color = AUDIO_INFO;
int width = (int)pgf_text_width(fileinfo->title);
if (width >= 390.0f) {
if (scroll_count < 60) {
scroll_x = title_x;
} else if (scroll_count < width + 90) {
scroll_x--;
} else if (scroll_count < width + 120) {
color = (color & 0x00FFFFFF) | ((((color >> 24) * (scroll_count - width - 90)) / 30) << 24); // fade-in in 0.5s
scroll_x = title_x;
} else {
scroll_count = 0;
}
scroll_count++;
title_x = scroll_x;
}
pgf_draw_text(title_x, START_Y + (0 * FONT_Y_SPACE), color, fileinfo->title[0] == '\0' ? "-" : fileinfo->title);
pgf_draw_text(x, START_Y + (1 * FONT_Y_SPACE), AUDIO_INFO, fileinfo->album[0] == '\0' ? "-" : fileinfo->album);
pgf_draw_text(x, START_Y + (2 * FONT_Y_SPACE), AUDIO_INFO, fileinfo->artist[0] == '\0' ? "-" : fileinfo->artist);
pgf_draw_text(x, START_Y + (3 * FONT_Y_SPACE), AUDIO_INFO, fileinfo->genre[0] == '\0' ? "-" : fileinfo->genre);
pgf_draw_text(x, START_Y + (4 * FONT_Y_SPACE), AUDIO_INFO, fileinfo->year[0] == '\0' ? "-" : fileinfo->year);
vita2d_disable_clipping();
x -= 120.0f;
drawLyrics(lyrics, cur_time_string, &totalms, &lyricsIndex, x, START_Y + (6 * FONT_Y_SPACE));
float y = SCREEN_HEIGHT - 6.0f * SHELL_MARGIN_Y;
// Icon
vita2d_texture *icon = NULL;
if (getPlayingSpeedFunct() != 0) {
if (getPlayingSpeedFunct() < 0) {
icon = fastrewind_image;
} else {
icon = fastforward_image;
}
pgf_draw_textf(x + 45.0f, y, AUDIO_SPEED, "%dx", abs(getPlayingSpeedFunct() + (getPlayingSpeedFunct() < 0 ? -1 : 1)));
} else {
if (isPlayingFunct()) {
icon = pause_image;
} else {
icon = play_image;
}
}
vita2d_draw_texture(icon, x, y + 3.0f);
// Time
char string[32];
sprintf(string, "%s / %s", cur_time_string, fileinfo->strLength);
float time_x = ALIGN_RIGHT(SCREEN_WIDTH-SHELL_MARGIN_X, pgf_text_width(string));
int w = pgf_draw_text(time_x, y, AUDIO_TIME_CURRENT, cur_time_string);
pgf_draw_text(time_x + (float)w, y, AUDIO_TIME_SLASH, " /");
pgf_draw_text(ALIGN_RIGHT(SCREEN_WIDTH-SHELL_MARGIN_X, pgf_text_width(fileinfo->strLength)), y, AUDIO_TIME_TOTAL, fileinfo->strLength);
float length = SCREEN_WIDTH - 3.0f * SHELL_MARGIN_X - cover_size;
vita2d_draw_rectangle(x, (y) + FONT_Y_SPACE + 10.0f, length, 8, AUDIO_TIME_BAR_BG);
vita2d_draw_rectangle(x, (y) + FONT_Y_SPACE + 10.0f, getPercentageFunct() * length / 100.0f, 8, AUDIO_TIME_BAR);
// End drawing
endDrawing();
}
if (tex) {
vita2d_wait_rendering_done();
vita2d_free_texture(tex);
tex = NULL;
}
lrcParseClose(lyrics);
endFunct();
powerUnlock();
sceAppMgrReleaseBgmPort();
return 0;
}
/*
VitaShell
Copyright (C) 2015-2018, 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 "archive.h"
#include "audioplayer.h"
#include "file.h"
#include "theme.h"
#include "language.h"
#include "utils.h"
#include "audio/lrcparse.h"
#include "audio/player.h"
static struct fileInfo *fileinfo = NULL;
static vita2d_texture *tex = NULL;
/**
* Calculate the x-axis position if draw text in center
* @param[in] sx start x-axis
* @param[in] ex end x-axis
* @param[in] text
* @return x-axis position
*/
float getCenteroffset(float sx,float ex,char* string){
if(!string||(string[0] == '\0'))
return sx;
float drawWidthSpace = ex - sx;
uint16_t stringWidth = pgf_text_width(string);
return stringWidth > drawWidthSpace ? sx : sx + (drawWidthSpace - stringWidth) / 2 ;
}
/**
* Try to load lrc file from audio path
* @param[in] path audio path
* @param[out] totalms set 0
* @param[out] lyricsIndex set 0
* @return Lyrics pointer , NULL is fail
*/
Lyrics* loadLyricsFile(const char *path, uint64_t *totalms, uint32_t *lyricsIndex){
size_t pathlength = strlen(path);
*totalms = *lyricsIndex = 0;
while(pathlength > 0){
if(path[pathlength] == '.'){
break;
}
pathlength--;
}
if(pathlength < 0)
return NULL;
char lrcPath[pathlength + 5 * sizeof(char)];
memccpy(lrcPath,path,sizeof(char),pathlength);//copy path string except filename extension
strcpy(lrcPath+pathlength,".lrc");
return lrcParseLoadWithFile(lrcPath);
}
/**
* Draw the lyrics from the designated area
* @param[in] lyrics Lyrics pointer
* @param[in] cur_time_string Playing time string
* @param[out] totalms Playing time (millisecond)
* @param[out] lyricsIndex Index of lyrics
* @param[in] lrcSpaceX Designated area starting point x
* @param[in] lrcSpaceX Designated area starting point y
*/
void drawLyrics(Lyrics* lyrics, const char *cur_time_string, uint64_t* totalms, uint32_t* lyricsIndex, float lrcSpaceX, float lrcSpaceY){
if(!lyrics)
return;
char hourString[3];
char minuteString[3];
char secondString[3];
strncpy(hourString,cur_time_string,sizeof(hourString));
strncpy(minuteString,cur_time_string + 3,sizeof(minuteString));
strncpy(secondString,cur_time_string + 6,sizeof(secondString));
*totalms = (((atoi(hourString) * 60) + atoi(minuteString)) * 60 + atoi(secondString)) * 1000;
uint32_t m_index = *lyricsIndex >= 1 ? (*lyricsIndex - 1) : *lyricsIndex;
float right_max_x = SCREEN_WIDTH - SHELL_MARGIN_X;
//draw current lyrics
pgf_draw_textf(getCenteroffset(lrcSpaceX,right_max_x,lyrics->lrclines[m_index].word),lrcSpaceY, AUDIO_INFO_ASSIGN, "%s",lyrics->lrclines[m_index].word);
int i;
for (i = 1;i < 7; i++){//draw 6 line lyrics for preview
int n_index = m_index + i;
if(n_index + 1 > lyrics->lyricscount)
break;
pgf_draw_textf(getCenteroffset(lrcSpaceX,right_max_x,lyrics->lrclines[n_index].word),lrcSpaceY + FONT_Y_SPACE * i, AUDIO_INFO, "%s",lyrics->lrclines[n_index].word);
}
if (*totalms >= (lyrics->lrclines[*lyricsIndex].totalms) ){
*lyricsIndex = *lyricsIndex + 1;
} else if (( *lyricsIndex >= 1 ) & ( *totalms < (lyrics->lrclines[*lyricsIndex - 1].totalms ))) {
*lyricsIndex = *lyricsIndex - 1;
}
}
void shortenString(char *out, const char *in, int width) {
strcpy(out, in);
int i;
for (i = strlen(out)-1; i > 0; i--) {
if (pgf_text_width(out) < width)
break;
out[i] = '\0';
}
}
vita2d_texture *getAlternativeCoverImage(const char *file) {
char path[MAX_PATH_LENGTH];
char *p = strrchr(file, '/');
if (p) {
*p = '\0';
snprintf(path, MAX_PATH_LENGTH - 1, "%s/cover.jpg", file);
if (checkFileExist(path)) {
*p = '/';
return vita2d_load_JPEG_file(path);
}
snprintf(path, MAX_PATH_LENGTH - 1, "%s/folder.jpg", file);
if (checkFileExist(path)) {
*p = '/';
return vita2d_load_JPEG_file(path);
}
*p = '/';
}
return NULL;
}
void getAudioInfo(const char *file) {
char *buffer = NULL;
fileinfo = getInfoFunct();
if (tex) {
vita2d_wait_rendering_done();
vita2d_free_texture(tex);
tex = NULL;
}
switch (fileinfo->encapsulatedPictureType) {
case JPEG_IMAGE:
case PNG_IMAGE:
{
SceUID fd = sceIoOpen(file, SCE_O_RDONLY, 0);
if (fd >= 0) {
char *buffer = malloc(fileinfo->encapsulatedPictureLength);
if (buffer) {
sceIoLseek32(fd, fileinfo->encapsulatedPictureOffset, SCE_SEEK_SET);
sceIoRead(fd, buffer, fileinfo->encapsulatedPictureLength);
sceIoClose(fd);
if (fileinfo->encapsulatedPictureType == JPEG_IMAGE)
tex = vita2d_load_JPEG_buffer(buffer, fileinfo->encapsulatedPictureLength);
if (fileinfo->encapsulatedPictureType == PNG_IMAGE)
tex = vita2d_load_PNG_buffer(buffer);
if (tex)
vita2d_texture_set_filters(tex, SCE_GXM_TEXTURE_FILTER_LINEAR, SCE_GXM_TEXTURE_FILTER_LINEAR);
free(buffer);
}
break;
}
}
}
if (!tex)
tex = getAlternativeCoverImage(file);
}
int audioPlayer(const char *file, int type, FileList *list, FileListEntry *entry, int *base_pos, int *rel_pos) {
static int speed_list[] = { -7, -3, -1, 0, 1, 3, 7 };
#define N_SPEED (sizeof(speed_list) / sizeof(int))
sceAppMgrAcquireBgmPort();
powerLock();
setAudioFunctions(type);
initFunct(0);
loadFunct((char *)file);
playFunct();
getAudioInfo(file);
uint64_t totalms = 0;
uint32_t lyricsIndex = 0;
Lyrics* lyrics = loadLyricsFile(file,&totalms,&lyricsIndex);
int scroll_count = 0;
float scroll_x = 0.0f;
while (1) {
char cur_time_string[12];
getTimeStringFunct(cur_time_string);
readPad();
// Cancel
if (pressed_pad[PAD_CANCEL]) {
break;
}
// Display off
if (pressed_pad[PAD_TRIANGLE]) {
scePowerRequestDisplayOff();
}
// Toggle play/pause
if (pressed_pad[PAD_ENTER]) {
if (isPlayingFunct() && getPlayingSpeedFunct() == 0) {
pauseFunct();
} else {
setPlayingSpeedFunct(0);
playFunct();
}
}
if (pressed_pad[PAD_LEFT] || pressed_pad[PAD_RIGHT]) {
int speed = getPlayingSpeedFunct();
if (pressed_pad[PAD_LEFT]) {
int i;
for (i = 0; i < N_SPEED; i++) {
if (speed_list[i] == speed) {
if (i > 0)
speed = speed_list[i-1];
break;
}
}
}
if (pressed_pad[PAD_RIGHT]) {
int i;
for (i = 0; i < N_SPEED; i++) {
if (speed_list[i] == speed) {
if (i < N_SPEED - 1)
speed = speed_list[i + 1];
break;
}
}
}
setPlayingSpeedFunct(speed);
playFunct();
}
// Previous/next song.
if (getPercentageFunct() == 100.0f || endOfStreamFunct() ||
pressed_pad[PAD_LTRIGGER] || pressed_pad[PAD_RTRIGGER]) {
int previous = pressed_pad[PAD_LTRIGGER];
if (previous && strcmp(cur_time_string, "00:00:00") != 0) {
lrcParseClose(lyrics);
endFunct();
initFunct(0);
loadFunct((char *)file);
playFunct();
getAudioInfo(file);
lyrics = loadLyricsFile(file,&totalms,&lyricsIndex);
} else {
int available = 0;
int old_base_pos = *base_pos;
int old_rel_pos = *rel_pos;
FileListEntry *old_entry = entry;
if (getPercentageFunct() == 100.0f && !endOfStreamFunct())
previous = 1;
if (endOfStreamFunct())
previous = 0;
while (previous ? entry->previous : entry->next) {
entry = previous ? entry->previous : entry->next;
if (previous) {
if (*rel_pos > 0) {
(*rel_pos)--;
} else if (*base_pos > 0) {
(*base_pos)--;
}
} else {
if ((*rel_pos + 1) < list->length) {
if ((*rel_pos + 1) < MAX_POSITION) {
(*rel_pos)++;
} else if ((*base_pos+*rel_pos + 1) < list->length) {
(*base_pos)++;
}
}
}
if (!entry->is_folder) {
char path[MAX_PATH_LENGTH];
snprintf(path, MAX_PATH_LENGTH - 1, "%s%s", list->path, entry->name);
int type = getFileType(path);
if (type == FILE_TYPE_MP3 || type == FILE_TYPE_OGG) {
file = path;
lrcParseClose(lyrics);
endFunct();
setAudioFunctions(type);
initFunct(0);
loadFunct((char *)file);
playFunct();
getAudioInfo(file);
lyrics = loadLyricsFile(file,&totalms,&lyricsIndex);
available = 1;
break;
}
}
}
if (!available) {
*base_pos = old_base_pos;
*rel_pos = old_rel_pos;
entry = old_entry;
break;
}
}
}
// Start drawing
startDrawing(bg_audio_image);
// Draw shell info
drawShellInfo(file);
float cover_size = MAX_ENTRIES * FONT_Y_SPACE;
// Cover
if (tex) {
vita2d_draw_texture_scale(tex, SHELL_MARGIN_X, START_Y, cover_size / vita2d_texture_get_width(tex), cover_size / vita2d_texture_get_height(tex));
} else {
vita2d_draw_texture(cover_image, SHELL_MARGIN_X, START_Y);
}
// Info
float x = 2.0f * SHELL_MARGIN_X + cover_size;
pgf_draw_text(x, START_Y + (0 * FONT_Y_SPACE), AUDIO_INFO_ASSIGN, language_container[TITLE]);
pgf_draw_text(x, START_Y + (1 * FONT_Y_SPACE), AUDIO_INFO_ASSIGN, language_container[ALBUM]);
pgf_draw_text(x, START_Y + (2 * FONT_Y_SPACE), AUDIO_INFO_ASSIGN, language_container[ARTIST]);
pgf_draw_text(x, START_Y + (3 * FONT_Y_SPACE), AUDIO_INFO_ASSIGN, language_container[GENRE]);
pgf_draw_text(x, START_Y + (4 * FONT_Y_SPACE), AUDIO_INFO_ASSIGN, language_container[YEAR]);
x += 120.0f;
vita2d_enable_clipping();
vita2d_set_clip_rectangle(x + 1.0f, START_Y, x + 1.0f + 390.0f, START_Y + (5 * FONT_Y_SPACE));
float title_x = x;
uint32_t color = AUDIO_INFO;
int width = (int)pgf_text_width(fileinfo->title);
if (width >= 390.0f) {
if (scroll_count < 60) {
scroll_x = title_x;
} else if (scroll_count < width + 90) {
scroll_x--;
} else if (scroll_count < width + 120) {
color = (color & 0x00FFFFFF) | ((((color >> 24) * (scroll_count - width - 90)) / 30) << 24); // fade-in in 0.5s
scroll_x = title_x;
} else {
scroll_count = 0;
}
scroll_count++;
title_x = scroll_x;
}
pgf_draw_text(title_x, START_Y + (0 * FONT_Y_SPACE), color, fileinfo->title[0] == '\0' ? "-" : fileinfo->title);
pgf_draw_text(x, START_Y + (1 * FONT_Y_SPACE), AUDIO_INFO, fileinfo->album[0] == '\0' ? "-" : fileinfo->album);
pgf_draw_text(x, START_Y + (2 * FONT_Y_SPACE), AUDIO_INFO, fileinfo->artist[0] == '\0' ? "-" : fileinfo->artist);
pgf_draw_text(x, START_Y + (3 * FONT_Y_SPACE), AUDIO_INFO, fileinfo->genre[0] == '\0' ? "-" : fileinfo->genre);
pgf_draw_text(x, START_Y + (4 * FONT_Y_SPACE), AUDIO_INFO, fileinfo->year[0] == '\0' ? "-" : fileinfo->year);
vita2d_disable_clipping();
x -= 120.0f;
drawLyrics(lyrics, cur_time_string, &totalms, &lyricsIndex, x, START_Y + (6 * FONT_Y_SPACE));
float y = SCREEN_HEIGHT - 6.0f * SHELL_MARGIN_Y;
// Icon
vita2d_texture *icon = NULL;
if (getPlayingSpeedFunct() != 0) {
if (getPlayingSpeedFunct() < 0) {
icon = fastrewind_image;
} else {
icon = fastforward_image;
}
pgf_draw_textf(x + 45.0f, y, AUDIO_SPEED, "%dx", abs(getPlayingSpeedFunct() + (getPlayingSpeedFunct() < 0 ? -1 : 1)));
} else {
if (isPlayingFunct()) {
icon = pause_image;
} else {
icon = play_image;
}
}
vita2d_draw_texture(icon, x, y + 3.0f);
// Time
char string[32];
sprintf(string, "%s / %s", cur_time_string, fileinfo->strLength);
float time_x = ALIGN_RIGHT(SCREEN_WIDTH-SHELL_MARGIN_X, pgf_text_width(string));
int w = pgf_draw_text(time_x, y, AUDIO_TIME_CURRENT, cur_time_string);
pgf_draw_text(time_x + (float)w, y, AUDIO_TIME_SLASH, " /");
pgf_draw_text(ALIGN_RIGHT(SCREEN_WIDTH-SHELL_MARGIN_X, pgf_text_width(fileinfo->strLength)), y, AUDIO_TIME_TOTAL, fileinfo->strLength);
float length = SCREEN_WIDTH - 3.0f * SHELL_MARGIN_X - cover_size;
vita2d_draw_rectangle(x, (y) + FONT_Y_SPACE + 10.0f, length, 8, AUDIO_TIME_BAR_BG);
vita2d_draw_rectangle(x, (y) + FONT_Y_SPACE + 10.0f, getPercentageFunct() * length / 100.0f, 8, AUDIO_TIME_BAR);
// End drawing
endDrawing();
}
if (tex) {
vita2d_wait_rendering_done();
vita2d_free_texture(tex);
tex = NULL;
}
lrcParseClose(lyrics);
endFunct();
powerUnlock();
sceAppMgrReleaseBgmPort();
return 0;
}

View File

@ -1,24 +1,24 @@
/*
VitaShell
Copyright (C) 2015-2018, 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 __AUDIOPLAYER_H__
#define __AUDIOPLAYER_H__
int audioPlayer(const char *file, int type, FileList *list, FileListEntry *entry, int *base_pos, int *rel_pos);
/*
VitaShell
Copyright (C) 2015-2018, 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 __AUDIOPLAYER_H__
#define __AUDIOPLAYER_H__
int audioPlayer(const char *file, int type, FileList *list, FileListEntry *entry, int *base_pos, int *rel_pos);
#endif

View File

@ -1,337 +1,337 @@
/*
VitaShell
Copyright (C) 2015-2018, 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 "file.h"
#include "utils.h"
#include "theme.h"
#include "coredump.h"
#include "elf.h"
typedef struct {
int unk_0; // 0x00
int size; // 0x04
int unk_8; // 0x08
char name[16]; // 0x0C
int unk_1C; // 0x1C
int num; // 0x20
} InfoHeader; // 0x24
typedef struct {
int unk; // 0x00
int perm; // 0x04
uint32_t addr; // 0x08
uint32_t size; // 0x0C
int unk_10; // 0x10
} ModuleSegment; // 0x14
typedef struct {
int unk_0; // 0x00
int uid; // 0x04
int sdk_version; // 0x08
int version; // 0xC
int unk_10; // 0x10
int addr_14; // 0x14
int unk_18; // 0x18
int addr_1C; // 0x1C
int unk_20; // 0x20
char name[28]; // 0x24
int unk_44; // 0x40
int unk_48; // 0x44 2
uint32_t nid; // 0x48
int num_segments; // 0x4C
ModuleSegment segments[1]; // 0x50
uint32_t addr[4]; // 0x78
} ModuleInfoOneSegment; // 0x88
typedef struct {
int unk_0; // 0x00
int uid; // 0x04
int sdk_version; // 0x08
int version; // 0xC
int unk_10; // 0x10
int addr_14; // 0x14
int unk_18; // 0x18
int addr_1C; // 0x1C
int unk_20; // 0x20
char name[28]; // 0x24
int unk_44; // 0x40
int unk_48; // 0x44 2
uint32_t nid; // 0x48
int num_segments; // 0x4C
ModuleSegment segments[2]; // 0x50
uint32_t addr[4]; // 0x78
} ModuleInfoTwoSegment; // 0x88
typedef struct {
int unk; // 0x00
int uid; // 0x04
char name[32]; // 0x08
int type; // 0x28
uint32_t vaddr; // 0x2C
uint32_t vsize; // 0x30
int unk_34;
int unk_38;
int unk_3C;
int unk_40;
int unk_44;
} MemBlkInfo; // 0x48
typedef struct {
int size; // 0x00
int uid; // 0x04
char name[32]; // 0x08
int unk_28; // 0x28
int unk_2C[18]; // 0x2C
int cause; // 0x74
int unk_78[9]; // 0x78
uint32_t pc; // 0x9C
int unk_A0[10]; // 0xA0
} ThreadInfo; // 0xC8
typedef struct {
int size; // 0x00
int uid; // 0x04
uint32_t regs[16]; // 0x08
int unk[75]; // 0x48
uint32_t bad_v_addr; // 0x174
} ThreadRegInfo; // 0x178
// ARM registers
static char *regnames[] = { "a1", "a2", "a3", "a4",
"v1", "v2", "v3", "v4",
"v5", "v6", "v7", "v8",
"ip", "sp", "lr", "pc" };
static char *getCauseName(int cause) {
switch (cause) {
case 0x30002:
return "Undefined instruction exception";
case 0x30003:
return "Prefetch abort exception";
case 0x30004:
return "Data abort exception";
case 0x60080:
return "Division by zero";
}
return "Unknown cause";
}
static int decompressGzip(uint8_t *dst, int size_dst, uint8_t *src, int size_src) {
z_stream z;
memset(&z, 0, sizeof(z_stream));
z.avail_in = size_src;
z.next_in = src;
z.avail_out = size_dst;
z.next_out = dst;
if (inflateInit2(&z, 15 + 32) != Z_OK)
return -1;
if (inflate(&z, Z_FINISH) != Z_STREAM_END) {
inflateEnd(&z);
return -2;
}
inflateEnd(&z);
return z.total_out;
}
int coredumpViewer(const char *file) {
void *buffer = memalign(4096, BIG_BUFFER_SIZE);
if (!buffer)
return VITASHELL_ERROR_NO_MEMORY;
int size = ReadFile(file, buffer, BIG_BUFFER_SIZE);
if (*(uint16_t *)buffer == 0x8B1F) {
void *out_buf = memalign(4096, BIG_BUFFER_SIZE);
if (!out_buf) {
free(buffer);
return VITASHELL_ERROR_NO_MEMORY;
}
int out_size = decompressGzip(out_buf, BIG_BUFFER_SIZE, buffer, size);
if (out_size < 0) {
free(out_buf);
free(buffer);
return -3;
}
memcpy(buffer, out_buf, out_size);
free(out_buf);
}
Elf32_Ehdr *ehdr = (Elf32_Ehdr *)buffer;
Elf32_Phdr *phdr = (Elf32_Phdr *)((uint32_t)buffer + ehdr->e_phoff);
if (ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
ehdr->e_ident[EI_MAG3] != ELFMAG3) {
free(buffer);
return VITASHELL_ERROR_INVALID_MAGIC;
}
char thname[32], modname[32];
SceUID thid = -1, modid = -1;
uint32_t epc = -1, rel_epc = -1;
int cause = -1;
uint32_t bad_v_addr = -1;
uint32_t regs[16];
int i;
for (i = 0; i < ehdr->e_phnum; i++) {
if (phdr[i].p_type == 0x4) {
void *program = malloc(phdr[i].p_filesz);
if (!program) {
free(buffer);
return VITASHELL_ERROR_NO_MEMORY;
}
memcpy(program, buffer + phdr[i].p_offset, phdr[i].p_filesz);
InfoHeader *info = (InfoHeader *)program;
if (strcmp(info->name, "THREAD_INFO") == 0) {
int j;
for (j = 0; j < ((InfoHeader *)program)->num; j++) {
ThreadInfo *thread_info = (ThreadInfo *)(program + sizeof(InfoHeader));
if (thread_info[j].cause != 0) {
strcpy(thname, thread_info[j].name);
thid = thread_info[j].uid;
epc = thread_info[j].pc;
cause = thread_info[j].cause;
break;
}
}
} else if (strcmp(info->name, "THREAD_REG_INFO") == 0) {
int j;
for (j = 0; j < ((InfoHeader *)program)->num; j++) {
ThreadRegInfo *thread_reg_info = (ThreadRegInfo *)(program + sizeof(InfoHeader));
if (thread_reg_info[j].uid == thid) {
memcpy(&regs, thread_reg_info[j].regs, sizeof(regs));
bad_v_addr = thread_reg_info[j].bad_v_addr;
break;
}
}
} else if (strcmp(info->name, "MODULE_INFO") == 0) {
uint32_t offset = 0;
int j;
for (j = 0; j < ((InfoHeader *)program)->num; j++) {
ModuleInfoTwoSegment *mod_info = (ModuleInfoTwoSegment *)(program + sizeof(InfoHeader) + offset);
if (epc >= mod_info->segments[0].addr && epc < (mod_info->segments[0].addr+mod_info->segments[0].size)) {
strcpy(modname, mod_info->name);
modid = mod_info->uid;
rel_epc = epc - mod_info->segments[0].addr;
break;
}
if (mod_info->num_segments == 2) {
offset += sizeof(ModuleInfoTwoSegment);
} else {
offset += sizeof(ModuleInfoOneSegment);
}
}
}
free(program);
}
}
while (1) {
readPad();
if (pressed_pad[PAD_CANCEL]) {
break;
}
// Start drawing
startDrawing(bg_text_image);
// Draw shell info
drawShellInfo(file);
float y = START_Y;
// Exception
pgf_draw_text(SHELL_MARGIN_X, y, TEXT_COLOR, "Exception");
pgf_draw_text(COREDUMP_INFO_X, y, TEXT_COLOR, getCauseName(cause));
y += FONT_Y_SPACE;
// Thread ID
pgf_draw_text(SHELL_MARGIN_X, y, TEXT_COLOR, "Thread ID");
pgf_draw_textf(COREDUMP_INFO_X, y, TEXT_COLOR, "0x%08X", thid);
y += FONT_Y_SPACE;
// Thread name
pgf_draw_text(SHELL_MARGIN_X, y, TEXT_COLOR, "Thread name");
pgf_draw_text(COREDUMP_INFO_X, y, TEXT_COLOR, thname);
y += FONT_Y_SPACE;
// EPC
pgf_draw_text(SHELL_MARGIN_X, y, TEXT_COLOR, "EPC");
if (rel_epc != -1)
pgf_draw_textf(COREDUMP_INFO_X, y, TEXT_COLOR, "%s + 0x%08X", modname, rel_epc);
else
pgf_draw_textf(COREDUMP_INFO_X, y, TEXT_COLOR, "0x%08X", epc);
y += FONT_Y_SPACE;
// Cause
pgf_draw_text(SHELL_MARGIN_X, y, TEXT_COLOR, "Cause");
pgf_draw_textf(COREDUMP_INFO_X, y, TEXT_COLOR, "0x%08X", cause);
y += FONT_Y_SPACE;
// BadVAddr
pgf_draw_text(SHELL_MARGIN_X, y, TEXT_COLOR, "BadVAddr");
pgf_draw_textf(COREDUMP_INFO_X, y, TEXT_COLOR, "0x%08X", bad_v_addr);
y += FONT_Y_SPACE;
// Registers
int j;
for (j = 0; j < 4; j++) {
float x = SHELL_MARGIN_X;
int i;
for (i = 0; i < 4; i++) {
pgf_draw_textf(x, y, TEXT_COLOR, "%s:", regnames[j * 4 + i]);
x += COREDUMP_REGISTER_NAME_SPACE;
pgf_draw_textf(x, y, TEXT_COLOR, "0x%08X", regs[j * 4 + i]);
x += COREDUMP_REGISTER_SPACE;
}
y += FONT_Y_SPACE;
}
// End drawing
endDrawing();
}
free(buffer);
return 0;
/*
VitaShell
Copyright (C) 2015-2018, 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 "file.h"
#include "utils.h"
#include "theme.h"
#include "coredump.h"
#include "elf.h"
typedef struct {
int unk_0; // 0x00
int size; // 0x04
int unk_8; // 0x08
char name[16]; // 0x0C
int unk_1C; // 0x1C
int num; // 0x20
} InfoHeader; // 0x24
typedef struct {
int unk; // 0x00
int perm; // 0x04
uint32_t addr; // 0x08
uint32_t size; // 0x0C
int unk_10; // 0x10
} ModuleSegment; // 0x14
typedef struct {
int unk_0; // 0x00
int uid; // 0x04
int sdk_version; // 0x08
int version; // 0xC
int unk_10; // 0x10
int addr_14; // 0x14
int unk_18; // 0x18
int addr_1C; // 0x1C
int unk_20; // 0x20
char name[28]; // 0x24
int unk_44; // 0x40
int unk_48; // 0x44 2
uint32_t nid; // 0x48
int num_segments; // 0x4C
ModuleSegment segments[1]; // 0x50
uint32_t addr[4]; // 0x78
} ModuleInfoOneSegment; // 0x88
typedef struct {
int unk_0; // 0x00
int uid; // 0x04
int sdk_version; // 0x08
int version; // 0xC
int unk_10; // 0x10
int addr_14; // 0x14
int unk_18; // 0x18
int addr_1C; // 0x1C
int unk_20; // 0x20
char name[28]; // 0x24
int unk_44; // 0x40
int unk_48; // 0x44 2
uint32_t nid; // 0x48
int num_segments; // 0x4C
ModuleSegment segments[2]; // 0x50
uint32_t addr[4]; // 0x78
} ModuleInfoTwoSegment; // 0x88
typedef struct {
int unk; // 0x00
int uid; // 0x04
char name[32]; // 0x08
int type; // 0x28
uint32_t vaddr; // 0x2C
uint32_t vsize; // 0x30
int unk_34;
int unk_38;
int unk_3C;
int unk_40;
int unk_44;
} MemBlkInfo; // 0x48
typedef struct {
int size; // 0x00
int uid; // 0x04
char name[32]; // 0x08
int unk_28; // 0x28
int unk_2C[18]; // 0x2C
int cause; // 0x74
int unk_78[9]; // 0x78
uint32_t pc; // 0x9C
int unk_A0[10]; // 0xA0
} ThreadInfo; // 0xC8
typedef struct {
int size; // 0x00
int uid; // 0x04
uint32_t regs[16]; // 0x08
int unk[75]; // 0x48
uint32_t bad_v_addr; // 0x174
} ThreadRegInfo; // 0x178
// ARM registers
static char *regnames[] = { "a1", "a2", "a3", "a4",
"v1", "v2", "v3", "v4",
"v5", "v6", "v7", "v8",
"ip", "sp", "lr", "pc" };
static char *getCauseName(int cause) {
switch (cause) {
case 0x30002:
return "Undefined instruction exception";
case 0x30003:
return "Prefetch abort exception";
case 0x30004:
return "Data abort exception";
case 0x60080:
return "Division by zero";
}
return "Unknown cause";
}
static int decompressGzip(uint8_t *dst, int size_dst, uint8_t *src, int size_src) {
z_stream z;
memset(&z, 0, sizeof(z_stream));
z.avail_in = size_src;
z.next_in = src;
z.avail_out = size_dst;
z.next_out = dst;
if (inflateInit2(&z, 15 + 32) != Z_OK)
return -1;
if (inflate(&z, Z_FINISH) != Z_STREAM_END) {
inflateEnd(&z);
return -2;
}
inflateEnd(&z);
return z.total_out;
}
int coredumpViewer(const char *file) {
void *buffer = memalign(4096, BIG_BUFFER_SIZE);
if (!buffer)
return VITASHELL_ERROR_NO_MEMORY;
int size = ReadFile(file, buffer, BIG_BUFFER_SIZE);
if (*(uint16_t *)buffer == 0x8B1F) {
void *out_buf = memalign(4096, BIG_BUFFER_SIZE);
if (!out_buf) {
free(buffer);
return VITASHELL_ERROR_NO_MEMORY;
}
int out_size = decompressGzip(out_buf, BIG_BUFFER_SIZE, buffer, size);
if (out_size < 0) {
free(out_buf);
free(buffer);
return -3;
}
memcpy(buffer, out_buf, out_size);
free(out_buf);
}
Elf32_Ehdr *ehdr = (Elf32_Ehdr *)buffer;
Elf32_Phdr *phdr = (Elf32_Phdr *)((uint32_t)buffer + ehdr->e_phoff);
if (ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
ehdr->e_ident[EI_MAG3] != ELFMAG3) {
free(buffer);
return VITASHELL_ERROR_INVALID_MAGIC;
}
char thname[32], modname[32];
SceUID thid = -1, modid = -1;
uint32_t epc = -1, rel_epc = -1;
int cause = -1;
uint32_t bad_v_addr = -1;
uint32_t regs[16];
int i;
for (i = 0; i < ehdr->e_phnum; i++) {
if (phdr[i].p_type == 0x4) {
void *program = malloc(phdr[i].p_filesz);
if (!program) {
free(buffer);
return VITASHELL_ERROR_NO_MEMORY;
}
memcpy(program, buffer + phdr[i].p_offset, phdr[i].p_filesz);
InfoHeader *info = (InfoHeader *)program;
if (strcmp(info->name, "THREAD_INFO") == 0) {
int j;
for (j = 0; j < ((InfoHeader *)program)->num; j++) {
ThreadInfo *thread_info = (ThreadInfo *)(program + sizeof(InfoHeader));
if (thread_info[j].cause != 0) {
strcpy(thname, thread_info[j].name);
thid = thread_info[j].uid;
epc = thread_info[j].pc;
cause = thread_info[j].cause;
break;
}
}
} else if (strcmp(info->name, "THREAD_REG_INFO") == 0) {
int j;
for (j = 0; j < ((InfoHeader *)program)->num; j++) {
ThreadRegInfo *thread_reg_info = (ThreadRegInfo *)(program + sizeof(InfoHeader));
if (thread_reg_info[j].uid == thid) {
memcpy(&regs, thread_reg_info[j].regs, sizeof(regs));
bad_v_addr = thread_reg_info[j].bad_v_addr;
break;
}
}
} else if (strcmp(info->name, "MODULE_INFO") == 0) {
uint32_t offset = 0;
int j;
for (j = 0; j < ((InfoHeader *)program)->num; j++) {
ModuleInfoTwoSegment *mod_info = (ModuleInfoTwoSegment *)(program + sizeof(InfoHeader) + offset);
if (epc >= mod_info->segments[0].addr && epc < (mod_info->segments[0].addr+mod_info->segments[0].size)) {
strcpy(modname, mod_info->name);
modid = mod_info->uid;
rel_epc = epc - mod_info->segments[0].addr;
break;
}
if (mod_info->num_segments == 2) {
offset += sizeof(ModuleInfoTwoSegment);
} else {
offset += sizeof(ModuleInfoOneSegment);
}
}
}
free(program);
}
}
while (1) {
readPad();
if (pressed_pad[PAD_CANCEL]) {
break;
}
// Start drawing
startDrawing(bg_text_image);
// Draw shell info
drawShellInfo(file);
float y = START_Y;
// Exception
pgf_draw_text(SHELL_MARGIN_X, y, TEXT_COLOR, "Exception");
pgf_draw_text(COREDUMP_INFO_X, y, TEXT_COLOR, getCauseName(cause));
y += FONT_Y_SPACE;
// Thread ID
pgf_draw_text(SHELL_MARGIN_X, y, TEXT_COLOR, "Thread ID");
pgf_draw_textf(COREDUMP_INFO_X, y, TEXT_COLOR, "0x%08X", thid);
y += FONT_Y_SPACE;
// Thread name
pgf_draw_text(SHELL_MARGIN_X, y, TEXT_COLOR, "Thread name");
pgf_draw_text(COREDUMP_INFO_X, y, TEXT_COLOR, thname);
y += FONT_Y_SPACE;
// EPC
pgf_draw_text(SHELL_MARGIN_X, y, TEXT_COLOR, "EPC");
if (rel_epc != -1)
pgf_draw_textf(COREDUMP_INFO_X, y, TEXT_COLOR, "%s + 0x%08X", modname, rel_epc);
else
pgf_draw_textf(COREDUMP_INFO_X, y, TEXT_COLOR, "0x%08X", epc);
y += FONT_Y_SPACE;
// Cause
pgf_draw_text(SHELL_MARGIN_X, y, TEXT_COLOR, "Cause");
pgf_draw_textf(COREDUMP_INFO_X, y, TEXT_COLOR, "0x%08X", cause);
y += FONT_Y_SPACE;
// BadVAddr
pgf_draw_text(SHELL_MARGIN_X, y, TEXT_COLOR, "BadVAddr");
pgf_draw_textf(COREDUMP_INFO_X, y, TEXT_COLOR, "0x%08X", bad_v_addr);
y += FONT_Y_SPACE;
// Registers
int j;
for (j = 0; j < 4; j++) {
float x = SHELL_MARGIN_X;
int i;
for (i = 0; i < 4; i++) {
pgf_draw_textf(x, y, TEXT_COLOR, "%s:", regnames[j * 4 + i]);
x += COREDUMP_REGISTER_NAME_SPACE;
pgf_draw_textf(x, y, TEXT_COLOR, "0x%08X", regs[j * 4 + i]);
x += COREDUMP_REGISTER_SPACE;
}
y += FONT_Y_SPACE;
}
// End drawing
endDrawing();
}
free(buffer);
return 0;
}

View File

@ -1,24 +1,24 @@
/*
VitaShell
Copyright (C) 2015-2018, 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 __COREDUMP_H__
#define __COREDUMP_H__
int coredumpViewer(const char *file);
/*
VitaShell
Copyright (C) 2015-2018, 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 __COREDUMP_H__
#define __COREDUMP_H__
int coredumpViewer(const char *file);
#endif

View File

@ -1,177 +1,177 @@
# VitaShell German Translation by VegaRoXas and Tails32; updated by Ch3ck3r (VitaShell 1.62)
# Allgemeine Texte
ERROR = "Fehler 0x%08X."
OK = "OK"
YES = "Ja"
NO = "Nein"
CANCEL = "Abbrechen"
ON = "An"
OFF = "Aus"
FILE_ = "Datei"
FOLDER = "Ordner"
# Prozess-Texte
MOVING = "Verschiebe..."
COPYING = "Kopiere..."
DELETING = "Lösche..."
EXPORTING = "Exportiere..."
INSTALLING = "Installiere..."
DOWNLOADING = "Lade herunter..."
EXTRACTING = "Entpacke..."
COMPRESSING = "Komprimiere..."
HASHING = "Erstelle Hash..."
REFRESHING = "Aktualisiere..."
# Musik Player Texte
TITLE = "Titel"
ALBUM = "Album"
ARTIST = "Künstler"
GENRE = "Genre"
YEAR = "Jahr"
# Hex-Editor Texte
OFFSET = "Offset"
OPEN_HEX_EDITOR = "Im Hex-Editor öffnen"
# Text-Editor Texte
EDIT_LINE = "Zeile bearbeiten"
ENTER_SEARCH_TERM = "Suchbegriff eingeben"
# Dateibrowser-Kontextmenü Texte
REFRESH_LIVEAREA = "Livearea aktualisieren"
MOUNT_UMA0 = "Mount uma0:"
MOUNT_IMC0 = "Mount imc0:"
MOUNT_USB_UX0 = "Mount USB ux0:"
UMOUNT_USB_UX0 = "Umount USB ux0:"
SORT_BY = "Sortiere nach"
BY_NAME = "Name"
BY_SIZE = "Größe"
BY_DATE = "Datum"
MARK_ALL = "Alles auswählen"
UNMARK_ALL = "Auswahl aufheben"
MOVE = "Verschieben"
COPY = "Kopieren"
PASTE = "Einfügen"
DELETE = "Löschen"
RENAME = "Umbenennen"
NEW_FOLDER = "Neuer Ordner"
PROPERTIES = "Eigenschaften"
MORE = "Mehr"
COMPRESS = "Komprimieren"
INSTALL_ALL = "Alle installieren"
INSTALL_FOLDER = "Ordner installieren"
CALCULATE_SHA1 = "SHA1 berechnen"
EXPORT_MEDIA = "Medien exportieren"
CUT = "Ausschneiden"
INSERT_EMPTY_LINE = "Leere Zeile einfügen"
SEARCH = "Suchen"
# Dateibrowser Berechtigungs Texte
PROPERTY_NAME = "Name"
PROPERTY_TYPE = "Art"
PROPERTY_FSELF_MODE = "FSELF Modus"
PROPERTY_SIZE = "Größe"
PROPERTY_COMPRESSED_SIZE = "Komprimierte Größe"
PROPERTY_CONTAINS = "Beinhaltet"
PROPERTY_CONTAINS_FILES_FOLDERS = "%d Dateien, %d Ordner"
PROPERTY_CREATION_DATE = "Erstellungsdatum"
PROPERTY_MODFICATION_DATE = "Veränderungsdatum"
PROPERTY_TYPE_BMP = "Bitmap Bildformat"
PROPERTY_TYPE_INI = "Konfigurationsdatei"
PROPERTY_TYPE_JPEG = "JPEG Bildformat"
PROPERTY_TYPE_MP3 = "MP3 Audiodatei"
PROPERTY_TYPE_OGG = "OGG Audiodatei"
PROPERTY_TYPE_PNG = "PNG Bildformat"
PROPERTY_TYPE_RAR = "RAR Archiv"
PROPERTY_TYPE_SFO = "SFO Datei"
PROPERTY_TYPE_TXT = "Textdokument"
PROPERTY_TYPE_VPK = "VPK Paket"
PROPERTY_TYPE_XML = "XML Datei"
PROPERTY_TYPE_ZIP = "ZIP Archiv"
PROPERTY_TYPE_FSELF = "FSELF Datei"
PROPERTY_FSELF_MODE_SAFE = "Sicher"
PROPERTY_FSELF_MODE_UNSAFE = "Nicht Sicher"
PROPERTY_FSELF_MODE_SCE = "SCE signiert"
# Dateibrowser Texte
REFRESHED = "%d Datei(en) aktualisiert."
COPIED_FILE = "%d Datei(en) kopiert."
COPIED_FOLDER = "%d Ordner kopiert."
COPIED_FILES_FOLDERS = "%d Element(e) kopiert."
# Fragen in Dialogfenstern
DELETE_FILE_QUESTION = "Möchtest du die Datei wirklich löschen?"
DELETE_FOLDER_QUESTION = "Möchtest du den Ordner wirklich löschen?"
DELETE_FILES_FOLDERS_QUESTION = "Möchtest du die ausgewählten Elemente wirklich löschen?"
EXPORT_FILE_QUESTION = "Möchtest du diese Datei zu den Medien exportieren?"
EXPORT_FOLDER_QUESTION = "Möchtest du diesen Ordner zu den Medien exportieren?"
EXPORT_FILES_FOLDERS_QUESTION = "Möchtest du diese Elemente zu den Medien exportieren?"
EXPORT_NO_MEDIA = "Keine Mediendateien zum Exportieren verfügbar."
EXPORT_SONGS_INFO = "%d Lied(er) exportiert."
EXPORT_VIDEOS_INFO = "%d Video(s) exportiert."
EXPORT_PICTURES_INFO = "%d Bild(er) exportiert."
EXPORT_SONGS_VIDEOS_INFO = "%d Lied(er) und %d Video(s) exportiert."
EXPORT_SONGS_PICTURES_INFO = "%d Lied(er) und %d Bild(er) exportiert."
EXPORT_VIDEOS_PICTURES_INFO = "%d Video(s) und %d Bild(er) exportiert."
EXPORT_SONGS_VIDEOS_PICTURES_INFO = "%d Lied(er) %d Video(s) und %d Bild(er) exportiert."
INSTALL_ALL_QUESTION = "Möchtest du alle in diesem Ordner verfügbaren Pakete installieren?"
INSTALL_FOLDER_QUESTION = "Möchtest du diesen Ordner installieren?\Warnung: hierdurch wird nach der Installation\auch der Ordner gelöscht!"
INSTALL_QUESTION = "Möchtest du dieses Paket installieren?"
INSTALL_WARNING = "Dieses Paket benötigt erweiterte Berechtigungen.\Es wird Zugriff auf deine persönlichen Informationen haben.\Bitte installiere es nur, falls es aus einer vertrauenswürdigen Quelle stammt\oder fahre auf eigene Gefahr fort.\\Möchtest du die Installation fortsetzen?"
INSTALL_BRICK_WARNING = "Dieses Paket nutzt Funktionen, um Partitionen zu\verwalten und kann möglicherweise dein Gerät zerstören.\Bitte installiere es nur, falls es aus einer vertrauenswürdigen Quelle stammt\oder fahre auf eigene Gefahr fort.\\Möchtest du die Installation fortsetzen?"
HASH_FILE_QUESTION = "Einen SHA1-Hash zu erstellen kann einige Zeit\in Anspruch nehmen. Die benötigte Zeit\ist von der Dateigröße abhängig.\\Möchtest du fortfahren?"
SAVE_MODIFICATIONS = "Möchtest du die Änderungen speichern?"
REFRESH_LIVEAREA_QUESTION = "Die Livearea zu aktualisieren kann einige Zeit in Anspruch nehmen.\Möchtest du fortfahren?"
# HENkaku Einstellungen Texte
HENKAKU_SETTINGS = "HENkaku Einstellungen"
HENKAKU_ENABLE_PSN_SPOOFING = "Aktiviere PSN Vortäuschung"
HENKAKU_ENABLE_UNSAFE_HOMEBREW = "Nicht sichere Homebrews zulassen"
HENKAKU_ENABLE_VERSION_SPOOFING = "Aktiviere Versions Vortäuschung"
HENKAKU_SPOOFED_VERSION = "Vorgetäuschte Version"
HENKAKU_RESTORE_DEFAULT_SETTINGS = "Stelle Standardeinstellungen wieder her"
HENKAKU_RELOAD_CONFIG = "taiHEN config.txt zurücksetzen"
HENKAKU_RESTORE_DEFAULT_MESSAGE = "Standardeinstellungen wurden erfolgreich zurückgesetzt."
HENKAKU_RELOAD_CONFIG_MESSAGE = "taiHEN config.txt wurde erfolgreich zurückgesetzt."
HENKAKU_UNSAFE_HOMEBREW_MESSAGE = "Nicht sichere Homebrews können dein Gerät\permanent beschädigen, wenn diese falsch angewendet,\eingestellt oder böswillig genutzt werden.\Bitte sei vorsichtig, wenn du diese installierst."
# VitaShell Einstellungen
VITASHELL_SETTINGS_MAIN = "Haupteinstellungen"
VITASHELL_SETTINGS_LANGUAGE = "Sprache"
VITASHELL_SETTINGS_THEME = "Thema"
VITASHELL_SETTINGS_USBDEVICE = "USB Gerät"
VITASHELL_SETTINGS_SELECT_BUTTON = "SELECT Knopf"
VITASHELL_SETTINGS_NO_AUTO_UPDATE = "Auto-Update deaktivieren"
VITASHELL_SETTINGS_RESTART_SHELL = "VitaShell Neustarten"
VITASHELL_SETTINGS_POWER = "Power"
VITASHELL_SETTINGS_REBOOT = "Neustarten"
VITASHELL_SETTINGS_POWEROFF = "Ausschalten"
VITASHELL_SETTINGS_STANDBY = "Standby"
VITASHELL_SETTINGS_USB_MEMORY_CARD = "Memory Card"
VITASHELL_SETTINGS_USB_GAME_CARD = "Game Card"
VITASHELL_SETTINGS_SELECT_BUTTON_USB = "USB"
VITASHELL_SETTINGS_SELECT_BUTTON_FTP = "FTP"
# USB Texte
USB_CONNECTED = "USB verbunden"
USB_UMA0_MOUNTED = "uma0: mounted."
USB_UX0_MOUNTED = "USB ux0: mounted."
USB_UX0_UMOUNTED = "USB ux0: umounted."
USB_NOT_CONNECTED = "Verbinde dieses Gerät mit einem PC durch ein USB Kabel"
USB_CONNECTION_NOT_AVAILABLE = "USB Verbindung ist auf diesem Gerät nicht verfügbar."
USB_WAIT_ATTACH = "Zum Fortsetzen bitte ein USB Gerät anschließen.\Wenn es bereits angeschlossen ist, bitte trennen\und erneut anschließen."
# Andere
IMC0_MOUNTED = "imc0: mounted."
SAFE_MODE = "SICHERER MODUS"
UNSAFE_MODE = "UNSICHERER MODUS"
PLEASE_WAIT = "Bitte warten..."
AME_CARD_NOT_FOUND = "Bitte eine Game Card einstecken."
NO_SPACE_ERROR = "Es steht nicht genügend Speicherplatz zur Verfügung.\Es wird %s an zusätzlichem freien Speicher benötigt."
EXTENDED_PERMISSIONS_REQUIRED = "Diese Funktion benötigt erweiterte Berechtigungen.\Bitte aktiviere zuerst 'Nicht sichere Homebrews zulassen'."
WIFI_ERROR = "Es wird eine aktive WLAN-Verbindung benötigt."
FTP_SERVER = "FTP-Server läuft unter\ftp://%s:%i\\Drücke 'OK', um den Server im Hintergrund laufen zu lassen.\Drücke 'Abbrechen', um die Verbindung zu trennen."
UPDATE_QUESTION = "VitaShell %s ist jetzt verfügbar.\\Möchtest du die Anwendung aktualisieren?"
ARCHIVE_NAME = "Archiv Name"
COMPRESSION_LEVEL = "Kompressionslevel (0-9)"
# VitaShell German Translation by VegaRoXas and Tails32; updated by Ch3ck3r (VitaShell 1.62)
# Allgemeine Texte
ERROR = "Fehler 0x%08X."
OK = "OK"
YES = "Ja"
NO = "Nein"
CANCEL = "Abbrechen"
ON = "An"
OFF = "Aus"
FILE_ = "Datei"
FOLDER = "Ordner"
# Prozess-Texte
MOVING = "Verschiebe..."
COPYING = "Kopiere..."
DELETING = "Lösche..."
EXPORTING = "Exportiere..."
INSTALLING = "Installiere..."
DOWNLOADING = "Lade herunter..."
EXTRACTING = "Entpacke..."
COMPRESSING = "Komprimiere..."
HASHING = "Erstelle Hash..."
REFRESHING = "Aktualisiere..."
# Musik Player Texte
TITLE = "Titel"
ALBUM = "Album"
ARTIST = "Künstler"
GENRE = "Genre"
YEAR = "Jahr"
# Hex-Editor Texte
OFFSET = "Offset"
OPEN_HEX_EDITOR = "Im Hex-Editor öffnen"
# Text-Editor Texte
EDIT_LINE = "Zeile bearbeiten"
ENTER_SEARCH_TERM = "Suchbegriff eingeben"
# Dateibrowser-Kontextmenü Texte
REFRESH_LIVEAREA = "Livearea aktualisieren"
MOUNT_UMA0 = "Mount uma0:"
MOUNT_IMC0 = "Mount imc0:"
MOUNT_USB_UX0 = "Mount USB ux0:"
UMOUNT_USB_UX0 = "Umount USB ux0:"
SORT_BY = "Sortiere nach"
BY_NAME = "Name"
BY_SIZE = "Größe"
BY_DATE = "Datum"
MARK_ALL = "Alles auswählen"
UNMARK_ALL = "Auswahl aufheben"
MOVE = "Verschieben"
COPY = "Kopieren"
PASTE = "Einfügen"
DELETE = "Löschen"
RENAME = "Umbenennen"
NEW_FOLDER = "Neuer Ordner"
PROPERTIES = "Eigenschaften"
MORE = "Mehr"
COMPRESS = "Komprimieren"
INSTALL_ALL = "Alle installieren"
INSTALL_FOLDER = "Ordner installieren"
CALCULATE_SHA1 = "SHA1 berechnen"
EXPORT_MEDIA = "Medien exportieren"
CUT = "Ausschneiden"
INSERT_EMPTY_LINE = "Leere Zeile einfügen"
SEARCH = "Suchen"
# Dateibrowser Berechtigungs Texte
PROPERTY_NAME = "Name"
PROPERTY_TYPE = "Art"
PROPERTY_FSELF_MODE = "FSELF Modus"
PROPERTY_SIZE = "Größe"
PROPERTY_COMPRESSED_SIZE = "Komprimierte Größe"
PROPERTY_CONTAINS = "Beinhaltet"
PROPERTY_CONTAINS_FILES_FOLDERS = "%d Dateien, %d Ordner"
PROPERTY_CREATION_DATE = "Erstellungsdatum"
PROPERTY_MODFICATION_DATE = "Veränderungsdatum"
PROPERTY_TYPE_BMP = "Bitmap Bildformat"
PROPERTY_TYPE_INI = "Konfigurationsdatei"
PROPERTY_TYPE_JPEG = "JPEG Bildformat"
PROPERTY_TYPE_MP3 = "MP3 Audiodatei"
PROPERTY_TYPE_OGG = "OGG Audiodatei"
PROPERTY_TYPE_PNG = "PNG Bildformat"
PROPERTY_TYPE_RAR = "RAR Archiv"
PROPERTY_TYPE_SFO = "SFO Datei"
PROPERTY_TYPE_TXT = "Textdokument"
PROPERTY_TYPE_VPK = "VPK Paket"
PROPERTY_TYPE_XML = "XML Datei"
PROPERTY_TYPE_ZIP = "ZIP Archiv"
PROPERTY_TYPE_FSELF = "FSELF Datei"
PROPERTY_FSELF_MODE_SAFE = "Sicher"
PROPERTY_FSELF_MODE_UNSAFE = "Nicht Sicher"
PROPERTY_FSELF_MODE_SCE = "SCE signiert"
# Dateibrowser Texte
REFRESHED = "%d Datei(en) aktualisiert."
COPIED_FILE = "%d Datei(en) kopiert."
COPIED_FOLDER = "%d Ordner kopiert."
COPIED_FILES_FOLDERS = "%d Element(e) kopiert."
# Fragen in Dialogfenstern
DELETE_FILE_QUESTION = "Möchtest du die Datei wirklich löschen?"
DELETE_FOLDER_QUESTION = "Möchtest du den Ordner wirklich löschen?"
DELETE_FILES_FOLDERS_QUESTION = "Möchtest du die ausgewählten Elemente wirklich löschen?"
EXPORT_FILE_QUESTION = "Möchtest du diese Datei zu den Medien exportieren?"
EXPORT_FOLDER_QUESTION = "Möchtest du diesen Ordner zu den Medien exportieren?"
EXPORT_FILES_FOLDERS_QUESTION = "Möchtest du diese Elemente zu den Medien exportieren?"
EXPORT_NO_MEDIA = "Keine Mediendateien zum Exportieren verfügbar."
EXPORT_SONGS_INFO = "%d Lied(er) exportiert."
EXPORT_VIDEOS_INFO = "%d Video(s) exportiert."
EXPORT_PICTURES_INFO = "%d Bild(er) exportiert."
EXPORT_SONGS_VIDEOS_INFO = "%d Lied(er) und %d Video(s) exportiert."
EXPORT_SONGS_PICTURES_INFO = "%d Lied(er) und %d Bild(er) exportiert."
EXPORT_VIDEOS_PICTURES_INFO = "%d Video(s) und %d Bild(er) exportiert."
EXPORT_SONGS_VIDEOS_PICTURES_INFO = "%d Lied(er) %d Video(s) und %d Bild(er) exportiert."
INSTALL_ALL_QUESTION = "Möchtest du alle in diesem Ordner verfügbaren Pakete installieren?"
INSTALL_FOLDER_QUESTION = "Möchtest du diesen Ordner installieren?\Warnung: hierdurch wird nach der Installation\auch der Ordner gelöscht!"
INSTALL_QUESTION = "Möchtest du dieses Paket installieren?"
INSTALL_WARNING = "Dieses Paket benötigt erweiterte Berechtigungen.\Es wird Zugriff auf deine persönlichen Informationen haben.\Bitte installiere es nur, falls es aus einer vertrauenswürdigen Quelle stammt\oder fahre auf eigene Gefahr fort.\\Möchtest du die Installation fortsetzen?"
INSTALL_BRICK_WARNING = "Dieses Paket nutzt Funktionen, um Partitionen zu\verwalten und kann möglicherweise dein Gerät zerstören.\Bitte installiere es nur, falls es aus einer vertrauenswürdigen Quelle stammt\oder fahre auf eigene Gefahr fort.\\Möchtest du die Installation fortsetzen?"
HASH_FILE_QUESTION = "Einen SHA1-Hash zu erstellen kann einige Zeit\in Anspruch nehmen. Die benötigte Zeit\ist von der Dateigröße abhängig.\\Möchtest du fortfahren?"
SAVE_MODIFICATIONS = "Möchtest du die Änderungen speichern?"
REFRESH_LIVEAREA_QUESTION = "Die Livearea zu aktualisieren kann einige Zeit in Anspruch nehmen.\Möchtest du fortfahren?"
# HENkaku Einstellungen Texte
HENKAKU_SETTINGS = "HENkaku Einstellungen"
HENKAKU_ENABLE_PSN_SPOOFING = "Aktiviere PSN Vortäuschung"
HENKAKU_ENABLE_UNSAFE_HOMEBREW = "Nicht sichere Homebrews zulassen"
HENKAKU_ENABLE_VERSION_SPOOFING = "Aktiviere Versions Vortäuschung"
HENKAKU_SPOOFED_VERSION = "Vorgetäuschte Version"
HENKAKU_RESTORE_DEFAULT_SETTINGS = "Stelle Standardeinstellungen wieder her"
HENKAKU_RELOAD_CONFIG = "taiHEN config.txt zurücksetzen"
HENKAKU_RESTORE_DEFAULT_MESSAGE = "Standardeinstellungen wurden erfolgreich zurückgesetzt."
HENKAKU_RELOAD_CONFIG_MESSAGE = "taiHEN config.txt wurde erfolgreich zurückgesetzt."
HENKAKU_UNSAFE_HOMEBREW_MESSAGE = "Nicht sichere Homebrews können dein Gerät\permanent beschädigen, wenn diese falsch angewendet,\eingestellt oder böswillig genutzt werden.\Bitte sei vorsichtig, wenn du diese installierst."
# VitaShell Einstellungen
VITASHELL_SETTINGS_MAIN = "Haupteinstellungen"
VITASHELL_SETTINGS_LANGUAGE = "Sprache"
VITASHELL_SETTINGS_THEME = "Thema"
VITASHELL_SETTINGS_USBDEVICE = "USB Gerät"
VITASHELL_SETTINGS_SELECT_BUTTON = "SELECT Knopf"
VITASHELL_SETTINGS_NO_AUTO_UPDATE = "Auto-Update deaktivieren"
VITASHELL_SETTINGS_RESTART_SHELL = "VitaShell Neustarten"
VITASHELL_SETTINGS_POWER = "Power"
VITASHELL_SETTINGS_REBOOT = "Neustarten"
VITASHELL_SETTINGS_POWEROFF = "Ausschalten"
VITASHELL_SETTINGS_STANDBY = "Standby"
VITASHELL_SETTINGS_USB_MEMORY_CARD = "Memory Card"
VITASHELL_SETTINGS_USB_GAME_CARD = "Game Card"
VITASHELL_SETTINGS_SELECT_BUTTON_USB = "USB"
VITASHELL_SETTINGS_SELECT_BUTTON_FTP = "FTP"
# USB Texte
USB_CONNECTED = "USB verbunden"
USB_UMA0_MOUNTED = "uma0: mounted."
USB_UX0_MOUNTED = "USB ux0: mounted."
USB_UX0_UMOUNTED = "USB ux0: umounted."
USB_NOT_CONNECTED = "Verbinde dieses Gerät mit einem PC durch ein USB Kabel"
USB_CONNECTION_NOT_AVAILABLE = "USB Verbindung ist auf diesem Gerät nicht verfügbar."
USB_WAIT_ATTACH = "Zum Fortsetzen bitte ein USB Gerät anschließen.\Wenn es bereits angeschlossen ist, bitte trennen\und erneut anschließen."
# Andere
IMC0_MOUNTED = "imc0: mounted."
SAFE_MODE = "SICHERER MODUS"
UNSAFE_MODE = "UNSICHERER MODUS"
PLEASE_WAIT = "Bitte warten..."
AME_CARD_NOT_FOUND = "Bitte eine Game Card einstecken."
NO_SPACE_ERROR = "Es steht nicht genügend Speicherplatz zur Verfügung.\Es wird %s an zusätzlichem freien Speicher benötigt."
EXTENDED_PERMISSIONS_REQUIRED = "Diese Funktion benötigt erweiterte Berechtigungen.\Bitte aktiviere zuerst 'Nicht sichere Homebrews zulassen'."
WIFI_ERROR = "Es wird eine aktive WLAN-Verbindung benötigt."
FTP_SERVER = "FTP-Server läuft unter\ftp://%s:%i\\Drücke 'OK', um den Server im Hintergrund laufen zu lassen.\Drücke 'Abbrechen', um die Verbindung zu trennen."
UPDATE_QUESTION = "VitaShell %s ist jetzt verfügbar.\\Möchtest du die Anwendung aktualisieren?"
ARCHIVE_NAME = "Archiv Name"
COMPRESSION_LEVEL = "Kompressionslevel (0-9)"

View File

@ -1,203 +1,203 @@
# VitaShell norwegian translation by habibi
# General strings
ERROR = "Feilmelding 0x%08X."
OK = "OK"
YES = "Ja"
NO = "Nei"
CANCEL = "Avbryt"
ON = "På"
OFF = "Av"
FILE_ = "Fil"
FOLDER = "Mappe"
# Progress strings
MOVING = "Flytter..."
COPYING = "Kopierer..."
DELETING = "Sletter..."
IMPORTING = "Importerer..."
EXPORTING = "Eksporterer..."
INSTALLING = "Installerer..."
DOWNLOADING = "Laster ned..."
EXTRACTING = "Pakker ut..."
COMPRESSING = "Komprimerer..."
HASHING = "Sjekker hash..."
REFRESHING = "Oppdaterer..."
SENDING = "Sender..."
RECEIVING = "Mottar..."
# Audio player strings
TITLE = "Tittel"
ALBUM = "Album"
ARTIST = "Artist"
GENRE = "Sjanger"
YEAR = "År"
# Hex editor strings
OFFSET = "Offset"
OPEN_HEX_EDITOR = "Åpne hex-redigeringsprogram"
# Text editor strings
EDIT_LINE = "Rediger linje"
ENTER_SEARCH_TERM = "Skriv inn søkeord"
# Context menu strings
REFRESH_LIVEAREA = "Oppdater LiveArea™"
REFRESH_LICENSE_DB = "Oppdater lisensdatabase"
MOUNT_UMA0 = "Monter uma0:"
MOUNT_IMC0 = "Monter imc0:"
MOUNT_USB_UX0 = "Monter USB ux0:"
UMOUNT_USB_UX0 = "Avmonter USB ux0:"
SORT_BY = "Sorter etter"
BY_NAME = "Navn"
BY_SIZE = "Størrelse"
BY_DATE = "Dato"
MARK_ALL = "Marker alle"
UNMARK_ALL = "Fjern markering"
MOVE = "Klipp ut"
COPY = "Kopier"
PASTE = "Lim inn"
DELETE = "Slett"
RENAME = "Endre navn"
NEW_FOLDER = "Ny mappe"
PROPERTIES = "Egenskaper"
SEND = "Send"
RECEIVE = "Motta"
MORE = "Mer"
COMPRESS = "Komprimer"
INSTALL_ALL = "Installer alle"
INSTALL_FOLDER = "Installer mappe"
CALCULATE_SHA1 = "Kalkuler SHA1"
OPEN_DECRYPTED = "Åpne dekryptert"
EXPORT_MEDIA = "Eksporter media"
CUT = "Kutt"
INSERT_EMPTY_LINE = "Sett inn tom linje"
SEARCH = "Søk"
# File browser properties strings
PROPERTY_NAME = "Navn"
PROPERTY_TYPE = "Type"
PROPERTY_FSELF_MODE = "FSELF modus"
PROPERTY_SIZE = "Størrelse"
PROPERTY_COMPRESSED_SIZE = "Komprimert størrelse"
PROPERTY_CONTAINS = "Inneholder"
PROPERTY_CONTAINS_FILES_FOLDERS = "%d filer, %d mapper"
PROPERTY_CREATION_DATE = "Opprettet"
PROPERTY_MODFICATION_DATE = "Modifisert"
PROPERTY_TYPE_ARCHIVE = "Arkiv"
PROPERTY_TYPE_BMP = "BMP bilde"
PROPERTY_TYPE_INI = "Konfigurasjonsfil"
PROPERTY_TYPE_JPEG = "JPEG bilde"
PROPERTY_TYPE_MP3 = "MP3 lydfil"
PROPERTY_TYPE_OGG = "OGG lydfil"
PROPERTY_TYPE_PNG = "PNG bilde"
PROPERTY_TYPE_SFO = "SFO fil"
PROPERTY_TYPE_TXT = "Tekstdokument"
PROPERTY_TYPE_VPK = "VPK pakke"
PROPERTY_TYPE_XML = "XML fil"
PROPERTY_TYPE_FSELF = "FSELF fil"
PROPERTY_FSELF_MODE_SAFE = "Sikker"
PROPERTY_FSELF_MODE_UNSAFE = "Usikker"
PROPERTY_FSELF_MODE_SCE = "SCE signert"
# File browser strings
REFRESHED = "Oppdaterte %d elementer."
COPIED_FILE = "Kopierte %d fil(er)."
COPIED_FOLDER = "Kopierte %d mappe(r)."
COPIED_FILES_FOLDERS = "Kopierte %d file(r)/mappe(r)."
IMPORTED_LICENSES = "Importerte %d lisens(er)."
# Dialog questions
DELETE_FILE_QUESTION = "Er du sikker på at du vil slette denne filen?"
DELETE_FOLDER_QUESTION = "Er du sikker på at du vil slette denne mappen?"
DELETE_FILES_FOLDERS_QUESTION = "Er du sikker på at du vil slette disse filene/mappene?"
EXPORT_FILE_QUESTION = "Vil du eksportere denne filen til media?"
EXPORT_FOLDER_QUESTION = "Vil du eksportere denne mappen til media?"
EXPORT_FILES_FOLDERS_QUESTION = "Vil du eksportere disse filene/mappene til media?"
EXPORT_NO_MEDIA = "Ingen mediafiler tilgjengelig til å eksportere."
EXPORT_SONGS_INFO = "Eksporterte %d song(er)."
EXPORT_VIDEOS_INFO = "Eksporterte %d video(er)."
EXPORT_PICTURES_INFO = "Eksporterte %d bilde(r)."
EXPORT_SONGS_VIDEOS_INFO = "Eksporterte %d sang(er) and %d video(er)."
EXPORT_SONGS_PICTURES_INFO = "Eksporterte %d sang(er) and %d bilde(r)."
EXPORT_VIDEOS_PICTURES_INFO = "Eksporterte %d video(er) and %d bilde(r)."
EXPORT_SONGS_VIDEOS_PICTURES_INFO = "Eksporterte %d sang(er) %d video(er) and %d bilde(r)."
INSTALL_ALL_QUESTION = "Vil du installere alle pakkene i denne mappen?"
INSTALL_FOLDER_QUESTION = "Vil du installere denne mappen?\Varsel: denne handlingen vil også slette\mappen etter installasjon!"
INSTALL_QUESTION = "Vil du installere denne pakken?"
INSTALL_WARNING = "Denne pakken krever utvidede tillatelser.\Den vil ha tilgang til dine personlige opplysninger.\Hvis du ikke fikk den av en trygg kilde,\fortsett på egen risiko.\\Vil du fortsette installasjonen?"
INSTALL_BRICK_WARNING = "Denne pakken bruker funksjoner som remonterer\partisjoner og kan potensielt ødelegge din enhet.\Hvis du ikke fikk den av en trygg kilde,\fortsett på egen risiko.\\Vil du fortsette installasjonen?"
HASH_FILE_QUESTION = "SHA1-hashing kan ta lang tid. Fortsette?"
SAVE_MODIFICATIONS = "Lagre endringer?"
REFRESH_LIVEAREA_QUESTION = "Oppdatering av LiveArea™ kan ta lang tid. Fortsette?"
REFRESH_LICENSE_DB_QUESTION = "Oppdatering av lisensdatabase kan ta lang tid. Fortsette?"
# HENkaku settings strings
HENKAKU_SETTINGS = "HENkaku instillinger"
HENKAKU_ENABLE_PSN_SPOOFING = "Aktiver PSN-forfalskning"
HENKAKU_ENABLE_UNSAFE_HOMEBREW = "Aktiver usikker homebrew"
HENKAKU_ENABLE_VERSION_SPOOFING = "Aktiver versjon-forfalskning"
HENKAKU_SPOOFED_VERSION = "Forfalsket versjon"
HENKAKU_RESTORE_DEFAULT_SETTINGS = "Gjenopprett standardinnstillinger"
HENKAKU_RELOAD_CONFIG = "Last inn taiHEN config.txt"
HENKAKU_RESTORE_DEFAULT_MESSAGE = "Standardinnstillinger gjenopprettet."
HENKAKU_RELOAD_CONFIG_MESSAGE = "taiHEN config.txt lastet inn."
HENKAKU_UNSAFE_HOMEBREW_MESSAGE = "Usikker homebrew kan skade enheten din\permanent, hvis de er misbrukt, feilkonfigurert,\eller skadelig.\Fortsett på egen risiko."
# VitaShell settings
VITASHELL_SETTINGS_MAIN = "Hovedinnstillinger"
VITASHELL_SETTINGS_LANGUAGE = "Språk"
VITASHELL_SETTINGS_THEME = "Tema"
VITASHELL_SETTINGS_USBDEVICE = "USB-enhet"
VITASHELL_SETTINGS_SELECT_BUTTON = "SELECT-knapp"
VITASHELL_SETTINGS_NO_AUTO_UPDATE = "Deaktiver automatiske oppdateringer"
VITASHELL_SETTINGS_RESTART_SHELL = "Restart VitaShell"
VITASHELL_SETTINGS_POWER = "Strøm"
VITASHELL_SETTINGS_REBOOT = "Restart"
VITASHELL_SETTINGS_POWEROFF = "Skru av"
VITASHELL_SETTINGS_STANDBY = "Standby"
VITASHELL_SETTINGS_USB_MEMORY_CARD = "Minnekort"
VITASHELL_SETTINGS_USB_GAME_CARD = "Spillkort"
VITASHELL_SETTINGS_USB_SD2VITA = "sd2vita"
VITASHELL_SETTINGS_USB_PSVSD = "psvsd"
VITASHELL_SETTINGS_SELECT_BUTTON_USB = "USB"
VITASHELL_SETTINGS_SELECT_BUTTON_FTP = "FTP"
# USB strings
USB_CONNECTED = "USB tilkoblet"
USB_UMA0_MOUNTED = "uma0: montert."
USB_UX0_MOUNTED = "USB ux0: montert."
USB_UX0_UMOUNTED = "USB ux0: avmontert."
USB_NOT_CONNECTED = "Koble til denne enheten med USB-kabel."
USB_CONNECTION_NOT_AVAILABLE = "USB-tilkobling er ikke tilgjengelig på denne enheten."
USB_WAIT_ATTACH = "Koble til USB-enhet for å fortsette.\Hvis den allerede er koblet til,\koble inn og ut."
# QR strings
QR_SCANNING = "Leter etter QR koder..."
QR_OPEN_WEBSITE = "Vil du åpne denne lenken?\%s"
QR_SHOW_CONTENTS = "QR Code sier:\%s"
QR_CONFIRM_INSTALL = "Vil du installere denne pakken?\%s\Fil: %s\Størrelse: %s"
QR_CONFIRM_DOWNLOAD = "Vil du laste ned denne filen?\%s\Fil: %s\Størrelse: %s"
# Adhoc strings
ADHOC_RECEIVE_SEARCHING_PSVITA = "Leter etter PS Vita.\Vennligst vent..."
ADHOC_SELECT_PSVITA = "Velg PS Vita:"
ADHOC_RECEIVE_QUESTION = "Vil du motta fra %s?"
ADHOC_CLIENT_DECLINED = "Klienten har nektet forespørselen."
# Others
IMC0_MOUNTED = "imc0: montert."
SAFE_MODE = "SIKKER MODUS"
UNSAFE_MODE = "USIKKER MODUS"
PLEASE_WAIT = "Vennligst vent..."
MEMORY_CARD_NOT_FOUND = "Vennligst sett inn minnekort."
GAME_CARD_NOT_FOUND = "Vennligst sett inn spillkort."
MICROSD_NOT_FOUND = "Vennligst sett inn microSD."
NO_SPACE_ERROR = "Det er ikke nok plass på minnekortet.\Minst %s mer plass er nødvendig."
EXTENDED_PERMISSIONS_REQUIRED = "Denne funksjonen krever utvidede tillatelser.\Vennligst skru på 'Aktiver usikker homebrew' først."
WIFI_ERROR = "Du trenger Wi-Fi for å gjøre dette."
FTP_SERVER = "FTP-server kjører på\ftp://%s:%i\\Velg 'OK' for å holde det i bakgrunnen.\Velg 'Avbryt' for å koble av."
UPDATE_QUESTION = "VitaShell %s er nå tilgjengelig.\\Vil du oppdatere?"
ARCHIVE_NAME = "Arkivnavn"
COMPRESSION_LEVEL = "Komprimeringsnivå (0-9)"
ENTER_PASSWORD = "Skriv inn passord"
# VitaShell norwegian translation by habibi
# General strings
ERROR = "Feilmelding 0x%08X."
OK = "OK"
YES = "Ja"
NO = "Nei"
CANCEL = "Avbryt"
ON = "På"
OFF = "Av"
FILE_ = "Fil"
FOLDER = "Mappe"
# Progress strings
MOVING = "Flytter..."
COPYING = "Kopierer..."
DELETING = "Sletter..."
IMPORTING = "Importerer..."
EXPORTING = "Eksporterer..."
INSTALLING = "Installerer..."
DOWNLOADING = "Laster ned..."
EXTRACTING = "Pakker ut..."
COMPRESSING = "Komprimerer..."
HASHING = "Sjekker hash..."
REFRESHING = "Oppdaterer..."
SENDING = "Sender..."
RECEIVING = "Mottar..."
# Audio player strings
TITLE = "Tittel"
ALBUM = "Album"
ARTIST = "Artist"
GENRE = "Sjanger"
YEAR = "År"
# Hex editor strings
OFFSET = "Offset"
OPEN_HEX_EDITOR = "Åpne hex-redigeringsprogram"
# Text editor strings
EDIT_LINE = "Rediger linje"
ENTER_SEARCH_TERM = "Skriv inn søkeord"
# Context menu strings
REFRESH_LIVEAREA = "Oppdater LiveArea™"
REFRESH_LICENSE_DB = "Oppdater lisensdatabase"
MOUNT_UMA0 = "Monter uma0:"
MOUNT_IMC0 = "Monter imc0:"
MOUNT_USB_UX0 = "Monter USB ux0:"
UMOUNT_USB_UX0 = "Avmonter USB ux0:"
SORT_BY = "Sorter etter"
BY_NAME = "Navn"
BY_SIZE = "Størrelse"
BY_DATE = "Dato"
MARK_ALL = "Marker alle"
UNMARK_ALL = "Fjern markering"
MOVE = "Klipp ut"
COPY = "Kopier"
PASTE = "Lim inn"
DELETE = "Slett"
RENAME = "Endre navn"
NEW_FOLDER = "Ny mappe"
PROPERTIES = "Egenskaper"
SEND = "Send"
RECEIVE = "Motta"
MORE = "Mer"
COMPRESS = "Komprimer"
INSTALL_ALL = "Installer alle"
INSTALL_FOLDER = "Installer mappe"
CALCULATE_SHA1 = "Kalkuler SHA1"
OPEN_DECRYPTED = "Åpne dekryptert"
EXPORT_MEDIA = "Eksporter media"
CUT = "Kutt"
INSERT_EMPTY_LINE = "Sett inn tom linje"
SEARCH = "Søk"
# File browser properties strings
PROPERTY_NAME = "Navn"
PROPERTY_TYPE = "Type"
PROPERTY_FSELF_MODE = "FSELF modus"
PROPERTY_SIZE = "Størrelse"
PROPERTY_COMPRESSED_SIZE = "Komprimert størrelse"
PROPERTY_CONTAINS = "Inneholder"
PROPERTY_CONTAINS_FILES_FOLDERS = "%d filer, %d mapper"
PROPERTY_CREATION_DATE = "Opprettet"
PROPERTY_MODFICATION_DATE = "Modifisert"
PROPERTY_TYPE_ARCHIVE = "Arkiv"
PROPERTY_TYPE_BMP = "BMP bilde"
PROPERTY_TYPE_INI = "Konfigurasjonsfil"
PROPERTY_TYPE_JPEG = "JPEG bilde"
PROPERTY_TYPE_MP3 = "MP3 lydfil"
PROPERTY_TYPE_OGG = "OGG lydfil"
PROPERTY_TYPE_PNG = "PNG bilde"
PROPERTY_TYPE_SFO = "SFO fil"
PROPERTY_TYPE_TXT = "Tekstdokument"
PROPERTY_TYPE_VPK = "VPK pakke"
PROPERTY_TYPE_XML = "XML fil"
PROPERTY_TYPE_FSELF = "FSELF fil"
PROPERTY_FSELF_MODE_SAFE = "Sikker"
PROPERTY_FSELF_MODE_UNSAFE = "Usikker"
PROPERTY_FSELF_MODE_SCE = "SCE signert"
# File browser strings
REFRESHED = "Oppdaterte %d elementer."
COPIED_FILE = "Kopierte %d fil(er)."
COPIED_FOLDER = "Kopierte %d mappe(r)."
COPIED_FILES_FOLDERS = "Kopierte %d file(r)/mappe(r)."
IMPORTED_LICENSES = "Importerte %d lisens(er)."
# Dialog questions
DELETE_FILE_QUESTION = "Er du sikker på at du vil slette denne filen?"
DELETE_FOLDER_QUESTION = "Er du sikker på at du vil slette denne mappen?"
DELETE_FILES_FOLDERS_QUESTION = "Er du sikker på at du vil slette disse filene/mappene?"
EXPORT_FILE_QUESTION = "Vil du eksportere denne filen til media?"
EXPORT_FOLDER_QUESTION = "Vil du eksportere denne mappen til media?"
EXPORT_FILES_FOLDERS_QUESTION = "Vil du eksportere disse filene/mappene til media?"
EXPORT_NO_MEDIA = "Ingen mediafiler tilgjengelig til å eksportere."
EXPORT_SONGS_INFO = "Eksporterte %d song(er)."
EXPORT_VIDEOS_INFO = "Eksporterte %d video(er)."
EXPORT_PICTURES_INFO = "Eksporterte %d bilde(r)."
EXPORT_SONGS_VIDEOS_INFO = "Eksporterte %d sang(er) and %d video(er)."
EXPORT_SONGS_PICTURES_INFO = "Eksporterte %d sang(er) and %d bilde(r)."
EXPORT_VIDEOS_PICTURES_INFO = "Eksporterte %d video(er) and %d bilde(r)."
EXPORT_SONGS_VIDEOS_PICTURES_INFO = "Eksporterte %d sang(er) %d video(er) and %d bilde(r)."
INSTALL_ALL_QUESTION = "Vil du installere alle pakkene i denne mappen?"
INSTALL_FOLDER_QUESTION = "Vil du installere denne mappen?\Varsel: denne handlingen vil også slette\mappen etter installasjon!"
INSTALL_QUESTION = "Vil du installere denne pakken?"
INSTALL_WARNING = "Denne pakken krever utvidede tillatelser.\Den vil ha tilgang til dine personlige opplysninger.\Hvis du ikke fikk den av en trygg kilde,\fortsett på egen risiko.\\Vil du fortsette installasjonen?"
INSTALL_BRICK_WARNING = "Denne pakken bruker funksjoner som remonterer\partisjoner og kan potensielt ødelegge din enhet.\Hvis du ikke fikk den av en trygg kilde,\fortsett på egen risiko.\\Vil du fortsette installasjonen?"
HASH_FILE_QUESTION = "SHA1-hashing kan ta lang tid. Fortsette?"
SAVE_MODIFICATIONS = "Lagre endringer?"
REFRESH_LIVEAREA_QUESTION = "Oppdatering av LiveArea™ kan ta lang tid. Fortsette?"
REFRESH_LICENSE_DB_QUESTION = "Oppdatering av lisensdatabase kan ta lang tid. Fortsette?"
# HENkaku settings strings
HENKAKU_SETTINGS = "HENkaku instillinger"
HENKAKU_ENABLE_PSN_SPOOFING = "Aktiver PSN-forfalskning"
HENKAKU_ENABLE_UNSAFE_HOMEBREW = "Aktiver usikker homebrew"
HENKAKU_ENABLE_VERSION_SPOOFING = "Aktiver versjon-forfalskning"
HENKAKU_SPOOFED_VERSION = "Forfalsket versjon"
HENKAKU_RESTORE_DEFAULT_SETTINGS = "Gjenopprett standardinnstillinger"
HENKAKU_RELOAD_CONFIG = "Last inn taiHEN config.txt"
HENKAKU_RESTORE_DEFAULT_MESSAGE = "Standardinnstillinger gjenopprettet."
HENKAKU_RELOAD_CONFIG_MESSAGE = "taiHEN config.txt lastet inn."
HENKAKU_UNSAFE_HOMEBREW_MESSAGE = "Usikker homebrew kan skade enheten din\permanent, hvis de er misbrukt, feilkonfigurert,\eller skadelig.\Fortsett på egen risiko."
# VitaShell settings
VITASHELL_SETTINGS_MAIN = "Hovedinnstillinger"
VITASHELL_SETTINGS_LANGUAGE = "Språk"
VITASHELL_SETTINGS_THEME = "Tema"
VITASHELL_SETTINGS_USBDEVICE = "USB-enhet"
VITASHELL_SETTINGS_SELECT_BUTTON = "SELECT-knapp"
VITASHELL_SETTINGS_NO_AUTO_UPDATE = "Deaktiver automatiske oppdateringer"
VITASHELL_SETTINGS_RESTART_SHELL = "Restart VitaShell"
VITASHELL_SETTINGS_POWER = "Strøm"
VITASHELL_SETTINGS_REBOOT = "Restart"
VITASHELL_SETTINGS_POWEROFF = "Skru av"
VITASHELL_SETTINGS_STANDBY = "Standby"
VITASHELL_SETTINGS_USB_MEMORY_CARD = "Minnekort"
VITASHELL_SETTINGS_USB_GAME_CARD = "Spillkort"
VITASHELL_SETTINGS_USB_SD2VITA = "sd2vita"
VITASHELL_SETTINGS_USB_PSVSD = "psvsd"
VITASHELL_SETTINGS_SELECT_BUTTON_USB = "USB"
VITASHELL_SETTINGS_SELECT_BUTTON_FTP = "FTP"
# USB strings
USB_CONNECTED = "USB tilkoblet"
USB_UMA0_MOUNTED = "uma0: montert."
USB_UX0_MOUNTED = "USB ux0: montert."
USB_UX0_UMOUNTED = "USB ux0: avmontert."
USB_NOT_CONNECTED = "Koble til denne enheten med USB-kabel."
USB_CONNECTION_NOT_AVAILABLE = "USB-tilkobling er ikke tilgjengelig på denne enheten."
USB_WAIT_ATTACH = "Koble til USB-enhet for å fortsette.\Hvis den allerede er koblet til,\koble inn og ut."
# QR strings
QR_SCANNING = "Leter etter QR koder..."
QR_OPEN_WEBSITE = "Vil du åpne denne lenken?\%s"
QR_SHOW_CONTENTS = "QR Code sier:\%s"
QR_CONFIRM_INSTALL = "Vil du installere denne pakken?\%s\Fil: %s\Størrelse: %s"
QR_CONFIRM_DOWNLOAD = "Vil du laste ned denne filen?\%s\Fil: %s\Størrelse: %s"
# Adhoc strings
ADHOC_RECEIVE_SEARCHING_PSVITA = "Leter etter PS Vita.\Vennligst vent..."
ADHOC_SELECT_PSVITA = "Velg PS Vita:"
ADHOC_RECEIVE_QUESTION = "Vil du motta fra %s?"
ADHOC_CLIENT_DECLINED = "Klienten har nektet forespørselen."
# Others
IMC0_MOUNTED = "imc0: montert."
SAFE_MODE = "SIKKER MODUS"
UNSAFE_MODE = "USIKKER MODUS"
PLEASE_WAIT = "Vennligst vent..."
MEMORY_CARD_NOT_FOUND = "Vennligst sett inn minnekort."
GAME_CARD_NOT_FOUND = "Vennligst sett inn spillkort."
MICROSD_NOT_FOUND = "Vennligst sett inn microSD."
NO_SPACE_ERROR = "Det er ikke nok plass på minnekortet.\Minst %s mer plass er nødvendig."
EXTENDED_PERMISSIONS_REQUIRED = "Denne funksjonen krever utvidede tillatelser.\Vennligst skru på 'Aktiver usikker homebrew' først."
WIFI_ERROR = "Du trenger Wi-Fi for å gjøre dette."
FTP_SERVER = "FTP-server kjører på\ftp://%s:%i\\Velg 'OK' for å holde det i bakgrunnen.\Velg 'Avbryt' for å koble av."
UPDATE_QUESTION = "VitaShell %s er nå tilgjengelig.\\Vil du oppdatere?"
ARCHIVE_NAME = "Arkivnavn"
COMPRESSION_LEVEL = "Komprimeringsnivå (0-9)"
ENTER_PASSWORD = "Skriv inn passord"

View File

@ -1,217 +1,217 @@
# VitaShell language file | класть в ux0:VitaShell/language/ | перевод play007 ('http://4pda.ru/forum/index.php?showuser=4495180')
# General strings
ERROR = "Ошибка 0x%08X."
OK = "OK"
YES = "Да"
NO = "Нет"
CANCEL = "Отмена"
ON = "Вкл."
OFF = "Откл."
FILE_ = "Файл"
FOLDER = "<Папка>"
# Progress strings
MOVING = "Перемещение.."
COPYING = "Копирование.."
DELETING = "Удаление.."
IMPORTING = "Импорт медиафайлов.."
EXPORTING = "Экспорт медиафайлов.."
INSTALLING = "Установка.."
DOWNLOADING = "Загрузка.."
EXTRACTING = "Извлечение.."
COMPRESSING = "Архивирование.."
HASHING = "Хеширование.."
REFRESHING = "Обновление.."
SENDING = "Отправка.."
RECEIVING = "Получение.."
# Audio player strings
TITLE = "Название"
ALBUM = "Альбом"
ARTIST = "Исполнитель"
GENRE = "Жанр"
YEAR = "Год"
# Hex editor strings
OFFSET = "Смещение:"
OPEN_HEX_EDITOR = "Открыть в Hex редакторе"
# Text editor strings
EDIT_LINE = "Редактировать строку"
ENTER_SEARCH_TERM = "Поиск.."
# Context menu strings
REFRESH_LIVEAREA = "Обновить LiveArea™"
REFRESH_LICENSE_DB = "Обновить базу лицензий"
MOUNT_UMA0 = "Смонтировать uma0:"
MOUNT_IMC0 = "Смонтировать imc0:"
MOUNT_XMC0 = "Смонтировать xmc0:"
UMOUNT_UMA0 = "Размонтировать uma0:"
UMOUNT_IMC0 = "Размонтировать imc0:"
UMOUNT_XMC0 = "Размонтировать xmc0:"
MOUNT_USB_UX0 = "Смонтировать USB в ux0:"
UMOUNT_USB_UX0 = "Размонтировать USB с ux0:"
MOUNT_GAMECARD_UX0 = "Смонтировать карту с игрой в ux0:"
UMOUNT_GAMECARD_UX0 = "Размонтировать карту с игрой в ux0:"
SORT_BY = "Сортировка"
BY_NAME = "По имени"
BY_SIZE = "По размеру"
BY_DATE = "По дате"
MARK_ALL = "Выделить всё"
UNMARK_ALL = "Снять выделение"
MOVE = "Переместить"
COPY = "Копировать"
PASTE = "Вставить"
DELETE = "Удалить"
RENAME = "Переименовать"
NEW_FOLDER = "Создать папку"
NEW = "Создать"
NEW_FILE = "Создать файл"
PROPERTIES = "Свойства"
SEND = "Отправить"
RECEIVE = "Принять"
MORE = "Дополнительно"
COMPRESS = "Архивировать"
INSTALL_ALL = "Установить все .vpk"
INSTALL_FOLDER = "Установить из папки"
CALCULATE_SHA1 = "Вычислить SHA1"
OPEN_DECRYPTED = "Открыть расшифрованным"
EXPORT_MEDIA = "Экспорт медиафайлов"
CUT = "Вырезать"
INSERT_EMPTY_LINE = "Вставить пустую строку"
SEARCH = "Поиск"
# File browser properties strings
PROPERTY_NAME = "Имя"
PROPERTY_TYPE = "Тип файла"
PROPERTY_FSELF_MODE = "Режим FSELF"
PROPERTY_SIZE = "Размер"
PROPERTY_COMPRESSED_SIZE = "Сжат до"
PROPERTY_CONTAINS = "Содержимое"
PROPERTY_CONTAINS_FILES_FOLDERS = "Файлов: %d, папок: %d"
PROPERTY_CREATION_DATE = "Дата создания"
PROPERTY_MODFICATION_DATE = "Дата изменения"
PROPERTY_TYPE_ARCHIVE = "Архив"
PROPERTY_TYPE_BMP = "Точечный рисунок"
PROPERTY_TYPE_INI = "Файл настроек"
PROPERTY_TYPE_JPEG = "Изображение JPEG"
PROPERTY_TYPE_MP3 = "Аудиофайл MP3"
PROPERTY_TYPE_OGG = "Аудиофайл OGG"
PROPERTY_TYPE_PNG = "Изображение PNG"
PROPERTY_TYPE_SFO = "Файл SFO"
PROPERTY_TYPE_TXT = "Текст. документ"
PROPERTY_TYPE_VPK = "Пакет VPK"
PROPERTY_TYPE_XML = "Файл XML"
PROPERTY_TYPE_FSELF = "Файл FSELF"
PROPERTY_FSELF_MODE_SAFE = "Безопасный"
PROPERTY_FSELF_MODE_UNSAFE = "Небезопасный"
PROPERTY_FSELF_MODE_SCE = "Подписан SCE"
# File browser strings
REFRESHED = "Обновлено %d файл(-ов)"
COPIED_FILE = "Скопирован(-о) %d файл(-ов)"
COPIED_FOLDER = "Скопирован(-о) %d папок(-ка)"
COPIED_FILES_FOLDERS = "Скопирован(-о) %d файлов/папок"
IMPORTED_LICENSES = "Импортировано %d лицензий(-я)."
# Dialog questions
DELETE_FILE_QUESTION = "Вы действительно хотите удалить этот файл?"
DELETE_FOLDER_QUESTION = "Вы действительно хотите удалить эту папку?"
DELETE_FILES_FOLDERS_QUESTION = "Вы действительно хотите удалить эти данные?"
EXPORT_FILE_QUESTION = "Экспортировать этот файл в медиатеку?"
EXPORT_FOLDER_QUESTION = "Экспортировать эту папку в медиатеку?"
EXPORT_FILES_FOLDERS_QUESTION = "Экспортировать выбранные данные в медиатеку?"
EXPORT_NO_MEDIA = "Нет подходящих для экспорта медиафайлов"
EXPORT_SONGS_INFO = "Отчёт:\\Экспортировано композиций: %d"
EXPORT_VIDEOS_INFO = "Отчёт:\\Экспортировано видео: %d"
EXPORT_PICTURES_INFO = "Отчёт:\\Экспортировано изображений: %d"
EXPORT_SONGS_VIDEOS_INFO = "Отчёт:\\Экспортировано:\Композиций: %d\Видео: %d"
EXPORT_SONGS_PICTURES_INFO = "Отчёт:\\Экспортировано:\Композиций: %d\Изображений: %d"
EXPORT_VIDEOS_PICTURES_INFO = "Отчёт:\\Экспортировано:\Видео: %d\Изображений: %d"
EXPORT_SONGS_VIDEOS_PICTURES_INFO = "Отчёт:\\Экспортировано:\Композиций: %d\Видео: %d\Изображений: %d"
INSTALL_ALL_QUESTION = "Установка vpk\\Установить все .vpk из этой папки?"
INSTALL_FOLDER_QUESTION = "Установка из папки\\Использовать данную папку в качестве источника\для установки пакета?\Внимание:\По окончанию процесса установки папка и её\содержимое будут удалены!"
INSTALL_QUESTION = "Установка .vpk\\Установить данный пакет?"
INSTALL_WARNING = "Внимание!\\Установка пакета требует доступа к системным разделам.\Это позволяет получить доступ к вашим личным данным.\Пакеты, скачанные из непроверенных источников, могут\содержать вредоносный код.\\Продолжить установку?"
INSTALL_BRICK_WARNING = "Внимание!\\Установка пакета требует доступа к системным разделам.\При наличии вредоносного кода, ваше устройство может\быть безвозвратно выведено из строя.\Установка пакетов, скачанных из непроверенных источников,\производится на ваш страх и риск.\\Продолжить установку?"
HASH_FILE_QUESTION = "Внимание!\\Рассчёт хеша SHA1 может занять длительное время.\Продолжить?"
SAVE_MODIFICATIONS = "Вы хотите сохранить свои изменения?"
REFRESH_LIVEAREA_QUESTION = "Обновление LiveArea™ может занять время. Продолжить?"
REFRESH_LICENSE_DB_QUESTION = "Обновление базы лицензий может занять время. Продолжить?"
# HENkaku settings strings
HENKAKU_SETTINGS = "Настройки HENkaku"
HENKAKU_ENABLE_PSN_SPOOFING = "Включить PSN спуффинг"
HENKAKU_ENABLE_UNSAFE_HOMEBREW = "Включить небезопасные приложения"
HENKAKU_ENABLE_VERSION_SPOOFING = "Включить подмену версии"
HENKAKU_SPOOFED_VERSION = "Поддельная версия"
HENKAKU_RESTORE_DEFAULT_SETTINGS = "Восстановить стандартные настройки"
HENKAKU_RELOAD_CONFIG = "Перезагрузить taiHEN config.txt"
HENKAKU_RESTORE_DEFAULT_MESSAGE = "Стандартные настройки восстановлены"
HENKAKU_RELOAD_CONFIG_MESSAGE = "taiHEN config.txt был успешно перезагружен"
HENKAKU_UNSAFE_HOMEBREW_MESSAGE = "Небезопасные приложения могут повредить ваше устройство навсегда, если они используются неправильно, неправильно настроены, или вредоносны.\Пожалуйста, проявляйте осторожность при их установке."
# VitaShell settings
VITASHELL_SETTINGS_MAIN = "Настройки VitaShell"
VITASHELL_SETTINGS_LANGUAGE = "Язык%"
VITASHELL_SETTINGS_THEME = "Тема:"
VITASHELL_SETTINGS_USBDEVICE = "USB устройство:"
VITASHELL_SETTINGS_SELECT_BUTTON = "Действие кнопки SELECT:"
VITASHELL_SETTINGS_NO_AUTO_UPDATE = "Отключить автообновление:"
VITASHELL_SETTINGS_RESTART_SHELL = "Перезапустить VitaShell"
VITASHELL_SETTINGS_POWER = "Питание"
VITASHELL_SETTINGS_REBOOT = "Перезагрузка"
VITASHELL_SETTINGS_POWEROFF = "Выключение"
VITASHELL_SETTINGS_STANDBY = "Сон"
VITASHELL_SETTINGS_USB_MEMORY_CARD = "Карта памяти"
VITASHELL_SETTINGS_USB_GAME_CARD = "Карта с игрой"
VITASHELL_SETTINGS_USB_SD2VITA = "SD2Vita"
VITASHELL_SETTINGS_USB_PSVSD = "psvsd"
VITASHELL_SETTINGS_SELECT_BUTTON_USB = "USB соединение"
VITASHELL_SETTINGS_SELECT_BUTTON_FTP = "FTP сервер"
# USB strings
USB_CONNECTED = "Передача данных:\USB соединение установлено"
USB_UX0_MOUNTED = "USB носитель смонтирован в ux0:"
USB_UX0_UMOUNTED = "USB носитель размонтирован с ux0:"
GAMECARD_UX0_MOUNTED = "Карта с игрой смонтирована в ux0:"
GAMECARD_UX0_uMOUNTED = "Карта с игрой размонтирована с ux0:"
USB_NOT_CONNECTED = "Передача данных:\Подключите PS Vita к ПК с помощью USB кабеля"
USB_CONNECTION_NOT_AVAILABLE = "Ошибка:\\Невозножно активировать USB соединение на этом устройстве"
USB_WAIT_ATTACH = "Подключите USB накопитель, прежде чем продолжить.\Если уже установлено, попробуйте\извлечь его и подключить повторно"
# QR strings
QR_SCANNING = "Поднесите приставку к QR-коду"
QR_OPEN_WEBSITE = "Вы хотите открыть этот сайт?:\%s"
QR_SHOW_CONTENTS = "QR-код имеет:\%s"
QR_CONFIRM_INSTALL = "Вы хотите установить:\%s\Файл: %s\Размер: %s"
QR_CONFIRM_DOWNLOAD = "Вы хотите скачать:\%s\Файл: %s\Размер: %s"
# Adhoc strings
ADHOC_RECEIVE_SEARCHING_PSVITA = "Поиск PSVita для получения файла\Пожалуйста, подождите"
ADHOC_SELECT_PSVITA = "Выберите PSVita:"
ADHOC_RECEIVE_QUESTION = "Вы хотите получить от %s?"
ADHOC_CLIENT_DECLINED = "Клиент отклонил ваш запрос"
# Others
UMA0_MOUNTED = "uma0: смонтировано"
UMA0_UMOUNTED = "uma0: размонтировано"
IMC0_MOUNTED = "imc0: смонтировано"
IMC0_UMOUNTED = "imc0: размонтировано"
XMC0_MOUNTED = "xmc0: смонтировано"
XMC0_UMOUNTED = "xmc0: размонтировано"
SAFE_MODE = "БЕЗОПАСНЫЙ РЕЖИМ"
UNSAFE_MODE = "НЕБЕЗОПАСНЫЙ РЕЖИМ"
PLEASE_WAIT = "Момент.."
MEMORY_CARD_NOT_FOUND = "Пожалуйста, вставьте карту памяти в PS Vita"
GAME_CARD_NOT_FOUND = "Пожалуйста, вставьте карту с игрой"
MICROSD_NOT_FOUND = "Пожалуйста, вставьте MicroSD"
NO_SPACE_ERROR = "Внимание!\Недостаточно свободного места на карте памяти.\Необходимо минимум %s."
EXTENDED_PERMISSIONS_REQUIRED = "Для выполения этого действия нужны права\Чтобы их получить, поставьте галку на/'Включить небезопасные приложения' в настройках HENkaku"
WIFI_ERROR = "Для запуска FTP-сервера нужно Wi-Fi соединение"
FTP_SERVER = "FTP-сервер доступен по адресу:\ftp://%s:%i\\'OK' - скрыть окно (сервер в фоне)\'Отмена' - остановка сервера"
UPDATE_QUESTION = "Для установки доступна VitaShell %s.\\Выполнить обновление?"
ARCHIVE_NAME = "Имя архива"
COMPRESSION_LEVEL = "Уровень сжатия (0-9)"
ENTER_PASSWORD = "Введите пароль"
# VitaShell language file | класть в ux0:VitaShell/language/ | перевод play007 ('http://4pda.ru/forum/index.php?showuser=4495180')
# General strings
ERROR = "Ошибка 0x%08X."
OK = "OK"
YES = "Да"
NO = "Нет"
CANCEL = "Отмена"
ON = "Вкл."
OFF = "Откл."
FILE_ = "Файл"
FOLDER = "<Папка>"
# Progress strings
MOVING = "Перемещение.."
COPYING = "Копирование.."
DELETING = "Удаление.."
IMPORTING = "Импорт медиафайлов.."
EXPORTING = "Экспорт медиафайлов.."
INSTALLING = "Установка.."
DOWNLOADING = "Загрузка.."
EXTRACTING = "Извлечение.."
COMPRESSING = "Архивирование.."
HASHING = "Хеширование.."
REFRESHING = "Обновление.."
SENDING = "Отправка.."
RECEIVING = "Получение.."
# Audio player strings
TITLE = "Название"
ALBUM = "Альбом"
ARTIST = "Исполнитель"
GENRE = "Жанр"
YEAR = "Год"
# Hex editor strings
OFFSET = "Смещение:"
OPEN_HEX_EDITOR = "Открыть в Hex редакторе"
# Text editor strings
EDIT_LINE = "Редактировать строку"
ENTER_SEARCH_TERM = "Поиск.."
# Context menu strings
REFRESH_LIVEAREA = "Обновить LiveArea™"
REFRESH_LICENSE_DB = "Обновить базу лицензий"
MOUNT_UMA0 = "Смонтировать uma0:"
MOUNT_IMC0 = "Смонтировать imc0:"
MOUNT_XMC0 = "Смонтировать xmc0:"
UMOUNT_UMA0 = "Размонтировать uma0:"
UMOUNT_IMC0 = "Размонтировать imc0:"
UMOUNT_XMC0 = "Размонтировать xmc0:"
MOUNT_USB_UX0 = "Смонтировать USB в ux0:"
UMOUNT_USB_UX0 = "Размонтировать USB с ux0:"
MOUNT_GAMECARD_UX0 = "Смонтировать карту с игрой в ux0:"
UMOUNT_GAMECARD_UX0 = "Размонтировать карту с игрой в ux0:"
SORT_BY = "Сортировка"
BY_NAME = "По имени"
BY_SIZE = "По размеру"
BY_DATE = "По дате"
MARK_ALL = "Выделить всё"
UNMARK_ALL = "Снять выделение"
MOVE = "Переместить"
COPY = "Копировать"
PASTE = "Вставить"
DELETE = "Удалить"
RENAME = "Переименовать"
NEW_FOLDER = "Создать папку"
NEW = "Создать"
NEW_FILE = "Создать файл"
PROPERTIES = "Свойства"
SEND = "Отправить"
RECEIVE = "Принять"
MORE = "Дополнительно"
COMPRESS = "Архивировать"
INSTALL_ALL = "Установить все .vpk"
INSTALL_FOLDER = "Установить из папки"
CALCULATE_SHA1 = "Вычислить SHA1"
OPEN_DECRYPTED = "Открыть расшифрованным"
EXPORT_MEDIA = "Экспорт медиафайлов"
CUT = "Вырезать"
INSERT_EMPTY_LINE = "Вставить пустую строку"
SEARCH = "Поиск"
# File browser properties strings
PROPERTY_NAME = "Имя"
PROPERTY_TYPE = "Тип файла"
PROPERTY_FSELF_MODE = "Режим FSELF"
PROPERTY_SIZE = "Размер"
PROPERTY_COMPRESSED_SIZE = "Сжат до"
PROPERTY_CONTAINS = "Содержимое"
PROPERTY_CONTAINS_FILES_FOLDERS = "Файлов: %d, папок: %d"
PROPERTY_CREATION_DATE = "Дата создания"
PROPERTY_MODFICATION_DATE = "Дата изменения"
PROPERTY_TYPE_ARCHIVE = "Архив"
PROPERTY_TYPE_BMP = "Точечный рисунок"
PROPERTY_TYPE_INI = "Файл настроек"
PROPERTY_TYPE_JPEG = "Изображение JPEG"
PROPERTY_TYPE_MP3 = "Аудиофайл MP3"
PROPERTY_TYPE_OGG = "Аудиофайл OGG"
PROPERTY_TYPE_PNG = "Изображение PNG"
PROPERTY_TYPE_SFO = "Файл SFO"
PROPERTY_TYPE_TXT = "Текст. документ"
PROPERTY_TYPE_VPK = "Пакет VPK"
PROPERTY_TYPE_XML = "Файл XML"
PROPERTY_TYPE_FSELF = "Файл FSELF"
PROPERTY_FSELF_MODE_SAFE = "Безопасный"
PROPERTY_FSELF_MODE_UNSAFE = "Небезопасный"
PROPERTY_FSELF_MODE_SCE = "Подписан SCE"
# File browser strings
REFRESHED = "Обновлено %d файл(-ов)"
COPIED_FILE = "Скопирован(-о) %d файл(-ов)"
COPIED_FOLDER = "Скопирован(-о) %d папок(-ка)"
COPIED_FILES_FOLDERS = "Скопирован(-о) %d файлов/папок"
IMPORTED_LICENSES = "Импортировано %d лицензий(-я)."
# Dialog questions
DELETE_FILE_QUESTION = "Вы действительно хотите удалить этот файл?"
DELETE_FOLDER_QUESTION = "Вы действительно хотите удалить эту папку?"
DELETE_FILES_FOLDERS_QUESTION = "Вы действительно хотите удалить эти данные?"
EXPORT_FILE_QUESTION = "Экспортировать этот файл в медиатеку?"
EXPORT_FOLDER_QUESTION = "Экспортировать эту папку в медиатеку?"
EXPORT_FILES_FOLDERS_QUESTION = "Экспортировать выбранные данные в медиатеку?"
EXPORT_NO_MEDIA = "Нет подходящих для экспорта медиафайлов"
EXPORT_SONGS_INFO = "Отчёт:\\Экспортировано композиций: %d"
EXPORT_VIDEOS_INFO = "Отчёт:\\Экспортировано видео: %d"
EXPORT_PICTURES_INFO = "Отчёт:\\Экспортировано изображений: %d"
EXPORT_SONGS_VIDEOS_INFO = "Отчёт:\\Экспортировано:\Композиций: %d\Видео: %d"
EXPORT_SONGS_PICTURES_INFO = "Отчёт:\\Экспортировано:\Композиций: %d\Изображений: %d"
EXPORT_VIDEOS_PICTURES_INFO = "Отчёт:\\Экспортировано:\Видео: %d\Изображений: %d"
EXPORT_SONGS_VIDEOS_PICTURES_INFO = "Отчёт:\\Экспортировано:\Композиций: %d\Видео: %d\Изображений: %d"
INSTALL_ALL_QUESTION = "Установка vpk\\Установить все .vpk из этой папки?"
INSTALL_FOLDER_QUESTION = "Установка из папки\\Использовать данную папку в качестве источника\для установки пакета?\Внимание:\По окончанию процесса установки папка и её\содержимое будут удалены!"
INSTALL_QUESTION = "Установка .vpk\\Установить данный пакет?"
INSTALL_WARNING = "Внимание!\\Установка пакета требует доступа к системным разделам.\Это позволяет получить доступ к вашим личным данным.\Пакеты, скачанные из непроверенных источников, могут\содержать вредоносный код.\\Продолжить установку?"
INSTALL_BRICK_WARNING = "Внимание!\\Установка пакета требует доступа к системным разделам.\При наличии вредоносного кода, ваше устройство может\быть безвозвратно выведено из строя.\Установка пакетов, скачанных из непроверенных источников,\производится на ваш страх и риск.\\Продолжить установку?"
HASH_FILE_QUESTION = "Внимание!\\Рассчёт хеша SHA1 может занять длительное время.\Продолжить?"
SAVE_MODIFICATIONS = "Вы хотите сохранить свои изменения?"
REFRESH_LIVEAREA_QUESTION = "Обновление LiveArea™ может занять время. Продолжить?"
REFRESH_LICENSE_DB_QUESTION = "Обновление базы лицензий может занять время. Продолжить?"
# HENkaku settings strings
HENKAKU_SETTINGS = "Настройки HENkaku"
HENKAKU_ENABLE_PSN_SPOOFING = "Включить PSN спуффинг"
HENKAKU_ENABLE_UNSAFE_HOMEBREW = "Включить небезопасные приложения"
HENKAKU_ENABLE_VERSION_SPOOFING = "Включить подмену версии"
HENKAKU_SPOOFED_VERSION = "Поддельная версия"
HENKAKU_RESTORE_DEFAULT_SETTINGS = "Восстановить стандартные настройки"
HENKAKU_RELOAD_CONFIG = "Перезагрузить taiHEN config.txt"
HENKAKU_RESTORE_DEFAULT_MESSAGE = "Стандартные настройки восстановлены"
HENKAKU_RELOAD_CONFIG_MESSAGE = "taiHEN config.txt был успешно перезагружен"
HENKAKU_UNSAFE_HOMEBREW_MESSAGE = "Небезопасные приложения могут повредить ваше устройство навсегда, если они используются неправильно, неправильно настроены, или вредоносны.\Пожалуйста, проявляйте осторожность при их установке."
# VitaShell settings
VITASHELL_SETTINGS_MAIN = "Настройки VitaShell"
VITASHELL_SETTINGS_LANGUAGE = "Язык%"
VITASHELL_SETTINGS_THEME = "Тема:"
VITASHELL_SETTINGS_USBDEVICE = "USB устройство:"
VITASHELL_SETTINGS_SELECT_BUTTON = "Действие кнопки SELECT:"
VITASHELL_SETTINGS_NO_AUTO_UPDATE = "Отключить автообновление:"
VITASHELL_SETTINGS_RESTART_SHELL = "Перезапустить VitaShell"
VITASHELL_SETTINGS_POWER = "Питание"
VITASHELL_SETTINGS_REBOOT = "Перезагрузка"
VITASHELL_SETTINGS_POWEROFF = "Выключение"
VITASHELL_SETTINGS_STANDBY = "Сон"
VITASHELL_SETTINGS_USB_MEMORY_CARD = "Карта памяти"
VITASHELL_SETTINGS_USB_GAME_CARD = "Карта с игрой"
VITASHELL_SETTINGS_USB_SD2VITA = "SD2Vita"
VITASHELL_SETTINGS_USB_PSVSD = "psvsd"
VITASHELL_SETTINGS_SELECT_BUTTON_USB = "USB соединение"
VITASHELL_SETTINGS_SELECT_BUTTON_FTP = "FTP сервер"
# USB strings
USB_CONNECTED = "Передача данных:\USB соединение установлено"
USB_UX0_MOUNTED = "USB носитель смонтирован в ux0:"
USB_UX0_UMOUNTED = "USB носитель размонтирован с ux0:"
GAMECARD_UX0_MOUNTED = "Карта с игрой смонтирована в ux0:"
GAMECARD_UX0_uMOUNTED = "Карта с игрой размонтирована с ux0:"
USB_NOT_CONNECTED = "Передача данных:\Подключите PS Vita к ПК с помощью USB кабеля"
USB_CONNECTION_NOT_AVAILABLE = "Ошибка:\\Невозножно активировать USB соединение на этом устройстве"
USB_WAIT_ATTACH = "Подключите USB накопитель, прежде чем продолжить.\Если уже установлено, попробуйте\извлечь его и подключить повторно"
# QR strings
QR_SCANNING = "Поднесите приставку к QR-коду"
QR_OPEN_WEBSITE = "Вы хотите открыть этот сайт?:\%s"
QR_SHOW_CONTENTS = "QR-код имеет:\%s"
QR_CONFIRM_INSTALL = "Вы хотите установить:\%s\Файл: %s\Размер: %s"
QR_CONFIRM_DOWNLOAD = "Вы хотите скачать:\%s\Файл: %s\Размер: %s"
# Adhoc strings
ADHOC_RECEIVE_SEARCHING_PSVITA = "Поиск PSVita для получения файла\Пожалуйста, подождите"
ADHOC_SELECT_PSVITA = "Выберите PSVita:"
ADHOC_RECEIVE_QUESTION = "Вы хотите получить от %s?"
ADHOC_CLIENT_DECLINED = "Клиент отклонил ваш запрос"
# Others
UMA0_MOUNTED = "uma0: смонтировано"
UMA0_UMOUNTED = "uma0: размонтировано"
IMC0_MOUNTED = "imc0: смонтировано"
IMC0_UMOUNTED = "imc0: размонтировано"
XMC0_MOUNTED = "xmc0: смонтировано"
XMC0_UMOUNTED = "xmc0: размонтировано"
SAFE_MODE = "БЕЗОПАСНЫЙ РЕЖИМ"
UNSAFE_MODE = "НЕБЕЗОПАСНЫЙ РЕЖИМ"
PLEASE_WAIT = "Момент.."
MEMORY_CARD_NOT_FOUND = "Пожалуйста, вставьте карту памяти в PS Vita"
GAME_CARD_NOT_FOUND = "Пожалуйста, вставьте карту с игрой"
MICROSD_NOT_FOUND = "Пожалуйста, вставьте MicroSD"
NO_SPACE_ERROR = "Внимание!\Недостаточно свободного места на карте памяти.\Необходимо минимум %s."
EXTENDED_PERMISSIONS_REQUIRED = "Для выполения этого действия нужны права\Чтобы их получить, поставьте галку на/'Включить небезопасные приложения' в настройках HENkaku"
WIFI_ERROR = "Для запуска FTP-сервера нужно Wi-Fi соединение"
FTP_SERVER = "FTP-сервер доступен по адресу:\ftp://%s:%i\\'OK' - скрыть окно (сервер в фоне)\'Отмена' - остановка сервера"
UPDATE_QUESTION = "Для установки доступна VitaShell %s.\\Выполнить обновление?"
ARCHIVE_NAME = "Имя архива"
COMPRESSION_LEVEL = "Уровень сжатия (0-9)"
ENTER_PASSWORD = "Введите пароль"

View File

@ -1,217 +1,217 @@
# VitaShell spanish translation by ppizarror, Shadyck, Darkmet98, Keizel and NikowFreak
# General strings - Carácteres generales
ERROR = "Error 0x%08X."
OK = "Aceptar"
YES = "Sí"
NO = "No"
CANCEL = "Cancelar"
ON = "Encendido"
OFF = "Apagado"
FILE_ = "Archivo"
FOLDER = "Carpeta"
# Progress strings - Carácteres de progresos
MOVING = "Moviendo..."
COPYING = "Copiando..."
DELETING = "Eliminando..."
IMPORTING = "Importando..."
EXPORTING = "Exportando..."
INSTALLING = "Instalando..."
DOWNLOADING = "Descargando..."
EXTRACTING = "Extrayendo..."
COMPRESSING = "Comprimiendo..."
HASHING = "Hashing..."
REFRESHING = "Actualizando..."
SENDING = "Enviando..."
RECEIVING = "Recibiendo..."
# Audio player strings - Carácteres del reproductor de audio
TITLE = "Título"
ALBUM = "Álbum"
ARTIST = "Artista"
GENRE = "Género"
YEAR = "Año"
# Hex editor strings - Carácteres del editor hexadecimal
OFFSET = "Offset"
OPEN_HEX_EDITOR = "Abrir editor hexadecimal"
# Text editor strings - Carácteres del editor de texto
EDIT_LINE = "Editar línea"
ENTER_SEARCH_TERM = "Introduzca el término de búsqueda"
# File browser context menu strings - Carácteres del menú contextual del explorador de archivos
REFRESH_LIVEAREA = "Actualizar LiveArea™"
REFRESH_LICENSE_DB = "Actualizar DB de licencias"
MOUNT_UMA0 = "Montar uma0:"
MOUNT_IMC0 = "Montar imc0:"
MOUNT_XMC0 = "Montar xmc0:"
UMOUNT_UMA0 = "Desmontar uma0:"
UMOUNT_IMC0 = "Desmontar imc0:"
UMOUNT_XMC0 = "Desmontar xmc0:"
MOUNT_USB_UX0 = "Montar USB ux0:"
UMOUNT_USB_UX0 = "Desmontar USB ux0:"
MOUNT_GAMECARD_UX0 = "Montar gamecard ux0:"
UMOUNT_GAMECARD_UX0 = "Desmontar gamecard ux0:"
SORT_BY = "Ordenar por"
BY_NAME = "Nombre"
BY_SIZE = "Tamaño"
BY_DATE = "Fecha"
MARK_ALL = "Marcar todo"
UNMARK_ALL = "Desmarcar todo"
MOVE = "Mover"
COPY = "Copiar"
PASTE = "Pegar"
DELETE = "Eliminar"
RENAME = "Renombrar"
NEW_FOLDER = "Nueva carpeta"
NEW = "Nuevo"
NEW_FILE = "Nuevo archivo"
PROPERTIES = "Propiedades"
SEND = "Enviar"
RECEIVE = "Recibir"
MORE = "Más"
COMPRESS = "Compresión"
INSTALL_ALL = "Instalar todo"
INSTALL_FOLDER = "Instalar carpeta"
CALCULATE_SHA1 = "Calcular SHA1"
OPEN_DECRYPTED = "Abrir desencriptado"
EXPORT_MEDIA = "Exportar multimedia"
CUT = "Cortar"
INSERT_EMPTY_LINE = "Insertar una línea"
SEARCH = "Buscar"
# File browser properties strings - Carácteres de las propiedades del explorador de archivos
PROPERTY_NAME = "Nombre"
PROPERTY_TYPE = "Tipo"
PROPERTY_FSELF_MODE = "Modo FSELF"
PROPERTY_SIZE = "Tamaño"
PROPERTY_COMPRESSED_SIZE = "Tamaño comprimido"
PROPERTY_CONTAINS = "Contiene"
PROPERTY_CONTAINS_FILES_FOLDERS = "%d archivos, %d carpetas"
PROPERTY_CREATION_DATE = "Fecha de creación"
PROPERTY_MODFICATION_DATE = "Fecha de última modificación"
PROPERTY_TYPE_ARCHIVE = "Archivo"
PROPERTY_TYPE_BMP = "Imagen Bitmap"
PROPERTY_TYPE_INI = "Archivo de configuración"
PROPERTY_TYPE_JPEG = "Imagen JPEG"
PROPERTY_TYPE_MP3 = "Archivo de audio MP3"
PROPERTY_TYPE_OGG = "Archivo de audio OGG"
PROPERTY_TYPE_PNG = "Imagen PNG"
PROPERTY_TYPE_SFO = "Archivo SFO"
PROPERTY_TYPE_TXT = "Documento de texto"
PROPERTY_TYPE_VPK = "Fichero VPK"
PROPERTY_TYPE_XML = "Archivo XML"
PROPERTY_TYPE_FSELF = "Archivo FSELF"
PROPERTY_FSELF_MODE_SAFE = "Seguro"
PROPERTY_FSELF_MODE_UNSAFE = "Inseguro"
PROPERTY_FSELF_MODE_SCE = "Firmado SCE"
# File browser strings - Carácteres del explorador de archivos
REFRESHED = "Actualizados %d elementos."
COPIED_FILE = "Copiados %d archivo/os."
COPIED_FOLDER = "Copiados %d carpeta/as."
COPIED_FILES_FOLDERS = "Copiados %d archivos y/o carpetas."
IMPORTED_LICENSES = "Importadas %d licencias."
# Dialog questions - Preguntas del diálogo
DELETE_FILE_QUESTION = "¿Estás seguro de que quieres eliminar este/os archivo/os?"
DELETE_FOLDER_QUESTION = "¿Estás seguro de que quieres eliminar esta/as carpeta/as?"
DELETE_FILES_FOLDERS_QUESTION = "¿Estás seguro de que quieres eliminar estas carpetas y/o archivos?"
EXPORT_FILE_QUESTION = "¿Quieres exportar este archivo a multimedia?"
EXPORT_FOLDER_QUESTION = "¿Quieres exportar esta carpeta a multimedia?"
EXPORT_FILES_FOLDERS_QUESTION = "¿Quieres exportar estas carpetas y/o archivos a multimedia?"
EXPORT_NO_MEDIA = "No hay archivos multimedia disponibles para exportar"
EXPORT_SONGS_INFO = "Exportada %d canción/es."
EXPORT_VIDEOS_INFO = "Exportado %d video/os."
EXPORT_PICTURES_INFO = "Exportada %d imagen/es."
EXPORT_SONGS_VIDEOS_INFO = "Exportado %d canción/es y %d vídeo/os."
EXPORT_SONGS_PICTURES_INFO = "Exportado %d canción/es y %d imagen/es."
EXPORT_VIDEOS_PICTURES_INFO = "Exportado %d vídeo/os y %d imagen/es."
EXPORT_SONGS_VIDEOS_PICTURES_INFO = "Exportado %d canción/es %d vídeo/os y %d imagen/es."
INSTALL_ALL_QUESTION = "¿Quieres instalar todos los ficheros que hay de esta carpeta?"
INSTALL_FOLDER_QUESTION = "¿Quieres instalar esta carpeta?\Aviso: ¡Esta acción también borrará\la carpeta después de la instalación!"
INSTALL_QUESTION = "¿Quieres instalar este fichero?"
INSTALL_WARNING = "Este fichero requiere de permisos especiales.\Puede tener acceso a tu información personal\Si no lo has obtenido en un sitio seguro,\por favor, procede con cuidado\\¿Quieres continuar con la instalación?"
INSTALL_BRICK_WARNING = "Este fichero usa funciones que remontan\particiones y puede dañar gravemente tu dispositivo\Si no lo has obtenido en un sitio seguro,\por favor, procede con cuidado\\¿Quieres continuar con la instalación?"
HASH_FILE_QUESTION = "Realizar la operación para el hashing SHA1 puede llegar a tardar un tiempo. ¿Quieres continuar?"
SAVE_MODIFICATIONS = "¿Desea guardar los cambios?"
REFRESH_LIVEAREA_QUESTION = "Actualizar LiveArea™ puede demorar unos minutos. ¿Quieres continuar?"
REFRESH_LICENSE_DB_QUESTION = "Actualizar la DB de licencias puede demorar unos minutos. ¿Quieres continuar?"
# HENkaku settings strings - Ajustes de HENkaku
HENKAKU_SETTINGS = "Opciones de HENkaku"
HENKAKU_ENABLE_PSN_SPOOFING = "Activar spoofing de PSN"
HENKAKU_ENABLE_UNSAFE_HOMEBREW = "Activar homebrew inseguro"
HENKAKU_ENABLE_VERSION_SPOOFING = "Activar spoofing de versión"
HENKAKU_SPOOFED_VERSION = "Versión spoofeada"
HENKAKU_RESTORE_DEFAULT_SETTINGS = "Restablecer opciones por defecto"
HENKAKU_RELOAD_CONFIG = "Recargar taiHEN config.txt"
HENKAKU_RESTORE_DEFAULT_MESSAGE = "La configuración por defecto ha sido correctamente restaurada."
HENKAKU_RELOAD_CONFIG_MESSAGE = "taiHEN config.txt ha sido correctamente recargado."
HENKAKU_UNSAFE_HOMEBREW_MESSAGE = "Homebrews inseguros pueden dañar tu dispositivo\permanentemente si se usan inadecuadamente, si se encuentran mal configurados,\o si son maliciosos.\\Por favor, procede con cuidado al instalarlos."
# VitaShell settings - Ajustes de VitaShell
VITASHELL_SETTINGS_MAIN = "Configuración principal"
VITASHELL_SETTINGS_LANGUAGE = "Idioma"
VITASHELL_SETTINGS_THEME = "Tema"
VITASHELL_SETTINGS_USBDEVICE = "Dispositivo USB"
VITASHELL_SETTINGS_SELECT_BUTTON = "Botón SELECT"
VITASHELL_SETTINGS_NO_AUTO_UPDATE = "Desactivar auto-actualización"
VITASHELL_SETTINGS_RESTART_SHELL = "Reiniciar VitaShell"
VITASHELL_SETTINGS_POWER = "Menú de Apagado"
VITASHELL_SETTINGS_REBOOT = "Reiniciar"
VITASHELL_SETTINGS_POWEROFF = "Apagar"
VITASHELL_SETTINGS_STANDBY = "Suspensión"
VITASHELL_SETTINGS_USB_MEMORY_CARD = "Tarjeta de Memoria"
VITASHELL_SETTINGS_USB_GAME_CARD = "Tarjeta de Juego"
VITASHELL_SETTINGS_USB_SD2VITA = "sd2vita"
VITASHELL_SETTINGS_USB_PSVSD = "psvsd"
VITASHELL_SETTINGS_SELECT_BUTTON_USB = "USB"
VITASHELL_SETTINGS_SELECT_BUTTON_FTP = "FTP"
# USB strings - Carácteres USB
USB_CONNECTED = "USB conectado"
USB_UX0_MOUNTED = "USB ux0: montada."
USB_UX0_UMOUNTED = "USB ux0: desmontada."
GAMECARD_UX0_MOUNTED = "gamecard ux0: montada."
GAMECARD_UX0_uMOUNTED = "gamecard ux0: desmontada."
USB_NOT_CONNECTED = "Conecta este sistema a un PC usando un cable USB."
USB_CONNECTION_NOT_AVAILABLE = "La conexión USB no está disponible en este dispositivo."
USB_WAIT_ATTACH = "Por favor, conecte un Pendrive USB para continuar\Si ya se ha conectado, por favor, desconectelo\y vuelva a conectarlo."
# QR strings - Carácteres QR
QR_SCANNING = "Escaneando códigos QR..."
QR_OPEN_WEBSITE = "¿Quieres abrir este enlace:\%s ?"
QR_SHOW_CONTENTS = "El código QR dice:\%s"
QR_CONFIRM_INSTALL = "¿Quieres instalar este paquete:\%s?\Archivo: %s\Peso: %s"
QR_CONFIRM_DOWNLOAD = "¿Quieres descargar este archivo:\%s?\Archivo: %s\Peso: %s"
# Adhoc strings - Carácteres Adhoc
ADHOC_RECEIVE_SEARCHING_PSVITA = "Buscando una PSVita para recibir archivos...\Por favor espere..."
ADHOC_SELECT_PSVITA = "Seleccione una PSVita:"
ADHOC_RECEIVE_QUESTION = "Quiere recibir desde %s?"
ADHOC_CLIENT_DECLINED = "El cliente ha rechazado su solicitud."
# Others - Otros
UMA0_MOUNTED = "uma0: montada."
UMA0_UMOUNTED = "uma0: desmontada."
IMC0_MOUNTED = "imc0: montada."
IMC0_UMOUNTED = "imc0: desmontada."
XMC0_MOUNTED = "xmc0: montada."
XMC0_UMOUNTED = "xmc0: desmontada."
SAFE_MODE = "MODO SEGURO"
UNSAFE_MODE = "MODO INSEGURO"
PLEASE_WAIT = "Por favor, espere..."
MEMORY_CARD_NOT_FOUND = "Por favor, introduzca la tarjeta de memoria."
GAME_CARD_NOT_FOUND = "Por favor, introduzca la tarjeta del juego."
MICROSD_NOT_FOUND = "Por favor, introduzca la Micro SD."
NO_SPACE_ERROR = "No hay espacio libre en la tarjeta de memoria.\Se necesita al menos %s de espacio."
EXTENDED_PERMISSIONS_REQUIRED = "Esta caracteristica requiere permisos especiales.\Por favor, activa 'Activar homebrew inseguro' primero."
WIFI_ERROR = "Tienes que activar la conexión Wi-Fi para usar esta función."
FTP_SERVER = "El servidor FTP está activo en\ftp://%s:%i\\Pulsa 'Aceptar' para mantenerlo en segundo plano\Pulsa 'Cancelar' para desconectarte."
UPDATE_QUESTION = "VitaShell %s está disponible\\¿Quieres actualizar la aplicación?"
ARCHIVE_NAME = "Nombre de archivo"
COMPRESSION_LEVEL = "Nivel de compresión (0-9)"
ENTER_PASSWORD = "Ingrese contraseña"
# VitaShell spanish translation by ppizarror, Shadyck, Darkmet98, Keizel and NikowFreak
# General strings - Carácteres generales
ERROR = "Error 0x%08X."
OK = "Aceptar"
YES = "Sí"
NO = "No"
CANCEL = "Cancelar"
ON = "Encendido"
OFF = "Apagado"
FILE_ = "Archivo"
FOLDER = "Carpeta"
# Progress strings - Carácteres de progresos
MOVING = "Moviendo..."
COPYING = "Copiando..."
DELETING = "Eliminando..."
IMPORTING = "Importando..."
EXPORTING = "Exportando..."
INSTALLING = "Instalando..."
DOWNLOADING = "Descargando..."
EXTRACTING = "Extrayendo..."
COMPRESSING = "Comprimiendo..."
HASHING = "Hashing..."
REFRESHING = "Actualizando..."
SENDING = "Enviando..."
RECEIVING = "Recibiendo..."
# Audio player strings - Carácteres del reproductor de audio
TITLE = "Título"
ALBUM = "Álbum"
ARTIST = "Artista"
GENRE = "Género"
YEAR = "Año"
# Hex editor strings - Carácteres del editor hexadecimal
OFFSET = "Offset"
OPEN_HEX_EDITOR = "Abrir editor hexadecimal"
# Text editor strings - Carácteres del editor de texto
EDIT_LINE = "Editar línea"
ENTER_SEARCH_TERM = "Introduzca el término de búsqueda"
# File browser context menu strings - Carácteres del menú contextual del explorador de archivos
REFRESH_LIVEAREA = "Actualizar LiveArea™"
REFRESH_LICENSE_DB = "Actualizar DB de licencias"
MOUNT_UMA0 = "Montar uma0:"
MOUNT_IMC0 = "Montar imc0:"
MOUNT_XMC0 = "Montar xmc0:"
UMOUNT_UMA0 = "Desmontar uma0:"
UMOUNT_IMC0 = "Desmontar imc0:"
UMOUNT_XMC0 = "Desmontar xmc0:"
MOUNT_USB_UX0 = "Montar USB ux0:"
UMOUNT_USB_UX0 = "Desmontar USB ux0:"
MOUNT_GAMECARD_UX0 = "Montar gamecard ux0:"
UMOUNT_GAMECARD_UX0 = "Desmontar gamecard ux0:"
SORT_BY = "Ordenar por"
BY_NAME = "Nombre"
BY_SIZE = "Tamaño"
BY_DATE = "Fecha"
MARK_ALL = "Marcar todo"
UNMARK_ALL = "Desmarcar todo"
MOVE = "Mover"
COPY = "Copiar"
PASTE = "Pegar"
DELETE = "Eliminar"
RENAME = "Renombrar"
NEW_FOLDER = "Nueva carpeta"
NEW = "Nuevo"
NEW_FILE = "Nuevo archivo"
PROPERTIES = "Propiedades"
SEND = "Enviar"
RECEIVE = "Recibir"
MORE = "Más"
COMPRESS = "Compresión"
INSTALL_ALL = "Instalar todo"
INSTALL_FOLDER = "Instalar carpeta"
CALCULATE_SHA1 = "Calcular SHA1"
OPEN_DECRYPTED = "Abrir desencriptado"
EXPORT_MEDIA = "Exportar multimedia"
CUT = "Cortar"
INSERT_EMPTY_LINE = "Insertar una línea"
SEARCH = "Buscar"
# File browser properties strings - Carácteres de las propiedades del explorador de archivos
PROPERTY_NAME = "Nombre"
PROPERTY_TYPE = "Tipo"
PROPERTY_FSELF_MODE = "Modo FSELF"
PROPERTY_SIZE = "Tamaño"
PROPERTY_COMPRESSED_SIZE = "Tamaño comprimido"
PROPERTY_CONTAINS = "Contiene"
PROPERTY_CONTAINS_FILES_FOLDERS = "%d archivos, %d carpetas"
PROPERTY_CREATION_DATE = "Fecha de creación"
PROPERTY_MODFICATION_DATE = "Fecha de última modificación"
PROPERTY_TYPE_ARCHIVE = "Archivo"
PROPERTY_TYPE_BMP = "Imagen Bitmap"
PROPERTY_TYPE_INI = "Archivo de configuración"
PROPERTY_TYPE_JPEG = "Imagen JPEG"
PROPERTY_TYPE_MP3 = "Archivo de audio MP3"
PROPERTY_TYPE_OGG = "Archivo de audio OGG"
PROPERTY_TYPE_PNG = "Imagen PNG"
PROPERTY_TYPE_SFO = "Archivo SFO"
PROPERTY_TYPE_TXT = "Documento de texto"
PROPERTY_TYPE_VPK = "Fichero VPK"
PROPERTY_TYPE_XML = "Archivo XML"
PROPERTY_TYPE_FSELF = "Archivo FSELF"
PROPERTY_FSELF_MODE_SAFE = "Seguro"
PROPERTY_FSELF_MODE_UNSAFE = "Inseguro"
PROPERTY_FSELF_MODE_SCE = "Firmado SCE"
# File browser strings - Carácteres del explorador de archivos
REFRESHED = "Actualizados %d elementos."
COPIED_FILE = "Copiados %d archivo/os."
COPIED_FOLDER = "Copiados %d carpeta/as."
COPIED_FILES_FOLDERS = "Copiados %d archivos y/o carpetas."
IMPORTED_LICENSES = "Importadas %d licencias."
# Dialog questions - Preguntas del diálogo
DELETE_FILE_QUESTION = "¿Estás seguro de que quieres eliminar este/os archivo/os?"
DELETE_FOLDER_QUESTION = "¿Estás seguro de que quieres eliminar esta/as carpeta/as?"
DELETE_FILES_FOLDERS_QUESTION = "¿Estás seguro de que quieres eliminar estas carpetas y/o archivos?"
EXPORT_FILE_QUESTION = "¿Quieres exportar este archivo a multimedia?"
EXPORT_FOLDER_QUESTION = "¿Quieres exportar esta carpeta a multimedia?"
EXPORT_FILES_FOLDERS_QUESTION = "¿Quieres exportar estas carpetas y/o archivos a multimedia?"
EXPORT_NO_MEDIA = "No hay archivos multimedia disponibles para exportar"
EXPORT_SONGS_INFO = "Exportada %d canción/es."
EXPORT_VIDEOS_INFO = "Exportado %d video/os."
EXPORT_PICTURES_INFO = "Exportada %d imagen/es."
EXPORT_SONGS_VIDEOS_INFO = "Exportado %d canción/es y %d vídeo/os."
EXPORT_SONGS_PICTURES_INFO = "Exportado %d canción/es y %d imagen/es."
EXPORT_VIDEOS_PICTURES_INFO = "Exportado %d vídeo/os y %d imagen/es."
EXPORT_SONGS_VIDEOS_PICTURES_INFO = "Exportado %d canción/es %d vídeo/os y %d imagen/es."
INSTALL_ALL_QUESTION = "¿Quieres instalar todos los ficheros que hay de esta carpeta?"
INSTALL_FOLDER_QUESTION = "¿Quieres instalar esta carpeta?\Aviso: ¡Esta acción también borrará\la carpeta después de la instalación!"
INSTALL_QUESTION = "¿Quieres instalar este fichero?"
INSTALL_WARNING = "Este fichero requiere de permisos especiales.\Puede tener acceso a tu información personal\Si no lo has obtenido en un sitio seguro,\por favor, procede con cuidado\\¿Quieres continuar con la instalación?"
INSTALL_BRICK_WARNING = "Este fichero usa funciones que remontan\particiones y puede dañar gravemente tu dispositivo\Si no lo has obtenido en un sitio seguro,\por favor, procede con cuidado\\¿Quieres continuar con la instalación?"
HASH_FILE_QUESTION = "Realizar la operación para el hashing SHA1 puede llegar a tardar un tiempo. ¿Quieres continuar?"
SAVE_MODIFICATIONS = "¿Desea guardar los cambios?"
REFRESH_LIVEAREA_QUESTION = "Actualizar LiveArea™ puede demorar unos minutos. ¿Quieres continuar?"
REFRESH_LICENSE_DB_QUESTION = "Actualizar la DB de licencias puede demorar unos minutos. ¿Quieres continuar?"
# HENkaku settings strings - Ajustes de HENkaku
HENKAKU_SETTINGS = "Opciones de HENkaku"
HENKAKU_ENABLE_PSN_SPOOFING = "Activar spoofing de PSN"
HENKAKU_ENABLE_UNSAFE_HOMEBREW = "Activar homebrew inseguro"
HENKAKU_ENABLE_VERSION_SPOOFING = "Activar spoofing de versión"
HENKAKU_SPOOFED_VERSION = "Versión spoofeada"
HENKAKU_RESTORE_DEFAULT_SETTINGS = "Restablecer opciones por defecto"
HENKAKU_RELOAD_CONFIG = "Recargar taiHEN config.txt"
HENKAKU_RESTORE_DEFAULT_MESSAGE = "La configuración por defecto ha sido correctamente restaurada."
HENKAKU_RELOAD_CONFIG_MESSAGE = "taiHEN config.txt ha sido correctamente recargado."
HENKAKU_UNSAFE_HOMEBREW_MESSAGE = "Homebrews inseguros pueden dañar tu dispositivo\permanentemente si se usan inadecuadamente, si se encuentran mal configurados,\o si son maliciosos.\\Por favor, procede con cuidado al instalarlos."
# VitaShell settings - Ajustes de VitaShell
VITASHELL_SETTINGS_MAIN = "Configuración principal"
VITASHELL_SETTINGS_LANGUAGE = "Idioma"
VITASHELL_SETTINGS_THEME = "Tema"
VITASHELL_SETTINGS_USBDEVICE = "Dispositivo USB"
VITASHELL_SETTINGS_SELECT_BUTTON = "Botón SELECT"
VITASHELL_SETTINGS_NO_AUTO_UPDATE = "Desactivar auto-actualización"
VITASHELL_SETTINGS_RESTART_SHELL = "Reiniciar VitaShell"
VITASHELL_SETTINGS_POWER = "Menú de Apagado"
VITASHELL_SETTINGS_REBOOT = "Reiniciar"
VITASHELL_SETTINGS_POWEROFF = "Apagar"
VITASHELL_SETTINGS_STANDBY = "Suspensión"
VITASHELL_SETTINGS_USB_MEMORY_CARD = "Tarjeta de Memoria"
VITASHELL_SETTINGS_USB_GAME_CARD = "Tarjeta de Juego"
VITASHELL_SETTINGS_USB_SD2VITA = "sd2vita"
VITASHELL_SETTINGS_USB_PSVSD = "psvsd"
VITASHELL_SETTINGS_SELECT_BUTTON_USB = "USB"
VITASHELL_SETTINGS_SELECT_BUTTON_FTP = "FTP"
# USB strings - Carácteres USB
USB_CONNECTED = "USB conectado"
USB_UX0_MOUNTED = "USB ux0: montada."
USB_UX0_UMOUNTED = "USB ux0: desmontada."
GAMECARD_UX0_MOUNTED = "gamecard ux0: montada."
GAMECARD_UX0_uMOUNTED = "gamecard ux0: desmontada."
USB_NOT_CONNECTED = "Conecta este sistema a un PC usando un cable USB."
USB_CONNECTION_NOT_AVAILABLE = "La conexión USB no está disponible en este dispositivo."
USB_WAIT_ATTACH = "Por favor, conecte un Pendrive USB para continuar\Si ya se ha conectado, por favor, desconectelo\y vuelva a conectarlo."
# QR strings - Carácteres QR
QR_SCANNING = "Escaneando códigos QR..."
QR_OPEN_WEBSITE = "¿Quieres abrir este enlace:\%s ?"
QR_SHOW_CONTENTS = "El código QR dice:\%s"
QR_CONFIRM_INSTALL = "¿Quieres instalar este paquete:\%s?\Archivo: %s\Peso: %s"
QR_CONFIRM_DOWNLOAD = "¿Quieres descargar este archivo:\%s?\Archivo: %s\Peso: %s"
# Adhoc strings - Carácteres Adhoc
ADHOC_RECEIVE_SEARCHING_PSVITA = "Buscando una PSVita para recibir archivos...\Por favor espere..."
ADHOC_SELECT_PSVITA = "Seleccione una PSVita:"
ADHOC_RECEIVE_QUESTION = "Quiere recibir desde %s?"
ADHOC_CLIENT_DECLINED = "El cliente ha rechazado su solicitud."
# Others - Otros
UMA0_MOUNTED = "uma0: montada."
UMA0_UMOUNTED = "uma0: desmontada."
IMC0_MOUNTED = "imc0: montada."
IMC0_UMOUNTED = "imc0: desmontada."
XMC0_MOUNTED = "xmc0: montada."
XMC0_UMOUNTED = "xmc0: desmontada."
SAFE_MODE = "MODO SEGURO"
UNSAFE_MODE = "MODO INSEGURO"
PLEASE_WAIT = "Por favor, espere..."
MEMORY_CARD_NOT_FOUND = "Por favor, introduzca la tarjeta de memoria."
GAME_CARD_NOT_FOUND = "Por favor, introduzca la tarjeta del juego."
MICROSD_NOT_FOUND = "Por favor, introduzca la Micro SD."
NO_SPACE_ERROR = "No hay espacio libre en la tarjeta de memoria.\Se necesita al menos %s de espacio."
EXTENDED_PERMISSIONS_REQUIRED = "Esta caracteristica requiere permisos especiales.\Por favor, activa 'Activar homebrew inseguro' primero."
WIFI_ERROR = "Tienes que activar la conexión Wi-Fi para usar esta función."
FTP_SERVER = "El servidor FTP está activo en\ftp://%s:%i\\Pulsa 'Aceptar' para mantenerlo en segundo plano\Pulsa 'Cancelar' para desconectarte."
UPDATE_QUESTION = "VitaShell %s está disponible\\¿Quieres actualizar la aplicación?"
ARCHIVE_NAME = "Nombre de archivo"
COMPRESSION_LEVEL = "Nivel de compresión (0-9)"
ENTER_PASSWORD = "Ingrese contraseña"

File diff suppressed because it is too large Load Diff

View File

@ -1,49 +1,49 @@
cmake_minimum_required(VERSION 2.8)
if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
if(DEFINED ENV{VITASDK})
set(CMAKE_TOOLCHAIN_FILE "$ENV{VITASDK}/share/vita.toolchain.cmake" CACHE PATH "toolchain file")
else()
message(FATAL_ERROR "Please define VITASDK to point to your SDK path!")
endif()
endif()
project(kernel)
include("${VITASDK}/share/vita.cmake" REQUIRED)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-q -Wall -O3 -nostdlib")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions")
add_executable(kernel
main.c
)
target_link_libraries(kernel
SceIofilemgrForDriver_stub
SceSysclibForDriver_stub
SceSysmemForDriver_stub
SceModulemgrForDriver_stub
SceThreadmgrForDriver_stub
SceProcessmgrForDriver_stub
SceNpDrmForDriver_stub
taihenForKernel_stub
taihenModuleUtils_stub
)
vita_create_self(kernel.skprx kernel CONFIG exports.yml UNSAFE)
vita_create_stubs(stubs kernel ${CMAKE_SOURCE_DIR}/exports.yml KERNEL)
install(DIRECTORY ${CMAKE_BINARY_DIR}/stubs/
DESTINATION lib
FILES_MATCHING PATTERN "*.a"
)
install(FILES vitashell_kernel.h
DESTINATION include
)
add_custom_target(copy
COMMAND cp kernel.skprx ../../../resources/kernel.skprx
DEPENDS kernel.skprx
cmake_minimum_required(VERSION 2.8)
if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
if(DEFINED ENV{VITASDK})
set(CMAKE_TOOLCHAIN_FILE "$ENV{VITASDK}/share/vita.toolchain.cmake" CACHE PATH "toolchain file")
else()
message(FATAL_ERROR "Please define VITASDK to point to your SDK path!")
endif()
endif()
project(kernel)
include("${VITASDK}/share/vita.cmake" REQUIRED)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-q -Wall -O3 -nostdlib")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions")
add_executable(kernel
main.c
)
target_link_libraries(kernel
SceIofilemgrForDriver_stub
SceSysclibForDriver_stub
SceSysmemForDriver_stub
SceModulemgrForDriver_stub
SceThreadmgrForDriver_stub
SceProcessmgrForDriver_stub
SceNpDrmForDriver_stub
taihenForKernel_stub
taihenModuleUtils_stub
)
vita_create_self(kernel.skprx kernel CONFIG exports.yml UNSAFE)
vita_create_stubs(stubs kernel ${CMAKE_SOURCE_DIR}/exports.yml KERNEL)
install(DIRECTORY ${CMAKE_BINARY_DIR}/stubs/
DESTINATION lib
FILES_MATCHING PATTERN "*.a"
)
install(FILES vitashell_kernel.h
DESTINATION include
)
add_custom_target(copy
COMMAND cp kernel.skprx ../../../resources/kernel.skprx
DEPENDS kernel.skprx
)

View File

@ -1,16 +1,16 @@
VitaShellKernel2:
attributes: 0
version:
major: 1
minor: 0
main:
start: module_start
stop: module_stop
modules:
VitaShellKernel2Library:
syscall: true
functions:
- shellKernelIsUx0Redirected
- shellKernelRedirectUx0
- shellKernelMountById
VitaShellKernel2:
attributes: 0
version:
major: 1
minor: 0
main:
start: module_start
stop: module_stop
modules:
VitaShellKernel2Library:
syscall: true
functions:
- shellKernelIsUx0Redirected
- shellKernelRedirectUx0
- shellKernelMountById
- shellKernelGetRifVitaKey

View File

@ -1,290 +1,290 @@
/*
VitaShell
Copyright (C) 2015-2018, 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 <psp2kern/kernel/cpu.h>
#include <psp2kern/kernel/modulemgr.h>
#include <psp2kern/kernel/sysmem.h>
#include <psp2kern/kernel/threadmgr.h>
#include <psp2kern/io/fcntl.h>
#include <stdio.h>
#include <string.h>
#include <taihen.h>
#include "vitashell_kernel.h"
#define MOUNT_POINT_ID 0x800
int module_get_export_func(SceUID pid, const char *modname, uint32_t libnid, uint32_t funcnid, uintptr_t *func);
int module_get_offset(SceUID pid, SceUID modid, int segidx, size_t offset, uintptr_t *addr);
typedef struct {
const char *dev;
const char *dev2;
const char *blkdev;
const char *blkdev2;
int id;
} SceIoDevice;
typedef struct {
int id;
const char *dev_unix;
int unk;
int dev_major;
int dev_minor;
const char *dev_filesystem;
int unk2;
SceIoDevice *dev;
int unk3;
SceIoDevice *dev2;
int unk4;
int unk5;
int unk6;
int unk7;
} SceIoMountPoint;
static char ux0_blkdev[64], ux0_blkdev2[64];
static SceIoDevice ux0_dev = { "ux0:", "exfatux0", ux0_blkdev, ux0_blkdev2, MOUNT_POINT_ID };
static SceIoMountPoint *(* sceIoFindMountPoint)(int id) = NULL;
static SceUID hookid = -1;
static tai_hook_ref_t ksceSysrootIsSafeModeRef;
static tai_hook_ref_t ksceSblAimgrIsDolceRef;
static int ksceSysrootIsSafeModePatched() {
return 1;
}
static int ksceSblAimgrIsDolcePatched() {
return 1;
}
int shellKernelIsUx0Redirected(const char *blkdev, const char *blkdev2) {
char k_blkdev[64], k_blkdev2[64];
uint32_t state;
ENTER_SYSCALL(state);
SceIoMountPoint *mount = sceIoFindMountPoint(MOUNT_POINT_ID);
if (!mount) {
EXIT_SYSCALL(state);
return 0;
}
ksceKernelStrncpyUserToKernel(k_blkdev, blkdev, sizeof(k_blkdev)-1);
ksceKernelStrncpyUserToKernel(k_blkdev2, blkdev2, sizeof(k_blkdev2)-1);
if (mount && mount->dev && mount->dev->blkdev && strcmp(mount->dev->blkdev, k_blkdev) == 0) {
EXIT_SYSCALL(state);
return 1;
}
EXIT_SYSCALL(state);
return 0;
}
int shellKernelRedirectUx0(const char *blkdev, const char *blkdev2) {
uint32_t state;
ENTER_SYSCALL(state);
SceIoMountPoint *mount = sceIoFindMountPoint(MOUNT_POINT_ID);
if (!mount) {
EXIT_SYSCALL(state);
return -1;
}
ksceKernelStrncpyUserToKernel(ux0_blkdev, blkdev, sizeof(ux0_blkdev)-1);
ksceKernelStrncpyUserToKernel(ux0_blkdev2, blkdev2, sizeof(ux0_blkdev2)-1);
mount->dev = &ux0_dev;
mount->dev2 = &ux0_dev;
EXIT_SYSCALL(state);
return 0;
}
int _shellKernelMountById(ShellMountIdArgs *args) {
int res;
void *(* sceAppMgrFindProcessInfoByPid)(void *data, SceUID pid);
int (* sceAppMgrMountById)(SceUID pid, void *info, int id, const char *titleid, const char *path, const char *desired_mount_point, const void *klicensee, char *mount_point);
int (* _ksceKernelGetModuleInfo)(SceUID pid, SceUID modid, SceKernelModuleInfo *info);
// Get tai module info
tai_module_info_t tai_info;
tai_info.size = sizeof(tai_module_info_t);
if (taiGetModuleInfoForKernel(KERNEL_PID, "SceAppMgr", &tai_info) < 0)
return SCE_KERNEL_START_SUCCESS;
switch (tai_info.module_nid) {
case 0xDBB29DB7: // 3.60 retail
module_get_offset(KERNEL_PID, tai_info.modid, 0, 0x2DE1, (uintptr_t *)&sceAppMgrFindProcessInfoByPid);
module_get_offset(KERNEL_PID, tai_info.modid, 0, 0x19B51, (uintptr_t *)&sceAppMgrMountById);
break;
case 0x1C9879D6: // 3.65 retail
module_get_offset(KERNEL_PID, tai_info.modid, 0, 0x2DE1, (uintptr_t *)&sceAppMgrFindProcessInfoByPid);
module_get_offset(KERNEL_PID, tai_info.modid, 0, 0x19E61, (uintptr_t *)&sceAppMgrMountById);
break;
case 0x54E2E984: // 3.67 retail
case 0xC3C538DE: // 3.68 retail
module_get_offset(KERNEL_PID, tai_info.modid, 0, 0x2DE1, (uintptr_t *)&sceAppMgrFindProcessInfoByPid);
module_get_offset(KERNEL_PID, tai_info.modid, 0, 0x19E6D, (uintptr_t *)&sceAppMgrMountById);
break;
}
res = module_get_export_func(KERNEL_PID, "SceKernelModulemgr", 0xC445FA63, 0xD269F915, (uintptr_t *)&_ksceKernelGetModuleInfo);
if (res < 0)
res = module_get_export_func(KERNEL_PID, "SceKernelModulemgr", 0x92C9FFC2, 0xDAA90093, (uintptr_t *)&_ksceKernelGetModuleInfo);
if (res < 0)
return res;
// Module info
SceKernelModuleInfo mod_info;
mod_info.size = sizeof(SceKernelModuleInfo);
res = _ksceKernelGetModuleInfo(KERNEL_PID, tai_info.modid, &mod_info);
if (res < 0)
return res;
uint32_t appmgr_data_addr = (uint32_t)mod_info.segments[1].vaddr;
SceUID process_id = ksceKernelGetProcessId();
void *info = sceAppMgrFindProcessInfoByPid((void *)(appmgr_data_addr + 0x500), process_id);
if (!info)
return -1;
char process_titleid[12];
char path[256];
char desired_mount_point[16];
char mount_point[16];
char klicensee[16];
memset(mount_point, 0, sizeof(mount_point));
if (args->process_titleid)
ksceKernelStrncpyUserToKernel(process_titleid, (uintptr_t)args->process_titleid, 11);
if (args->path)
ksceKernelStrncpyUserToKernel(path, (uintptr_t)args->path, 255);
if (args->desired_mount_point)
ksceKernelStrncpyUserToKernel(desired_mount_point, (uintptr_t)args->desired_mount_point, 15);
if (args->klicensee)
ksceKernelMemcpyUserToKernel(klicensee, (uintptr_t)args->klicensee, 0x10);
res = sceAppMgrMountById(process_id, info + 0x580, args->id, args->process_titleid ? process_titleid : NULL, args->path ? path : NULL,
args->desired_mount_point ? desired_mount_point : NULL, args->klicensee ? klicensee : NULL, mount_point);
if (args->mount_point)
ksceKernelStrncpyKernelToUser((uintptr_t)args->mount_point, mount_point, 15);
return res;
}
int shellKernelMountById(ShellMountIdArgs *args) {
uint32_t state;
ENTER_SYSCALL(state);
ShellMountIdArgs k_args;
ksceKernelMemcpyUserToKernel(&k_args, (uintptr_t)args, sizeof(ShellMountIdArgs));
int res = ksceKernelRunWithStack(0x2000, (void *)_shellKernelMountById, &k_args);
EXIT_SYSCALL(state);
return res;
}
int shellKernelGetRifVitaKey(const void *license_buf, void *klicensee) {
char k_license_buf[0x200];
char k_klicensee[0x10];
memset(k_klicensee, 0, sizeof(k_klicensee));
if (license_buf)
ksceKernelMemcpyUserToKernel(k_license_buf, license_buf, sizeof(k_license_buf));
int res = ksceNpDrmGetRifVitaKey(k_license_buf, k_klicensee, NULL, NULL, NULL, NULL);
if (klicensee)
ksceKernelMemcpyKernelToUser(klicensee, k_klicensee, sizeof(k_klicensee));
return res;
}
void _start() __attribute__ ((weak, alias("module_start")));
int module_start(SceSize args, void *argp) {
SceUID tmp1, tmp2;
// Get tai module info
tai_module_info_t info;
info.size = sizeof(tai_module_info_t);
if (taiGetModuleInfoForKernel(KERNEL_PID, "SceIofilemgr", &info) < 0)
return SCE_KERNEL_START_SUCCESS;
// Get important function
switch (info.module_nid) {
case 0x9642948C: // 3.60 retail
module_get_offset(KERNEL_PID, info.modid, 0, 0x138C1, (uintptr_t *)&sceIoFindMountPoint);
break;
case 0xA96ACE9D: // 3.65 retail
case 0x3347A95F: // 3.67 retail
case 0x90DA33DE: // 3.68 retail
module_get_offset(KERNEL_PID, info.modid, 0, 0x182F5, (uintptr_t *)&sceIoFindMountPoint);
break;
default:
return SCE_KERNEL_START_SUCCESS;
}
// Fake safe mode so that SceUsbMass can be loaded
tmp1 = taiHookFunctionExportForKernel(KERNEL_PID, &ksceSysrootIsSafeModeRef, "SceSysmem", 0x2ED7F97A, 0x834439A7, ksceSysrootIsSafeModePatched);
if (tmp1 < 0)
return SCE_KERNEL_START_SUCCESS;
// this patch is only needed on handheld units
tmp2 = taiHookFunctionExportForKernel(KERNEL_PID, &ksceSblAimgrIsDolceRef, "SceSysmem", 0xFD00C69A, 0x71608CA3, ksceSblAimgrIsDolcePatched);
if (tmp2 < 0)
return SCE_KERNEL_START_SUCCESS;
// Load SceUsbMass
SceUID modid = ksceKernelLoadStartModule("ux0:VitaShell/module/umass.skprx", 0, NULL, 0, NULL, NULL);
// Release patch
taiHookReleaseForKernel(tmp1, ksceSysrootIsSafeModeRef);
taiHookReleaseForKernel(tmp2, ksceSblAimgrIsDolceRef);
// Check result
if (modid < 0)
return SCE_KERNEL_START_SUCCESS;
// Fake safe mode in SceUsbServ
hookid = taiHookFunctionImportForKernel(KERNEL_PID, &ksceSysrootIsSafeModeRef, "SceUsbServ", 0x2ED7F97A, 0x834439A7, ksceSysrootIsSafeModePatched);
return SCE_KERNEL_START_SUCCESS;
}
int module_stop(SceSize args, void *argp) {
if (hookid >= 0)
taiHookReleaseForKernel(hookid, ksceSysrootIsSafeModeRef);
return SCE_KERNEL_STOP_SUCCESS;
/*
VitaShell
Copyright (C) 2015-2018, 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 <psp2kern/kernel/cpu.h>
#include <psp2kern/kernel/modulemgr.h>
#include <psp2kern/kernel/sysmem.h>
#include <psp2kern/kernel/threadmgr.h>
#include <psp2kern/io/fcntl.h>
#include <stdio.h>
#include <string.h>
#include <taihen.h>
#include "vitashell_kernel.h"
#define MOUNT_POINT_ID 0x800
int module_get_export_func(SceUID pid, const char *modname, uint32_t libnid, uint32_t funcnid, uintptr_t *func);
int module_get_offset(SceUID pid, SceUID modid, int segidx, size_t offset, uintptr_t *addr);
typedef struct {
const char *dev;
const char *dev2;
const char *blkdev;
const char *blkdev2;
int id;
} SceIoDevice;
typedef struct {
int id;
const char *dev_unix;
int unk;
int dev_major;
int dev_minor;
const char *dev_filesystem;
int unk2;
SceIoDevice *dev;
int unk3;
SceIoDevice *dev2;
int unk4;
int unk5;
int unk6;
int unk7;
} SceIoMountPoint;
static char ux0_blkdev[64], ux0_blkdev2[64];
static SceIoDevice ux0_dev = { "ux0:", "exfatux0", ux0_blkdev, ux0_blkdev2, MOUNT_POINT_ID };
static SceIoMountPoint *(* sceIoFindMountPoint)(int id) = NULL;
static SceUID hookid = -1;
static tai_hook_ref_t ksceSysrootIsSafeModeRef;
static tai_hook_ref_t ksceSblAimgrIsDolceRef;
static int ksceSysrootIsSafeModePatched() {
return 1;
}
static int ksceSblAimgrIsDolcePatched() {
return 1;
}
int shellKernelIsUx0Redirected(const char *blkdev, const char *blkdev2) {
char k_blkdev[64], k_blkdev2[64];
uint32_t state;
ENTER_SYSCALL(state);
SceIoMountPoint *mount = sceIoFindMountPoint(MOUNT_POINT_ID);
if (!mount) {
EXIT_SYSCALL(state);
return 0;
}
ksceKernelStrncpyUserToKernel(k_blkdev, blkdev, sizeof(k_blkdev)-1);
ksceKernelStrncpyUserToKernel(k_blkdev2, blkdev2, sizeof(k_blkdev2)-1);
if (mount && mount->dev && mount->dev->blkdev && strcmp(mount->dev->blkdev, k_blkdev) == 0) {
EXIT_SYSCALL(state);
return 1;
}
EXIT_SYSCALL(state);
return 0;
}
int shellKernelRedirectUx0(const char *blkdev, const char *blkdev2) {
uint32_t state;
ENTER_SYSCALL(state);
SceIoMountPoint *mount = sceIoFindMountPoint(MOUNT_POINT_ID);
if (!mount) {
EXIT_SYSCALL(state);
return -1;
}
ksceKernelStrncpyUserToKernel(ux0_blkdev, blkdev, sizeof(ux0_blkdev)-1);
ksceKernelStrncpyUserToKernel(ux0_blkdev2, blkdev2, sizeof(ux0_blkdev2)-1);
mount->dev = &ux0_dev;
mount->dev2 = &ux0_dev;
EXIT_SYSCALL(state);
return 0;
}
int _shellKernelMountById(ShellMountIdArgs *args) {
int res;
void *(* sceAppMgrFindProcessInfoByPid)(void *data, SceUID pid);
int (* sceAppMgrMountById)(SceUID pid, void *info, int id, const char *titleid, const char *path, const char *desired_mount_point, const void *klicensee, char *mount_point);
int (* _ksceKernelGetModuleInfo)(SceUID pid, SceUID modid, SceKernelModuleInfo *info);
// Get tai module info
tai_module_info_t tai_info;
tai_info.size = sizeof(tai_module_info_t);
if (taiGetModuleInfoForKernel(KERNEL_PID, "SceAppMgr", &tai_info) < 0)
return SCE_KERNEL_START_SUCCESS;
switch (tai_info.module_nid) {
case 0xDBB29DB7: // 3.60 retail
module_get_offset(KERNEL_PID, tai_info.modid, 0, 0x2DE1, (uintptr_t *)&sceAppMgrFindProcessInfoByPid);
module_get_offset(KERNEL_PID, tai_info.modid, 0, 0x19B51, (uintptr_t *)&sceAppMgrMountById);
break;
case 0x1C9879D6: // 3.65 retail
module_get_offset(KERNEL_PID, tai_info.modid, 0, 0x2DE1, (uintptr_t *)&sceAppMgrFindProcessInfoByPid);
module_get_offset(KERNEL_PID, tai_info.modid, 0, 0x19E61, (uintptr_t *)&sceAppMgrMountById);
break;
case 0x54E2E984: // 3.67 retail
case 0xC3C538DE: // 3.68 retail
module_get_offset(KERNEL_PID, tai_info.modid, 0, 0x2DE1, (uintptr_t *)&sceAppMgrFindProcessInfoByPid);
module_get_offset(KERNEL_PID, tai_info.modid, 0, 0x19E6D, (uintptr_t *)&sceAppMgrMountById);
break;
}
res = module_get_export_func(KERNEL_PID, "SceKernelModulemgr", 0xC445FA63, 0xD269F915, (uintptr_t *)&_ksceKernelGetModuleInfo);
if (res < 0)
res = module_get_export_func(KERNEL_PID, "SceKernelModulemgr", 0x92C9FFC2, 0xDAA90093, (uintptr_t *)&_ksceKernelGetModuleInfo);
if (res < 0)
return res;
// Module info
SceKernelModuleInfo mod_info;
mod_info.size = sizeof(SceKernelModuleInfo);
res = _ksceKernelGetModuleInfo(KERNEL_PID, tai_info.modid, &mod_info);
if (res < 0)
return res;
uint32_t appmgr_data_addr = (uint32_t)mod_info.segments[1].vaddr;
SceUID process_id = ksceKernelGetProcessId();
void *info = sceAppMgrFindProcessInfoByPid((void *)(appmgr_data_addr + 0x500), process_id);
if (!info)
return -1;
char process_titleid[12];
char path[256];
char desired_mount_point[16];
char mount_point[16];
char klicensee[16];
memset(mount_point, 0, sizeof(mount_point));
if (args->process_titleid)
ksceKernelStrncpyUserToKernel(process_titleid, (uintptr_t)args->process_titleid, 11);
if (args->path)
ksceKernelStrncpyUserToKernel(path, (uintptr_t)args->path, 255);
if (args->desired_mount_point)
ksceKernelStrncpyUserToKernel(desired_mount_point, (uintptr_t)args->desired_mount_point, 15);
if (args->klicensee)
ksceKernelMemcpyUserToKernel(klicensee, (uintptr_t)args->klicensee, 0x10);
res = sceAppMgrMountById(process_id, info + 0x580, args->id, args->process_titleid ? process_titleid : NULL, args->path ? path : NULL,
args->desired_mount_point ? desired_mount_point : NULL, args->klicensee ? klicensee : NULL, mount_point);
if (args->mount_point)
ksceKernelStrncpyKernelToUser((uintptr_t)args->mount_point, mount_point, 15);
return res;
}
int shellKernelMountById(ShellMountIdArgs *args) {
uint32_t state;
ENTER_SYSCALL(state);
ShellMountIdArgs k_args;
ksceKernelMemcpyUserToKernel(&k_args, (uintptr_t)args, sizeof(ShellMountIdArgs));
int res = ksceKernelRunWithStack(0x2000, (void *)_shellKernelMountById, &k_args);
EXIT_SYSCALL(state);
return res;
}
int shellKernelGetRifVitaKey(const void *license_buf, void *klicensee) {
char k_license_buf[0x200];
char k_klicensee[0x10];
memset(k_klicensee, 0, sizeof(k_klicensee));
if (license_buf)
ksceKernelMemcpyUserToKernel(k_license_buf, license_buf, sizeof(k_license_buf));
int res = ksceNpDrmGetRifVitaKey(k_license_buf, k_klicensee, NULL, NULL, NULL, NULL);
if (klicensee)
ksceKernelMemcpyKernelToUser(klicensee, k_klicensee, sizeof(k_klicensee));
return res;
}
void _start() __attribute__ ((weak, alias("module_start")));
int module_start(SceSize args, void *argp) {
SceUID tmp1, tmp2;
// Get tai module info
tai_module_info_t info;
info.size = sizeof(tai_module_info_t);
if (taiGetModuleInfoForKernel(KERNEL_PID, "SceIofilemgr", &info) < 0)
return SCE_KERNEL_START_SUCCESS;
// Get important function
switch (info.module_nid) {
case 0x9642948C: // 3.60 retail
module_get_offset(KERNEL_PID, info.modid, 0, 0x138C1, (uintptr_t *)&sceIoFindMountPoint);
break;
case 0xA96ACE9D: // 3.65 retail
case 0x3347A95F: // 3.67 retail
case 0x90DA33DE: // 3.68 retail
module_get_offset(KERNEL_PID, info.modid, 0, 0x182F5, (uintptr_t *)&sceIoFindMountPoint);
break;
default:
return SCE_KERNEL_START_SUCCESS;
}
// Fake safe mode so that SceUsbMass can be loaded
tmp1 = taiHookFunctionExportForKernel(KERNEL_PID, &ksceSysrootIsSafeModeRef, "SceSysmem", 0x2ED7F97A, 0x834439A7, ksceSysrootIsSafeModePatched);
if (tmp1 < 0)
return SCE_KERNEL_START_SUCCESS;
// this patch is only needed on handheld units
tmp2 = taiHookFunctionExportForKernel(KERNEL_PID, &ksceSblAimgrIsDolceRef, "SceSysmem", 0xFD00C69A, 0x71608CA3, ksceSblAimgrIsDolcePatched);
if (tmp2 < 0)
return SCE_KERNEL_START_SUCCESS;
// Load SceUsbMass
SceUID modid = ksceKernelLoadStartModule("ux0:VitaShell/module/umass.skprx", 0, NULL, 0, NULL, NULL);
// Release patch
taiHookReleaseForKernel(tmp1, ksceSysrootIsSafeModeRef);
taiHookReleaseForKernel(tmp2, ksceSblAimgrIsDolceRef);
// Check result
if (modid < 0)
return SCE_KERNEL_START_SUCCESS;
// Fake safe mode in SceUsbServ
hookid = taiHookFunctionImportForKernel(KERNEL_PID, &ksceSysrootIsSafeModeRef, "SceUsbServ", 0x2ED7F97A, 0x834439A7, ksceSysrootIsSafeModePatched);
return SCE_KERNEL_START_SUCCESS;
}
int module_stop(SceSize args, void *argp) {
if (hookid >= 0)
taiHookReleaseForKernel(hookid, ksceSysrootIsSafeModeRef);
return SCE_KERNEL_STOP_SUCCESS;
}

View File

@ -1,32 +1,32 @@
cmake_minimum_required(VERSION 2.8)
if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
if(DEFINED ENV{VITASDK})
set(CMAKE_TOOLCHAIN_FILE "$ENV{VITASDK}/share/vita.toolchain.cmake" CACHE PATH "toolchain file")
else()
message(FATAL_ERROR "Please define VITASDK to point to your SDK path!")
endif()
endif()
project(patch)
include("${VITASDK}/share/vita.cmake" REQUIRED)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-q -Wall -O3 -nostdlib")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions")
add_executable(patch
main.c
)
target_link_libraries(patch
taihenForKernel_stub
)
vita_create_self(patch.skprx patch CONFIG exports.yml UNSAFE)
vita_create_stubs(stubs patch ${CMAKE_SOURCE_DIR}/exports.yml KERNEL)
add_custom_target(copy
COMMAND cp patch.skprx ../../../resources/patch.skprx
DEPENDS patch.skprx
cmake_minimum_required(VERSION 2.8)
if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
if(DEFINED ENV{VITASDK})
set(CMAKE_TOOLCHAIN_FILE "$ENV{VITASDK}/share/vita.toolchain.cmake" CACHE PATH "toolchain file")
else()
message(FATAL_ERROR "Please define VITASDK to point to your SDK path!")
endif()
endif()
project(patch)
include("${VITASDK}/share/vita.cmake" REQUIRED)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-q -Wall -O3 -nostdlib")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions")
add_executable(patch
main.c
)
target_link_libraries(patch
taihenForKernel_stub
)
vita_create_self(patch.skprx patch CONFIG exports.yml UNSAFE)
vita_create_stubs(stubs patch ${CMAKE_SOURCE_DIR}/exports.yml KERNEL)
add_custom_target(copy
COMMAND cp patch.skprx ../../../resources/patch.skprx
DEPENDS patch.skprx
)

View File

@ -1,8 +1,8 @@
VitaShellPatch:
attributes: 0
version:
major: 1
minor: 0
main:
start: module_start
VitaShellPatch:
attributes: 0
version:
major: 1
minor: 0
main:
start: module_start
stop: module_stop

View File

@ -1,59 +1,59 @@
/*
VitaShell
Copyright (C) 2015-2018, 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 <psp2kern/kernel/modulemgr.h>
#include <taihen.h>
static SceUID hooks[2];
void _start() __attribute__ ((weak, alias("module_start")));
int module_start(SceSize args, void *argp) {
// Get tai module info
tai_module_info_t info;
info.size = sizeof(tai_module_info_t);
if (taiGetModuleInfoForKernel(KERNEL_PID, "SceAppMgr", &info) < 0)
return SCE_KERNEL_START_SUCCESS;
// Patch to allow Memory Card remount
uint32_t nop_nop_opcode = 0xBF00BF00;
switch (info.module_nid) {
case 0xDBB29DB7: // 3.60 retail
case 0x1C9879D6: // 3.65 retail
hooks[0] = taiInjectDataForKernel(KERNEL_PID, info.modid, 0, 0xB338, &nop_nop_opcode, 4);
hooks[1] = taiInjectDataForKernel(KERNEL_PID, info.modid, 0, 0xB368, &nop_nop_opcode, 2);
break;
case 0x54E2E984: // 3.67 retail
case 0xC3C538DE: // 3.68 retail
hooks[0] = taiInjectDataForKernel(KERNEL_PID, info.modid, 0, 0xB344, &nop_nop_opcode, 4);
hooks[1] = taiInjectDataForKernel(KERNEL_PID, info.modid, 0, 0xB374, &nop_nop_opcode, 2);
break;
}
return SCE_KERNEL_START_SUCCESS;
}
int module_stop(SceSize args, void *argp) {
if (hooks[1] >= 0)
taiInjectReleaseForKernel(hooks[1]);
if (hooks[0] >= 0)
taiInjectReleaseForKernel(hooks[0]);
return SCE_KERNEL_STOP_SUCCESS;
/*
VitaShell
Copyright (C) 2015-2018, 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 <psp2kern/kernel/modulemgr.h>
#include <taihen.h>
static SceUID hooks[2];
void _start() __attribute__ ((weak, alias("module_start")));
int module_start(SceSize args, void *argp) {
// Get tai module info
tai_module_info_t info;
info.size = sizeof(tai_module_info_t);
if (taiGetModuleInfoForKernel(KERNEL_PID, "SceAppMgr", &info) < 0)
return SCE_KERNEL_START_SUCCESS;
// Patch to allow Memory Card remount
uint32_t nop_nop_opcode = 0xBF00BF00;
switch (info.module_nid) {
case 0xDBB29DB7: // 3.60 retail
case 0x1C9879D6: // 3.65 retail
hooks[0] = taiInjectDataForKernel(KERNEL_PID, info.modid, 0, 0xB338, &nop_nop_opcode, 4);
hooks[1] = taiInjectDataForKernel(KERNEL_PID, info.modid, 0, 0xB368, &nop_nop_opcode, 2);
break;
case 0x54E2E984: // 3.67 retail
case 0xC3C538DE: // 3.68 retail
hooks[0] = taiInjectDataForKernel(KERNEL_PID, info.modid, 0, 0xB344, &nop_nop_opcode, 4);
hooks[1] = taiInjectDataForKernel(KERNEL_PID, info.modid, 0, 0xB374, &nop_nop_opcode, 2);
break;
}
return SCE_KERNEL_START_SUCCESS;
}
int module_stop(SceSize args, void *argp) {
if (hooks[1] >= 0)
taiInjectReleaseForKernel(hooks[1]);
if (hooks[0] >= 0)
taiInjectReleaseForKernel(hooks[0]);
return SCE_KERNEL_STOP_SUCCESS;
}

View File

@ -1,32 +1,32 @@
cmake_minimum_required(VERSION 2.8)
if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
if(DEFINED ENV{VITASDK})
set(CMAKE_TOOLCHAIN_FILE "$ENV{VITASDK}/share/vita.toolchain.cmake" CACHE PATH "toolchain file")
else()
message(FATAL_ERROR "Please define VITASDK to point to your SDK path!")
endif()
endif()
project(usbdevice)
include("${VITASDK}/share/vita.cmake" REQUIRED)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-q -Wall -O3 -nostdlib")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions")
add_executable(usbdevice
main.c
)
target_link_libraries(usbdevice
SceIofilemgrForDriver_stub
SceSysclibForDriver_stub
taihenForKernel_stub
)
vita_create_self(usbdevice.skprx usbdevice CONFIG exports.yml UNSAFE)
add_custom_target(copy
COMMAND cp usbdevice.skprx ../../../resources/usbdevice.skprx
DEPENDS usbdevice.skprx
cmake_minimum_required(VERSION 2.8)
if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
if(DEFINED ENV{VITASDK})
set(CMAKE_TOOLCHAIN_FILE "$ENV{VITASDK}/share/vita.toolchain.cmake" CACHE PATH "toolchain file")
else()
message(FATAL_ERROR "Please define VITASDK to point to your SDK path!")
endif()
endif()
project(usbdevice)
include("${VITASDK}/share/vita.cmake" REQUIRED)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-q -Wall -O3 -nostdlib")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions")
add_executable(usbdevice
main.c
)
target_link_libraries(usbdevice
SceIofilemgrForDriver_stub
SceSysclibForDriver_stub
taihenForKernel_stub
)
vita_create_self(usbdevice.skprx usbdevice CONFIG exports.yml UNSAFE)
add_custom_target(copy
COMMAND cp usbdevice.skprx ../../../resources/usbdevice.skprx
DEPENDS usbdevice.skprx
)

View File

@ -1,8 +1,8 @@
VitaShellUsbDevice:
attributes: 0
version:
major: 1
minor: 0
main:
start: module_start
VitaShellUsbDevice:
attributes: 0
version:
major: 1
minor: 0
main:
start: module_start
stop: module_stop

View File

@ -1,95 +1,95 @@
/*
VitaShell
Copyright (C) 2015-2018, 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 <psp2kern/kernel/modulemgr.h>
#include <psp2kern/io/fcntl.h>
#include <stdio.h>
#include <string.h>
#include <taihen.h>
static tai_hook_ref_t ksceIoOpenRef;
static tai_hook_ref_t ksceIoReadRef;
static SceUID hooks[3];
static int first = 1;
static SceUID ksceIoOpenPatched(const char *file, int flags, SceMode mode) {
first = 1;
SceUID fd = TAI_CONTINUE(SceUID, ksceIoOpenRef, file, flags, mode);
if (fd == 0x800F090D)
return TAI_CONTINUE(SceUID, ksceIoOpenRef, file, flags & ~SCE_O_WRONLY, mode);
return fd;
}
static int ksceIoReadPatched(SceUID fd, void *data, SceSize size) {
int res = TAI_CONTINUE(int, ksceIoReadRef, fd, data, size);
if (first) {
first = 0;
// Manipulate boot sector to support exFAT
if (memcmp(data + 0x3, "EXFAT", 5) == 0) {
// Sector size
*(uint16_t *)(data + 0xB) = 1 << *(uint8_t *)(data + 0x6C);
// Volume size
*(uint32_t *)(data + 0x20) = *(uint32_t *)(data + 0x48);
}
}
return res;
}
void _start() __attribute__ ((weak, alias("module_start")));
int module_start(SceSize args, void *argp) {
// Get tai module info
tai_module_info_t info;
info.size = sizeof(tai_module_info_t);
if (taiGetModuleInfoForKernel(KERNEL_PID, "SceUsbstorVStorDriver", &info) < 0)
return SCE_KERNEL_START_SUCCESS;
// Remove image path limitation
char zero[0x6E];
memset(zero, 0, 0x6E);
hooks[0] = taiInjectDataForKernel(KERNEL_PID, info.modid, 0, 0x1738, zero, 0x6E);
// Add patches to support exFAT
hooks[1] = taiHookFunctionImportForKernel(KERNEL_PID, &ksceIoOpenRef, "SceUsbstorVStorDriver", 0x40FD29C7, 0x75192972, ksceIoOpenPatched);
hooks[2] = taiHookFunctionImportForKernel(KERNEL_PID, &ksceIoReadRef, "SceUsbstorVStorDriver", 0x40FD29C7, 0xE17EFC03, ksceIoReadPatched);
return SCE_KERNEL_START_SUCCESS;
}
int module_stop(SceSize args, void *argp) {
if (hooks[2] >= 0)
taiHookReleaseForKernel(hooks[2], ksceIoReadRef);
if (hooks[1] >= 0)
taiHookReleaseForKernel(hooks[1], ksceIoOpenRef);
if (hooks[0] >= 0)
taiInjectReleaseForKernel(hooks[0]);
return SCE_KERNEL_STOP_SUCCESS;
}
/*
VitaShell
Copyright (C) 2015-2018, 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 <psp2kern/kernel/modulemgr.h>
#include <psp2kern/io/fcntl.h>
#include <stdio.h>
#include <string.h>
#include <taihen.h>
static tai_hook_ref_t ksceIoOpenRef;
static tai_hook_ref_t ksceIoReadRef;
static SceUID hooks[3];
static int first = 1;
static SceUID ksceIoOpenPatched(const char *file, int flags, SceMode mode) {
first = 1;
SceUID fd = TAI_CONTINUE(SceUID, ksceIoOpenRef, file, flags, mode);
if (fd == 0x800F090D)
return TAI_CONTINUE(SceUID, ksceIoOpenRef, file, flags & ~SCE_O_WRONLY, mode);
return fd;
}
static int ksceIoReadPatched(SceUID fd, void *data, SceSize size) {
int res = TAI_CONTINUE(int, ksceIoReadRef, fd, data, size);
if (first) {
first = 0;
// Manipulate boot sector to support exFAT
if (memcmp(data + 0x3, "EXFAT", 5) == 0) {
// Sector size
*(uint16_t *)(data + 0xB) = 1 << *(uint8_t *)(data + 0x6C);
// Volume size
*(uint32_t *)(data + 0x20) = *(uint32_t *)(data + 0x48);
}
}
return res;
}
void _start() __attribute__ ((weak, alias("module_start")));
int module_start(SceSize args, void *argp) {
// Get tai module info
tai_module_info_t info;
info.size = sizeof(tai_module_info_t);
if (taiGetModuleInfoForKernel(KERNEL_PID, "SceUsbstorVStorDriver", &info) < 0)
return SCE_KERNEL_START_SUCCESS;
// Remove image path limitation
char zero[0x6E];
memset(zero, 0, 0x6E);
hooks[0] = taiInjectDataForKernel(KERNEL_PID, info.modid, 0, 0x1738, zero, 0x6E);
// Add patches to support exFAT
hooks[1] = taiHookFunctionImportForKernel(KERNEL_PID, &ksceIoOpenRef, "SceUsbstorVStorDriver", 0x40FD29C7, 0x75192972, ksceIoOpenPatched);
hooks[2] = taiHookFunctionImportForKernel(KERNEL_PID, &ksceIoReadRef, "SceUsbstorVStorDriver", 0x40FD29C7, 0xE17EFC03, ksceIoReadPatched);
return SCE_KERNEL_START_SUCCESS;
}
int module_stop(SceSize args, void *argp) {
if (hooks[2] >= 0)
taiHookReleaseForKernel(hooks[2], ksceIoReadRef);
if (hooks[1] >= 0)
taiHookReleaseForKernel(hooks[1], ksceIoOpenRef);
if (hooks[0] >= 0)
taiInjectReleaseForKernel(hooks[0]);
return SCE_KERNEL_STOP_SUCCESS;
}

View File

@ -1,43 +1,43 @@
cmake_minimum_required(VERSION 2.8)
if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
if(DEFINED ENV{VITASDK})
set(CMAKE_TOOLCHAIN_FILE "$ENV{VITASDK}/share/vita.toolchain.cmake" CACHE PATH "toolchain file")
else()
message(FATAL_ERROR "Please define VITASDK to point to your SDK path!")
endif()
endif()
project(user)
include("${VITASDK}/share/vita.cmake" REQUIRED)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-q -Wall -O3 -nostdlib")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions")
add_executable(user
main.c
)
target_link_libraries(user
SceLibKernel_stub
SceIofilemgr_stub
VitaShellKernel2_stub
)
vita_create_self(user.suprx user CONFIG exports.yml UNSAFE)
vita_create_stubs(stubs user ${CMAKE_SOURCE_DIR}/exports.yml)
install(DIRECTORY ${CMAKE_BINARY_DIR}/stubs/
DESTINATION lib
FILES_MATCHING PATTERN "*.a"
)
install(FILES vitashell_user.h
DESTINATION include
)
add_custom_target(copy
COMMAND cp user.suprx ../../../resources/user.suprx
DEPENDS user.suprx
cmake_minimum_required(VERSION 2.8)
if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
if(DEFINED ENV{VITASDK})
set(CMAKE_TOOLCHAIN_FILE "$ENV{VITASDK}/share/vita.toolchain.cmake" CACHE PATH "toolchain file")
else()
message(FATAL_ERROR "Please define VITASDK to point to your SDK path!")
endif()
endif()
project(user)
include("${VITASDK}/share/vita.cmake" REQUIRED)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-q -Wall -O3 -nostdlib")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions")
add_executable(user
main.c
)
target_link_libraries(user
SceLibKernel_stub
SceIofilemgr_stub
VitaShellKernel2_stub
)
vita_create_self(user.suprx user CONFIG exports.yml UNSAFE)
vita_create_stubs(stubs user ${CMAKE_SOURCE_DIR}/exports.yml)
install(DIRECTORY ${CMAKE_BINARY_DIR}/stubs/
DESTINATION lib
FILES_MATCHING PATTERN "*.a"
)
install(FILES vitashell_user.h
DESTINATION include
)
add_custom_target(copy
COMMAND cp user.suprx ../../../resources/user.suprx
DEPENDS user.suprx
)

View File

@ -1,16 +1,16 @@
VitaShellUser:
attributes: 0
version:
major: 1
minor: 0
main:
start: module_start
stop: module_stop
modules:
VitaShellUserLibrary:
syscall: false
functions:
- shellUserIsUx0Redirected
- shellUserRedirectUx0
- shellUserMountById
VitaShellUser:
attributes: 0
version:
major: 1
minor: 0
main:
start: module_start
stop: module_stop
modules:
VitaShellUserLibrary:
syscall: false
functions:
- shellUserIsUx0Redirected
- shellUserRedirectUx0
- shellUserMountById
- shellUserGetRifVitaKey

View File

@ -1,52 +1,52 @@
/*
VitaShell
Copyright (C) 2015-2018, 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 <psp2/kernel/modulemgr.h>
#include <psp2/kernel/sysmem.h>
#include <psp2/io/fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include "vitashell_user.h"
int shellUserIsUx0Redirected(const char *blkdev, const char *blkdev2) {
return shellKernelIsUx0Redirected(blkdev, blkdev2);
}
int shellUserRedirectUx0(const char *blkdev, const char *blkdev2) {
return shellKernelRedirectUx0(blkdev, blkdev2);
}
int shellUserMountById(ShellMountIdArgs *args) {
return shellKernelMountById(args);
}
int shellUserGetRifVitaKey(const void *license_buf, void *klicensee) {
return shellKernelGetRifVitaKey(license_buf, klicensee);
}
void _start() __attribute__ ((weak, alias("module_start")));
int module_start(SceSize args, void *argp) {
return SCE_KERNEL_START_SUCCESS;
}
int module_stop(SceSize args, void *argp) {
return SCE_KERNEL_STOP_SUCCESS;
/*
VitaShell
Copyright (C) 2015-2018, 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 <psp2/kernel/modulemgr.h>
#include <psp2/kernel/sysmem.h>
#include <psp2/io/fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include "vitashell_user.h"
int shellUserIsUx0Redirected(const char *blkdev, const char *blkdev2) {
return shellKernelIsUx0Redirected(blkdev, blkdev2);
}
int shellUserRedirectUx0(const char *blkdev, const char *blkdev2) {
return shellKernelRedirectUx0(blkdev, blkdev2);
}
int shellUserMountById(ShellMountIdArgs *args) {
return shellKernelMountById(args);
}
int shellUserGetRifVitaKey(const void *license_buf, void *klicensee) {
return shellKernelGetRifVitaKey(license_buf, klicensee);
}
void _start() __attribute__ ((weak, alias("module_start")));
int module_start(SceSize args, void *argp) {
return SCE_KERNEL_START_SUCCESS;
}
int module_stop(SceSize args, void *argp) {
return SCE_KERNEL_STOP_SUCCESS;
}

View File

@ -1,278 +1,278 @@
/*
VitaShell
Copyright (C) 2015-2018, 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 "io_process.h"
#include "network_download.h"
#include "package_installer.h"
#include "archive.h"
#include "file.h"
#include "message_dialog.h"
#include "language.h"
#include "utils.h"
#define VITASHELL_USER_AGENT "VitaShell/1.00 libhttp/1.1"
int getDownloadFileSize(const char *src, uint64_t *size) {
int res;
int statusCode;
int tmplId = -1, connId = -1, reqId = -1;
res = sceHttpCreateTemplate(VITASHELL_USER_AGENT, SCE_HTTP_VERSION_1_1, SCE_TRUE);
if (res < 0)
goto ERROR_EXIT;
tmplId = res;
res = sceHttpCreateConnectionWithURL(tmplId, src, SCE_TRUE);
if (res < 0)
goto ERROR_EXIT;
connId = res;
res = sceHttpCreateRequestWithURL(connId, SCE_HTTP_METHOD_GET, src, 0);
if (res < 0)
goto ERROR_EXIT;
reqId = res;
res = sceHttpSendRequest(reqId, NULL, 0);
if (res < 0)
goto ERROR_EXIT;
res = sceHttpGetStatusCode(reqId, &statusCode);
if (res < 0)
goto ERROR_EXIT;
if (statusCode == 200) {
res = sceHttpGetResponseContentLength(reqId, size);
}
ERROR_EXIT:
if (reqId >= 0)
sceHttpDeleteRequest(reqId);
if (connId >= 0)
sceHttpDeleteConnection(connId);
if (tmplId >= 0)
sceHttpDeleteTemplate(tmplId);
return res;
}
int getFieldFromHeader(const char *src, const char *field, const char **data, unsigned int *valueLen) {
int res;
char *header;
unsigned int headerSize;
int tmplId = -1, connId = -1, reqId = -1;
res = sceHttpCreateTemplate(VITASHELL_USER_AGENT, SCE_HTTP_VERSION_1_1, SCE_TRUE);
if (res < 0)
goto ERROR_EXIT;
tmplId = res;
res = sceHttpCreateConnectionWithURL(tmplId, src, SCE_TRUE);
if (res < 0)
goto ERROR_EXIT;
connId = res;
res = sceHttpCreateRequestWithURL(connId, SCE_HTTP_METHOD_GET, src, 0);
if (res < 0)
goto ERROR_EXIT;
reqId = res;
res = sceHttpSendRequest(reqId, NULL, 0);
if (res < 0)
goto ERROR_EXIT;
res = sceHttpGetAllResponseHeaders(reqId, &header, &headerSize);
if (res < 0)
goto ERROR_EXIT;
res = sceHttpParseResponseHeader(header, headerSize, field, data, valueLen);
if (res < 0) {
*data = "";
*valueLen = 0;
res = 0;
}
ERROR_EXIT:
if (reqId >= 0)
sceHttpDeleteRequest(reqId);
if (connId >= 0)
sceHttpDeleteConnection(connId);
if (tmplId >= 0)
sceHttpDeleteTemplate(tmplId);
return res;
}
int downloadFile(const char *src, const char *dst, FileProcessParam *param) {
int res;
int statusCode;
int tmplId = -1, connId = -1, reqId = -1;
SceUID fd = -1;
int ret = 1;
res = sceHttpCreateTemplate(VITASHELL_USER_AGENT, SCE_HTTP_VERSION_1_1, SCE_TRUE);
if (res < 0)
goto ERROR_EXIT;
tmplId = res;
res = sceHttpCreateConnectionWithURL(tmplId, src, SCE_TRUE);
if (res < 0)
goto ERROR_EXIT;
connId = res;
res = sceHttpCreateRequestWithURL(connId, SCE_HTTP_METHOD_GET, src, 0);
if (res < 0)
goto ERROR_EXIT;
reqId = res;
res = sceHttpSendRequest(reqId, NULL, 0);
if (res < 0)
goto ERROR_EXIT;
res = sceHttpGetStatusCode(reqId, &statusCode);
if (res < 0)
goto ERROR_EXIT;
if (statusCode == 200) {
res = sceIoOpen(dst, SCE_O_WRONLY | SCE_O_CREAT | SCE_O_TRUNC, 0777);
if (res < 0)
goto ERROR_EXIT;
fd = res;
uint8_t buf[4096];
while (1) {
int read = sceHttpReadData(reqId, buf, sizeof(buf));
if (read < 0) {
res = read;
break;
}
if (read == 0)
break;
int written = sceIoWrite(fd, buf, read);
if (written < 0) {
res = written;
break;
}
if (param) {
if (param->value)
(*param->value) += read;
if (param->SetProgress)
param->SetProgress(param->value ? *param->value : 0, param->max);
if (param->cancelHandler && param->cancelHandler()) {
ret = 0;
break;
}
}
}
}
ERROR_EXIT:
if (fd >= 0)
sceIoClose(fd);
if (reqId >= 0)
sceHttpDeleteRequest(reqId);
if (connId >= 0)
sceHttpDeleteConnection(connId);
if (tmplId >= 0)
sceHttpDeleteTemplate(tmplId);
if (res < 0)
return res;
return ret;
}
int downloadFileProcess(const char *url, const char *dest, int successStep) {
SceUID thid = -1;
// Lock power timers
powerLock();
// Set progress to 0%
sceMsgDialogProgressBarSetValue(SCE_MSG_DIALOG_PROGRESSBAR_TARGET_BAR_DEFAULT, 0);
sceKernelDelayThread(DIALOG_WAIT); // Needed to see the percentage
// File size
uint64_t size = 0;
getDownloadFileSize(url, &size);
// Update thread
thid = createStartUpdateThread(size, 1);
// Download
uint64_t value = 0;
FileProcessParam param;
param.value = &value;
param.max = size;
param.SetProgress = SetProgress;
param.cancelHandler = cancelHandler;
int res = downloadFile(url, dest, &param);
if (res <= 0) {
sceIoRemove(dest);
closeWaitDialog();
setDialogStep(DIALOG_STEP_CANCELED);
errorDialog(res);
goto EXIT;
}
// Set progress to 100%
sceMsgDialogProgressBarSetValue(SCE_MSG_DIALOG_PROGRESSBAR_TARGET_BAR_DEFAULT, 100);
sceKernelDelayThread(COUNTUP_WAIT);
// Close
if (successStep != 0) {
sceMsgDialogClose();
setDialogStep(successStep);
}
EXIT:
if (thid >= 0)
sceKernelWaitThreadEnd(thid, NULL, NULL);
// Unlock power timers
powerUnlock();
return sceKernelExitDeleteThread(0);
/*
VitaShell
Copyright (C) 2015-2018, 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 "io_process.h"
#include "network_download.h"
#include "package_installer.h"
#include "archive.h"
#include "file.h"
#include "message_dialog.h"
#include "language.h"
#include "utils.h"
#define VITASHELL_USER_AGENT "VitaShell/1.00 libhttp/1.1"
int getDownloadFileSize(const char *src, uint64_t *size) {
int res;
int statusCode;
int tmplId = -1, connId = -1, reqId = -1;
res = sceHttpCreateTemplate(VITASHELL_USER_AGENT, SCE_HTTP_VERSION_1_1, SCE_TRUE);
if (res < 0)
goto ERROR_EXIT;
tmplId = res;
res = sceHttpCreateConnectionWithURL(tmplId, src, SCE_TRUE);
if (res < 0)
goto ERROR_EXIT;
connId = res;
res = sceHttpCreateRequestWithURL(connId, SCE_HTTP_METHOD_GET, src, 0);
if (res < 0)
goto ERROR_EXIT;
reqId = res;
res = sceHttpSendRequest(reqId, NULL, 0);
if (res < 0)
goto ERROR_EXIT;
res = sceHttpGetStatusCode(reqId, &statusCode);
if (res < 0)
goto ERROR_EXIT;
if (statusCode == 200) {
res = sceHttpGetResponseContentLength(reqId, size);
}
ERROR_EXIT:
if (reqId >= 0)
sceHttpDeleteRequest(reqId);
if (connId >= 0)
sceHttpDeleteConnection(connId);
if (tmplId >= 0)
sceHttpDeleteTemplate(tmplId);
return res;
}
int getFieldFromHeader(const char *src, const char *field, const char **data, unsigned int *valueLen) {
int res;
char *header;
unsigned int headerSize;
int tmplId = -1, connId = -1, reqId = -1;
res = sceHttpCreateTemplate(VITASHELL_USER_AGENT, SCE_HTTP_VERSION_1_1, SCE_TRUE);
if (res < 0)
goto ERROR_EXIT;
tmplId = res;
res = sceHttpCreateConnectionWithURL(tmplId, src, SCE_TRUE);
if (res < 0)
goto ERROR_EXIT;
connId = res;
res = sceHttpCreateRequestWithURL(connId, SCE_HTTP_METHOD_GET, src, 0);
if (res < 0)
goto ERROR_EXIT;
reqId = res;
res = sceHttpSendRequest(reqId, NULL, 0);
if (res < 0)
goto ERROR_EXIT;
res = sceHttpGetAllResponseHeaders(reqId, &header, &headerSize);
if (res < 0)
goto ERROR_EXIT;
res = sceHttpParseResponseHeader(header, headerSize, field, data, valueLen);
if (res < 0) {
*data = "";
*valueLen = 0;
res = 0;
}
ERROR_EXIT:
if (reqId >= 0)
sceHttpDeleteRequest(reqId);
if (connId >= 0)
sceHttpDeleteConnection(connId);
if (tmplId >= 0)
sceHttpDeleteTemplate(tmplId);
return res;
}
int downloadFile(const char *src, const char *dst, FileProcessParam *param) {
int res;
int statusCode;
int tmplId = -1, connId = -1, reqId = -1;
SceUID fd = -1;
int ret = 1;
res = sceHttpCreateTemplate(VITASHELL_USER_AGENT, SCE_HTTP_VERSION_1_1, SCE_TRUE);
if (res < 0)
goto ERROR_EXIT;
tmplId = res;
res = sceHttpCreateConnectionWithURL(tmplId, src, SCE_TRUE);
if (res < 0)
goto ERROR_EXIT;
connId = res;
res = sceHttpCreateRequestWithURL(connId, SCE_HTTP_METHOD_GET, src, 0);
if (res < 0)
goto ERROR_EXIT;
reqId = res;
res = sceHttpSendRequest(reqId, NULL, 0);
if (res < 0)
goto ERROR_EXIT;
res = sceHttpGetStatusCode(reqId, &statusCode);
if (res < 0)
goto ERROR_EXIT;
if (statusCode == 200) {
res = sceIoOpen(dst, SCE_O_WRONLY | SCE_O_CREAT | SCE_O_TRUNC, 0777);
if (res < 0)
goto ERROR_EXIT;
fd = res;
uint8_t buf[4096];
while (1) {
int read = sceHttpReadData(reqId, buf, sizeof(buf));
if (read < 0) {
res = read;
break;
}
if (read == 0)
break;
int written = sceIoWrite(fd, buf, read);
if (written < 0) {
res = written;
break;
}
if (param) {
if (param->value)
(*param->value) += read;
if (param->SetProgress)
param->SetProgress(param->value ? *param->value : 0, param->max);
if (param->cancelHandler && param->cancelHandler()) {
ret = 0;
break;
}
}
}
}
ERROR_EXIT:
if (fd >= 0)
sceIoClose(fd);
if (reqId >= 0)
sceHttpDeleteRequest(reqId);
if (connId >= 0)
sceHttpDeleteConnection(connId);
if (tmplId >= 0)
sceHttpDeleteTemplate(tmplId);
if (res < 0)
return res;
return ret;
}
int downloadFileProcess(const char *url, const char *dest, int successStep) {
SceUID thid = -1;
// Lock power timers
powerLock();
// Set progress to 0%
sceMsgDialogProgressBarSetValue(SCE_MSG_DIALOG_PROGRESSBAR_TARGET_BAR_DEFAULT, 0);
sceKernelDelayThread(DIALOG_WAIT); // Needed to see the percentage
// File size
uint64_t size = 0;
getDownloadFileSize(url, &size);
// Update thread
thid = createStartUpdateThread(size, 1);
// Download
uint64_t value = 0;
FileProcessParam param;
param.value = &value;
param.max = size;
param.SetProgress = SetProgress;
param.cancelHandler = cancelHandler;
int res = downloadFile(url, dest, &param);
if (res <= 0) {
sceIoRemove(dest);
closeWaitDialog();
setDialogStep(DIALOG_STEP_CANCELED);
errorDialog(res);
goto EXIT;
}
// Set progress to 100%
sceMsgDialogProgressBarSetValue(SCE_MSG_DIALOG_PROGRESSBAR_TARGET_BAR_DEFAULT, 100);
sceKernelDelayThread(COUNTUP_WAIT);
// Close
if (successStep != 0) {
sceMsgDialogClose();
setDialogStep(successStep);
}
EXIT:
if (thid >= 0)
sceKernelWaitThreadEnd(thid, NULL, NULL);
// Unlock power timers
powerUnlock();
return sceKernelExitDeleteThread(0);
}

View File

@ -1,33 +1,33 @@
/*
VitaShell
Copyright (C) 2015-2018, 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/>.
*/
/*
* network_download
* same as network_update.h // network_update.c
* just modified to download any file from url, destination and successStep (0 for no step)
*/
#ifndef __NETWORK_DOWNLOAD_H__
#define __NETWORK_DOWNLOAD_H__
int getDownloadFileSize(const char *src, uint64_t *size);
int getFieldFromHeader(const char *src, const char *field, const char **data, unsigned int *valueLen);
int downloadFile(const char *src, const char *dst, FileProcessParam *param);
int downloadFileProcess(const char *url, const char *dest, int successStep);
/*
VitaShell
Copyright (C) 2015-2018, 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/>.
*/
/*
* network_download
* same as network_update.h // network_update.c
* just modified to download any file from url, destination and successStep (0 for no step)
*/
#ifndef __NETWORK_DOWNLOAD_H__
#define __NETWORK_DOWNLOAD_H__
int getDownloadFileSize(const char *src, uint64_t *size);
int getFieldFromHeader(const char *src, const char *field, const char **data, unsigned int *valueLen);
int downloadFile(const char *src, const char *dst, FileProcessParam *param);
int downloadFileProcess(const char *url, const char *dest, int successStep);
#endif

1060
psarc.c

File diff suppressed because it is too large Load Diff

706
qr.c
View File

@ -1,354 +1,354 @@
/*
VitaShell
Copyright (C) 2015-2018, 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 "qr.h"
#include <psp2/kernel/processmgr.h>
#include <psp2/kernel/threadmgr.h>
#include <psp2/camera.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <quirc.h>
#include <vita2d.h>
#include "main.h"
#include "io_process.h"
#include "network_download.h"
#include "package_installer.h"
#include "archive.h"
#include "file.h"
#include "message_dialog.h"
#include "language.h"
#include "utils.h"
static int qr_enabled;
static struct quirc *qr;
static uint32_t* qr_data;
static char *data;
static int qr_next;
static vita2d_texture *camera_tex;
static SceCameraInfo cam_info;
static SceCameraRead cam_info_read;
static char last_qr[MAX_QR_LENGTH];
static char last_download[MAX_QR_LENGTH];
static int last_qr_len;
static int qr_scanned = 0;
static SceUID thid;
int qr_thread() {
qr = quirc_new();
quirc_resize(qr, CAM_WIDTH, CAM_HEIGHT);
qr_next = 1;
while (1) {
sceKernelDelayThread(10);
if (qr_next == 0 && qr_scanned == 0) {
uint8_t *image;
int w, h;
image = quirc_begin(qr, &w, &h);
uint32_t colourRGBA;
int i;
for (i = 0; i < w*h; i++) {
colourRGBA = qr_data[i];
image[i] = ((colourRGBA & 0x000000FF) + ((colourRGBA & 0x0000FF00) >> 8) + ((colourRGBA & 0x00FF0000) >> 16)) / 3;
}
quirc_end(qr);
int num_codes = quirc_count(qr);
if (num_codes > 0) {
struct quirc_code code;
struct quirc_data data;
quirc_decode_error_t err;
quirc_extract(qr, 0, &code);
err = quirc_decode(&code, &data);
if (err) {
} else {
memcpy(last_qr, data.payload, data.payload_len);
last_qr_len = data.payload_len;
qr_scanned = 1;
}
} else {
memset(last_qr, 0, MAX_QR_LENGTH);
}
qr_next = 1;
sceKernelDelayThread(250000);
}
}
}
int qr_scan_thread(SceSize args, void *argp) {
data = last_qr;
if (last_qr_len > 4) {
if (!(data[0] == 'h' && data[1] == 't' && data[2] == 't' && data[3] == 'p')) {
initMessageDialog(SCE_MSG_DIALOG_BUTTON_TYPE_OK, language_container[QR_SHOW_CONTENTS], data);
setDialogStep(DIALOG_STEP_QR_SHOW_CONTENTS);
return sceKernelExitDeleteThread(0);
}
} else {
initMessageDialog(SCE_MSG_DIALOG_BUTTON_TYPE_OK, language_container[QR_SHOW_CONTENTS], data);
setDialogStep(DIALOG_STEP_QR_SHOW_CONTENTS);
return sceKernelExitDeleteThread(0);
}
initMessageDialog(SCE_MSG_DIALOG_BUTTON_TYPE_NONE, language_container[PLEASE_WAIT]);
// check for attached file
const char *headerData;
unsigned int headerLen;
unsigned int fileNameLength = 0;
int vpk = 0;
char *fileName = "";
uint64_t fileSize;
char sizeString[16];
int ret;
ret = getDownloadFileSize(data, &fileSize);
if (ret < 0)
goto NETWORK_FAILURE;
ret = getFieldFromHeader(data, "Content-Disposition", &headerData, &headerLen);
if (ret < 0)
goto NETWORK_FAILURE;
getSizeString(sizeString, fileSize);
sceMsgDialogClose();
// Wait for it to stop loading
while (isMessageDialogRunning()) {
sceKernelDelayThread(10 * 1000);
}
if (headerLen <= 0) {
char *next;
fileName = data;
while ((next = strpbrk(fileName + 1, "\\/"))) fileName = next;
if (fileName != last_qr) fileName++;
char *ext = strrchr(fileName, '.');
if (ext) {
vpk = getFileType(fileName) == FILE_TYPE_VPK;
} else {
initMessageDialog(SCE_MSG_DIALOG_BUTTON_TYPE_YESNO, language_container[QR_OPEN_WEBSITE], data);
setDialogStep(DIALOG_STEP_QR_OPEN_WEBSITE);
return sceKernelExitDeleteThread(0);
}
} else {
if (strstr(headerData, "inline") != NULL) {
initMessageDialog(SCE_MSG_DIALOG_BUTTON_TYPE_YESNO, language_container[QR_OPEN_WEBSITE], data);
setDialogStep(DIALOG_STEP_QR_OPEN_WEBSITE);
return sceKernelExitDeleteThread(0);
}
char *p = strstr(headerData, "filename=");
if (!p)
goto EXIT;
fileName = p+9;
p = strchr(fileName, '\n');
if (p)
*p = '\0';
// Trim at beginning
while (*fileName < 0x20 ||
*fileName == ' ' || *fileName == '\\' ||
*fileName == '/' || *fileName == ':' ||
*fileName == '*' || *fileName == '?' ||
*fileName == '"' || *fileName == '<' ||
*fileName == '>' || *fileName == '|') {
fileName++;
}
// Trim at end
int i;
for (i = strlen(fileName)-1; i >= 0; i--) {
if (fileName[i] < 0x20 ||
fileName[i] == ' ' || fileName[i] == '\\' ||
fileName[i] == '/' || fileName[i] == ':' ||
fileName[i] == '*' || fileName[i] == '?' ||
fileName[i] == '"' || fileName[i] == '<' ||
fileName[i] == '>' || fileName[i] == '|') {
fileName[i] = 0;
} else {
break;
}
}
// VPK type
vpk = getFileType(fileName) == FILE_TYPE_VPK;
}
if (vpk)
initMessageDialog(SCE_MSG_DIALOG_BUTTON_TYPE_YESNO, language_container[QR_CONFIRM_INSTALL], data, fileName, sizeString);
else
initMessageDialog(SCE_MSG_DIALOG_BUTTON_TYPE_YESNO, language_container[QR_CONFIRM_DOWNLOAD], data, fileName, sizeString);
setDialogStep(DIALOG_STEP_QR_CONFIRM);
// Wait for response
while (getDialogStep() == DIALOG_STEP_QR_CONFIRM) {
sceKernelDelayThread(10 * 1000);
}
// No
if (getDialogStep() == DIALOG_STEP_NONE) {
goto EXIT;
}
// Yes
char download_path[MAX_URL_LENGTH];
char short_name[MAX_URL_LENGTH];
int count = 0;
char *ext = strrchr(fileName, '.');
if (ext) {
int len = ext-fileName;
if (len > sizeof(short_name) - 1)
len = sizeof(short_name) - 1;
strncpy(short_name, fileName, len);
short_name[len] = '\0';
} else {
strncpy(short_name, fileName, sizeof(short_name) - 1);
ext = "";
}
while (1) {
if (count == 0)
snprintf(download_path, sizeof(download_path) - 1, "ux0:download/%s", fileName);
else
snprintf(download_path, sizeof(download_path) - 1, "ux0:download/%s (%d)%s", short_name, count, ext);
SceIoStat stat;
memset(&stat, 0, sizeof(SceIoStat));
if (sceIoGetstat(download_path, &stat) < 0)
break;
count++;
}
sceIoMkdir("ux0:download", 0006);
strcpy(last_download, download_path);
if (vpk)
return downloadFileProcess(data, download_path, DIALOG_STEP_QR_DOWNLOADED_VPK);
else
return downloadFileProcess(data, download_path, DIALOG_STEP_QR_DOWNLOADED);
EXIT:
return sceKernelExitDeleteThread(0);
NETWORK_FAILURE:
sceMsgDialogClose();
while (isMessageDialogRunning()) {
sceKernelDelayThread(10 * 1000);
}
initMessageDialog(SCE_MSG_DIALOG_BUTTON_TYPE_YESNO, language_container[QR_OPEN_WEBSITE], data);
setDialogStep(DIALOG_STEP_QR_OPEN_WEBSITE);
return sceKernelExitDeleteThread(0);
}
int initQR() {
SceKernelMemBlockType orig = vita2d_texture_get_alloc_memblock_type();
vita2d_texture_set_alloc_memblock_type(SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW);
camera_tex = vita2d_create_empty_texture(CAM_WIDTH, CAM_HEIGHT);
vita2d_texture_set_alloc_memblock_type(orig);
cam_info.size = sizeof(SceCameraInfo);
cam_info.format = SCE_CAMERA_FORMAT_ABGR;
cam_info.resolution = SCE_CAMERA_RESOLUTION_640_360;
cam_info.pitch = vita2d_texture_get_stride(camera_tex) - (CAM_WIDTH << 2);
cam_info.sizeIBase = (CAM_WIDTH * CAM_HEIGHT) << 2;
cam_info.pIBase = vita2d_texture_get_datap(camera_tex);
cam_info.framerate = 30;
cam_info_read.size = sizeof(SceCameraRead);
cam_info_read.mode = 0;
if (sceCameraOpen(1, &cam_info) < 0) {
qr_enabled = 0;
vita2d_free_texture(camera_tex);
return -1;
}
thid = sceKernelCreateThread("qr_decode_thread", qr_thread, 0x40, 0x100000, 0, 0, NULL);
if (thid >= 0) sceKernelStartThread(thid, 0, NULL);
qr_enabled = 1;
return 0;
}
int finishQR() {
sceKernelDeleteThread(thid);
vita2d_free_texture(camera_tex);
sceCameraClose(1);
quirc_destroy(qr);
return 0;
}
int startQR() {
return sceCameraStart(1);
}
int stopQR() {
int res = sceCameraStop(1);
int y;
for (y = 0; y < CAM_HEIGHT; y++) {
int x;
for (x = 0; x < CAM_WIDTH; x++) {
((uint32_t *)qr_data)[x + CAM_WIDTH * y] = 0;
}
}
return res;
}
int renderCameraQR(int x, int y) {
sceCameraRead(1, &cam_info_read);
vita2d_draw_texture(camera_tex, x, y);
if (qr_next) {
qr_data = (uint32_t *)vita2d_texture_get_datap(camera_tex);
qr_next = 0;
}
return 0;
}
char *getLastQR() {
return data;
}
char *getLastDownloadQR() {
return last_download;
}
int scannedQR() {
return qr_scanned;
}
void setScannedQR(int s) {
qr_scanned = s;
}
int enabledQR() {
return qr_enabled;
/*
VitaShell
Copyright (C) 2015-2018, 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 "qr.h"
#include <psp2/kernel/processmgr.h>
#include <psp2/kernel/threadmgr.h>
#include <psp2/camera.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <quirc.h>
#include <vita2d.h>
#include "main.h"
#include "io_process.h"
#include "network_download.h"
#include "package_installer.h"
#include "archive.h"
#include "file.h"
#include "message_dialog.h"
#include "language.h"
#include "utils.h"
static int qr_enabled;
static struct quirc *qr;
static uint32_t* qr_data;
static char *data;
static int qr_next;
static vita2d_texture *camera_tex;
static SceCameraInfo cam_info;
static SceCameraRead cam_info_read;
static char last_qr[MAX_QR_LENGTH];
static char last_download[MAX_QR_LENGTH];
static int last_qr_len;
static int qr_scanned = 0;
static SceUID thid;
int qr_thread() {
qr = quirc_new();
quirc_resize(qr, CAM_WIDTH, CAM_HEIGHT);
qr_next = 1;
while (1) {
sceKernelDelayThread(10);
if (qr_next == 0 && qr_scanned == 0) {
uint8_t *image;
int w, h;
image = quirc_begin(qr, &w, &h);
uint32_t colourRGBA;
int i;
for (i = 0; i < w*h; i++) {
colourRGBA = qr_data[i];
image[i] = ((colourRGBA & 0x000000FF) + ((colourRGBA & 0x0000FF00) >> 8) + ((colourRGBA & 0x00FF0000) >> 16)) / 3;
}
quirc_end(qr);
int num_codes = quirc_count(qr);
if (num_codes > 0) {
struct quirc_code code;
struct quirc_data data;
quirc_decode_error_t err;
quirc_extract(qr, 0, &code);
err = quirc_decode(&code, &data);
if (err) {
} else {
memcpy(last_qr, data.payload, data.payload_len);
last_qr_len = data.payload_len;
qr_scanned = 1;
}
} else {
memset(last_qr, 0, MAX_QR_LENGTH);
}
qr_next = 1;
sceKernelDelayThread(250000);
}
}
}
int qr_scan_thread(SceSize args, void *argp) {
data = last_qr;
if (last_qr_len > 4) {
if (!(data[0] == 'h' && data[1] == 't' && data[2] == 't' && data[3] == 'p')) {
initMessageDialog(SCE_MSG_DIALOG_BUTTON_TYPE_OK, language_container[QR_SHOW_CONTENTS], data);
setDialogStep(DIALOG_STEP_QR_SHOW_CONTENTS);
return sceKernelExitDeleteThread(0);
}
} else {
initMessageDialog(SCE_MSG_DIALOG_BUTTON_TYPE_OK, language_container[QR_SHOW_CONTENTS], data);
setDialogStep(DIALOG_STEP_QR_SHOW_CONTENTS);
return sceKernelExitDeleteThread(0);
}
initMessageDialog(SCE_MSG_DIALOG_BUTTON_TYPE_NONE, language_container[PLEASE_WAIT]);
// check for attached file
const char *headerData;
unsigned int headerLen;
unsigned int fileNameLength = 0;
int vpk = 0;
char *fileName = "";
uint64_t fileSize;
char sizeString[16];
int ret;
ret = getDownloadFileSize(data, &fileSize);
if (ret < 0)
goto NETWORK_FAILURE;
ret = getFieldFromHeader(data, "Content-Disposition", &headerData, &headerLen);
if (ret < 0)
goto NETWORK_FAILURE;
getSizeString(sizeString, fileSize);
sceMsgDialogClose();
// Wait for it to stop loading
while (isMessageDialogRunning()) {
sceKernelDelayThread(10 * 1000);
}
if (headerLen <= 0) {
char *next;
fileName = data;
while ((next = strpbrk(fileName + 1, "\\/"))) fileName = next;
if (fileName != last_qr) fileName++;
char *ext = strrchr(fileName, '.');
if (ext) {
vpk = getFileType(fileName) == FILE_TYPE_VPK;
} else {
initMessageDialog(SCE_MSG_DIALOG_BUTTON_TYPE_YESNO, language_container[QR_OPEN_WEBSITE], data);
setDialogStep(DIALOG_STEP_QR_OPEN_WEBSITE);
return sceKernelExitDeleteThread(0);
}
} else {
if (strstr(headerData, "inline") != NULL) {
initMessageDialog(SCE_MSG_DIALOG_BUTTON_TYPE_YESNO, language_container[QR_OPEN_WEBSITE], data);
setDialogStep(DIALOG_STEP_QR_OPEN_WEBSITE);
return sceKernelExitDeleteThread(0);
}
char *p = strstr(headerData, "filename=");
if (!p)
goto EXIT;
fileName = p+9;
p = strchr(fileName, '\n');
if (p)
*p = '\0';
// Trim at beginning
while (*fileName < 0x20 ||
*fileName == ' ' || *fileName == '\\' ||
*fileName == '/' || *fileName == ':' ||
*fileName == '*' || *fileName == '?' ||
*fileName == '"' || *fileName == '<' ||
*fileName == '>' || *fileName == '|') {
fileName++;
}
// Trim at end
int i;
for (i = strlen(fileName)-1; i >= 0; i--) {
if (fileName[i] < 0x20 ||
fileName[i] == ' ' || fileName[i] == '\\' ||
fileName[i] == '/' || fileName[i] == ':' ||
fileName[i] == '*' || fileName[i] == '?' ||
fileName[i] == '"' || fileName[i] == '<' ||
fileName[i] == '>' || fileName[i] == '|') {
fileName[i] = 0;
} else {
break;
}
}
// VPK type
vpk = getFileType(fileName) == FILE_TYPE_VPK;
}
if (vpk)
initMessageDialog(SCE_MSG_DIALOG_BUTTON_TYPE_YESNO, language_container[QR_CONFIRM_INSTALL], data, fileName, sizeString);
else
initMessageDialog(SCE_MSG_DIALOG_BUTTON_TYPE_YESNO, language_container[QR_CONFIRM_DOWNLOAD], data, fileName, sizeString);
setDialogStep(DIALOG_STEP_QR_CONFIRM);
// Wait for response
while (getDialogStep() == DIALOG_STEP_QR_CONFIRM) {
sceKernelDelayThread(10 * 1000);
}
// No
if (getDialogStep() == DIALOG_STEP_NONE) {
goto EXIT;
}
// Yes
char download_path[MAX_URL_LENGTH];
char short_name[MAX_URL_LENGTH];
int count = 0;
char *ext = strrchr(fileName, '.');
if (ext) {
int len = ext-fileName;
if (len > sizeof(short_name) - 1)
len = sizeof(short_name) - 1;
strncpy(short_name, fileName, len);
short_name[len] = '\0';
} else {
strncpy(short_name, fileName, sizeof(short_name) - 1);
ext = "";
}
while (1) {
if (count == 0)
snprintf(download_path, sizeof(download_path) - 1, "ux0:download/%s", fileName);
else
snprintf(download_path, sizeof(download_path) - 1, "ux0:download/%s (%d)%s", short_name, count, ext);
SceIoStat stat;
memset(&stat, 0, sizeof(SceIoStat));
if (sceIoGetstat(download_path, &stat) < 0)
break;
count++;
}
sceIoMkdir("ux0:download", 0006);
strcpy(last_download, download_path);
if (vpk)
return downloadFileProcess(data, download_path, DIALOG_STEP_QR_DOWNLOADED_VPK);
else
return downloadFileProcess(data, download_path, DIALOG_STEP_QR_DOWNLOADED);
EXIT:
return sceKernelExitDeleteThread(0);
NETWORK_FAILURE:
sceMsgDialogClose();
while (isMessageDialogRunning()) {
sceKernelDelayThread(10 * 1000);
}
initMessageDialog(SCE_MSG_DIALOG_BUTTON_TYPE_YESNO, language_container[QR_OPEN_WEBSITE], data);
setDialogStep(DIALOG_STEP_QR_OPEN_WEBSITE);
return sceKernelExitDeleteThread(0);
}
int initQR() {
SceKernelMemBlockType orig = vita2d_texture_get_alloc_memblock_type();
vita2d_texture_set_alloc_memblock_type(SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW);
camera_tex = vita2d_create_empty_texture(CAM_WIDTH, CAM_HEIGHT);
vita2d_texture_set_alloc_memblock_type(orig);
cam_info.size = sizeof(SceCameraInfo);
cam_info.format = SCE_CAMERA_FORMAT_ABGR;
cam_info.resolution = SCE_CAMERA_RESOLUTION_640_360;
cam_info.pitch = vita2d_texture_get_stride(camera_tex) - (CAM_WIDTH << 2);
cam_info.sizeIBase = (CAM_WIDTH * CAM_HEIGHT) << 2;
cam_info.pIBase = vita2d_texture_get_datap(camera_tex);
cam_info.framerate = 30;
cam_info_read.size = sizeof(SceCameraRead);
cam_info_read.mode = 0;
if (sceCameraOpen(1, &cam_info) < 0) {
qr_enabled = 0;
vita2d_free_texture(camera_tex);
return -1;
}
thid = sceKernelCreateThread("qr_decode_thread", qr_thread, 0x40, 0x100000, 0, 0, NULL);
if (thid >= 0) sceKernelStartThread(thid, 0, NULL);
qr_enabled = 1;
return 0;
}
int finishQR() {
sceKernelDeleteThread(thid);
vita2d_free_texture(camera_tex);
sceCameraClose(1);
quirc_destroy(qr);
return 0;
}
int startQR() {
return sceCameraStart(1);
}
int stopQR() {
int res = sceCameraStop(1);
int y;
for (y = 0; y < CAM_HEIGHT; y++) {
int x;
for (x = 0; x < CAM_WIDTH; x++) {
((uint32_t *)qr_data)[x + CAM_WIDTH * y] = 0;
}
}
return res;
}
int renderCameraQR(int x, int y) {
sceCameraRead(1, &cam_info_read);
vita2d_draw_texture(camera_tex, x, y);
if (qr_next) {
qr_data = (uint32_t *)vita2d_texture_get_datap(camera_tex);
qr_next = 0;
}
return 0;
}
char *getLastQR() {
return data;
}
char *getLastDownloadQR() {
return last_download;
}
int scannedQR() {
return qr_scanned;
}
void setScannedQR(int s) {
qr_scanned = s;
}
int enabledQR() {
return qr_enabled;
}

72
qr.h
View File

@ -1,37 +1,37 @@
/*
VitaShell
Copyright (C) 2015-2018, 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 __QR_H__
#define __QR_H__
#include <psp2/kernel/sysmem.h>
int qr_scan_thread(SceSize args, void *argp);
int initQR();
int finishQR();
int startQR();
int stopQR();
int enabledQR();
int scannedQR();
int renderCameraQR(int x, int y);
char *getLastQR();
char *getLastDownloadQR();
void setScannedQR(int scanned);
/*
VitaShell
Copyright (C) 2015-2018, 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 __QR_H__
#define __QR_H__
#include <psp2/kernel/sysmem.h>
int qr_scan_thread(SceSize args, void *argp);
int initQR();
int finishQR();
int startQR();
int stopQR();
int enabledQR();
int scannedQR();
int renderCameraQR(int x, int y);
char *getLastQR();
char *getLastDownloadQR();
void setScannedQR(int scanned);
#endif

876
refresh.c
View File

@ -1,438 +1,438 @@
/*
VitaShell
Copyright (C) 2015-2018, TheFloW
Copyright (C) 2017, VitaSmith
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 "init.h"
#include "io_process.h"
#include "refresh.h"
#include "package_installer.h"
#include "sfo.h"
#include "file.h"
#include "message_dialog.h"
#include "language.h"
#include "utils.h"
#include "rif.h"
// Note: The promotion process is *VERY* sensitive to the directories used below
// Don't change them unless you know what you are doing!
#define APP_TEMP "ux0:temp/app"
#define DLC_TEMP "ux0:temp/addcont"
#define MAX_DLC_PER_TITLE 1024
int isCustomHomebrew(const char* path)
{
uint32_t work[RIF_SIZE/4];
if (ReadFile(path, work, sizeof(work)) != sizeof(work))
return 0;
for (int i = 0; i < sizeof(work) / sizeof(uint32_t); i++)
if (work[i] != 0)
return 0;
return 1;
}
int refreshNeeded(const char *app_path)
{
char sfo_path[MAX_PATH_LENGTH];
// TODO: Check app vs dlc from SFO
int res, is_app = (app_path[6] == 'p');
// Read param.sfo
snprintf(sfo_path, MAX_PATH_LENGTH - 1, "%s/sce_sys/param.sfo", app_path);
void *sfo_buffer = NULL;
int sfo_size = allocateReadFile(sfo_path, &sfo_buffer);
if (sfo_size < 0) {
if (sfo_buffer)
free(sfo_buffer);
return sfo_size;
}
// Get title and content ids
char titleid[12], contentid[50];
getSfoString(sfo_buffer, "TITLE_ID", titleid, sizeof(titleid));
getSfoString(sfo_buffer, "CONTENT_ID", contentid, sizeof(contentid));
// Free sfo buffer
free(sfo_buffer);
// Check if app exists
if (checkAppExist(titleid)) {
char rif_name[48];
uint64_t aid;
sceRegMgrGetKeyBin("/CONFIG/NP", "account_id", &aid, sizeof(uint64_t));
// Check if bounded rif file exits
_sceNpDrmGetRifName(rif_name, 0, aid);
if (is_app)
snprintf(sfo_path, MAX_PATH_LENGTH - 1, "ux0:license/app/%s/%s", titleid, rif_name);
else
snprintf(sfo_path, MAX_PATH_LENGTH - 1, "ux0:license/addcont/%s/%s/%s", titleid, &contentid[20], rif_name);
if (checkFileExist(sfo_path))
return 0;
// Check if fixed rif file exits
_sceNpDrmGetFixedRifName(rif_name, 0, 0);
if (is_app)
snprintf(sfo_path, MAX_PATH_LENGTH - 1, "ux0:license/app/%s/%s", titleid, rif_name);
else
snprintf(sfo_path, MAX_PATH_LENGTH - 1, "ux0:license/addcont/%s/%s/%s", titleid, &contentid[20], rif_name);
if (checkFileExist(sfo_path))
return 0;
}
return 1;
}
int refreshApp(const char *app_path)
{
char work_bin_path[MAX_PATH_LENGTH];
int res;
snprintf(work_bin_path, MAX_PATH_LENGTH - 1, "%s/sce_sys/package/work.bin", app_path);
// Remove work.bin for custom homebrews
if (isCustomHomebrew(work_bin_path)) {
sceIoRemove(work_bin_path);
} else if (!checkFileExist(work_bin_path)) {
// If available, restore work.bin from licenses.db
void *sfo_buffer = NULL;
char sfo_path[MAX_PATH_LENGTH], contentid[50];
snprintf(sfo_path, MAX_PATH_LENGTH - 1, "%s/sce_sys/param.sfo", app_path);
int sfo_size = allocateReadFile(sfo_path, &sfo_buffer);
if (sfo_size > 0) {
getSfoString(sfo_buffer, "CONTENT_ID", contentid, sizeof(contentid));
uint8_t* rif = query_rif(LICENSE_DB, contentid);
if (rif != NULL) {
int fh = sceIoOpen(work_bin_path, SCE_O_WRONLY | SCE_O_CREAT, 0777);
if (fh > 0) {
sceIoWrite(fh, rif, RIF_SIZE);
sceIoClose(fh);
}
free(rif);
}
}
free(sfo_buffer);
}
// Promote app/dlc
res = promoteApp(app_path);
return (res < 0) ? res : 1;
}
// target_type should be either SCE_S_IFREG for files or SCE_S_IFDIR for directories
int parse_dir_with_callback(int target_type, const char* path, void(*callback)(void*, const char*, const char*), void* data)
{
SceUID dfd = sceIoDopen(path);
if (dfd >= 0) {
int res = 0;
do {
SceIoDirent dir;
memset(&dir, 0, sizeof(SceIoDirent));
res = sceIoDread(dfd, &dir);
if (res > 0) {
if ((dir.d_stat.st_mode & SCE_S_IFMT) == target_type) {
callback(data, path, dir.d_name);
if (cancelHandler()) {
closeWaitDialog();
setDialogStep(DIALOG_STEP_CANCELED);
return -1;
}
}
}
} while (res > 0);
sceIoDclose(dfd);
}
return 0;
}
typedef struct {
int refresh_pass;
int count;
int processed;
int refreshed;
} refresh_data_t;
typedef struct {
refresh_data_t *refresh_data;
char* list[MAX_DLC_PER_TITLE];
int list_size;
} dlc_data_t;
typedef struct {
int copy_pass;
int count;
int processed;
int copied;
int cur_depth;
int max_depth;
uint8_t* rif;
} license_data_t;
void app_callback(void* data, const char* dir, const char* subdir)
{
refresh_data_t *refresh_data = (refresh_data_t*)data;
char path[MAX_PATH_LENGTH];
if (strcasecmp(subdir, vitashell_titleid) == 0)
return;
if (refresh_data->refresh_pass) {
snprintf(path, MAX_PATH_LENGTH - 1, "%s/%s", dir, subdir);
if (refreshNeeded(path)) {
// Move the directory to temp for installation
removePath(APP_TEMP, NULL);
sceIoRename(path, APP_TEMP);
if (refreshApp(APP_TEMP) == 1)
refresh_data->refreshed++;
else
// Restore folder on error
sceIoRename(APP_TEMP, path);
}
SetProgress(++refresh_data->processed, refresh_data->count);
} else {
refresh_data->count++;
}
}
void dlc_callback_inner(void* data, const char* dir, const char* subdir)
{
dlc_data_t *dlc_data = (dlc_data_t*)data;
char path[MAX_PATH_LENGTH];
// Ignore "sce_sys" and "sce_pfs" directories
if (strncasecmp(subdir, "sce_", 4) == 0)
return;
if (dlc_data->refresh_data->refresh_pass) {
snprintf(path, MAX_PATH_LENGTH - 1, "%s/%s", dir, subdir);
if (dlc_data->list_size < MAX_DLC_PER_TITLE)
dlc_data->list[dlc_data->list_size++] = strdup(path);
} else {
dlc_data->refresh_data->count++;
}
}
void dlc_callback_outer(void* data, const char* dir, const char* subdir)
{
refresh_data_t *refresh_data = (refresh_data_t*)data;
dlc_data_t dlc_data;
dlc_data.refresh_data = refresh_data;
dlc_data.list_size = 0;
char path[MAX_PATH_LENGTH];
// Get the title's dlc subdirectories
int len = snprintf(path, sizeof(path), "%s/%s", dir, subdir);
parse_dir_with_callback(SCE_S_IFDIR, path, dlc_callback_inner, &dlc_data);
if (refresh_data->refresh_pass) {
// For dlc, the process happens in two phases to avoid promotion errors:
// 1. Move all dlc that require refresh out of addcont/title_id
// 2. Refresh the moved dlc_data
for (int i = 0; i < dlc_data.list_size; i++) {
if (refreshNeeded(dlc_data.list[i])) {
snprintf(path, MAX_PATH_LENGTH - 1, DLC_TEMP "/%s", &dlc_data.list[i][len + 1]);
removePath(path, NULL);
sceIoRename(dlc_data.list[i], path);
} else {
free(dlc_data.list[i]);
dlc_data.list[i] = NULL;
SetProgress(++refresh_data->processed, refresh_data->count);
}
}
// Now that the dlc we need are out of addcont/title_id, refresh them
for (int i = 0; i < dlc_data.list_size; i++) {
if (dlc_data.list[i] != NULL) {
snprintf(path, MAX_PATH_LENGTH - 1, DLC_TEMP "/%s", &dlc_data.list[i][len + 1]);
if (refreshApp(path) == 1)
refresh_data->refreshed++;
else
sceIoRename(path, dlc_data.list[i]);
SetProgress(++refresh_data->processed, refresh_data->count);
free(dlc_data.list[i]);
}
}
}
}
int refresh_thread(SceSize args, void *argp)
{
SceUID thid = -1;
refresh_data_t refresh_data = { 0, 0, 0, 0 };
// Lock power timers
powerLock();
// Set progress to 0%
sceMsgDialogProgressBarSetValue(SCE_MSG_DIALOG_PROGRESSBAR_TARGET_BAR_DEFAULT, 0);
sceKernelDelayThread(DIALOG_WAIT); // Needed to see the percentage
// Get the app count
if (parse_dir_with_callback(SCE_S_IFDIR, "ux0:app", app_callback, &refresh_data) < 0)
goto EXIT;
// Get the dlc count
if (parse_dir_with_callback(SCE_S_IFDIR, "ux0:addcont", dlc_callback_outer, &refresh_data) < 0)
goto EXIT;
// Update thread
thid = createStartUpdateThread(refresh_data.count, 0);
// Make sure we have the temp directories we need
sceIoMkdir("ux0:temp", 0006);
sceIoMkdir("ux0:temp/addcont", 0006);
refresh_data.refresh_pass = 1;
// Refresh apps
if (parse_dir_with_callback(SCE_S_IFDIR, "ux0:app", app_callback, &refresh_data) < 0)
goto EXIT;
// Refresh dlc
if (parse_dir_with_callback(SCE_S_IFDIR, "ux0:addcont", dlc_callback_outer, &refresh_data) < 0)
goto EXIT;
sceIoRmdir("ux0:temp/addcont");
// Set progress to 100%
sceMsgDialogProgressBarSetValue(SCE_MSG_DIALOG_PROGRESSBAR_TARGET_BAR_DEFAULT, 100);
sceKernelDelayThread(COUNTUP_WAIT);
// Close
closeWaitDialog();
infoDialog(language_container[REFRESHED], refresh_data.refreshed);
EXIT:
if (thid >= 0)
sceKernelWaitThreadEnd(thid, NULL, NULL);
// Unlock power timers
powerUnlock();
return sceKernelExitDeleteThread(0);
}
// Note: This is currently not optimized AT ALL.
// Ultimately, we want to use a single transaction and avoid trying to
// re-insert rifs that are already present.
void license_file_callback(void* data, const char* dir, const char* file)
{
license_data_t *license_data = (license_data_t*)data;
char path[MAX_PATH_LENGTH];
// Ignore non rif content
if ((strlen(file) < 4) || (strcasecmp(&file[strlen(file) - 4], ".rif") != 0))
return;
if (license_data->copy_pass) {
snprintf(path, sizeof(path), "%s/%s", dir, file);
SceUID fd = sceIoOpen(path, SCE_O_RDONLY, 0777);
if (fd > 0) {
int read = sceIoRead(fd, license_data->rif, RIF_SIZE);
if (read == RIF_SIZE) {
if (insert_rif(LICENSE_DB, license_data->rif) == 0)
license_data->copied++;
}
sceIoClose(fd);
}
SetProgress(++license_data->processed, license_data->count);
} else {
license_data->count++;
}
}
void license_dir_callback(void* data, const char* dir, const char* subdir)
{
license_data_t *license_data = (license_data_t*)data;
char path[MAX_PATH_LENGTH];
snprintf(path, sizeof(path), "%s/%s", dir, subdir);
if (++license_data->cur_depth == license_data->max_depth)
parse_dir_with_callback(SCE_S_IFREG, path, license_file_callback, data);
else
parse_dir_with_callback(SCE_S_IFDIR, path, license_dir_callback, data);
license_data->cur_depth--;
}
int license_thread(SceSize args, void *argp)
{
SceUID thid = -1;
license_data_t license_data = { 0, 0, 0, 0, 0, 1, malloc(RIF_SIZE) };
if (license_data.rif == NULL)
goto EXIT;
// Lock power timers
powerLock();
// Set progress to 0%
sceMsgDialogProgressBarSetValue(SCE_MSG_DIALOG_PROGRESSBAR_TARGET_BAR_DEFAULT, 0);
sceKernelDelayThread(DIALOG_WAIT); // Needed to see the percentage
// NB: ux0:license access requires elevated permisions
if (parse_dir_with_callback(SCE_S_IFDIR, "ux0:license/app", license_dir_callback, &license_data) < 0)
goto EXIT;
license_data.max_depth++;
if (parse_dir_with_callback(SCE_S_IFDIR, "ux0:license/addcont", license_dir_callback, &license_data) < 0)
goto EXIT;
// Update thread
thid = createStartUpdateThread(license_data.count, 0);
// Create the DB if needed
SceUID fd = sceIoOpen(LICENSE_DB, SCE_O_RDONLY, 0777);
if (fd > 0) {
sceIoClose(fd);
} else if (create_db(LICENSE_DB, LICENSE_DB_SCHEMA) != 0) {
goto EXIT;
}
// Insert the licenses
license_data.copy_pass = 1;
license_data.max_depth = 1;
if (parse_dir_with_callback(SCE_S_IFDIR, "ux0:license/app", license_dir_callback, &license_data) < 0)
goto EXIT;
license_data.max_depth++;
if (parse_dir_with_callback(SCE_S_IFDIR, "ux0:license/addcont", license_dir_callback, &license_data) < 0)
goto EXIT;
// Set progress to 100%
sceMsgDialogProgressBarSetValue(SCE_MSG_DIALOG_PROGRESSBAR_TARGET_BAR_DEFAULT, 100);
sceKernelDelayThread(COUNTUP_WAIT);
// Close
closeWaitDialog();
infoDialog(language_container[IMPORTED_LICENSES], license_data.copied);
EXIT:
if (thid >= 0)
sceKernelWaitThreadEnd(thid, NULL, NULL);
// Unlock power timers
powerUnlock();
free(license_data.rif);
return sceKernelExitDeleteThread(0);
}
/*
VitaShell
Copyright (C) 2015-2018, TheFloW
Copyright (C) 2017, VitaSmith
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 "init.h"
#include "io_process.h"
#include "refresh.h"
#include "package_installer.h"
#include "sfo.h"
#include "file.h"
#include "message_dialog.h"
#include "language.h"
#include "utils.h"
#include "rif.h"
// Note: The promotion process is *VERY* sensitive to the directories used below
// Don't change them unless you know what you are doing!
#define APP_TEMP "ux0:temp/app"
#define DLC_TEMP "ux0:temp/addcont"
#define MAX_DLC_PER_TITLE 1024
int isCustomHomebrew(const char* path)
{
uint32_t work[RIF_SIZE/4];
if (ReadFile(path, work, sizeof(work)) != sizeof(work))
return 0;
for (int i = 0; i < sizeof(work) / sizeof(uint32_t); i++)
if (work[i] != 0)
return 0;
return 1;
}
int refreshNeeded(const char *app_path)
{
char sfo_path[MAX_PATH_LENGTH];
// TODO: Check app vs dlc from SFO
int res, is_app = (app_path[6] == 'p');
// Read param.sfo
snprintf(sfo_path, MAX_PATH_LENGTH - 1, "%s/sce_sys/param.sfo", app_path);
void *sfo_buffer = NULL;
int sfo_size = allocateReadFile(sfo_path, &sfo_buffer);
if (sfo_size < 0) {
if (sfo_buffer)
free(sfo_buffer);
return sfo_size;
}
// Get title and content ids
char titleid[12], contentid[50];
getSfoString(sfo_buffer, "TITLE_ID", titleid, sizeof(titleid));
getSfoString(sfo_buffer, "CONTENT_ID", contentid, sizeof(contentid));
// Free sfo buffer
free(sfo_buffer);
// Check if app exists
if (checkAppExist(titleid)) {
char rif_name[48];
uint64_t aid;
sceRegMgrGetKeyBin("/CONFIG/NP", "account_id", &aid, sizeof(uint64_t));
// Check if bounded rif file exits
_sceNpDrmGetRifName(rif_name, 0, aid);
if (is_app)
snprintf(sfo_path, MAX_PATH_LENGTH - 1, "ux0:license/app/%s/%s", titleid, rif_name);
else
snprintf(sfo_path, MAX_PATH_LENGTH - 1, "ux0:license/addcont/%s/%s/%s", titleid, &contentid[20], rif_name);
if (checkFileExist(sfo_path))
return 0;
// Check if fixed rif file exits
_sceNpDrmGetFixedRifName(rif_name, 0, 0);
if (is_app)
snprintf(sfo_path, MAX_PATH_LENGTH - 1, "ux0:license/app/%s/%s", titleid, rif_name);
else
snprintf(sfo_path, MAX_PATH_LENGTH - 1, "ux0:license/addcont/%s/%s/%s", titleid, &contentid[20], rif_name);
if (checkFileExist(sfo_path))
return 0;
}
return 1;
}
int refreshApp(const char *app_path)
{
char work_bin_path[MAX_PATH_LENGTH];
int res;
snprintf(work_bin_path, MAX_PATH_LENGTH - 1, "%s/sce_sys/package/work.bin", app_path);
// Remove work.bin for custom homebrews
if (isCustomHomebrew(work_bin_path)) {
sceIoRemove(work_bin_path);
} else if (!checkFileExist(work_bin_path)) {
// If available, restore work.bin from licenses.db
void *sfo_buffer = NULL;
char sfo_path[MAX_PATH_LENGTH], contentid[50];
snprintf(sfo_path, MAX_PATH_LENGTH - 1, "%s/sce_sys/param.sfo", app_path);
int sfo_size = allocateReadFile(sfo_path, &sfo_buffer);
if (sfo_size > 0) {
getSfoString(sfo_buffer, "CONTENT_ID", contentid, sizeof(contentid));
uint8_t* rif = query_rif(LICENSE_DB, contentid);
if (rif != NULL) {
int fh = sceIoOpen(work_bin_path, SCE_O_WRONLY | SCE_O_CREAT, 0777);
if (fh > 0) {
sceIoWrite(fh, rif, RIF_SIZE);
sceIoClose(fh);
}
free(rif);
}
}
free(sfo_buffer);
}
// Promote app/dlc
res = promoteApp(app_path);
return (res < 0) ? res : 1;
}
// target_type should be either SCE_S_IFREG for files or SCE_S_IFDIR for directories
int parse_dir_with_callback(int target_type, const char* path, void(*callback)(void*, const char*, const char*), void* data)
{
SceUID dfd = sceIoDopen(path);
if (dfd >= 0) {
int res = 0;
do {
SceIoDirent dir;
memset(&dir, 0, sizeof(SceIoDirent));
res = sceIoDread(dfd, &dir);
if (res > 0) {
if ((dir.d_stat.st_mode & SCE_S_IFMT) == target_type) {
callback(data, path, dir.d_name);
if (cancelHandler()) {
closeWaitDialog();
setDialogStep(DIALOG_STEP_CANCELED);
return -1;
}
}
}
} while (res > 0);
sceIoDclose(dfd);
}
return 0;
}
typedef struct {
int refresh_pass;
int count;
int processed;
int refreshed;
} refresh_data_t;
typedef struct {
refresh_data_t *refresh_data;
char* list[MAX_DLC_PER_TITLE];
int list_size;
} dlc_data_t;
typedef struct {
int copy_pass;
int count;
int processed;
int copied;
int cur_depth;
int max_depth;
uint8_t* rif;
} license_data_t;
void app_callback(void* data, const char* dir, const char* subdir)
{
refresh_data_t *refresh_data = (refresh_data_t*)data;
char path[MAX_PATH_LENGTH];
if (strcasecmp(subdir, vitashell_titleid) == 0)
return;
if (refresh_data->refresh_pass) {
snprintf(path, MAX_PATH_LENGTH - 1, "%s/%s", dir, subdir);
if (refreshNeeded(path)) {
// Move the directory to temp for installation
removePath(APP_TEMP, NULL);
sceIoRename(path, APP_TEMP);
if (refreshApp(APP_TEMP) == 1)
refresh_data->refreshed++;
else
// Restore folder on error
sceIoRename(APP_TEMP, path);
}
SetProgress(++refresh_data->processed, refresh_data->count);
} else {
refresh_data->count++;
}
}
void dlc_callback_inner(void* data, const char* dir, const char* subdir)
{
dlc_data_t *dlc_data = (dlc_data_t*)data;
char path[MAX_PATH_LENGTH];
// Ignore "sce_sys" and "sce_pfs" directories
if (strncasecmp(subdir, "sce_", 4) == 0)
return;
if (dlc_data->refresh_data->refresh_pass) {
snprintf(path, MAX_PATH_LENGTH - 1, "%s/%s", dir, subdir);
if (dlc_data->list_size < MAX_DLC_PER_TITLE)
dlc_data->list[dlc_data->list_size++] = strdup(path);
} else {
dlc_data->refresh_data->count++;
}
}
void dlc_callback_outer(void* data, const char* dir, const char* subdir)
{
refresh_data_t *refresh_data = (refresh_data_t*)data;
dlc_data_t dlc_data;
dlc_data.refresh_data = refresh_data;
dlc_data.list_size = 0;
char path[MAX_PATH_LENGTH];
// Get the title's dlc subdirectories
int len = snprintf(path, sizeof(path), "%s/%s", dir, subdir);
parse_dir_with_callback(SCE_S_IFDIR, path, dlc_callback_inner, &dlc_data);
if (refresh_data->refresh_pass) {
// For dlc, the process happens in two phases to avoid promotion errors:
// 1. Move all dlc that require refresh out of addcont/title_id
// 2. Refresh the moved dlc_data
for (int i = 0; i < dlc_data.list_size; i++) {
if (refreshNeeded(dlc_data.list[i])) {
snprintf(path, MAX_PATH_LENGTH - 1, DLC_TEMP "/%s", &dlc_data.list[i][len + 1]);
removePath(path, NULL);
sceIoRename(dlc_data.list[i], path);
} else {
free(dlc_data.list[i]);
dlc_data.list[i] = NULL;
SetProgress(++refresh_data->processed, refresh_data->count);
}
}
// Now that the dlc we need are out of addcont/title_id, refresh them
for (int i = 0; i < dlc_data.list_size; i++) {
if (dlc_data.list[i] != NULL) {
snprintf(path, MAX_PATH_LENGTH - 1, DLC_TEMP "/%s", &dlc_data.list[i][len + 1]);
if (refreshApp(path) == 1)
refresh_data->refreshed++;
else
sceIoRename(path, dlc_data.list[i]);
SetProgress(++refresh_data->processed, refresh_data->count);
free(dlc_data.list[i]);
}
}
}
}
int refresh_thread(SceSize args, void *argp)
{
SceUID thid = -1;
refresh_data_t refresh_data = { 0, 0, 0, 0 };
// Lock power timers
powerLock();
// Set progress to 0%
sceMsgDialogProgressBarSetValue(SCE_MSG_DIALOG_PROGRESSBAR_TARGET_BAR_DEFAULT, 0);
sceKernelDelayThread(DIALOG_WAIT); // Needed to see the percentage
// Get the app count
if (parse_dir_with_callback(SCE_S_IFDIR, "ux0:app", app_callback, &refresh_data) < 0)
goto EXIT;
// Get the dlc count
if (parse_dir_with_callback(SCE_S_IFDIR, "ux0:addcont", dlc_callback_outer, &refresh_data) < 0)
goto EXIT;
// Update thread
thid = createStartUpdateThread(refresh_data.count, 0);
// Make sure we have the temp directories we need
sceIoMkdir("ux0:temp", 0006);
sceIoMkdir("ux0:temp/addcont", 0006);
refresh_data.refresh_pass = 1;
// Refresh apps
if (parse_dir_with_callback(SCE_S_IFDIR, "ux0:app", app_callback, &refresh_data) < 0)
goto EXIT;
// Refresh dlc
if (parse_dir_with_callback(SCE_S_IFDIR, "ux0:addcont", dlc_callback_outer, &refresh_data) < 0)
goto EXIT;
sceIoRmdir("ux0:temp/addcont");
// Set progress to 100%
sceMsgDialogProgressBarSetValue(SCE_MSG_DIALOG_PROGRESSBAR_TARGET_BAR_DEFAULT, 100);
sceKernelDelayThread(COUNTUP_WAIT);
// Close
closeWaitDialog();
infoDialog(language_container[REFRESHED], refresh_data.refreshed);
EXIT:
if (thid >= 0)
sceKernelWaitThreadEnd(thid, NULL, NULL);
// Unlock power timers
powerUnlock();
return sceKernelExitDeleteThread(0);
}
// Note: This is currently not optimized AT ALL.
// Ultimately, we want to use a single transaction and avoid trying to
// re-insert rifs that are already present.
void license_file_callback(void* data, const char* dir, const char* file)
{
license_data_t *license_data = (license_data_t*)data;
char path[MAX_PATH_LENGTH];
// Ignore non rif content
if ((strlen(file) < 4) || (strcasecmp(&file[strlen(file) - 4], ".rif") != 0))
return;
if (license_data->copy_pass) {
snprintf(path, sizeof(path), "%s/%s", dir, file);
SceUID fd = sceIoOpen(path, SCE_O_RDONLY, 0777);
if (fd > 0) {
int read = sceIoRead(fd, license_data->rif, RIF_SIZE);
if (read == RIF_SIZE) {
if (insert_rif(LICENSE_DB, license_data->rif) == 0)
license_data->copied++;
}
sceIoClose(fd);
}
SetProgress(++license_data->processed, license_data->count);
} else {
license_data->count++;
}
}
void license_dir_callback(void* data, const char* dir, const char* subdir)
{
license_data_t *license_data = (license_data_t*)data;
char path[MAX_PATH_LENGTH];
snprintf(path, sizeof(path), "%s/%s", dir, subdir);
if (++license_data->cur_depth == license_data->max_depth)
parse_dir_with_callback(SCE_S_IFREG, path, license_file_callback, data);
else
parse_dir_with_callback(SCE_S_IFDIR, path, license_dir_callback, data);
license_data->cur_depth--;
}
int license_thread(SceSize args, void *argp)
{
SceUID thid = -1;
license_data_t license_data = { 0, 0, 0, 0, 0, 1, malloc(RIF_SIZE) };
if (license_data.rif == NULL)
goto EXIT;
// Lock power timers
powerLock();
// Set progress to 0%
sceMsgDialogProgressBarSetValue(SCE_MSG_DIALOG_PROGRESSBAR_TARGET_BAR_DEFAULT, 0);
sceKernelDelayThread(DIALOG_WAIT); // Needed to see the percentage
// NB: ux0:license access requires elevated permisions
if (parse_dir_with_callback(SCE_S_IFDIR, "ux0:license/app", license_dir_callback, &license_data) < 0)
goto EXIT;
license_data.max_depth++;
if (parse_dir_with_callback(SCE_S_IFDIR, "ux0:license/addcont", license_dir_callback, &license_data) < 0)
goto EXIT;
// Update thread
thid = createStartUpdateThread(license_data.count, 0);
// Create the DB if needed
SceUID fd = sceIoOpen(LICENSE_DB, SCE_O_RDONLY, 0777);
if (fd > 0) {
sceIoClose(fd);
} else if (create_db(LICENSE_DB, LICENSE_DB_SCHEMA) != 0) {
goto EXIT;
}
// Insert the licenses
license_data.copy_pass = 1;
license_data.max_depth = 1;
if (parse_dir_with_callback(SCE_S_IFDIR, "ux0:license/app", license_dir_callback, &license_data) < 0)
goto EXIT;
license_data.max_depth++;
if (parse_dir_with_callback(SCE_S_IFDIR, "ux0:license/addcont", license_dir_callback, &license_data) < 0)
goto EXIT;
// Set progress to 100%
sceMsgDialogProgressBarSetValue(SCE_MSG_DIALOG_PROGRESSBAR_TARGET_BAR_DEFAULT, 100);
sceKernelDelayThread(COUNTUP_WAIT);
// Close
closeWaitDialog();
infoDialog(language_container[IMPORTED_LICENSES], license_data.copied);
EXIT:
if (thid >= 0)
sceKernelWaitThreadEnd(thid, NULL, NULL);
// Unlock power timers
powerUnlock();
free(license_data.rif);
return sceKernelExitDeleteThread(0);
}

388
sfo.c
View File

@ -1,194 +1,194 @@
/*
VitaShell
Copyright (C) 2015-2018, 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 "archive.h"
#include "file.h"
#include "text.h"
#include "hex.h"
#include "message_dialog.h"
#include "theme.h"
#include "language.h"
#include "utils.h"
#include "sfo.h"
int getSfoValue(void *buffer, const char *name, uint32_t *value) {
SfoHeader *header = (SfoHeader *)buffer;
SfoEntry *entries = (SfoEntry *)((uint32_t)buffer + sizeof(SfoHeader));
if (header->magic != SFO_MAGIC)
return VITASHELL_ERROR_INVALID_MAGIC;
int i;
for (i = 0; i < header->count; i++) {
if (strcmp(buffer + header->keyofs + entries[i].nameofs, name) == 0) {
*value = *(uint32_t *)(buffer + header->valofs + entries[i].dataofs);
return 0;
}
}
return VITASHELL_ERROR_NOT_FOUND;
}
int getSfoString(void *buffer, const char *name, char *string, int length) {
SfoHeader *header = (SfoHeader *)buffer;
SfoEntry *entries = (SfoEntry *)((uint32_t)buffer + sizeof(SfoHeader));
if (header->magic != SFO_MAGIC)
return VITASHELL_ERROR_INVALID_MAGIC;
int i;
for (i = 0; i < header->count; i++) {
if (strcmp(buffer + header->keyofs + entries[i].nameofs, name) == 0) {
memset(string, 0, length);
strncpy(string, buffer + header->valofs + entries[i].dataofs, length);
string[length - 1] = '\0';
return 0;
}
}
return VITASHELL_ERROR_NOT_FOUND;
}
int setSfoValue(void *buffer, const char *name, uint32_t value) {
SfoHeader *header = (SfoHeader *)buffer;
SfoEntry *entries = (SfoEntry *)((uint32_t)buffer + sizeof(SfoHeader));
if (header->magic != SFO_MAGIC)
return VITASHELL_ERROR_INVALID_MAGIC;
int i;
for (i = 0; i < header->count; i++) {
if (strcmp(buffer + header->keyofs + entries[i].nameofs, name) == 0) {
*(uint32_t *)(buffer + header->valofs + entries[i].dataofs) = value;
return 0;
}
}
return VITASHELL_ERROR_NOT_FOUND;
}
int setSfoString(void *buffer, const char *name, const char *string) {
SfoHeader *header = (SfoHeader *)buffer;
SfoEntry *entries = (SfoEntry *)((uint32_t)buffer + sizeof(SfoHeader));
if (header->magic != SFO_MAGIC)
return VITASHELL_ERROR_INVALID_MAGIC;
int i;
for (i = 0; i < header->count; i++) {
if (strcmp(buffer + header->keyofs + entries[i].nameofs, name) == 0) {
strcpy(buffer + header->valofs + entries[i].dataofs, string);
return 0;
}
}
return VITASHELL_ERROR_NOT_FOUND;
}
int SFOReader(const char *file) {
uint8_t *buffer = memalign(4096, BIG_BUFFER_SIZE);
if (!buffer)
return VITASHELL_ERROR_NO_MEMORY;
int size = 0;
if (isInArchive()) {
size = ReadArchiveFile(file, buffer, BIG_BUFFER_SIZE);
} else {
size = ReadFile(file, buffer, BIG_BUFFER_SIZE);
}
if (size <= 0) {
free(buffer);
return size;
}
SfoHeader *sfo_header = (SfoHeader *)buffer;
if (sfo_header->magic != SFO_MAGIC)
return VITASHELL_ERROR_INVALID_MAGIC;
int base_pos = 0, rel_pos = 0;
while (1) {
readPad();
if (pressed_pad[PAD_CANCEL]) {
break;
}
if (hold_pad[PAD_UP] || hold2_pad[PAD_LEFT_ANALOG_UP]) {
if (rel_pos > 0) {
rel_pos--;
} else if (base_pos > 0) {
base_pos--;
}
} else if (hold_pad[PAD_DOWN] || hold2_pad[PAD_LEFT_ANALOG_DOWN]) {
if ((rel_pos + 1) < sfo_header->count) {
if ((rel_pos + 1) < MAX_POSITION) {
rel_pos++;
} else if ((base_pos + rel_pos + 1) < sfo_header->count) {
base_pos++;
}
}
}
// Start drawing
startDrawing(bg_text_image);
// Draw shell info
drawShellInfo(file);
// Draw scroll bar
drawScrollBar(base_pos, sfo_header->count);
int i;
for (i = 0; i < MAX_ENTRIES && (base_pos + i) < sfo_header->count; i++) {
SfoEntry *entries = (SfoEntry *)(buffer + sizeof(SfoHeader) + (sizeof(SfoEntry) * (i + base_pos)));
uint32_t color = (rel_pos == i) ? TEXT_FOCUS_COLOR : TEXT_COLOR;
char *name = (char *)buffer + sfo_header->keyofs + entries->nameofs;
pgf_draw_textf(SHELL_MARGIN_X, START_Y + (FONT_Y_SPACE * i), color, "%s", name);
char string[128];
void *data = (void *)buffer + sfo_header->valofs + entries->dataofs;
switch (entries->type) {
case PSF_TYPE_BIN:
break;
case PSF_TYPE_STR:
snprintf(string, sizeof(string), "%s", (char *)data);
break;
case PSF_TYPE_VAL:
snprintf(string, sizeof(string), "0x%X", *(unsigned int *)data);
break;
}
pgf_draw_textf(ALIGN_RIGHT(INFORMATION_X, pgf_text_width(string)), START_Y + (FONT_Y_SPACE * i), color, string);
}
// End drawing
endDrawing();
}
free(buffer);
return 0;
}
/*
VitaShell
Copyright (C) 2015-2018, 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 "archive.h"
#include "file.h"
#include "text.h"
#include "hex.h"
#include "message_dialog.h"
#include "theme.h"
#include "language.h"
#include "utils.h"
#include "sfo.h"
int getSfoValue(void *buffer, const char *name, uint32_t *value) {
SfoHeader *header = (SfoHeader *)buffer;
SfoEntry *entries = (SfoEntry *)((uint32_t)buffer + sizeof(SfoHeader));
if (header->magic != SFO_MAGIC)
return VITASHELL_ERROR_INVALID_MAGIC;
int i;
for (i = 0; i < header->count; i++) {
if (strcmp(buffer + header->keyofs + entries[i].nameofs, name) == 0) {
*value = *(uint32_t *)(buffer + header->valofs + entries[i].dataofs);
return 0;
}
}
return VITASHELL_ERROR_NOT_FOUND;
}
int getSfoString(void *buffer, const char *name, char *string, int length) {
SfoHeader *header = (SfoHeader *)buffer;
SfoEntry *entries = (SfoEntry *)((uint32_t)buffer + sizeof(SfoHeader));
if (header->magic != SFO_MAGIC)
return VITASHELL_ERROR_INVALID_MAGIC;
int i;
for (i = 0; i < header->count; i++) {
if (strcmp(buffer + header->keyofs + entries[i].nameofs, name) == 0) {
memset(string, 0, length);
strncpy(string, buffer + header->valofs + entries[i].dataofs, length);
string[length - 1] = '\0';
return 0;
}
}
return VITASHELL_ERROR_NOT_FOUND;
}
int setSfoValue(void *buffer, const char *name, uint32_t value) {
SfoHeader *header = (SfoHeader *)buffer;
SfoEntry *entries = (SfoEntry *)((uint32_t)buffer + sizeof(SfoHeader));
if (header->magic != SFO_MAGIC)
return VITASHELL_ERROR_INVALID_MAGIC;
int i;
for (i = 0; i < header->count; i++) {
if (strcmp(buffer + header->keyofs + entries[i].nameofs, name) == 0) {
*(uint32_t *)(buffer + header->valofs + entries[i].dataofs) = value;
return 0;
}
}
return VITASHELL_ERROR_NOT_FOUND;
}
int setSfoString(void *buffer, const char *name, const char *string) {
SfoHeader *header = (SfoHeader *)buffer;
SfoEntry *entries = (SfoEntry *)((uint32_t)buffer + sizeof(SfoHeader));
if (header->magic != SFO_MAGIC)
return VITASHELL_ERROR_INVALID_MAGIC;
int i;
for (i = 0; i < header->count; i++) {
if (strcmp(buffer + header->keyofs + entries[i].nameofs, name) == 0) {
strcpy(buffer + header->valofs + entries[i].dataofs, string);
return 0;
}
}
return VITASHELL_ERROR_NOT_FOUND;
}
int SFOReader(const char *file) {
uint8_t *buffer = memalign(4096, BIG_BUFFER_SIZE);
if (!buffer)
return VITASHELL_ERROR_NO_MEMORY;
int size = 0;
if (isInArchive()) {
size = ReadArchiveFile(file, buffer, BIG_BUFFER_SIZE);
} else {
size = ReadFile(file, buffer, BIG_BUFFER_SIZE);
}
if (size <= 0) {
free(buffer);
return size;
}
SfoHeader *sfo_header = (SfoHeader *)buffer;
if (sfo_header->magic != SFO_MAGIC)
return VITASHELL_ERROR_INVALID_MAGIC;
int base_pos = 0, rel_pos = 0;
while (1) {
readPad();
if (pressed_pad[PAD_CANCEL]) {
break;
}
if (hold_pad[PAD_UP] || hold2_pad[PAD_LEFT_ANALOG_UP]) {
if (rel_pos > 0) {
rel_pos--;
} else if (base_pos > 0) {
base_pos--;
}
} else if (hold_pad[PAD_DOWN] || hold2_pad[PAD_LEFT_ANALOG_DOWN]) {
if ((rel_pos + 1) < sfo_header->count) {
if ((rel_pos + 1) < MAX_POSITION) {
rel_pos++;
} else if ((base_pos + rel_pos + 1) < sfo_header->count) {
base_pos++;
}
}
}
// Start drawing
startDrawing(bg_text_image);
// Draw shell info
drawShellInfo(file);
// Draw scroll bar
drawScrollBar(base_pos, sfo_header->count);
int i;
for (i = 0; i < MAX_ENTRIES && (base_pos + i) < sfo_header->count; i++) {
SfoEntry *entries = (SfoEntry *)(buffer + sizeof(SfoHeader) + (sizeof(SfoEntry) * (i + base_pos)));
uint32_t color = (rel_pos == i) ? TEXT_FOCUS_COLOR : TEXT_COLOR;
char *name = (char *)buffer + sfo_header->keyofs + entries->nameofs;
pgf_draw_textf(SHELL_MARGIN_X, START_Y + (FONT_Y_SPACE * i), color, "%s", name);
char string[128];
void *data = (void *)buffer + sfo_header->valofs + entries->dataofs;
switch (entries->type) {
case PSF_TYPE_BIN:
break;
case PSF_TYPE_STR:
snprintf(string, sizeof(string), "%s", (char *)data);
break;
case PSF_TYPE_VAL:
snprintf(string, sizeof(string), "0x%X", *(unsigned int *)data);
break;
}
pgf_draw_textf(ALIGN_RIGHT(INFORMATION_X, pgf_text_width(string)), START_Y + (FONT_Y_SPACE * i), color, string);
}
// End drawing
endDrawing();
}
free(buffer);
return 0;
}

104
sfo.h
View File

@ -1,53 +1,53 @@
/*
VitaShell
Copyright (C) 2015-2018, 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 __SFO_H__
#define __SFO_H__
#define SFO_MAGIC 0x46535000
#define PSF_TYPE_BIN 0
#define PSF_TYPE_STR 2
#define PSF_TYPE_VAL 4
typedef struct SfoHeader {
uint32_t magic;
uint32_t version;
uint32_t keyofs;
uint32_t valofs;
uint32_t count;
} __attribute__((packed)) SfoHeader;
typedef struct SfoEntry {
uint16_t nameofs;
uint8_t alignment;
uint8_t type;
uint32_t valsize;
uint32_t totalsize;
uint32_t dataofs;
} __attribute__((packed)) SfoEntry;
int getSfoValue(void *buffer, const char *name, uint32_t *value);
int getSfoString(void *buffer, const char *name, char *string, int length);
int setSfoValue(void *buffer, const char *name, uint32_t value);
int setSfoString(void *buffer, const char *name, const char *string);
int SFOReader(const char *file);
/*
VitaShell
Copyright (C) 2015-2018, 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 __SFO_H__
#define __SFO_H__
#define SFO_MAGIC 0x46535000
#define PSF_TYPE_BIN 0
#define PSF_TYPE_STR 2
#define PSF_TYPE_VAL 4
typedef struct SfoHeader {
uint32_t magic;
uint32_t version;
uint32_t keyofs;
uint32_t valofs;
uint32_t count;
} __attribute__((packed)) SfoHeader;
typedef struct SfoEntry {
uint16_t nameofs;
uint8_t alignment;
uint8_t type;
uint32_t valsize;
uint32_t totalsize;
uint32_t dataofs;
} __attribute__((packed)) SfoEntry;
int getSfoValue(void *buffer, const char *name, uint32_t *value);
int getSfoString(void *buffer, const char *name, char *string, int length);
int setSfoValue(void *buffer, const char *name, uint32_t value);
int setSfoString(void *buffer, const char *name, const char *string);
int SFOReader(const char *file);
#endif