Intelligent zoom for photoviewer. Using double linked lists

This commit is contained in:
TheFloW 2016-01-28 17:36:29 +01:00
parent dc751d20ad
commit de282271d2
17 changed files with 367 additions and 276 deletions

95
file.c
View File

@ -257,35 +257,34 @@ int copyPath(char *src, char *dst, uint32_t *value, uint32_t max, void (* SetPro
return 0;
}
typedef struct {
char *extension;
int type;
} ExtensionType;
ExtensionType extension_types[] = {
{ ".7Z", FILE_TYPE_7ZIP },
{ ".BMP", FILE_TYPE_BMP },
{ ".ELF", FILE_TYPE_ELF },
{ ".JPG", FILE_TYPE_JPEG },
{ ".JPEG", FILE_TYPE_JPEG },
{ ".PBP", FILE_TYPE_PBP },
{ ".PNG", FILE_TYPE_PNG },
{ ".RAR", FILE_TYPE_RAR },
{ ".SELF", FILE_TYPE_ELF },
//{ ".TXT", FILE_TYPE_TXT },
{ ".VELF", FILE_TYPE_ELF },
{ ".ZIP", FILE_TYPE_ZIP },
};
int getFileType(char *file) {
uint32_t magic;
uint32_t read = 0;
if (isInArchive()) {
read = ReadArchiveFile(file, &magic, sizeof(uint32_t));
} else {
read = ReadFile(file, &magic, sizeof(uint32_t));
}
if (read == sizeof(uint32_t)) {
uint16_t magic2 = magic & 0xFFFF;
if (magic2 == 0x4D42) {
return FILE_TYPE_BMP;
} else if (magic == 0x464C457F) {
return FILE_TYPE_ELF;
} else if (magic == 0x474E5089) {
return FILE_TYPE_PNG;
} else if (magic == 0xE0FFD8FF || magic == 0xE1FFD8FF) {
return FILE_TYPE_JPEG;
} else if (magic == 0x50425000) {
return FILE_TYPE_PBP;
} else if (magic == 0x5E7E4552 || magic == 0x21726152) {
return FILE_TYPE_RAR;
} else if (magic == 0xAFBC7A37) {
return FILE_TYPE_7ZIP;
} else if (magic == 0x04034B50 || magic == 0x06054B50) {
return FILE_TYPE_ZIP;
char *p = strrchr(file, '.');
if (p) {
int i;
for (i = 0; i < (sizeof(extension_types) / sizeof(ExtensionType)); i++) {
if (strcasecmp(p, extension_types[i].extension) == 0) {
return extension_types[i].type;
}
}
}
@ -356,6 +355,7 @@ FileListEntry *fileListGetNthEntry(FileList *list, int n) {
void fileListAddEntry(FileList *list, FileListEntry *entry, int sort) {
entry->next = NULL;
entry->previous = NULL;
if (list->head == NULL) {
list->head = entry;
@ -396,16 +396,20 @@ void fileListAddEntry(FileList *list, FileListEntry *entry, int sort) {
p = p->next;
}
if (previous == NULL) { // Order: entry -> p
list->head = entry;
if (previous == NULL) { // Order: entry (new head) -> p (old head)
entry->next = p;
} else if (previous->next == NULL) { // Order: p -> entry at tail
p->previous = entry;
list->head = entry;
} else if (previous->next == NULL) { // Order: p (old tail) -> entry (new tail)
FileListEntry *tail = list->tail;
tail->next = entry;
entry->previous = tail;
list->tail = entry;
} else { // Order: previous -> entry -> p
previous->next = entry;
entry->previous = previous;
entry->next = p;
p->previous = entry;
}
} else {
FileListEntry *tail = list->tail;
@ -417,7 +421,30 @@ void fileListAddEntry(FileList *list, FileListEntry *entry, int sort) {
list->length++;
}
int fileListRemoveEntry(FileList *list, char *name) {
int fileListRemoveEntry(FileList *list, FileListEntry *entry) {
if (entry) {
if (entry->previous) {
entry->previous->next = entry->next;
} else {
list->head = entry->next;
}
if (entry->next) {
entry->next->previous = entry->previous;
} else {
list->tail = entry->previous;
}
list->length--;
free(entry);
return 1;
}
return 0;
}
int fileListRemoveEntryByName(FileList *list, char *name) {
FileListEntry *entry = list->head;
FileListEntry *previous = NULL;
@ -456,7 +483,9 @@ void fileListEmpty(FileList *list) {
entry = next;
}
memset(list, 0, sizeof(FileList));
list->head = NULL;
list->tail = NULL;
list->length = 0;
}
int fileListGetMountPointEntries(FileList *list) {

5
file.h
View File

@ -48,6 +48,7 @@ enum SortFlags {
typedef struct FileListEntry {
struct FileListEntry *next;
struct FileListEntry *previous;
char name[MAX_NAME_LENGTH];
int is_folder;
int type;
@ -59,6 +60,7 @@ typedef struct {
FileListEntry *head;
FileListEntry *tail;
int length;
char path[MAX_PATH_LENGTH];
} FileList;
int ReadFile(char *file, void *buf, int size);
@ -78,7 +80,8 @@ int replaceMountPoint(char *old_mount_point, char *new_mount_point);
FileListEntry *fileListFindEntry(FileList *list, char *name);
FileListEntry *fileListGetNthEntry(FileList *list, int n);
void fileListAddEntry(FileList *list, FileListEntry *entry, int sort);
int fileListRemoveEntry(FileList *list, char *name);
int fileListRemoveEntry(FileList *list, FileListEntry *entry);
int fileListRemoveEntryByName(FileList *list, char *name);
void fileListEmpty(FileList *list);
int fileListGetEntries(FileList *list, char *path);

23
hex.c
View File

@ -27,6 +27,7 @@
void hexListAddEntry(HexList *list, HexListEntry *entry) {
entry->next = NULL;
entry->previous = NULL;
if (list->head == NULL) {
list->head = entry;
@ -34,6 +35,7 @@ void hexListAddEntry(HexList *list, HexListEntry *entry) {
} else {
HexListEntry *tail = list->tail;
tail->next = entry;
entry->previous = tail;
list->tail = entry;
}
@ -49,7 +51,9 @@ void hexListEmpty(HexList *list) {
entry = next;
}
memset(list, 0, sizeof(HexList));
list->head = NULL;
list->tail = NULL;
list->length = 0;
}
HexListEntry *hexListGetNthEntry(HexList *list, int n) {
@ -121,20 +125,16 @@ int hexViewer(char *file) {
// Tail to head
list.tail->next = list.head;
list.head->previous = list.tail;
list.head = list.tail;
// Second last to tail
HexListEntry *second_last = list.tail->next;
while (second_last) {
if (second_last->next == list.tail)
break;
second_last = second_last->next;
}
list.tail = second_last;
list.tail = list.tail->previous;
list.tail->next = NULL;
// No previous
list.head->previous = NULL;
// Read
memcpy(list.head->data, buffer + base_pos, 0x10);
}
@ -148,12 +148,15 @@ int hexViewer(char *file) {
base_pos += 0x10;
// Head to tail
list.head->previous = list.tail;
list.tail->next = list.head;
list.tail = list.head;
// Second first to head
list.head = list.head->next;
list.head->previous = NULL;
// No next
list.tail->next = NULL;
// Read

1
hex.h
View File

@ -28,6 +28,7 @@ enum GroupSizes {
typedef struct HexListEntry {
struct HexListEntry *next;
struct HexListEntry *previous;
uint8_t data[0x10];
} HexListEntry;

View File

@ -791,8 +791,9 @@ int sceIoReadPatchedUVL(SceUID fd, void *data, SceSize size) {
int sceIoWritePatchedUVL(SceUID fd, const void *data, SceSize size) {
// Redirect to our debug logging and close the uvloader.log descriptor
debugPrintf((char *)data);
return sceIoClose(fd);
//debugPrintf((char *)data);
//return sceIoClose(fd);
return sceIoWrite(fd, data, size);
}
int sceIoClosePatchedUVL(SceUID fd) {
@ -896,8 +897,8 @@ int PatchUVL() {
#ifdef DISABLE_UVL_LOGGING
// Disable UVL logging because this causes crash for xerpi derpi
// makeThumbDummyFunction0(extractFunctionStub((uint32_t)&uvl_debug_log) & ~0x1);
// makeThumbDummyFunction0(extractFunctionStub((uint32_t)&uvl_log_write) & ~0x1);
makeThumbDummyFunction0(extractFunctionStub((uint32_t)&uvl_debug_log) & ~0x1);
makeThumbDummyFunction0(extractFunctionStub((uint32_t)&uvl_log_write) & ~0x1);
#endif
return 0;

4
init.c
View File

@ -353,14 +353,14 @@ void initVitaShell() {
#ifdef USE_HOST0
// Init psp2link
psp2LinkInit("192.168.178.20", 0x4711, 0x4712, 0x4712, 3);
//psp2LinkInit("192.168.178.20", 0x4711, 0x4712, 0x4712, 3);
#endif
}
void finishVitaShell() {
#ifdef USE_HOST0
// Finish psp2link
psp2LinkFinish();
//psp2LinkFinish();
#endif
// Finish netdbg

View File

@ -63,7 +63,7 @@ int delete_thread(SceSize args_size, DeleteArguments *args) {
for (i = 0; i < count; i++) {
disableAutoSuspend();
snprintf(path, MAX_PATH_LENGTH, "%s%s", args->cur_path, mark_entry->name);
snprintf(path, MAX_PATH_LENGTH, "%s%s", args->file_list->path, mark_entry->name);
removeEndSlash(path);
getPathInfo(path, &size, &folders, &files);
@ -79,7 +79,7 @@ int delete_thread(SceSize args_size, DeleteArguments *args) {
for (i = 0; i < count; i++) {
disableAutoSuspend();
snprintf(path, MAX_PATH_LENGTH, "%s%s", args->cur_path, mark_entry->name);
snprintf(path, MAX_PATH_LENGTH, "%s%s", args->file_list->path, mark_entry->name);
removeEndSlash(path);
int res = removePath(path, &value, folders + files, SetProgress);
@ -123,8 +123,8 @@ int copy_thread(SceSize args_size, CopyArguments *args) {
for (i = 0; i < args->copy_list->length; i++) {
disableAutoSuspend();
snprintf(src_path, MAX_PATH_LENGTH, "%s%s", args->copy_path, copy_entry->name);
snprintf(dst_path, MAX_PATH_LENGTH, "%s%s", args->cur_path, copy_entry->name);
snprintf(src_path, MAX_PATH_LENGTH, "%s%s", args->copy_list->path, copy_entry->name);
snprintf(dst_path, MAX_PATH_LENGTH, "%s%s", args->file_list->path, copy_entry->name);
int res = sceIoRename(src_path, dst_path);
// TODO: if (res == 0x80010011) if folder
@ -161,7 +161,7 @@ int copy_thread(SceSize args_size, CopyArguments *args) {
for (i = 0; i < args->copy_list->length; i++) {
disableAutoSuspend();
snprintf(src_path, MAX_PATH_LENGTH, "%s%s", args->copy_path, copy_entry->name);
snprintf(src_path, MAX_PATH_LENGTH, "%s%s", args->copy_list->path, copy_entry->name);
if (args->copy_mode == COPY_MODE_EXTRACT) {
addEndSlash(src_path);
@ -182,8 +182,8 @@ int copy_thread(SceSize args_size, CopyArguments *args) {
for (i = 0; i < args->copy_list->length; i++) {
disableAutoSuspend();
snprintf(src_path, MAX_PATH_LENGTH, "%s%s", args->copy_path, copy_entry->name);
snprintf(dst_path, MAX_PATH_LENGTH, "%s%s", args->cur_path, copy_entry->name);
snprintf(src_path, MAX_PATH_LENGTH, "%s%s", args->copy_list->path, copy_entry->name);
snprintf(dst_path, MAX_PATH_LENGTH, "%s%s", args->file_list->path, copy_entry->name);
if (args->copy_mode == COPY_MODE_EXTRACT) {
addEndSlash(src_path);

View File

@ -28,15 +28,12 @@
typedef struct {
FileList *file_list;
FileList *mark_list;
char *cur_path;
int index;
} DeleteArguments;
typedef struct {
FileList *file_list;
FileList *copy_list;
char *cur_path;
char *copy_path;
char *archive_path;
int copy_mode;
} CopyArguments;

View File

@ -23,6 +23,8 @@
#include "module.h"
#include "psp2link/psp2link.h"
static int io_patched = 0;
#ifdef USE_HOST0
int verifyFd(SceUID fd) {
@ -217,21 +219,25 @@ void PatchIO() {
makeFunctionStub((uint32_t)&sceIoDclose, sceIoDclosePatched);
makeFunctionStub((uint32_t)&sceIoGetstat, sceIoGetstatPatched);
makeFunctionStub((uint32_t)&sceIoChstat, sceIoChstatPatched);
io_patched = 1;
}
void restoreIOPatches() {
copyStub((uint32_t)&sceIoOpen, (void *)&_sceIoOpen);
copyStub((uint32_t)&sceIoClose, (void *)&_sceIoClose);
copyStub((uint32_t)&sceIoRead, (void *)&_sceIoRead);
copyStub((uint32_t)&sceIoWrite, (void *)&_sceIoWrite);
copyStub((uint32_t)&sceIoLseek, (void *)&_sceIoLseek);
copyStub((uint32_t)&sceIoRemove, (void *)&_sceIoRemove);
copyStub((uint32_t)&sceIoMkdir, (void *)&_sceIoMkdir);
copyStub((uint32_t)&sceIoRmdir, (void *)&_sceIoRmdir);
copyStub((uint32_t)&sceIoRename, (void *)&_sceIoRename);
copyStub((uint32_t)&sceIoDopen, (void *)&_sceIoDopen);
copyStub((uint32_t)&sceIoDread, (void *)&_sceIoDread);
copyStub((uint32_t)&sceIoDclose, (void *)&_sceIoDclose);
copyStub((uint32_t)&sceIoGetstat, (void *)&_sceIoGetstat);
copyStub((uint32_t)&sceIoChstat, (void *)&_sceIoChstat);
if (io_patched) {
copyStub((uint32_t)&sceIoOpen, (void *)&_sceIoOpen);
copyStub((uint32_t)&sceIoClose, (void *)&_sceIoClose);
copyStub((uint32_t)&sceIoRead, (void *)&_sceIoRead);
copyStub((uint32_t)&sceIoWrite, (void *)&_sceIoWrite);
copyStub((uint32_t)&sceIoLseek, (void *)&_sceIoLseek);
copyStub((uint32_t)&sceIoRemove, (void *)&_sceIoRemove);
copyStub((uint32_t)&sceIoMkdir, (void *)&_sceIoMkdir);
copyStub((uint32_t)&sceIoRmdir, (void *)&_sceIoRmdir);
copyStub((uint32_t)&sceIoRename, (void *)&_sceIoRename);
copyStub((uint32_t)&sceIoDopen, (void *)&_sceIoDopen);
copyStub((uint32_t)&sceIoDread, (void *)&_sceIoDread);
copyStub((uint32_t)&sceIoDclose, (void *)&_sceIoDclose);
copyStub((uint32_t)&sceIoGetstat, (void *)&_sceIoGetstat);
copyStub((uint32_t)&sceIoChstat, (void *)&_sceIoChstat);
}
}

75
main.c
View File

@ -18,8 +18,10 @@
/*
TODO:
- Fix psp2link finish...
- Fix UVL logging strange behaviour on homebrew loading or self reloading
- Photoviewer, handle big images
- Limit long file names on browser
- Handle big images
- Add shader compiler feature
- NEARLY DONE: Terminate thread / free stack of previous VitaShell when reloading
- Redirecting .data segment when reloading
@ -65,7 +67,7 @@ int _newlib_heap_size_user = 32 * 1024 * 1024;
static FileList file_list, mark_list, copy_list;
// Paths
static char cur_file[MAX_PATH_LENGTH], cur_path[MAX_PATH_LENGTH], copy_path[MAX_PATH_LENGTH], archive_path[MAX_PATH_LENGTH];
static char cur_file[MAX_PATH_LENGTH], archive_path[MAX_PATH_LENGTH];
// Mount point stat
static SceIoStat mount_point_stat;
@ -128,27 +130,27 @@ void dirUpCloseArchive() {
}
void dirUp() {
removeEndSlash(cur_path);
removeEndSlash(file_list.path);
char *p;
p = strrchr(cur_path, '/');
p = strrchr(file_list.path, '/');
if (p) {
p[1] = '\0';
dir_level--;
goto DIR_UP_RETURN;
}
p = strrchr(cur_path, ':');
p = strrchr(file_list.path, ':');
if (p) {
if (strlen(cur_path) - ((p + 1) - cur_path) > 0) {
if (strlen(file_list.path) - ((p + 1) - file_list.path) > 0) {
p[1] = '\0';
dir_level--;
goto DIR_UP_RETURN;
}
}
strcpy(cur_path, HOME_PATH);
strcpy(file_list.path, HOME_PATH);
dir_level = 0;
DIR_UP_RETURN:
@ -163,7 +165,7 @@ void refreshFileList() {
do {
fileListEmpty(&file_list);
res = fileListGetEntries(&file_list, cur_path);
res = fileListGetEntries(&file_list, file_list.path);
if (res < 0)
dirUp();
@ -191,12 +193,12 @@ void refreshMarkList() {
FileListEntry *next = entry->next;
char path[MAX_PATH_LENGTH];
snprintf(path, MAX_PATH_LENGTH, "%s%s", cur_path, entry->name);
snprintf(path, MAX_PATH_LENGTH, "%s%s", file_list.path, entry->name);
// Check if the entry still exits. If not, remove it from list
SceIoStat stat;
if (sceIoGetstat(path, &stat) < 0)
fileListRemoveEntry(&mark_list, entry->name);
fileListRemoveEntry(&mark_list, entry);
// Next
entry = next;
@ -214,12 +216,12 @@ void refreshCopyList() {
FileListEntry *next = entry->next;
char path[MAX_PATH_LENGTH];
snprintf(path, MAX_PATH_LENGTH, "%s%s", copy_path, entry->name);
snprintf(path, MAX_PATH_LENGTH, "%s%s", copy_list.path, entry->name);
// Check if the entry still exits. If not, remove it from list
SceIoStat stat;
if (sceIoGetstat(path, &stat) < 0)
fileListRemoveEntry(&copy_list, entry->name);
fileListRemoveEntry(&copy_list, entry);
// Next
entry = next;
@ -231,6 +233,9 @@ void resetFileLists() {
memset(&mark_list, 0, sizeof(FileList));
memset(&copy_list, 0, sizeof(FileList));
// Home
strcpy(file_list.path, HOME_PATH);
refreshFileList();
}
@ -291,7 +296,7 @@ int signPspFile(char *file) {
return 0;
}
int handleFile(char *file) {
int handleFile(char *file, FileListEntry *entry) {
int res = 0;
int type = getFileType(file);
@ -324,7 +329,7 @@ int handleFile(char *file) {
case FILE_TYPE_BMP:
case FILE_TYPE_PNG:
case FILE_TYPE_JPEG:
res = photoViewer(file, type);
res = photoViewer(file, type, &file_list, entry);
break;
case FILE_TYPE_PBP:
@ -672,7 +677,7 @@ void contextMenuCtrl() {
fileListAddEntry(&copy_list, copy_entry, SORT_NONE);
}
strcpy(copy_path, cur_path);
strcpy(copy_list.path, file_list.path);
char string[128];
sprintf(string, language_container[COPY_MESSAGE], copy_list.length);
@ -718,7 +723,7 @@ void contextMenuCtrl() {
FileListEntry *file_entry = fileListGetNthEntry(&file_list, base_pos + rel_pos);
char uri[MAX_PATH_LENGTH];
sprintf(uri, "email:send?attach=%s%s.", cur_path, file_entry->name);
sprintf(uri, "email:send?attach=%s%s.", file_list.path, file_entry->name);
debugPrintf("%s\n", uri);
sceAppMgrLaunchAppByUri(0xFFFFF, uri);
break;
@ -763,7 +768,7 @@ int dialogSteps() {
sceMsgDialogClose();
} else if (msg_result == MESSAGE_DIALOG_RESULT_FINISHED) {
if (psp2LinkRequestsIsConnected()) {
strcpy(cur_path, HOST0);
strcpy(file_list.path, HOST0);
memset(&mount_point_stat, 0, sizeof(SceIoStat));
sceIoGetstat(HOST0, &mount_point_stat);
@ -816,7 +821,7 @@ int dialogSteps() {
char *name = (char *)getImeDialogInputTextUTF8();
if (strlen(name) > 0) {
char path[MAX_PATH_LENGTH];
snprintf(path, MAX_PATH_LENGTH, "%s%s", cur_path, name);
snprintf(path, MAX_PATH_LENGTH, "%s%s", file_list.path, name);
int res = sceIoMkdir(path, 0777);
if (res < 0) {
@ -837,8 +842,6 @@ int dialogSteps() {
CopyArguments args;
args.file_list = &file_list;
args.copy_list = &copy_list;
args.cur_path = cur_path;
args.copy_path = copy_path;
args.archive_path = archive_path;
args.copy_mode = copy_mode;
@ -866,7 +869,6 @@ int dialogSteps() {
DeleteArguments args;
args.file_list = &file_list;
args.mark_list = &mark_list;
args.cur_path = cur_path;
args.index = base_pos + rel_pos;
SceUID thid = sceKernelCreateThread("delete_thread", (SceKernelThreadEntry)delete_thread, 0x40, 0x10000, 0, 0x70000, NULL);
@ -887,8 +889,8 @@ int dialogSteps() {
char old_path[MAX_PATH_LENGTH];
char new_path[MAX_PATH_LENGTH];
snprintf(old_path, MAX_PATH_LENGTH, "%s%s", cur_path, file_entry->name);
snprintf(new_path, MAX_PATH_LENGTH, "%s%s", cur_path, name);
snprintf(old_path, MAX_PATH_LENGTH, "%s%s", file_list.path, file_entry->name);
snprintf(new_path, MAX_PATH_LENGTH, "%s%s", file_list.path, name);
int res = sceIoRename(old_path, new_path);
if (res < 0) {
@ -994,7 +996,7 @@ void fileBrowserMenuCtrl() {
memcpy(mark_entry, file_entry, sizeof(FileListEntry));
fileListAddEntry(&mark_list, mark_entry, SORT_NONE);
} else {
fileListRemoveEntry(&mark_list, file_entry->name);
fileListRemoveEntryByName(&mark_list, file_entry->name);
}
}
}
@ -1022,7 +1024,7 @@ void fileBrowserMenuCtrl() {
initMessageDialog(SCE_MSG_DIALOG_BUTTON_TYPE_CANCEL, language_container[WAIT_CONNECTION]);
dialog_step = DIALOG_STEP_WAIT_CONNECTION;
} else {
strcpy(cur_path, file_entry->name);
strcpy(file_list.path, file_entry->name);
memset(&mount_point_stat, 0, sizeof(SceIoStat));
sceIoGetstat(file_entry->name, &mount_point_stat);
@ -1031,12 +1033,12 @@ void fileBrowserMenuCtrl() {
#endif
} else {
if (dir_level == 0) {
strcpy(cur_path, file_entry->name);
strcpy(file_list.path, file_entry->name);
memset(&mount_point_stat, 0, sizeof(SceIoStat));
sceIoGetstat(file_entry->name, &mount_point_stat);
} else {
addEndSlash(cur_path);
strcat(cur_path, file_entry->name);
addEndSlash(file_list.path);
strcat(file_list.path, file_entry->name);
}
dirLevelUp();
@ -1044,18 +1046,18 @@ void fileBrowserMenuCtrl() {
refreshFileList();
} else {
snprintf(cur_file, MAX_PATH_LENGTH, "%s%s", cur_path, file_entry->name);
int type = handleFile(cur_file);
snprintf(cur_file, MAX_PATH_LENGTH, "%s%s", file_list.path, file_entry->name);
int type = handleFile(cur_file, file_entry);
// Archive mode
if (type == FILE_TYPE_RAR || type == FILE_TYPE_7ZIP || type == FILE_TYPE_ZIP) {
is_in_archive = 1;
dir_level_archive = dir_level;
snprintf(archive_path, MAX_PATH_LENGTH, "%s%s", cur_path, file_entry->name);
snprintf(archive_path, MAX_PATH_LENGTH, "%s%s", file_list.path, file_entry->name);
strcat(cur_path, file_entry->name);
addEndSlash(cur_path);
strcat(file_list.path, file_entry->name);
addEndSlash(file_list.path);
dirLevelUp();
refreshFileList();
@ -1071,13 +1073,8 @@ int shellMain() {
// Paths
memset(cur_file, 0, sizeof(cur_file));
memset(cur_path, 0, sizeof(cur_path));
memset(copy_path, 0, sizeof(copy_path));
memset(archive_path, 0, sizeof(archive_path));
// Home
strcpy(cur_path, HOME_PATH);
// Reset file lists
resetFileLists();
@ -1108,7 +1105,7 @@ int shellMain() {
START_DRAWING();
// Draw shell info
drawShellInfo(cur_path);
drawShellInfo(file_list.path);
// Draw scroll bar
drawScrollBar(base_pos, file_list.length);

4
main.h
View File

@ -63,9 +63,7 @@
//#define RELEASE 1
#define USE_HOST0 1
//#define ENABLE_FILE_LOGGING 1
#define DISABLE_UVL_LOGGING 1
//#define ENABLE_DEBUGNET_LOGGING 1
//#define DISABLE_UVL_LOGGING 1
// VitaShell version major.minor
#define VITASHELL_VERSION_MAJOR 0

278
photo.c
View File

@ -26,32 +26,7 @@ int isHorizontal(float rad) {
return ((int)sinf(rad) == 0) ? 1 : 0;
}
void photoMode(float *zoom, float width, float height, float rad, int mode) {
int horizontal = isHorizontal(rad);
switch (mode) {
case MODE_CUSTOM:
break;
case MODE_FIT_HEIGHT:
*zoom = horizontal ? (SCREEN_HEIGHT / height) : (SCREEN_HEIGHT / width);
break;
case MODE_FIT_WIDTH:
*zoom = horizontal ? (SCREEN_WIDTH / width) : (SCREEN_WIDTH / height);
break;
}
}
int photoViewer(char *file, int type) {
int hex_viewer = 0;
vita2d_texture *tex = NULL;
char *buffer = malloc(BIG_BUFFER_SIZE);
if (!buffer)
return -1;
vita2d_texture *loadImage(char *file, int type, char *buffer) {
int size = 0;
if (isInArchive()) {
@ -61,10 +36,11 @@ int photoViewer(char *file, int type) {
}
if (size <= 0) {
free(buffer);
return size;
return NULL;
}
vita2d_texture *tex = NULL;
switch (type) {
case FILE_TYPE_BMP:
tex = vita2d_load_BMP_buffer(buffer);
@ -79,68 +55,167 @@ int photoViewer(char *file, int type) {
break;
}
// Set bilinear filter
if (tex)
vita2d_texture_set_filters(tex, SCE_GXM_TEXTURE_FILTER_LINEAR, SCE_GXM_TEXTURE_FILTER_LINEAR);
return tex;
}
void resetImageInfo(vita2d_texture *tex, float *width, float *height, float *x, float *y, float *rad, float *zoom, int *mode, uint64_t *time) {
*width = vita2d_texture_get_width(tex);
*height = vita2d_texture_get_height(tex);
*x = *width / 2.0f;
*y = *height / 2.0f;
*rad = 0;
*zoom = 1.0f;
*mode = MODE_PERFECT;
photoMode(zoom, *width, *height, *rad, *mode);
*time = sceKernelGetProcessTimeWide();
}
void photoMode(float *zoom, float width, float height, float rad, int mode) {
int horizontal = isHorizontal(rad);
switch (mode) {
case MODE_CUSTOM:
break;
case MODE_PERFECT: // this is only used for showing image the first time
if (height > SCREEN_HEIGHT) { // first priority, fit height
*zoom = SCREEN_HEIGHT / height;
} else if (width > SCREEN_WIDTH) { // second priority, fit screen
*zoom = SCREEN_WIDTH / width;
} else { // otherwise, original size
*zoom = 1.0f;
}
break;
case MODE_ORIGINAL:
*zoom = 1.0f;
break;
case MODE_FIT_HEIGHT:
*zoom = horizontal ? (SCREEN_HEIGHT / height) : (SCREEN_HEIGHT / width);
break;
case MODE_FIT_WIDTH:
*zoom = horizontal ? (SCREEN_WIDTH / width) : (SCREEN_WIDTH / height);
break;
}
}
int getNextZoomMode(float *zoom, float width, float height, float rad, int mode) {
float next_zoom = ZOOM_MAX;
int next_mode = MODE_ORIGINAL;
float smallest_zoom = ZOOM_MAX;
int smallest_mode = MODE_ORIGINAL;
int i = 0;
while (i < 3) {
if (mode == MODE_CUSTOM || mode == MODE_PERFECT || mode == MODE_FIT_WIDTH) {
mode = MODE_ORIGINAL;
} else {
mode++;
}
float new_zoom = 0.0f;
photoMode(&new_zoom, width, height, rad, mode);
if (new_zoom < smallest_zoom) {
smallest_zoom = new_zoom;
smallest_mode = mode;
}
if (new_zoom > *zoom && new_zoom < next_zoom) {
next_zoom = new_zoom;
next_mode = mode;
}
i++;
}
// Get smallest then
if (next_zoom == ZOOM_MAX) {
next_zoom = smallest_zoom;
next_mode = smallest_mode;
}
*zoom = next_zoom;
return next_mode;
}
int photoViewer(char *file, int type, FileList *list, FileListEntry *entry) {
char *buffer = malloc(BIG_BUFFER_SIZE);
if (!buffer)
return -1;
vita2d_texture *tex = loadImage(file, type, buffer);
if (!tex) {
free(buffer);
return -1;
}
// Set bilinear filter
vita2d_texture_set_filters(tex, SCE_GXM_TEXTURE_FILTER_LINEAR, SCE_GXM_TEXTURE_FILTER_LINEAR);
// Variables
float width = vita2d_texture_get_width(tex);
float height = vita2d_texture_get_height(tex);
float half_width = width / 2.0f;
float half_height = height / 2.0f;
float hotspot_x = half_width;
float hotspot_y = half_height;
float rad = 0;
float zoom = 1.0f;
// Photo mode
int mode = MODE_FIT_HEIGHT;
photoMode(&zoom, width, height, rad, mode);
float width = 0.0f, height = 0.0f, x = 0.0f, y = 0.0f, rad = 0.0f, zoom = 1.0f;
int mode = MODE_PERFECT;
uint64_t time = 0;
// Reset image
resetImageInfo(tex, &width, &height, &x, &y, &rad, &zoom, &mode, &time);
while (1) {
readPad();
// Cancel
if (pressed_buttons & SCE_CTRL_CANCEL) {
hex_viewer = 0;
break;
}
/*
// Switch to hex viewer
if (pressed_buttons & SCE_CTRL_SQUARE) {
hex_viewer = 1;
break;
// Previous/next image
if (pressed_buttons & SCE_CTRL_LEFT || pressed_buttons & SCE_CTRL_RIGHT) {
int previous = pressed_buttons & SCE_CTRL_LEFT;
while (previous ? entry->previous : entry->next) {
entry = previous ? entry->previous : entry->next;
if (!entry->is_folder) {
char path[MAX_PATH_LENGTH];
snprintf(path, MAX_PATH_LENGTH, "%s%s", list->path, entry->name);
int type = getFileType(path);
if (type == FILE_TYPE_BMP || type == FILE_TYPE_JPEG || FILE_TYPE_PNG) {
vita2d_free_texture(tex);
tex = loadImage(path, type, buffer);
if (!tex) {
free(buffer);
return -1;
}
// Reset image
resetImageInfo(tex, &width, &height, &x, &y, &rad, &zoom, &mode, &time);
break;
}
}
}
}
*/
// Photo mode
if (pressed_buttons & SCE_CTRL_ENTER) {
switch (mode) {
case MODE_CUSTOM:
mode = MODE_FIT_HEIGHT;
break;
case MODE_FIT_HEIGHT:
mode = MODE_FIT_WIDTH;
break;
case MODE_FIT_WIDTH:
mode = MODE_FIT_HEIGHT;
break;
}
time = sceKernelGetProcessTimeWide();
hotspot_x = half_width;
hotspot_y = half_height;
// Find next mode
int count = 0;
photoMode(&zoom, width, height, rad, mode);
x = width / 2.0f;
y = height / 2.0f;
mode = getNextZoomMode(&zoom, width, height, rad, mode);
}
// Rotate
@ -177,72 +252,56 @@ int photoViewer(char *file, int type) {
zoom = ZOOM_MAX;
}
// Move. TODO: Moving by pad.lx/pad.ly
float dx = 0.0f, dy = 0.0f;
// Move
if (pad.lx < (ANALOG_CENTER - ANALOG_SENSITIVITY) || pad.lx > (ANALOG_CENTER + ANALOG_SENSITIVITY)) {
float d = ((pad.lx - ANALOG_CENTER) / MOVE_DIVISION) / zoom;
if (current_buttons & SCE_CTRL_LEFT_ANALOG_LEFT) {
if (isHorizontal(rad)) {
dx = -cosf(rad);
x += cosf(rad) * d;
} else {
dy = sinf(rad);
}
} else if (current_buttons & SCE_CTRL_LEFT_ANALOG_RIGHT) {
if (isHorizontal(rad)) {
dx = cosf(rad);
} else {
dy = -sinf(rad);
y += -sinf(rad) * d;
}
}
if (current_buttons & SCE_CTRL_LEFT_ANALOG_UP) {
if (!isHorizontal(rad)) {
dx = -sinf(rad);
if (pad.ly < (ANALOG_CENTER - ANALOG_SENSITIVITY) || pad.ly > (ANALOG_CENTER + ANALOG_SENSITIVITY)) {
float d = ((pad.ly - ANALOG_CENTER) / MOVE_DIVISION) / zoom;
if (isHorizontal(rad)) {
y += cosf(rad) * d;
} else {
dy = -cosf(rad);
}
} else if (current_buttons & SCE_CTRL_LEFT_ANALOG_DOWN) {
if (!isHorizontal(rad)) {
dx = sinf(rad);
} else {
dy = cosf(rad);
x += sinf(rad) * d;
}
}
if (dx != 0.0f)
hotspot_x += dx * MOVE_INTERVAL / zoom;
if (dy != 0.0f)
hotspot_y += dy * MOVE_INTERVAL / zoom;
// Limit
float w = isHorizontal(rad) ? SCREEN_HALF_WIDTH : SCREEN_HALF_HEIGHT;
float h = isHorizontal(rad) ? SCREEN_HALF_HEIGHT : SCREEN_HALF_WIDTH;
if ((zoom * width) > 2.0f * w) {
if (hotspot_x < (w / zoom)) {
hotspot_x = w / zoom;
} else if (hotspot_x > (width - w / zoom)) {
hotspot_x = width - w / zoom;
if (x < (w / zoom)) {
x = w / zoom;
} else if (x > (width - w / zoom)) {
x = width - w / zoom;
}
} else {
hotspot_x = half_width;
x = width / 2.0f;
}
if ((zoom * height) > 2.0f * h) {
if (hotspot_y < (h / zoom)) {
hotspot_y = h / zoom;
} else if (hotspot_y > (height - h / zoom)) {
hotspot_y = height - h / zoom;
if (y < (h / zoom)) {
y = h / zoom;
} else if (y > (height - h / zoom)) {
y = height - h / zoom;
}
} else {
hotspot_y = half_height;
y = height / 2.0f;
}
// Start drawing
START_DRAWING();
// Photo
vita2d_draw_texture_scale_rotate_hotspot(tex, SCREEN_HALF_WIDTH, SCREEN_HALF_HEIGHT, zoom, zoom, rad, hotspot_x, hotspot_y);
vita2d_draw_texture_scale_rotate_hotspot(tex, SCREEN_HALF_WIDTH, SCREEN_HALF_HEIGHT, zoom, zoom, rad, x, y);
// Zoom text
if ((sceKernelGetProcessTimeWide() - time) < ZOOM_TEXT_TIME)
@ -256,8 +315,5 @@ int photoViewer(char *file, int type) {
free(buffer);
if (hex_viewer)
hexViewer(file);
return 0;
}

15
photo.h
View File

@ -19,20 +19,25 @@
#ifndef __PHOTO_H__
#define __PHOTO_H__
#include "file.h"
enum PhotoModes {
MODE_CUSTOM,
// MODE_ORIGINAL,
MODE_PERFECT,
MODE_ORIGINAL,
MODE_FIT_HEIGHT,
MODE_FIT_WIDTH,
N_PHOTO_MODES,
};
#define ZOOM_MIN 0.1f
#define ZOOM_MAX 100.0f
#define ZOOM_MAX 1000.0f
#define ZOOM_FACTOR 1.02f
#define MOVE_INTERVAL 15.0f
#define ZOOM_TEXT_TIME 4 * 1000 * 1000
#define MOVE_DIVISION 7.0f
int photoViewer(char *file, int type);
#define ZOOM_TEXT_TIME 3 * 1000 * 1000
int photoViewer(char *file, int type, FileList *list, FileListEntry *entry);
#endif

23
text.c
View File

@ -25,6 +25,7 @@
void textListAddEntry(TextList *list, TextListEntry *entry) {
entry->next = NULL;
entry->previous = NULL;
if (list->head == NULL) {
list->head = entry;
@ -32,6 +33,7 @@ void textListAddEntry(TextList *list, TextListEntry *entry) {
} else {
TextListEntry *tail = list->tail;
tail->next = entry;
entry->previous = tail;
list->tail = entry;
}
@ -47,7 +49,9 @@ void textListEmpty(TextList *list) {
entry = next;
}
memset(list, 0, sizeof(TextList));
list->head = NULL;
list->tail = NULL;
list->length = 0;
}
#define TAB_SIZE 4
@ -178,20 +182,16 @@ int textViewer(char *file) {
// Tail to head
list.tail->next = list.head;
list.head->previous = list.tail;
list.head = list.tail;
// Second last to tail
TextListEntry *second_last = list.tail->next;
while (second_last) {
if (second_last->next == list.tail)
break;
second_last = second_last->next;
}
list.tail = second_last;
list.tail = list.tail->previous;
list.tail->next = NULL;
// No previous
list.head->previous = NULL;
// Read
textReadLine(buffer, offset_list[base_pos], size, list.head->line);
}
@ -205,12 +205,15 @@ int textViewer(char *file) {
base_pos++;
// Head to tail
list.head->previous = list.tail;
list.tail->next = list.head;
list.tail = list.head;
// Second first to head
list.head = list.head->next;
list.head->previous = NULL;
// No next
list.tail->next = NULL;
// Read

1
text.h
View File

@ -24,6 +24,7 @@
typedef struct TextListEntry {
struct TextListEntry *next;
struct TextListEntry *previous;
char line[MAX_LINE_CHARACTERS];
} TextListEntry;

53
utils.c
View File

@ -39,37 +39,6 @@ void infoDialog(char *string) {
dialog_step = DIALOG_STEP_INFO;
}
int debugPrintf(char *text, ...) {
#ifndef RELEASE
va_list list;
char string[512];
va_start(list, text);
vsprintf(string, text, list);
va_end(list);
netdbg(string);
/*
#ifndef DISABLE_UVL_LOGGING
printf(string);
#endif
*/
#ifdef ENABLE_DEBUGNET_LOGGING
debugNetPrintf(3, string);
#endif
#ifdef ENABLE_FILE_LOGGING
SceUID fd = sceIoOpen("cache0:vitashell_log.txt", SCE_O_WRONLY | SCE_O_CREAT | SCE_O_APPEND, 0777);
if (fd >= 0) {
sceIoWrite(fd, string, strlen(string));
sceIoClose(fd);
}
#endif
#endif
return 0;
}
void disableAutoSuspend() {
sceKernelPowerTick(SCE_KERNEL_POWER_TICK_DISABLE_AUTO_SUSPEND);
sceKernelPowerTick(SCE_KERNEL_POWER_TICK_DISABLE_OLED_OFF);
@ -210,6 +179,28 @@ void getTimeString(char *string, int time_format, SceRtcTime *time) {
}
}
int debugPrintf(char *text, ...) {
#ifndef RELEASE
va_list list;
char string[512];
va_start(list, text);
vsprintf(string, text, list);
va_end(list);
netdbg(string);
uvl_log_write(string, strlen(string));
SceUID fd = sceIoOpen("cache0:vitashell_log.txt", SCE_O_WRONLY | SCE_O_CREAT | SCE_O_APPEND, 0777);
if (fd >= 0) {
sceIoWrite(fd, string, strlen(string));
sceIoClose(fd);
}
#endif
return 0;
}
int netdbg_init() {
int ret = 0;

View File

@ -26,8 +26,10 @@
#define ANALOG_CENTER 128
#define ANALOG_THRESHOLD 64
#define ANALOG_SENSITIVITY 16
#define NET_INIT_SIZE 1 * 1024 * 1024
#define NETDBG_DEFAULT_PORT 9023
enum {
SCE_CTRL_RIGHT_ANALOG_UP = 0x0020000,
@ -51,8 +53,6 @@ extern uint32_t old_buttons, current_buttons, pressed_buttons, hold_buttons, hol
void errorDialog(int error);
void infoDialog(char *string);
int debugPrintf(char *text, ...);
void disableAutoSuspend();
void readPad();
@ -65,7 +65,7 @@ void getSizeString(char *string, uint64_t size);
void getDateString(char *string, int date_format, SceRtcTime *time);
void getTimeString(char *string, int time_format, SceRtcTime *time);
#define NETDBG_DEFAULT_PORT 9023
int debugPrintf(char *text, ...);
int netdbg_init();
void netdbg_fini();