cmfilemanager-psp: Inital reimplementation in c++

This commit is contained in:
Joel16 2021-05-27 02:26:39 -04:00
commit f1bf39d6fe
200 changed files with 66815 additions and 0 deletions

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto

61
.gitignore vendored Normal file
View File

@ -0,0 +1,61 @@
# Prerequisites
*.d
.vscode/
# Object files
*.o
*.ko
*.obj
*.elf
*.SFO
# Linker output
*.ilk
*.map
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
*.PBP
*.prx
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
# CMFileManager PSP Specific objects
app/drivers/audio_driver.S
app/drivers/display_driver.S
app/drivers/fs_driver.S
app/drivers/impose_driver.S
app/drivers/input_driver.S

17
.travis.yml Normal file
View File

@ -0,0 +1,17 @@
language: c
dist: bionic
services:
- docker
script:
- docker run -it --rm -v "$PWD:/src" haydenkow/nu-pspdev make -f Makefile.psp
- sh .travis/.build.sh
deploy:
provider: pages
skip_cleanup: true
github_token: $GITHUB_TOKEN # Set in travis-ci.org dashboard
on:
branch: master

12
.travis/.build.sh Normal file
View File

@ -0,0 +1,12 @@
#!/bin/sh -e
rm -rf .git .travis common libs .gitattributes .gitignore .travis.yml ICON0.PNG LICENSE Makefile.psp README.md
mkdir -p PSP/GAME/CMFileManager
mv app/EBOOT.PBP PSP/GAME/CMFileManager/APP.PBP && mv launcher/EBOOT.PBP PSP/GAME/CMFileManager/EBOOT.PBP
mv audio_driver/audio_driver.prx PSP/GAME/CMFileManager/audio_driver.prx
mv display_driver/display_driver.prx PSP/GAME/CMFileManager/display_driver.prx
mv fs_driver/fs_driver.prx PSP/GAME/CMFileManager/fs_driver.prx
mv impose_driver/impose_driver.prx PSP/GAME/CMFileManager/impose_driver.prx
mv input_driver/input_driver.prx PSP/GAME/CMFileManager/input_driver.prx
zip -r CMFileManager-PSP.zip PSP/
rm -rf app audio_driver display_driver fs_driver impose_driver, input_driver launcher PSP

BIN
ICON0.PNG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

7
Makefile.psp Normal file
View File

@ -0,0 +1,7 @@
SUBDIRS = audio_driver display_driver fs_driver impose_driver input_driver app launcher
all:
@for dir in $(SUBDIRS); do $(MAKE) -C $$dir; done
clean:
@for dir in $(SUBDIRS); do $(MAKE) clean -C $$dir; done

55
README.MD Normal file
View File

@ -0,0 +1,55 @@
# CMFileManager PSP [![Build Status](https://travis-ci.org/joel16/CMFileManager-PSP.svg?branch=master)](https://travis-ci.org/joel16/CMFileManager-PSP) ![Github latest downloads](https://img.shields.io/github/downloads/joel16/CMFileManager-PSP/total.svg)
CMFileManager PSP is a PSP application built using the unofficial PSPSDK and [glib2d (modded)](https://github.com/joel16/gLib2D). The user interface in this homebrew is heavily inspired and based on the LineageOS/CM file manager. The aim of this project is to provide a stable and up to date file manager that makes use of updated tools, whilst offering a modernized and user friendly interace. CMFileManager PSP is the **only** homebrew that properly uses the 'move' function correctly for moving files/folder from one place to another. Unlike other file managers for PSP which copies a file from one place to another and then deletes it, which can take a while depending on the file size.
**Features:**
- Copy files/folders.
- Move files/folders.
- Delete files/folders.
- Multi file handling functions for copy/move/delete.
- File properties. (File size, creation time, modification time, access times, permissions)
- Creating directories.
- Renaming files/folders.
- Image viewer (BMP, GIF - non animated, JPG, PCX, PNG, PGM, PPM and TGA).
- Auto USB mount (with ef0:/ and ms0:/ support for PSP Go).
- Dark theme mode.
- EBOOT (homebrew/game) launcher - Also allows you to rip icon0/pic1 from eboot if it exists.
- Browse other drives like flah0, flash1 and UMD (if not using PSP Go).
- Support for both ef0:/ (internal) and ms0:/ (external) drives on PSP Go.
- Screenshots in .BMP format. Use L + R to capture a screenshot.
- Audio Player 16-Bit short 41K - 48K Hz. (FLAC, IT, MOD, MP3, OGG, OPUS, S3M, WAV and XM)
- FTP connection
**FTP Mode Instructions:**
1. Press *START* to open settings menu and select `FTP connection`.
3. Select a network connection when the Network dialog pops up.
4. After it is connected successfully, a message will appear saying `FTP Connection established IP:Port`. Use an FTP client like WinSCP and enter the IP and port (1337) and make sure to use anonymous login.
6. Once an FTP connection is established from your server, you won't see any folders or files. You have to manually search for the path `/ms0:` or `/ef0:`. You can also search for other devices like `/flash0:` or UMD - `/disc0:` (**Please use caution when browsing any flash0-flash3**)
**Buttons:**
- Press *DPAD Up* to move the cursor up.
- Press *DPAD Right* to move the cursor down.
- Press *DPAD Left* to position the cursor to the start of the directory.
- Press *DPAD Right* to position the cursor to the end of the directory.
- Press *Start* to open settings.
- Press *Select* to open menubar.
- Press *Triangle* to bring up file options.
- Press *enter button (depending on your region)* to enter directory/open file.
- Press *cancel button (depending on your region)* to go back to previous directory/menu.
- Press *L + R* to caputre screenshot.
- Press *Select + Start* to exit.
- Press *Start* on FTP mode or Audio player to disable/enable screen to save battery.
**Image Viewer controls:**
- L/R - Rotate anti-clockwise/clockwise
- Up/Down - Zoom in/out
- Select - Help menu
- Left/Right - Previous/Next image
- Analog stick - Position image after zoom
- Triangle - Flip vertically
- Square - Flip horizantally

44
app/Makefile Normal file
View File

@ -0,0 +1,44 @@
TARGET = CMFileManager
SOURCES := data drivers source source/audio source/gui
CFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.c))
SFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.S))
CPPFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.cpp))
GFXFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.png))
FONTFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.pgf))
OBJS := $(addsuffix .o,$(BINFILES)) \
$(CFILES:.c=.o) $(SFILES:.S=.o) $(CPPFILES:.cpp=.o) $(GFXFILES:.png=.o) $(FONTFILES:.pgf=.o)
VERSION_MAJOR := 4
VERSION_MINOR := 0
VERSION_MICRO := 0
INCDIR = ../libs/include ../libs/include/ogg ../libs/include/opus include
CFLAGS = -Os -G0 -Wall -ffast-math -fno-rtti -fno-exceptions \
-DVERSION_MAJOR=$(VERSION_MAJOR) -DVERSION_MINOR=$(VERSION_MINOR) -DVERSION_MICRO=$(VERSION_MICRO)
CXXFLAGS = $(CFLAGS) -std=gnu++17
ASFLAGS := $(CFLAGS)
BUILD_PRX = 1
PSP_LARGE_MEMORY = 1
LIBDIR = ../libs/lib
LDFLAGS =
LIBS = -lpsputility -lintrafont -lglib2d -lpspgu -lpsprtc -lpspvram \
-lxmp-lite -lmpg123 -lvorbisfile -lvorbis -lopusfile -lopus -lFLAC -logg -lpspaudio \
-lpspctrl -lpsppower -lpspreg -lpspusb -lpspusbstor -lpspusbdevice -lpspumd \
-lpspkubridge -lpspsystemctrl_user -lstdc++ -lm -lz
EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = CM File Manager PSP v$(VERSION_MAJOR).$(VERSION_MINOR)$(VERSION_MICRO)
PSP_EBOOT_ICON = ../ICON0.PNG
PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak
%.o: %.png
bin2o -i $< $@ $(addsuffix _png, $(basename $(notdir $<) ))
%.o: %.pgf
bin2o -i $< $@ $(addsuffix _pgf, $(basename $(notdir $<) ))

6
app/config.json Normal file
View File

@ -0,0 +1,6 @@
{
"config_ver": 4,
"sort": 0,
"dark_theme": 1,
"dev_options": 1
}

BIN
app/data/battery_20.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 327 B

BIN
app/data/battery_30.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 B

BIN
app/data/battery_50.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 B

BIN
app/data/battery_60.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 B

BIN
app/data/battery_80.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 328 B

BIN
app/data/battery_full.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 B

BIN
app/data/bg_header.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 364 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 425 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 812 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1020 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1020 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 802 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 B

BIN
app/data/ic_fso_default.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
app/data/ic_fso_folder.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 523 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 802 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 829 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 540 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 832 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 388 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 701 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 649 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 606 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 564 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 333 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 768 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 946 B

BIN
app/data/ic_play_btn.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

6
app/debug.log Normal file
View File

@ -0,0 +1,6 @@
pspOpenDir(ms0:) failed: 0x0
pspOpenDir(ms0:) failed: 0x0
pspOpenDir(ms0:) failed: 0x0
pspOpenDir(ms0:) failed: 0x0
pspOpenDir(ms0:) failed: 0x0
pspOpenDir(ms0:) failed: 0x0

140
app/drivers/mutex-imports.S Normal file
View File

@ -0,0 +1,140 @@
.set noreorder
#include <pspimport.s>
IMPORT_START "ThreadManForUser", 0x40010000
IMPORT_FUNC "ThreadManForUser", 0xB7D098C6, sceKernelCreateMutex
IMPORT_FUNC "ThreadManForUser", 0xF8170FBE, sceKernelDeleteMutex
IMPORT_FUNC "ThreadManForUser", 0x6B30100F, sceKernelUnlockMutex
IMPORT_FUNC "ThreadManForUser", 0xB011B11F, sceKernelLockMutex
IMPORT_FUNC "ThreadManForUser", 0x5bf4dd27, sceKernelLockMutexCB
IMPORT_FUNC "ThreadManForUser", 0x0DDCD2C9, sceKernelTryLockMutex
IMPORT_FUNC "ThreadManForUser", 0x6E9EA350,_sceKernelReturnFromCallback
IMPORT_FUNC "ThreadManForUser", 0x0C106E53, sceKernelRegisterThreadEventHandler
IMPORT_FUNC "ThreadManForUser", 0x72F3C145, sceKernelReleaseThreadEventHandler
IMPORT_FUNC "ThreadManForUser", 0x369EEB6B, sceKernelReferThreadEventHandlerStatus
IMPORT_FUNC "ThreadManForUser", 0xE81CAF8F, sceKernelCreateCallback
IMPORT_FUNC "ThreadManForUser", 0xEDBA5844, sceKernelDeleteCallback
IMPORT_FUNC "ThreadManForUser", 0xC11BA8C4, sceKernelNotifyCallback
IMPORT_FUNC "ThreadManForUser", 0xBA4051D6, sceKernelCancelCallback
IMPORT_FUNC "ThreadManForUser", 0x2A3D44FF, sceKernelGetCallbackCount
IMPORT_FUNC "ThreadManForUser", 0x349D6D6C, sceKernelCheckCallback
IMPORT_FUNC "ThreadManForUser", 0x730ED8BC, sceKernelReferCallbackStatus
IMPORT_FUNC "ThreadManForUser", 0x9ACE131E, sceKernelSleepThread
IMPORT_FUNC "ThreadManForUser", 0x82826F70, sceKernelSleepThreadCB
IMPORT_FUNC "ThreadManForUser", 0xD59EAD2F, sceKernelWakeupThread
IMPORT_FUNC "ThreadManForUser", 0xFCCFAD26, sceKernelCancelWakeupThread
IMPORT_FUNC "ThreadManForUser", 0x9944F31F, sceKernelSuspendThread
IMPORT_FUNC "ThreadManForUser", 0x75156E8F, sceKernelResumeThread
IMPORT_FUNC "ThreadManForUser", 0x278C0DF5, sceKernelWaitThreadEnd
IMPORT_FUNC "ThreadManForUser", 0x840E8133, sceKernelWaitThreadEndCB
IMPORT_FUNC "ThreadManForUser", 0xCEADEB47, sceKernelDelayThread
IMPORT_FUNC "ThreadManForUser", 0x68DA9E36, sceKernelDelayThreadCB
IMPORT_FUNC "ThreadManForUser", 0xBD123D9E, sceKernelDelaySysClockThread
IMPORT_FUNC "ThreadManForUser", 0x1181E963, sceKernelDelaySysClockThreadCB
IMPORT_FUNC "ThreadManForUser", 0xD6DA4BA1, sceKernelCreateSema
IMPORT_FUNC "ThreadManForUser", 0x28B6489C, sceKernelDeleteSema
IMPORT_FUNC "ThreadManForUser", 0x3F53E640, sceKernelSignalSema
IMPORT_FUNC "ThreadManForUser", 0x4E3A1105, sceKernelWaitSema
IMPORT_FUNC "ThreadManForUser", 0x6D212BAC, sceKernelWaitSemaCB
IMPORT_FUNC "ThreadManForUser", 0x58B1F937, sceKernelPollSema
IMPORT_FUNC "ThreadManForUser", 0x8FFDF9A2, sceKernelCancelSema
IMPORT_FUNC "ThreadManForUser", 0xBC6FEBC5, sceKernelReferSemaStatus
IMPORT_FUNC "ThreadManForUser", 0x55C20A00, sceKernelCreateEventFlag
IMPORT_FUNC "ThreadManForUser", 0xEF9E4C70, sceKernelDeleteEventFlag
IMPORT_FUNC "ThreadManForUser", 0x1FB15A32, sceKernelSetEventFlag
IMPORT_FUNC "ThreadManForUser", 0x812346E4, sceKernelClearEventFlag
IMPORT_FUNC "ThreadManForUser", 0x402FCF22, sceKernelWaitEventFlag
IMPORT_FUNC "ThreadManForUser", 0x328C546A, sceKernelWaitEventFlagCB
IMPORT_FUNC "ThreadManForUser", 0x30FD48F0, sceKernelPollEventFlag
IMPORT_FUNC "ThreadManForUser", 0xCD203292, sceKernelCancelEventFlag
IMPORT_FUNC "ThreadManForUser", 0xA66B0120, sceKernelReferEventFlagStatus
IMPORT_FUNC "ThreadManForUser", 0x8125221D, sceKernelCreateMbx
IMPORT_FUNC "ThreadManForUser", 0x86255ADA, sceKernelDeleteMbx
IMPORT_FUNC "ThreadManForUser", 0xE9B3061E, sceKernelSendMbx
IMPORT_FUNC "ThreadManForUser", 0x18260574, sceKernelReceiveMbx
IMPORT_FUNC "ThreadManForUser", 0xF3986382, sceKernelReceiveMbxCB
IMPORT_FUNC "ThreadManForUser", 0x0D81716A, sceKernelPollMbx
IMPORT_FUNC "ThreadManForUser", 0x87D4DD36, sceKernelCancelReceiveMbx
IMPORT_FUNC "ThreadManForUser", 0xA8E8C846, sceKernelReferMbxStatus
IMPORT_FUNC "ThreadManForUser", 0x7C0DC2A0, sceKernelCreateMsgPipe
IMPORT_FUNC "ThreadManForUser", 0xF0B7DA1C, sceKernelDeleteMsgPipe
IMPORT_FUNC "ThreadManForUser", 0x876DBFAD, sceKernelSendMsgPipe
IMPORT_FUNC "ThreadManForUser", 0x7C41F2C2, sceKernelSendMsgPipeCB
IMPORT_FUNC "ThreadManForUser", 0x884C9F90, sceKernelTrySendMsgPipe
IMPORT_FUNC "ThreadManForUser", 0x74829B76, sceKernelReceiveMsgPipe
IMPORT_FUNC "ThreadManForUser", 0xFBFA697D, sceKernelReceiveMsgPipeCB
IMPORT_FUNC "ThreadManForUser", 0xDF52098F, sceKernelTryReceiveMsgPipe
IMPORT_FUNC "ThreadManForUser", 0x349B864D, sceKernelCancelMsgPipe
IMPORT_FUNC "ThreadManForUser", 0x33BE4024, sceKernelReferMsgPipeStatus
IMPORT_FUNC "ThreadManForUser", 0x56C039B5, sceKernelCreateVpl
IMPORT_FUNC "ThreadManForUser", 0x89B3D48C, sceKernelDeleteVpl
IMPORT_FUNC "ThreadManForUser", 0xBED27435, sceKernelAllocateVpl
IMPORT_FUNC "ThreadManForUser", 0xEC0A693F, sceKernelAllocateVplCB
IMPORT_FUNC "ThreadManForUser", 0xAF36D708, sceKernelTryAllocateVpl
IMPORT_FUNC "ThreadManForUser", 0xB736E9FF, sceKernelFreeVpl
IMPORT_FUNC "ThreadManForUser", 0x1D371B8A, sceKernelCancelVpl
IMPORT_FUNC "ThreadManForUser", 0x39810265, sceKernelReferVplStatus
IMPORT_FUNC "ThreadManForUser", 0xC07BB470, sceKernelCreateFpl
IMPORT_FUNC "ThreadManForUser", 0xED1410E0, sceKernelDeleteFpl
IMPORT_FUNC "ThreadManForUser", 0xD979E9BF, sceKernelAllocateFpl
IMPORT_FUNC "ThreadManForUser", 0xE7282CB6, sceKernelAllocateFplCB
IMPORT_FUNC "ThreadManForUser", 0x623AE665, sceKernelTryAllocateFpl
IMPORT_FUNC "ThreadManForUser", 0xF6414A71, sceKernelFreeFpl
IMPORT_FUNC "ThreadManForUser", 0xA8AA591F, sceKernelCancelFpl
IMPORT_FUNC "ThreadManForUser", 0xD8199E4C, sceKernelReferFplStatus
IMPORT_FUNC "ThreadManForUser", 0x0E927AED,_sceKernelReturnFromTimerHandler
IMPORT_FUNC "ThreadManForUser", 0x110DEC9A, sceKernelUSec2SysClock
IMPORT_FUNC "ThreadManForUser", 0xC8CD158C, sceKernelUSec2SysClockWide
IMPORT_FUNC "ThreadManForUser", 0xBA6B92E2, sceKernelSysClock2USec
IMPORT_FUNC "ThreadManForUser", 0xE1619D7C, sceKernelSysClock2USecWide
IMPORT_FUNC "ThreadManForUser", 0xDB738F35, sceKernelGetSystemTime
IMPORT_FUNC "ThreadManForUser", 0x82BC5777, sceKernelGetSystemTimeWide
IMPORT_FUNC "ThreadManForUser", 0x369ED59D, sceKernelGetSystemTimeLow
IMPORT_FUNC "ThreadManForUser", 0x6652B8CA, sceKernelSetAlarm
IMPORT_FUNC "ThreadManForUser", 0xB2C25152, sceKernelSetSysClockAlarm
IMPORT_FUNC "ThreadManForUser", 0x7E65B999, sceKernelCancelAlarm
IMPORT_FUNC "ThreadManForUser", 0xDAA3F564, sceKernelReferAlarmStatus
IMPORT_FUNC "ThreadManForUser", 0x20FFF560, sceKernelCreateVTimer
IMPORT_FUNC "ThreadManForUser", 0x328F9E52, sceKernelDeleteVTimer
IMPORT_FUNC "ThreadManForUser", 0xB3A59970, sceKernelGetVTimerBase
IMPORT_FUNC "ThreadManForUser", 0xB7C18B77, sceKernelGetVTimerBaseWide
IMPORT_FUNC "ThreadManForUser", 0x034A921F, sceKernelGetVTimerTime
IMPORT_FUNC "ThreadManForUser", 0xC0B3FFD2, sceKernelGetVTimerTimeWide
IMPORT_FUNC "ThreadManForUser", 0x542AD630, sceKernelSetVTimerTime
IMPORT_FUNC "ThreadManForUser", 0xFB6425C3, sceKernelSetVTimerTimeWide
IMPORT_FUNC "ThreadManForUser", 0xC68D9437, sceKernelStartVTimer
IMPORT_FUNC "ThreadManForUser", 0xD0AEEE87, sceKernelStopVTimer
IMPORT_FUNC "ThreadManForUser", 0xD8B299AE, sceKernelSetVTimerHandler
IMPORT_FUNC "ThreadManForUser", 0x53B00E9A, sceKernelSetVTimerHandlerWide
IMPORT_FUNC "ThreadManForUser", 0xD2D615EF, sceKernelCancelVTimerHandler
IMPORT_FUNC "ThreadManForUser", 0x5F32BEAA, sceKernelReferVTimerStatus
IMPORT_FUNC "ThreadManForUser", 0x446D8DE6, sceKernelCreateThread
IMPORT_FUNC "ThreadManForUser", 0x9FA03CD3, sceKernelDeleteThread
IMPORT_FUNC "ThreadManForUser", 0xF475845D, sceKernelStartThread
IMPORT_FUNC "ThreadManForUser", 0x532A522E,_sceKernelExitThread
IMPORT_FUNC "ThreadManForUser", 0xAA73C935, sceKernelExitThread
IMPORT_FUNC "ThreadManForUser", 0x809CE29B, sceKernelExitDeleteThread
IMPORT_FUNC "ThreadManForUser", 0x616403BA, sceKernelTerminateThread
IMPORT_FUNC "ThreadManForUser", 0x383F7BCC, sceKernelTerminateDeleteThread
IMPORT_FUNC "ThreadManForUser", 0x3AD58B8C, sceKernelSuspendDispatchThread
IMPORT_FUNC "ThreadManForUser", 0x27E22EC2, sceKernelResumeDispatchThread
IMPORT_FUNC "ThreadManForUser", 0xEA748E31, sceKernelChangeCurrentThreadAttr
IMPORT_FUNC "ThreadManForUser", 0x71BC9871, sceKernelChangeThreadPriority
IMPORT_FUNC "ThreadManForUser", 0x912354A7, sceKernelRotateThreadReadyQueue
IMPORT_FUNC "ThreadManForUser", 0x2C34E053, sceKernelReleaseWaitThread
IMPORT_FUNC "ThreadManForUser", 0x293B45B8, sceKernelGetThreadId
IMPORT_FUNC "ThreadManForUser", 0x94AA61EE, sceKernelGetThreadCurrentPriority
IMPORT_FUNC "ThreadManForUser", 0x3B183E26, sceKernelGetThreadExitStatus
IMPORT_FUNC "ThreadManForUser", 0xD13BDE95, sceKernelCheckThreadStack
IMPORT_FUNC "ThreadManForUser", 0x52089CA1, sceKernelGetThreadStackFreeSize
IMPORT_FUNC "ThreadManForUser", 0x17C1684E, sceKernelReferThreadStatus
IMPORT_FUNC "ThreadManForUser", 0xFFC36A14, sceKernelReferThreadRunStatus
IMPORT_FUNC "ThreadManForUser", 0x627E6F3A, sceKernelReferSystemStatus
IMPORT_FUNC "ThreadManForUser", 0x94416130, sceKernelGetThreadmanIdList
IMPORT_FUNC "ThreadManForUser", 0x57CF62DD, sceKernelGetThreadmanIdType
IMPORT_FUNC "ThreadManForUser", 0x64D4540E, sceKernelReferThreadProfiler
IMPORT_FUNC "ThreadManForUser", 0x8218B4DD, sceKernelReferGlobalProfiler
IMPORT_FUNC "ThreadManForUser", 0xA9C2CB9A, sceKernelReferMutexStatus
IMPORT_FUNC "ThreadManForUser", 0x87D9223C, sceKernelCancelMutex

24
app/include/colours.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef _CMFILEMANAGER_COLOURS_H_
#define _CMFILEMANAGER_COLOURS_H_
#include <glib2d.h>
constexpr g2dColor BLACK_BG = G2D_RGBA(48, 48, 48, 255);
constexpr g2dColor STATUS_BAR_LIGHT = G2D_RGBA(37, 79, 174, 255);
constexpr g2dColor STATUS_BAR_DARK = G2D_RGBA(38, 50, 56, 255);
constexpr g2dColor MENU_BAR_LIGHT = G2D_RGBA(51, 103, 214, 255);
constexpr g2dColor MENU_BAR_DARK = G2D_RGBA(55, 71, 79, 255);
constexpr g2dColor SELECTOR_COLOUR_LIGHT = G2D_RGBA(241, 241, 241, 255);
constexpr g2dColor SELECTOR_COLOUR_DARK = G2D_RGBA(76, 76, 76, 255);
constexpr g2dColor TITLE_COLOUR_LIGHT = G2D_RGBA(30, 136, 229, 255);
constexpr g2dColor TITLE_COLOUR_DARK = G2D_RGBA(0, 150, 136, 255);
constexpr g2dColor TEXT_COLOUR_LIGHT = G2D_RGBA(32, 32, 32, 255);
constexpr g2dColor TEXT_COLOUR_DARK = G2D_RGBA(185, 185, 185, 255);
extern g2dColor BG_COLOUR, STATUS_BAR_COLOUR, MENU_BAR_COLOUR, SELECTOR_COLOUR, TITLE_COLOUR, TEXT_COLOUR;
namespace Colours {
void Get(void);
}
#endif

20
app/include/config.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef _CMFILEMANAGER_CONFIG_H_
#define _CMFILEMANAGER_CONFIG_H_
#include <string>
typedef struct {
int sort = 0;
bool dark_theme = false;
bool dev_options = false;
std::string cwd;
} config_t;
extern config_t cfg;
namespace Config {
int Save(config_t config);
int Load(void);
}
#endif

36
app/include/fs.h Normal file
View File

@ -0,0 +1,36 @@
#ifndef _CMFILEMANAGER_FS_H_
#define _CMFILEMANAGER_FS_H_
#include <pspiofilemgr.h>
#include <string>
#include <vector>
typedef enum FileType {
FileTypeNone,
FileTypeApp,
FileTypeArchive,
FileTypeAudio,
FileTypeImage,
FileTypeText
} FileType;
namespace FS {
bool FileExists(const std::string &path);
bool DirExists(const std::string &path);
int MakeDir(const std::string &path);
int CreateFile(const std::string &path);
std::string GetFileExt(const std::string &filename);
FileType GetFileType(const std::string &filename);
SceOff GetFileSize(const std::string &path);
int ReadFile(const std::string &path, void *buf, int size);
int WriteFile(const std::string &path, void *buf, int size);
int GetDirList(const std::string &path, std::vector<SceIoDirent> &entries);
int ChangeDirNext(const std::string &path, std::vector<SceIoDirent> &entries);
int ChangeDirPrev(std::vector<SceIoDirent> &entries);
void Copy(SceIoDirent *entry, const std::string &path);
int Paste(void);
int Move(void);
int Delete(SceIoDirent *entry);
}
#endif

71
app/include/ftppsp.h Normal file
View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2021 Sergi Granell (xerpi), Joel16
*/
#ifndef _CMFILEMANAGER_FTPPSP_H_
#define _CMFILEMANAGER_FTPPSP_H_
#include <pspsdk.h>
#include <arpa/inet.h>
typedef void (*ftppsp_log_cb_t)(const char *);
/* Returns PSVita's IP and FTP port. 0 on success */
int ftppsp_init(char *psp_ip, unsigned short int *psp_port);
void ftppsp_fini(void);
int ftppsp_is_initialized(void);
int ftppsp_add_device(const char *devname);
int ftppsp_del_device(const char *devname);
void ftppsp_set_info_log_cb(ftppsp_log_cb_t cb);
void ftppsp_set_debug_log_cb(ftppsp_log_cb_t cb);
void ftppsp_set_file_buf_size(unsigned int size);
/* Extended functionality */
typedef enum {
FTP_DATA_CONNECTION_NONE,
FTP_DATA_CONNECTION_ACTIVE,
FTP_DATA_CONNECTION_PASSIVE
} DataConnectionType;
typedef struct ftppsp_client_info {
/* Client number */
int num;
/* Thread UID */
SceUID thid;
/* Control connection socket FD */
int ctrl_sockfd;
/* Data connection attributes */
int data_sockfd;
DataConnectionType data_con_type;
struct sockaddr_in data_sockaddr;
/* PASV mode client socket */
struct sockaddr_in pasv_sockaddr;
int pasv_sockfd;
/* Remote client net info */
struct sockaddr_in addr;
/* Receive buffer attributes */
int n_recv;
char recv_buffer[1024];
/* Points to the character after the first space */
const char *recv_cmd_args;
/* Current working directory */
char cur_path[1024];
/* Rename path */
char rename_path[1024];
/* Client list */
struct ftppsp_client_info *next;
struct ftppsp_client_info *prev;
/* Offset for transfer resume */
unsigned int restore_point;
} ftppsp_client_info_t;
typedef void (*cmd_dispatch_func)(ftppsp_client_info_t *client); // Command handler
int ftppsp_ext_add_custom_command(const char *cmd, cmd_dispatch_func func);
int ftppsp_ext_del_custom_command(const char *cmd);
void ftppsp_ext_client_send_ctrl_msg(ftppsp_client_info_t *client, const char *msg);
void ftppsp_ext_client_send_data_msg(ftppsp_client_info_t *client, const char *str);
#endif

19
app/include/g2d.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef _CMFILEMANAGER_GLIB2D_HELPER_H_
#define _CMFILEMANAGER_GLIB2D_HELPER_H_
#include <glib2d.h>
#include <intraFont.h>
#include <string>
extern intraFont *font, *jpn0, *chn;
namespace G2D {
void DrawRect(float x, float y, float width, float height, g2dColor colour);
void DrawImage(g2dTexture *tex, float x, float y);
void DrawImageScale(g2dTexture *tex, float x, float y, float w, float h);
char *KeyboardGetText(const std::string &desc_msg, const std::string &initial_msg);
void FontSetStyle(intraFont *font, float size, unsigned int colour, unsigned int options);
float GetTextHeight(intraFont *font);
}
#endif

54
app/include/gui.h Normal file
View File

@ -0,0 +1,54 @@
#ifndef _CMFILEMANAGER_GUI_HELPER_H_
#define _CMFILEMANAGER_GUI_HELPER_H_
#include <pspiofilemgr.h>
#include <vector>
enum MENU_STATES {
MENU_STATE_FILEBROWSER,
MENU_STATE_OPTIONS,
MENU_STATE_DELETE,
MENU_STATE_PROPERTIES,
MENU_STATE_SETTINGS,
MENU_STATE_IMAGEVIEWER,
MENU_STATE_ARCHIVEEXTRACT,
MENU_STATE_TEXTREADER,
MENU_STATE_UPDATE
};
typedef struct {
MENU_STATES state = MENU_STATE_FILEBROWSER;
int selected = 0;
std::vector<SceIoDirent> entries;
std::vector<bool> checked;
std::vector<bool> checked_copy;
std::string checked_cwd;
int checked_count = 0;
u64 used_storage = 0;
u64 total_storage = 0;
g2dTexture *texture;
} MenuItem;
namespace GUI {
void ResetCheckbox(MenuItem *item);
void GetStorageSize(MenuItem *item);
void DisplayStatusBar(void);
int RenderLoop(void);
void DisplayFileBrowser(MenuItem *item);
void ControlFileBrowser(MenuItem *item, int *ctrl);
void DisplaySettings(MenuItem *item);
void ControlSettings(MenuItem *item, int *ctrl);
void DisplayFileOptions(MenuItem *item);
void ControlFileOptions(MenuItem *item, int *ctrl);
void DisplayDeleteOptions(MenuItem *item);
void ControlDeleteOptions(MenuItem *item, int *ctrl);
void DisplayImageViewer(MenuItem *item);
void ControlImageViewer(MenuItem *item, float *delta_time);
}
#endif

View File

@ -0,0 +1,43 @@
#ifndef _CMFILEMANAGER_KERNEL_FUNCTIONS_H_
#define _CMFILEMANAGER_KERNEL_FUNCTIONS_H_
#if defined (__cplusplus)
extern "C" {
#endif
#include <pspctrl.h>
#include <pspiofilemgr.h>
// Kernel function prototypes
// audio_driver functions
extern int pspAudioSetFrequency(int frequency);
// display_driver functions
extern int pspGetBrightness(int *brightness);
extern int pspSetBrightness(int brightness);
extern int pspDisplayEnable(void);
extern int pspDisplayDisable(void);
// fs_driver functions
extern int pspOpenDir(const char *dirname);
extern int pspReadDir(SceUID dir, SceIoDirent *dirent);
extern int pspCloseDir(SceUID dir);
// impose_driver functions
extern int pspGetVolume(void);
extern int pspSetVolume(int volume);
extern int pspGetMute(void);
extern int pspSetMute(int mute);
extern int pspGetEqualizerMode(void);
extern int pspSetEqualizerMode(int mode);
extern int pspSetHomePopup(int popup);
// input_driver functions
extern unsigned int pspGetButtons(void);
#if defined (__cplusplus)
}
#endif
#endif

10
app/include/log.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef _CMFILEMANAGER_LOG_H_
#define _CMFILEMANAGER_LOG_H_
namespace Log {
int OpenHande(void);
int CloseHandle(void);
int Error(const char *format, ...);
}
#endif

23
app/include/mutex.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef _CMFILEMANAGER_MUTEX_H_
#define _CMFILEMANAGER_MUTEX_H_
#define PSP_MUTEX_ATTR_FIFO 0
#define PSP_MUTEX_ATTR_PRIORITY 0x100
#define PSP_MUTEX_ATTR_ALLOW_RECURSIVE 0x200
#ifdef __cplusplus
extern "C" {
#endif
int sceKernelCreateMutex(const char *name, uint attributes, int initial_count, void* options);
int sceKernelDeleteMutex(int mutexId);
int sceKernelLockMutex(int mutexId, int count, uint* timeout);
int sceKernelTryLockMutex(int mutexId, int count);
int sceKernelUnlockMutex(int mutexId, int count);
#ifdef __cplusplus
}
#endif
#endif

23
app/include/textures.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef _CMFILEMANAGER_TEXTURES_H_
#define _CMFILEMANAGER_TEXTURES_H_
#include <glib2d.h>
constexpr int NUM_ICONS = 6;
constexpr int NUM_BATT_ICONS = 6;
extern g2dTexture *file_icons[NUM_ICONS], *icon_dir, *icon_dir_dark, *icon_check, *icon_check_dark, *icon_uncheck, \
*icon_uncheck_dark, *icon_toggle_on, *icon_toggle_dark_on, *icon_toggle_off, *icon_radio_off, \
*icon_radio_on, *icon_radio_dark_off, *icon_radio_dark_on, *icon_nav_drawer, *icon_back, \
*options_dialog, *options_dialog_dark, *properties_dialog, *properties_dialog_dark, *dialog, *dialog_dark, \
*battery_charging[NUM_BATT_ICONS], *battery[NUM_BATT_ICONS], *usb_icon, \
*default_artwork, *default_artwork_blur, *btn_play, *btn_pause, *btn_rewind, *btn_forward, \
*btn_repeat, *btn_shuffle, *btn_repeat_overlay, *btn_shuffle_overlay, \
*bg_header, *icon_sd, *icon_secure, *icon_sd_dark, *icon_secure_dark, *ic_play_btn;
namespace Textures {
void Load(void);
void Free(void);
}
#endif

48
app/include/utils.h Normal file
View File

@ -0,0 +1,48 @@
#ifndef _CMFILEMANAGER_UTILS_H_
#define _CMFILEMANAGER_UTILS_H_
#include <pspctrl.h>
#include <psptypes.h>
/// Checks whether a result code indicates success.
#define R_SUCCEEDED(res) ((res) >= 0)
/// Checks whether a result code indicates failure.
#define R_FAILED(res) ((res) < 0)
enum BROWSE_STATE {
BROWSE_STATE_INTERNAL,
BROWSE_STATE_EXTERNAL
};
extern bool psp_usb_cable_connection, is_ms_inserted, is_psp_go;
extern enum PspCtrlButtons PSP_CTRL_ENTER, PSP_CTRL_CANCEL;
extern BROWSE_STATE device;
namespace Utils {
void SetBounds(int *set, int min, int max);
void SetMax(int *set, int value, int max);
void SetMin(int *set, int value, int min);
void GetSizeString(char *string, double size);
void InitKernelDrivers(void);
void TermKernelDrivers(void);
void HandleUSB(void);
bool IsModelPSPGo(void);
int IsMemCardInserted(bool *is_inserted);
bool IsEF0(void);
int LaunchEboot(const char *path);
u64 GetTotalStorage(void);
u64 GetFreeStorage(void);
u64 GetUsedStorage(void);
int ReadControls(void);
int IsButtonPressed(enum PspCtrlButtons buttons);
int IsButtonHeld(enum PspCtrlButtons buttons);
int IsKButtonPressed(enum PspCtrlButtons buttons);
int IsKButtonHeld(enum PspCtrlButtons buttons);
int GetEnterButton(void);
int GetCancelButton(void);
float GetAnalogX(void);
float GetAnalogY(void);
bool IsCancelButtonPressed(void);
}
#endif

15
app/source/colours.cpp Normal file
View File

@ -0,0 +1,15 @@
#include "colours.h"
#include "config.h"
g2dColor BG_COLOUR, STATUS_BAR_COLOUR, MENU_BAR_COLOUR, SELECTOR_COLOUR, TITLE_COLOUR, TEXT_COLOUR;
namespace Colours {
void Get(void) {
BG_COLOUR = cfg.dark_theme? BLACK_BG : WHITE;
STATUS_BAR_COLOUR = cfg.dark_theme? STATUS_BAR_DARK : STATUS_BAR_LIGHT;
MENU_BAR_COLOUR = cfg.dark_theme? MENU_BAR_DARK : MENU_BAR_LIGHT;
SELECTOR_COLOUR = cfg.dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT;
TITLE_COLOUR = cfg.dark_theme? TITLE_COLOUR_DARK : TITLE_COLOUR_LIGHT;
TEXT_COLOUR = cfg.dark_theme? TEXT_COLOUR_DARK : TEXT_COLOUR_LIGHT;
}
}

86
app/source/config.cpp Normal file
View File

@ -0,0 +1,86 @@
#include "config.h"
#include "fs.h"
#include "log.h"
#include "rapidjson/document.h"
#include "utils.h"
constexpr int config_version = 4;
constexpr char config_file[] = "{\n\t\"config_ver\": %d,\n\t\"sort\": %d,\n\t\"dark_theme\": %d,\n\t\"dev_options\": %d\n}\n";
static int config_version_holder = 0;
config_t cfg;
namespace Config {
int Save(config_t config) {
int ret = 0;
char *buf = new char[128];
int len = snprintf(buf, 128, config_file, config_version, cfg.sort, cfg.dark_theme, cfg.dev_options);
if (R_FAILED(ret = FS::WriteFile("config.json", buf, len))) {
Log::Error("Read config failed in Config_Save 0x%lx\n", ret);
delete[] buf;
return ret;
}
delete[] buf;
return 0;
}
static void SetDefault(config_t *config) {
config->sort = 0;
config->dark_theme = false;
config->dev_options = false;
}
int Load(void) {
int ret = 0;
// Set root path and current working directory based on model.
cfg.cwd = is_psp_go? "ef0:" : "ms0:";
if (is_psp_go)
device = BROWSE_STATE_INTERNAL;
else
device = BROWSE_STATE_EXTERNAL;
if (!FS::FileExists("config.json")) {
Config::SetDefault(&cfg);
Log::Error("File doesn't exist\n");
return Save(cfg);
}
u64 size = FS::GetFileSize("config.json");
char *buf = new char[size];
if (R_FAILED(ret = FS::ReadFile("config.json", buf, size))) {
Log::Error("Read config failed in Config_Load 0x%lx\n", ret);
delete[] buf;
return ret;
}
buf[size] = '\0';
rapidjson::Document document;
document.Parse(buf);
assert(document.IsObject());
assert(document.HasMember("config_ver"));
assert(document.HasMember("sort"));
assert(document.HasMember("dark_theme"));
assert(document.HasMember("dev_options"));
config_version_holder = document["config_ver"].GetInt();
cfg.sort = document["sort"].GetInt();
cfg.dark_theme = document["dark_theme"].GetInt();
cfg.dev_options = document["dev_options"].GetInt();
delete[] buf;
// delete[] config file if config file is updated. This will rarely happen.
if (config_version_holder < config_version) {
sceIoRemove("config.json");
Config::SetDefault(&cfg);
return Config::Save(cfg);
}
return 0;
}
}

512
app/source/fs.cpp Normal file
View File

@ -0,0 +1,512 @@
#include <algorithm>
#include <cstring>
#include <filesystem>
#include <cstdarg>
#include "config.h"
#include "fs.h"
#include "kernel_functions.h"
#include "log.h"
#include "utils.h"
namespace FS {
typedef struct {
std::string copy_path;
std::string copy_filename;
bool is_dir = false;
} FSCopyEntry;
static FSCopyEntry fs_copy_entry;
bool FileExists(const std::string &path) {
SceUID file = 0;
if (R_SUCCEEDED(file = sceIoOpen(path.c_str(), PSP_O_RDONLY, 0777))) {
sceIoClose(file);
return true;
}
return false;
}
bool DirExists(const std::string &path) {
SceUID dir = 0;
if (R_SUCCEEDED(dir = sceIoDopen(path.c_str()))) {
sceIoDclose(dir);
return true;
}
return false;
}
int MakeDir(const std::string &path) {
int ret = 0;
if (R_FAILED(ret = sceIoMkdir(path.c_str(), 0777)))
return ret;
return 0;
}
int CreateFile(const std::string &path) {
SceUID file = 0;
if (R_SUCCEEDED(file = sceIoOpen(path.c_str(), PSP_O_WRONLY | PSP_O_CREAT | PSP_O_TRUNC, 0777))) {
sceIoClose(file);
return 0;
}
return file;
}
std::string GetFileExt(const std::string &filename) {
std::string ext = std::filesystem::path(filename).extension();
std::transform(ext.begin(), ext.end(), ext.begin(), ::toupper);
return ext;
}
FileType GetFileType(const std::string &filename) {
std::string ext = FS::GetFileExt(filename);
if (!ext.compare(".PBP"))
return FileTypeApp;
else if ((!ext.compare(".ZIP")) || (!ext.compare(".RAR")) || (!ext.compare(".7Z")) || (!ext.compare(".LZMA")))
return FileTypeArchive;
else if ((!ext.compare(".FLAC")) || (!ext.compare(".IT")) || (!ext.compare(".MOD")) || (!ext.compare(".MP3")) || (!ext.compare(".OGG"))
|| (!ext.compare(".OPUS")) || (!ext.compare(".S3M")) || (!ext.compare(".WAV")) || (!ext.compare(".XM")))
return FileTypeAudio;
else if ((!ext.compare(".BMP")) || (!ext.compare(".GIF")) || (!ext.compare(".JPG")) || (!ext.compare(".JPEG")) || (!ext.compare(".PGM"))
|| (!ext.compare(".PPM")) || (!ext.compare(".PNG")) || (!ext.compare(".PSD")) || (!ext.compare(".TGA")) || (!ext.compare(".WEBP")))
return FileTypeImage;
else if ((!ext.compare(".JSON")) || (!ext.compare(".LOG")) || (!ext.compare(".TXT")) || (!ext.compare(".CFG")) || (!ext.compare(".INI")))
return FileTypeText;
return FileTypeNone;
}
SceOff GetFileSize(const std::string &path) {
int ret = 0;
SceIoStat stat;
std::memset(&stat, 0, sizeof(stat));
if (R_FAILED(ret = sceIoGetstat(path.c_str(), &stat)))
return ret;
return stat.st_size;
}
int ReadFile(const std::string &path, void *buf, int size) {
SceUID file = 0;
if (R_SUCCEEDED(file = sceIoOpen(path.c_str(), PSP_O_RDONLY, 0))) {
int read = sceIoRead(file, buf, size);
sceIoClose(file);
return read;
}
return file;
}
int WriteFile(const std::string &path, void *buf, int size) {
SceUID file = 0;
if (R_SUCCEEDED(file = sceIoOpen(path.c_str(), PSP_O_WRONLY | PSP_O_CREAT | PSP_O_TRUNC, 0777))) {
int written = sceIoWrite(file, buf, size);
sceIoClose(file);
return written;
}
return file;
}
static bool Sort(const SceIoDirent &entryA, const SceIoDirent &entryB) {
if ((FIO_S_ISDIR(entryA.d_stat.st_mode)) && !(FIO_S_ISDIR(entryB.d_stat.st_mode)))
return true;
else if (!(FIO_S_ISDIR(entryA.d_stat.st_mode)) && (FIO_S_ISDIR(entryB.d_stat.st_mode)))
return false;
else {
switch(cfg.sort) {
case 0:
if (strcasecmp(entryA.d_name, entryB.d_name) < 0)
return true;
break;
case 1:
if (strcasecmp(entryB.d_name, entryA.d_name) < 0)
return true;
break;
case 2:
if (entryB.d_stat.st_size < entryA.d_stat.st_size)
return true;
break;
case 3:
if (entryA.d_stat.st_size < entryB.d_stat.st_size)
return true;
break;
default:
break;
}
}
return false;
}
int GetDirList(const std::string &path, std::vector<SceIoDirent> &entries) {
int ret = 0;
SceUID dir = 0;
entries.clear();
if (R_FAILED(ret = dir = sceIoDopen(path.c_str()))) {
Log::Error("sceIoDopen(%s) failed: 0x%lx\n", path.c_str(), ret);
return ret;
}
do {
SceIoDirent entry;
std::memset(&entry, 0, sizeof(entry));
ret = sceIoDread(dir, &entry);
if (ret > 0) {
if ((std::strcmp(entry.d_name, ".") == 0) || (std::strcmp(entry.d_name, "..") == 0))
continue;
entries.push_back(entry);
}
} while (ret > 0);
std::sort(entries.begin(), entries.end(), FS::Sort);
sceIoDclose(dir);
return 0;
}
//TODO: Clean up change directory impl.
static int ChangeDir(const std::string &path, std::vector<SceIoDirent> &entries) {
int ret = 0;
std::vector<SceIoDirent> new_entries;
if (R_FAILED(ret = FS::GetDirList(path, new_entries)))
return ret;
// Free entries and change the current working directory.
entries.clear();
cfg.cwd = path;
entries = new_entries;
return 0;
}
static int ChangeDirUp(char path[256]) {
if (cfg.cwd.back() == ':')
return -1;
// Remove upmost directory
bool copy = false;
int len = 0;
for (ssize_t i = cfg.cwd.length(); i >= 0; i--) {
if (cfg.cwd.c_str()[i] == '/')
copy = true;
if (copy) {
path[i] = cfg.cwd.c_str()[i];
len++;
}
}
// remove trailing slash
if (len > 1 && path[len - 1] == '/')
len--;
path[len] = '\0';
return 0;
}
int ChangeDirNext(const std::string &path, std::vector<SceIoDirent> &entries) {
std::string new_path = cfg.cwd;
new_path.append("/");
new_path.append(path);
return FS::ChangeDir(new_path, entries);
}
int ChangeDirPrev(std::vector<SceIoDirent> &entries) {
char new_path[256];
if (FS::ChangeDirUp(new_path) < 0)
return -1;
return FS::ChangeDir(std::string(new_path), entries);
}
static int CopyFile(const std::string &src_path, const std::string &dest_path) {
int ret = 0;
SceUID src_handle = 0, dest_handle = 0;
if (R_FAILED(ret = src_handle = sceIoOpen(src_path.c_str(), PSP_O_RDONLY, 0))) {
Log::Error("sceIoOpen(%s) failed: 0x%x\n", src_path.c_str(), ret);
return ret;
}
u64 size = sceIoLseek(src_handle, 0, PSP_SEEK_END);
sceIoLseek(src_handle, 0, PSP_SEEK_SET);
// Make sure we have enough storage to carry out this operation
if (Utils::GetFreeStorage() < size) {
Log::Error("Not enough storage is available to process this command 0x%x\n", src_path.c_str(), ret);
sceIoClose(src_handle);
return -1;
}
if (R_FAILED(ret = dest_handle = sceIoOpen(dest_path.c_str(), PSP_O_WRONLY | PSP_O_CREAT | PSP_O_APPEND, 0777))) {
Log::Error("sceIoOpen(%s) failed: 0x%x\n", dest_path.c_str(), ret);
sceIoClose(src_handle);
return ret;
}
u32 bytes_read = 0, bytes_written = 0;
const u64 buf_size = 0x10000;
u64 offset = 0;
u8 *buf = new u8[buf_size];
std::string filename = std::filesystem::path(src_path.data()).filename();
do {
if (Utils::IsCancelButtonPressed()) {
delete[] buf;
sceIoClose(src_handle);
sceIoClose(dest_handle);
return 0;
}
std::memset(buf, 0, buf_size);
if (R_FAILED(ret = bytes_read = sceIoRead(src_handle, buf, buf_size))) {
Log::Error("sceIoRead(%s) failed: 0x%x\n", src_path.c_str(), ret);
delete[] buf;
sceIoClose(src_handle);
sceIoClose(dest_handle);
return ret;
}
if (R_FAILED(ret = bytes_written = sceIoWrite(dest_handle, buf, bytes_read))) {
Log::Error("sceIoWrite(%s) failed: 0x%x\n", dest_path.c_str(), ret);
delete[] buf;
sceIoClose(src_handle);
sceIoClose(dest_handle);
return ret;
}
offset += bytes_read;
//GUI::ProgressBar("Copying", filename.c_str(), offset, size);
} while(offset < size);
delete[] buf;
sceIoClose(src_handle);
sceIoClose(dest_handle);
return 0;
}
static int CopyDir(const std::string &src_path, const std::string &dest_path) {
int ret = 0;
SceUID dir;
if (R_FAILED(dir = sceIoDopen(src_path.c_str()))) {
Log::Error("sceIoDopen(%s) failed: 0x%lx\n", src_path.c_str(), ret);
return dir;
}
// This may fail or not, but we don't care -> make the dir if it doesn't exist, otherwise continue.
sceIoMkdir(dest_path.c_str(), 0777);
do {
SceIoDirent entry;
std::memset(&entry, 0, sizeof(entry));
ret = sceIoDread(dir, &entry);
if (ret > 0) {
if ((std::strcmp(entry.d_name, ".") == 0) || (std::strcmp(entry.d_name, "..") == 0))
continue;
std::string src = src_path;
src.append("/");
src.append(entry.d_name);
std::string dest = dest_path;
dest.append("/");
dest.append(entry.d_name);
if (FIO_S_ISDIR(entry.d_stat.st_mode))
FS::CopyDir(src, dest); // Copy Folder (via recursion)
else
FS::CopyFile(src, dest); // Copy File
}
} while (ret > 0);
sceIoDclose(dir);
return 0;
}
static void ClearCopyData(void) {
fs_copy_entry.copy_path.clear();
fs_copy_entry.copy_filename.clear();
fs_copy_entry.is_dir = false;
}
void Copy(SceIoDirent *entry, const std::string &path) {
FS::ClearCopyData();
fs_copy_entry.copy_path = path;
fs_copy_entry.copy_path.append("/");
fs_copy_entry.copy_path.append(entry->d_name);
fs_copy_entry.copy_filename.append(entry->d_name);
if (FIO_S_ISDIR(entry->d_stat.st_mode))
fs_copy_entry.is_dir = true;
}
int Paste(void) {
int ret = 0;
std::string path = cfg.cwd;
path.append("/");
path.append(fs_copy_entry.copy_filename);
if (fs_copy_entry.is_dir) // Copy folder recursively
ret = FS::CopyDir(fs_copy_entry.copy_path, path);
else // Copy file
ret = FS::CopyFile(fs_copy_entry.copy_path, path);
FS::ClearCopyData();
return ret;
}
// Thanks to TN for finding this.
static int sceIoMove(const char *src, const char *dest) {
int ret = 0;
size_t i = 0;
char strage[32];
char *p1 = nullptr, *p2 = nullptr;
p1 = std::strchr(src, ':');
if (p1 == nullptr)
return -1;
p2 = std::strchr(dest, ':');
if (p2 == nullptr)
return -1;
if ((p1 - src) != (p2 - dest))
return -1;
for (i = 0; (src + i) <= p1; i++) {
if ((i+1) >= sizeof(strage))
return -1;
if (src[i] != dest[i])
return -1;
strage[i] = src[i];
}
strage[i] = '\0';
u32 data[2];
data[0] = (u32)(p1 + 1);
data[1] = (u32)(p2 + 1);
if (R_FAILED(ret = sceIoDevctl(strage, 0x02415830, &data, sizeof(data), nullptr, 0))) {
Log::Error("sceIoDevctl() failed!", ret);
return ret;
}
return 0;
}
int Move(void) {
int ret = 0;
std::string path = cfg.cwd;
path.append("/");
path.append(fs_copy_entry.copy_filename);
if (R_FAILED(ret = sceIoMove(fs_copy_entry.copy_path.c_str(), path.c_str()))) {
Log::Error("sceIoMove(%s, %s) failed: 0x%x\n", fs_copy_entry.copy_filename.c_str(), path.c_str(), ret);
FS::ClearCopyData();
return ret;
}
FS::ClearCopyData();
return 0;
}
static int DeleteDirectoryRecursive(const std::string &path) {
int ret = 0;
SceUID dir = 0;
if (R_FAILED(ret = dir = sceIoDopen(path.c_str()))) {
if (R_FAILED(ret = sceIoRemove(path.c_str()))) {
Log::Error("sceIoRemove(%s) failed: 0x%lx\n", path.c_str(), ret);
return ret;
}
}
do {
SceIoDirent entry;
std::memset(&entry, 0, sizeof(entry));
ret = sceIoDread(dir, &entry);
if (ret > 0) {
if ((std::strcmp(entry.d_name, ".") == 0) || (std::strcmp(entry.d_name, "..") == 0))
continue;
std::string new_path = path;
new_path.append("/");
new_path.append(entry.d_name);
if (FIO_S_ISDIR(entry.d_stat.st_mode)) {
int result = FS::DeleteDirectoryRecursive(new_path);
if (result <= 0) {
Log::Error("FS::DeleteDirectoryRecursive(%s) failed: 0x%lx\n", path.c_str(), ret);
sceIoDclose(dir);
return ret;
}
}
else {
int result = sceIoRemove(new_path.c_str());
if (R_FAILED(result)) {
Log::Error("sceIoRemove(%s) failed: 0x%lx\n", path.c_str(), ret);
sceIoDclose(dir);
return ret;
}
}
}
} while (ret > 0);
sceIoDclose(dir);
if (R_FAILED(ret = sceIoRmdir(path.c_str()))) {
Log::Error("sceIoRmdir(%s) failed: 0x%lx\n", path.c_str(), ret);
return ret;
}
return 1;
}
int Delete(SceIoDirent *entry) {
int ret = 0;
std::string path = cfg.cwd;
path.append("/");
path.append(entry->d_name);
if (FIO_S_ISDIR(entry->d_stat.st_mode)) {
if (R_FAILED(ret = FS::DeleteDirectoryRecursive(path))) {
Log::Error("FS::DeleteDirectoryRecursive(%s) failed: 0x%x\n", path.c_str(), ret);
return ret;
}
}
else {
if (R_FAILED(ret = sceIoRemove(path.c_str()))) {
Log::Error("sceIoRemove(%s) failed: 0x%x\n", path.c_str(), ret);
return ret;
}
}
return 0;
}
}

1095
app/source/ftppsp.cpp Normal file

File diff suppressed because it is too large Load Diff

147
app/source/g2d.cpp Normal file
View File

@ -0,0 +1,147 @@
#include <pspkernel.h>
#include <pspdisplay.h>
#include <pspgu.h>
#include <psputility.h>
#include <cstring>
#include "g2d.h"
#include "utils.h"
intraFont *font, *jpn0, *chn;
namespace G2D {
void DrawRect(float x, float y, float width, float height, g2dColor colour) {
g2dBeginRects(nullptr); {
g2dSetColor(colour);
g2dSetScaleWH(width, height);
g2dSetCoordXY(x, y);
g2dAdd();
}
g2dEnd();
}
void DrawImage(g2dTexture *tex, float x, float y) {
g2dBeginRects(tex); {
g2dSetCoordXY(x, y);
g2dAdd();
}
g2dEnd();
}
void DrawImageScale(g2dTexture *tex, float x, float y, float w, float h) {
g2dBeginRects(tex); {
g2dSetScaleWH(w, h);
g2dSetCoordXY(x, y);
g2dAdd();
}
g2dEnd();
}
static int GetText(char *input, unsigned short *intext, unsigned short *desc) {
bool done = false;
unsigned short outtext[128] = { 0 };
SceUtilityOskData data;
std::memset(&data, 0, sizeof(SceUtilityOskData));
data.language = PSP_UTILITY_OSK_LANGUAGE_DEFAULT; // Use system default for text input
data.lines = 1;
data.unk_24 = 1;
data.inputtype = PSP_UTILITY_OSK_INPUTTYPE_ALL; // Allow all input types
data.desc = desc;
data.intext = intext;
data.outtextlength = 128;
data.outtextlimit = 32; // Limit input to 32 characters
data.outtext = outtext;
SceUtilityOskParams params;
memset(&params, 0, sizeof(params));
params.base.size = sizeof(params);
sceUtilityGetSystemParamInt(PSP_SYSTEMPARAM_ID_INT_LANGUAGE, &params.base.language);
sceUtilityGetSystemParamInt(PSP_SYSTEMPARAM_ID_INT_UNKNOWN, &params.base.buttonSwap);
params.base.graphicsThread = 17;
params.base.accessThread = 19;
params.base.fontThread = 18;
params.base.soundThread = 16;
params.datacount = 1;
params.data = &data;
int ret = 0;
if (R_FAILED(ret = sceUtilityOskInitStart(&params)))
return ret;
while(!done) {
int i = 0, j = 0;
g2dClear(G2D_RGBA(39, 50, 56, 255));
sceGuFinish();
sceGuSync(0, 0);
switch(sceUtilityOskGetStatus()) {
case PSP_UTILITY_DIALOG_INIT:
break;
case PSP_UTILITY_DIALOG_VISIBLE:
sceUtilityOskUpdate(1);
break;
case PSP_UTILITY_DIALOG_QUIT:
sceUtilityOskShutdownStart();
break;
case PSP_UTILITY_DIALOG_FINISHED:
break;
case PSP_UTILITY_DIALOG_NONE:
done = true;
default:
break;
}
for(i = 0; data.outtext[i]; i++) {
if (data.outtext[i] != '\0' && data.outtext[i] != '\n' && data.outtext[i] != '\r') {
input[j] = data.outtext[i];
j++;
}
}
input[j] = 0;
g2dFlip(G2D_VSYNC);
}
return 0;
}
char *KeyboardGetText(const std::string &desc_msg, const std::string &initial_msg) {
int ret = 0;
size_t i = 0;
static char str[64];
unsigned short initial[128] = { 0 };
unsigned short desc[128] = { 0 };
if (initial_msg.c_str()[0] != 0) {
for (i = 0; i <= initial_msg.length(); i++)
initial[i] = static_cast<unsigned short>(initial_msg.c_str()[i]);
}
if (desc_msg.c_str()[0] != 0) {
for (i = 0; i <= desc_msg.length(); i++)
desc[i] = static_cast<unsigned short>(desc_msg.c_str()[i]);
}
if (R_SUCCEEDED(ret = G2D::GetText(str, initial, desc)))
return str;
return 0;
}
void FontSetStyle(intraFont *font, float size, unsigned int colour, unsigned int options) {
intraFontSetStyle(font, size, colour, G2D_RGBA(0, 0, 0, 0), 0.f, options);
}
float GetTextHeight(intraFont *font) {
return font->advancey * font->size / 4.f + 2.f;
}
}

122
app/source/gui.cpp Normal file
View File

@ -0,0 +1,122 @@
#include <psppower.h>
#include <sys/time.h>
#include <psprtc.h>
#include "config.h"
#include "colours.h"
#include "fs.h"
#include "g2d.h"
#include "gui.h"
#include "textures.h"
#include "utils.h"
namespace GUI {
void ResetCheckbox(MenuItem *item) {
item->checked.clear();
item->checked_copy.clear();
item->checked.resize(item->entries.size());
item->checked.assign(item->checked.size(), false);
item->checked_cwd.clear();
item->checked_count = 0;
};
void GetStorageSize(MenuItem *item) {
item->total_storage = Utils::GetTotalStorage();
item->used_storage = Utils::GetUsedStorage();
}
void DisplayStatusBar(void) {
pspTime time;
static char time_string[30];
if (R_SUCCEEDED(sceRtcGetCurrentClockLocalTime(&time)))
snprintf(time_string, 30, "%2i:%02i %s", ((time.hour % 12) == 0)? 12 : time.hour % 12, time.minutes, (time.hour / 12)? "PM" : "AM");
G2D::FontSetStyle(font, 1.0f, WHITE, INTRAFONT_ALIGN_LEFT);
intraFontPrint(font, 5, 14, time_string);
int state = scePowerIsBatteryCharging();
int percent = scePowerGetBatteryLifePercent();
int battery_val = (percent / 20);
static char percent_string[13];
snprintf(percent_string, 13, "%d%%", percent);
int percent_width = intraFontMeasureText(font, percent_string);
intraFontPrint(font, 475 - percent_width, 14, percent_string);
G2D::DrawImage(state != 0? battery_charging[battery_val] : battery[battery_val], 475 - percent_width - battery[battery_val]->w, 2);
}
int RenderLoop(void) {
bool done = false;
MenuItem item;
int ret = 0;
if (R_FAILED(ret = FS::GetDirList(cfg.cwd, item.entries)))
return ret;
GUI::ResetCheckbox(&item);
GUI::GetStorageSize(&item);
u64 last = 0;
u32 tick = sceRtcGetTickResolution();
sceRtcGetCurrentTick(&last);
Colours::Get();
while(!done) {
u64 current = 0;
sceRtcGetCurrentTick(&current);
float delta_time = (current - last) / static_cast<float>(tick);
last = current;
int ctrl = Utils::ReadControls();
g2dClear(BG_COLOUR);
G2D::DrawRect(0, 0, 480, 18, STATUS_BAR_COLOUR);
G2D::DrawRect(0, 18, 480, 34, MENU_BAR_COLOUR);
G2D::DrawImageScale(icon_nav_drawer, 5, 24, 26.f, 26.f);
GUI::DisplayStatusBar();
GUI::DisplayFileBrowser(&item);
switch(item.state) {
case MENU_STATE_FILEBROWSER:
GUI::ControlFileBrowser(&item, &ctrl);
break;
case MENU_STATE_OPTIONS:
GUI::DisplayFileOptions(&item);
GUI::ControlFileOptions(&item, &ctrl);
break;
case MENU_STATE_DELETE:
GUI::DisplayDeleteOptions(&item);
GUI::ControlDeleteOptions(&item, &ctrl);
break;
case MENU_STATE_SETTINGS:
GUI::DisplaySettings(&item);
GUI::ControlSettings(&item, &ctrl);
break;
case MENU_STATE_IMAGEVIEWER:
GUI::DisplayImageViewer(&item);
GUI::ControlImageViewer(&item, &delta_time);
break;
default:
break;
}
g2dFlip(G2D_VSYNC);
if (Utils::IsButtonPressed(PSP_CTRL_START))
item.state = MENU_STATE_SETTINGS;
else if (Utils::IsKButtonPressed(PSP_CTRL_HOME))
break;
}
return 0;
}
}

87
app/source/gui/delete.cpp Normal file
View File

@ -0,0 +1,87 @@
#include "config.h"
#include "fs.h"
#include "colours.h"
#include "g2d.h"
#include "gui.h"
#include "log.h"
#include "textures.h"
#include "utils.h"
namespace Options {
void Delete(MenuItem *item, int *selection) {
int ret = 0;
Log::CloseHandle();
if ((item->checked_count > 1) && (!item->checked_cwd.compare(cfg.cwd))) {
for (u32 i = 0; i < item->checked.size(); i++) {
if (item->checked.at(i)) {
if (R_FAILED(ret = FS::Delete(&item->entries[i]))) {
FS::GetDirList(cfg.cwd, item->entries);
GUI::ResetCheckbox(item);
break;
}
}
}
}
else
ret = FS::Delete(&item->entries[item->selected]);
if (R_SUCCEEDED(ret)) {
FS::GetDirList(cfg.cwd, item->entries);
GUI::ResetCheckbox(item);
}
GUI::GetStorageSize(item);
Log::OpenHande();
*selection = 0;
item->selected = 0;
item->state = MENU_STATE_FILEBROWSER;
}
}
namespace GUI {
static int selection = 0;
static const std::string prompt = "Do you wish to continue?";
void DisplayDeleteOptions(MenuItem *item) {
G2D::DrawRect(0, 18, 480, 254, G2D_RGBA(0, 0, 0, cfg.dark_theme? 50: 80));
G2D::DrawImage(cfg.dark_theme? dialog_dark : dialog, ((480 - (dialog->w)) / 2), ((272 - (dialog->h)) / 2));
G2D::FontSetStyle(font, 1.0f, TITLE_COLOUR, INTRAFONT_ALIGN_LEFT);
intraFontPrint(font, ((480 - (dialog->w)) / 2) + 10, ((272 - (dialog->h)) / 2) + 20, "Delete");
int prompt_width = intraFontMeasureText(font, prompt.c_str());
G2D::FontSetStyle(font, 1.0f, TEXT_COLOUR, INTRAFONT_ALIGN_LEFT);
intraFontPrint(font, ((480 - (prompt_width)) / 2), ((272 - (dialog->h)) / 2) + 60, prompt.c_str());
int confirm_width = intraFontMeasureText(font, "YES");
int cancel_width = intraFontMeasureText(font, "NO");
if (selection == 0)
G2D::DrawRect((364 - cancel_width) - 5, (180 - (font->texYSize - 15)) - 5, cancel_width + 10, (font->texYSize - 5) + 10, SELECTOR_COLOUR);
else
G2D::DrawRect((409 - (confirm_width)) - 5, (180 - (font->texYSize - 15)) - 5, confirm_width + 10, (font->texYSize - 5) + 10, SELECTOR_COLOUR);
G2D::FontSetStyle(font, 1.0f, TITLE_COLOUR, INTRAFONT_ALIGN_LEFT);
intraFontPrint(font, 409 - (confirm_width), (192 - (font->texYSize - 15)) - 3, "YES");
intraFontPrint(font, 364 - cancel_width, (192 - (font->texYSize - 15)) - 3, "NO");
}
void ControlDeleteOptions(MenuItem *item, int *ctrl) {
if (*ctrl & PSP_CTRL_RIGHT)
selection++;
else if (*ctrl & PSP_CTRL_LEFT)
selection--;
if (Utils::IsButtonPressed(PSP_CTRL_ENTER)) {
if (selection == 1)
Options::Delete(item, &selection);
else
item->state = MENU_STATE_OPTIONS;
}
else if (Utils::IsButtonPressed(PSP_CTRL_CANCEL))
item->state = MENU_STATE_OPTIONS;
Utils::SetBounds(&selection, 0, 1);
}
}

View File

@ -0,0 +1,148 @@
#include <algorithm>
#include <pspctrl.h>
#include "config.h"
#include "fs.h"
#include "colours.h"
#include "g2d.h"
#include "gui.h"
#include "textures.h"
#include "utils.h"
namespace GUI {
static const int sel_dist = 20;
static const int start_y = 52;
static const u32 max_entries = 11;
static int start = 0;
// static std::string empty_dir = "This is an empty directory";
// static float empty_dir_width = 0.f, empty_dir_height = 0.f;
void DisplayFileBrowser(MenuItem *item) {
G2D::FontSetStyle(font, 1.0f, WHITE, INTRAFONT_ALIGN_LEFT);
float height = G2D::GetTextHeight(font);
intraFontPrint(font, 40, 36, cfg.cwd.c_str());
G2D::DrawRect(40, 43, 400, 3, SELECTOR_COLOUR);
float fill = (static_cast<double>(item->used_storage)/static_cast<double>(item->total_storage)) * 400.f;
G2D::DrawRect(40, 43, fill, 3, TITLE_COLOUR);
for (u32 i = start; i < item->entries.size(); i++) {
std::string filename = item->entries[i].d_name;
if (i == static_cast<u32>(item->selected))
G2D::DrawRect(0, start_y + (sel_dist * (i - start)), 480, sel_dist, SELECTOR_COLOUR);
if ((item->checked[i]) && (!item->checked_cwd.compare(cfg.cwd)))
G2D::DrawImageScale(cfg.dark_theme? icon_check_dark : icon_check, 0, start_y + (sel_dist * (i - start)), 18.f, 18.f);
else
G2D::DrawImageScale(cfg.dark_theme? icon_uncheck_dark : icon_uncheck, 0, start_y + (sel_dist * (i - start)), 18.f, 18.f);
FileType file_type = FS::GetFileType(filename);
if (FIO_S_ISDIR(item->entries[i].d_stat.st_mode))
G2D::DrawImageScale(cfg.dark_theme? icon_dir_dark : icon_dir, 20, start_y + (sel_dist * (i - start)), 18.f, 18.f);
else
G2D::DrawImageScale(file_icons[file_type], 20, start_y + (sel_dist * (i - start)), 18.f, 18.f);
G2D::FontSetStyle(font, 1.0f, cfg.dark_theme? WHITE : BLACK, INTRAFONT_ALIGN_LEFT);
intraFontPrintf(font, 45, start_y + 10 + ((sel_dist - height) / 2) + (i - start) * sel_dist, filename.length() > 52? "%.52s..." : "%s", filename.c_str());
}
}
void ControlFileBrowser(MenuItem *item, int *ctrl) {
u32 size = (item->entries.size() - 1);
Utils::SetBounds(&item->selected, 0, size);
if (*ctrl & PSP_CTRL_UP) {
item->selected--;
if (item->selected < 0)
item->selected = size;
if (size < max_entries)
start = 0;
else if (start > item->selected)
start--;
else if ((static_cast<u32>(item->selected) == size) && (size > (max_entries - 1)))
start = size - (max_entries - 1);
}
else if (*ctrl & PSP_CTRL_DOWN) {
item->selected++;
if(static_cast<u32>(item->selected) > size)
item->selected = 0;
if ((static_cast<u32>(item->selected) > (start + (max_entries - 1))) && ((start + (max_entries - 1)) < size))
start++;
if (item->selected == 0)
start = 0;
}
if (Utils::IsButtonPressed(PSP_CTRL_LEFT)) {
item->selected = 0;
start = 0;
}
else if (Utils::IsButtonPressed(PSP_CTRL_RIGHT)) {
item->selected = item->entries.size() - 1;
if ((item->entries.size() - 1) > max_entries)
start = size - (max_entries - 1);
}
if (Utils::IsButtonPressed(PSP_CTRL_ENTER)) {
if (FIO_S_ISDIR(item->entries[item->selected].d_stat.st_mode)) {
if (item->entries.size() != 0) {
if (R_SUCCEEDED(FS::ChangeDirNext(item->entries[item->selected].d_name, item->entries))) {
start = 0;
// Make a copy before resizing our vector.
if ((item->checked_count > 1) && (item->checked_copy.empty()))
item->checked_copy = item->checked;
item->checked.resize(item->entries.size());
item->selected = 0;
}
}
}
else {
std::string path = cfg.cwd;
path.append(item->entries[item->selected].d_name);
FileType file_type = FS::GetFileType(item->entries[item->selected].d_name);
switch(file_type) {
case FileTypeImage:
item->texture = g2dTexLoad(path.c_str(), G2D_SWIZZLE);
if (item->texture)
item->state = MENU_STATE_IMAGEVIEWER;
break;
// case FileTypeZip:
// if (R_SUCCEEDED(ArchiveHelper::Extract(path))) {
// FS::GetDirList(cfg.cwd, item->entries);
// GUI::ResetCheckbox(item);
// }
// break;
default:
break;
}
}
}
else if (Utils::IsButtonPressed(PSP_CTRL_CANCEL)) {
if (R_SUCCEEDED(FS::ChangeDirPrev(item->entries))) {
// Make a copy before resizing our vector.
if (item->checked_count > 1)
item->checked_copy = item->checked;
item->checked.resize(item->entries.size());
item->selected = 0;
start = 0;
}
}
else if (Utils::IsButtonPressed(PSP_CTRL_SQUARE)) {
if ((!item->checked_cwd.empty()) && (item->checked_cwd.compare(cfg.cwd) != 0))
GUI::ResetCheckbox(item);
item->checked_cwd = cfg.cwd;
item->checked[item->selected] = !item->checked[item->selected];
item->checked_count = std::count(item->checked.begin(), item->checked.end(), true);
}
else if (Utils::IsButtonPressed(PSP_CTRL_TRIANGLE))
item->state = MENU_STATE_OPTIONS;
}
}

View File

@ -0,0 +1,125 @@
#include "config.h"
#include "fs.h"
#include "colours.h"
#include "g2d.h"
#include "gui.h"
#include "utils.h"
namespace ImageViewer {
static void Draw(g2dTexture *tex, float w, float h, float zoom_factor, int angle, int pos_x, int pos_y) {
g2dBeginRects(tex); {
g2dSetCoordMode(G2D_CENTER);
g2dSetScaleWH(w * zoom_factor, h * zoom_factor);
g2dSetCoordXY((G2D_SCR_W / 2) - (pos_x * zoom_factor - pos_x) / 2, (G2D_SCR_H / 2) - (pos_y * zoom_factor - pos_y) / 2);
g2dSetRotation(angle);
g2dAdd();
}
g2dEnd();
}
}
namespace GUI {
static bool properties = false, horizantal_flip = false, vertical_flip = false;
static float scale_factor = 0.f, width = 0.f, height = 0.f, zoom_factor = 1.f;
static int degrees = 0, pos_x = 0, pos_y = 0;
void DisplayImageViewer(MenuItem *item) {
g2dClear(BLACK_BG);
if (static_cast<float>(item->texture->h) > 272.f) {
scale_factor = (272.f / static_cast<float>(item->texture->h));
width = static_cast<float>(item->texture->w) * scale_factor;
height = static_cast<float>(item->texture->h) * scale_factor;
}
else {
width = static_cast<float>(item->texture->w);
height = static_cast<float>(item->texture->h);
}
ImageViewer::Draw(item->texture, width, height, zoom_factor, degrees, pos_x, pos_y);
}
void ControlImageViewer(MenuItem *item, float *delta_time) {
if (Utils::IsButtonPressed(PSP_CTRL_LTRIGGER)) {
degrees -= 90;
if (degrees < 0)
degrees = 270;
}
else if (Utils::IsButtonPressed(PSP_CTRL_RTRIGGER)) {
degrees += 90;
if (degrees > 270)
degrees = 0;
}
// Flip horizantally
if (Utils::IsButtonPressed(PSP_CTRL_SQUARE)) {
horizantal_flip = !horizantal_flip;
width = -width;
}
// Flip vertically
if (Utils::IsButtonPressed(PSP_CTRL_TRIANGLE)) {
vertical_flip = !vertical_flip;
height = -height;
}
if (Utils::IsButtonHeld(PSP_CTRL_UP)) {
zoom_factor += 0.5f * (*delta_time);
if (zoom_factor > 2.0f)
zoom_factor = 2.0f;
}
else if (Utils::IsButtonHeld(PSP_CTRL_DOWN)) {
zoom_factor -= 0.5f * (*delta_time);
if (zoom_factor < 0.5f)
zoom_factor = 0.5f;
if (zoom_factor <= 1.0f) {
pos_x = 0;
pos_y = 0;
}
}
if ((height * zoom_factor > 272.f) || (width * zoom_factor > 480.f)) {
double velocity = 2.f / zoom_factor;
if (Utils::GetAnalogY() < -0.4f)
pos_y -= ((velocity * zoom_factor) * (*delta_time) * 1000.f);
if (Utils::GetAnalogY() > 0.4f)
pos_y += ((velocity * zoom_factor) * (*delta_time) * 1000.f);
if (Utils::GetAnalogX() < -0.4f)
pos_x -= ((velocity * zoom_factor) * (*delta_time) * 1000.f);
if (Utils::GetAnalogX() > 0.4f)
pos_x += ((velocity * zoom_factor) * (*delta_time) * 1000.f);
}
if ((degrees == 0) || (degrees == 180)) {
Utils::SetMax(&pos_x, horizantal_flip? -width : width, horizantal_flip? -width : width);
Utils::SetMin(&pos_x, horizantal_flip? width : -width, horizantal_flip? width : -width);
Utils::SetMax(&pos_y, vertical_flip? -height : height, vertical_flip? -height : height);
Utils::SetMin(&pos_y, vertical_flip? height : -height, vertical_flip? height : -height);
}
else {
Utils::SetMax(&pos_x, vertical_flip? -height : height, vertical_flip? -height : height);
Utils::SetMin(&pos_x, vertical_flip? height : -height, vertical_flip? height : -height);
Utils::SetMax(&pos_y, horizantal_flip? -width : width, horizantal_flip? -width : width);
Utils::SetMin(&pos_y, horizantal_flip? width : -width, horizantal_flip? width : -width);
}
if (Utils::IsButtonPressed(PSP_CTRL_CANCEL)) {
if (!properties) {
if (item->texture)
g2dTexFree(&item->texture);
zoom_factor = 1.f;
pos_x = 0;
pos_y = 0;
item->state = MENU_STATE_FILEBROWSER;
}
else
properties = false;
}
}
}

258
app/source/gui/options.cpp Normal file
View File

@ -0,0 +1,258 @@
#include <pspctrl.h>
#include "config.h"
#include "fs.h"
#include "colours.h"
#include "g2d.h"
#include "gui.h"
#include "textures.h"
#include "utils.h"
static int row = 0, column = 0;
static bool copy = false, move = false, options_more = false;
namespace Options {
static void ResetSelector(void) {
row = 0;
column = 0;
}
static void HandleMultipleCopy(MenuItem *item, int (*func)()) {
int ret = 0;
std::vector<SceIoDirent> entries;
if (R_FAILED(ret = FS::GetDirList(item->checked_cwd.data(), entries)))
return;
for (u32 i = 0; i < item->checked_copy.size(); i++) {
if (item->checked_copy.at(i)) {
FS::Copy(&entries[i], item->checked_cwd);
if (R_FAILED((*func)())) {
FS::GetDirList(cfg.cwd, item->entries);
GUI::ResetCheckbox(item);
break;
}
}
}
FS::GetDirList(cfg.cwd, item->entries);
GUI::ResetCheckbox(item);
entries.clear();
}
static void CreateFolder(MenuItem *item) {
std::string path = cfg.cwd;
path.append("/");
std::string name = G2D::KeyboardGetText("Enter folder name", "New folder");
path.append(name);
if (R_SUCCEEDED(FS::MakeDir(path.c_str()))) {
FS::GetDirList(cfg.cwd, item->entries);
GUI::ResetCheckbox(item);
}
}
static void CreateFile(MenuItem *item) {
std::string path = cfg.cwd;
path.append("/");
std::string name = G2D::KeyboardGetText("Enter file name", "New File");
path.append(name);
if (R_SUCCEEDED(FS::CreateFile(path.c_str()))) {
FS::GetDirList(cfg.cwd, item->entries);
GUI::ResetCheckbox(item);
}
}
static void Rename(MenuItem *item, const std::string &filename) {
std::string src_path = cfg.cwd;
src_path.append("/");
src_path.append(item->entries[item->selected].d_name);
std::string dest_path = cfg.cwd;
dest_path.append("/");
std::string name = G2D::KeyboardGetText("Enter new name", filename);
dest_path.append(name);
if (R_SUCCEEDED(sceIoRename(src_path.c_str(), dest_path.c_str()))) {
FS::GetDirList(cfg.cwd, item->entries);
Options::ResetSelector();
options_more = false;
item->state = MENU_STATE_FILEBROWSER;
}
}
static void Copy(MenuItem *item) {
if (!copy) {
if ((item->checked_count >= 1) && (item->checked_cwd.compare(cfg.cwd) != 0))
GUI::ResetCheckbox(item);
if (item->checked_count <= 1)
FS::Copy(&item->entries[item->selected], cfg.cwd);
copy = !copy;
item->state = MENU_STATE_FILEBROWSER;
}
else {
if ((item->checked_count > 1) && (item->checked_cwd.compare(cfg.cwd) != 0))
Options::HandleMultipleCopy(item, &FS::Paste);
else {
if (R_SUCCEEDED(FS::Paste())) {
FS::GetDirList(cfg.cwd, item->entries);
GUI::ResetCheckbox(item);
}
}
GUI::GetStorageSize(item);
copy = !copy;
item->state = MENU_STATE_FILEBROWSER;
}
}
static void Move(MenuItem *item) {
if (!move) {
if ((item->checked_count >= 1) && (item->checked_cwd.compare(cfg.cwd) != 0))
GUI::ResetCheckbox(item);
if (item->checked_count <= 1)
FS::Copy(&item->entries[item->selected], cfg.cwd);
}
else {
if ((item->checked_count > 1) && (item->checked_cwd.compare(cfg.cwd) != 0))
Options::HandleMultipleCopy(item, &FS::Move);
else if (R_SUCCEEDED(FS::Move())) {
FS::GetDirList(cfg.cwd, item->entries);
GUI::ResetCheckbox(item);
}
}
move = !move;
item->state = MENU_STATE_FILEBROWSER;
}
}
namespace GUI {
void DisplayFileOptions(MenuItem *item) {
G2D::DrawRect(0, 18, 480, 254, G2D_RGBA(0, 0, 0, cfg.dark_theme? 50: 80));
G2D::DrawImage(cfg.dark_theme? options_dialog_dark : options_dialog, (480 - options_dialog->w) / 2, (272 - options_dialog->h) / 2);
G2D::FontSetStyle(font, 1.0f, TITLE_COLOUR, INTRAFONT_ALIGN_LEFT);
intraFontPrint(font, 140, 52, "Actions");
if (row == 0 && column == 0)
G2D::DrawRect(132, 71, 107, 38, SELECTOR_COLOUR);
else if (row == 1 && column == 0)
G2D::DrawRect(241, 71, 107, 38, SELECTOR_COLOUR);
else if (row == 0 && column == 1)
G2D::DrawRect(132, 110, 107, 38, SELECTOR_COLOUR);
else if (row == 1 && column == 1)
G2D::DrawRect(241, 110, 107, 38, SELECTOR_COLOUR);
else if (row == 0 && column == 2 && !options_more)
G2D::DrawRect(132, 148, 107, 38, SELECTOR_COLOUR);
else if (row == 1 && column == 2 && !options_more)
G2D::DrawRect(241, 148, 107, 38, SELECTOR_COLOUR);
else if (column == 3 && !options_more)
G2D::DrawRect((340 - intraFontMeasureText(font, "CANCEL")) - 5, (230 - (font->texYSize - 6)) - 5, intraFontMeasureText(font, "CANCEL") + 10,
(font->texYSize - 6) + 10, SELECTOR_COLOUR);
else if (column == 2 && options_more)
G2D::DrawRect((340 - intraFontMeasureText(font, "CANCEL")) - 5, (230 - (font->texYSize - 6)) - 5, intraFontMeasureText(font, "CANCEL") + 10,
(font->texYSize - 6) + 10, SELECTOR_COLOUR);
intraFontPrint(font, 340 - intraFontMeasureText(font, "CANCEL"), 230 - (font->texYSize - 15), "CANCEL");
G2D::FontSetStyle(font, 1.0f, TEXT_COLOUR, INTRAFONT_ALIGN_LEFT);
if (!options_more) {
intraFontPrint(font, 143, 95, "Properties");
intraFontPrint(font, 143, 133, copy? "Paste" : "Copy");
intraFontPrint(font, 143, 171, "Delete");
intraFontPrint(font, 247, 95, "Refresh");
intraFontPrint(font, 247, 133, move? "Paste" : "Move");
intraFontPrint(font, 247, 171, "More...");
}
else {
intraFontPrint(font, 143, 95, "New folder");
intraFontPrint(font, 143, 133, "Rename");
intraFontPrint(font, 247, 95, "New file");
}
}
void ControlFileOptions(MenuItem *item, int *ctrl) {
if (*ctrl & PSP_CTRL_RIGHT)
row++;
else if (*ctrl & PSP_CTRL_LEFT)
row--;
if (*ctrl & PSP_CTRL_DOWN)
column++;
else if (*ctrl & PSP_CTRL_UP)
column--;
if (!options_more) {
Utils::SetBounds(&row, 0, 1);
Utils::SetBounds(&column, 0, 3);
}
else {
Utils::SetBounds(&column, 0, 2);
if (column == 1)
Utils::SetBounds(&row, 0, 0);
else
Utils::SetBounds(&row, 0, 1);
}
if (Utils::IsButtonPressed(PSP_CTRL_CROSS)) {
const std::string filename = item->entries[item->selected].d_name;
if (row == 0) {
if (!options_more) {
if (column == 0)
item->state = MENU_STATE_PROPERTIES;
else if (column == 1)
Options::Copy(item);
else if (column == 2)
item->state = MENU_STATE_DELETE;
}
else {
if (column == 0)
Options::CreateFolder(item);
else if (column == 1)
Options::Rename(item, filename);
}
}
else if (row == 1) {
if (!options_more) {
if (column == 0) {
FS::GetDirList(cfg.cwd, item->entries);
Options::ResetSelector();
options_more = false;
item->selected = 0;
item->state = MENU_STATE_FILEBROWSER;
}
else if (column == 1)
Options::Move(item);
else if (column == 2) {
Options::ResetSelector();
options_more = true;
}
}
else {
if (column == 0)
Options::CreateFile(item);
}
}
if (column == 3) {
copy = false;
move = false;
Options::ResetSelector();
options_more = false;
item->state = MENU_STATE_FILEBROWSER;
}
}
if (Utils::IsButtonPressed(PSP_CTRL_CANCEL)) {
Options::ResetSelector();
if (!options_more)
item->state = MENU_STATE_FILEBROWSER;
else
options_more = false;
}
}
}

156
app/source/gui/settings.cpp Normal file
View File

@ -0,0 +1,156 @@
#include "config.h"
#include "colours.h"
#include "fs.h"
#include "g2d.h"
#include "gui.h"
#include "textures.h"
#include "utils.h"
namespace GUI {
enum SETTINGS_STATE {
GENERAL_SETTINGS,
FTP_SETTINGS,
SORT_SETTINGS,
ABOUT_SETTINGS
};
static SETTINGS_STATE settings_state = GENERAL_SETTINGS;
static int selection = 0;
static const int sel_dist = 44;
static void DisplaySortSettings(void) {
intraFontPrint(font, 40, 40, "Sorting Options");
G2D::FontSetStyle(font, 1.0f, cfg.dark_theme? WHITE : BLACK, INTRAFONT_ALIGN_LEFT);
intraFontPrint(font, 40, 72, "Alphabetical");
intraFontPrint(font, 40, 86, "Sort alphabetically in ascending order.");
intraFontPrint(font, 40, 116, "Alphabetical");
intraFontPrint(font, 40, 130, "Sort alphabetically in descending order.");
intraFontPrint(font, 40, 160, "Size");
intraFontPrint(font, 40, 174, "Sort by size (largest first).");
intraFontPrint(font, 40, 204, "Size");
intraFontPrint(font, 40, 218, "Sort by size (smallest first).");
G2D::DrawImage(cfg.sort == 0? (cfg.dark_theme? icon_radio_dark_on : icon_radio_on) : (cfg.dark_theme? icon_radio_dark_off : icon_radio_off), 425, 60);
G2D::DrawImage(cfg.sort == 1? (cfg.dark_theme? icon_radio_dark_on : icon_radio_on) : (cfg.dark_theme? icon_radio_dark_off : icon_radio_off), 425, 104);
G2D::DrawImage(cfg.sort == 2? (cfg.dark_theme? icon_radio_dark_on : icon_radio_on) : (cfg.dark_theme? icon_radio_dark_off : icon_radio_off), 425, 148);
G2D::DrawImage(cfg.sort == 3? (cfg.dark_theme? icon_radio_dark_on : icon_radio_on) : (cfg.dark_theme? icon_radio_dark_off : icon_radio_off), 425, 192);
}
static void ControlSortSettings(MenuItem *item, int *ctrl) {
if (Utils::IsButtonPressed(PSP_CTRL_ENTER)) {
cfg.sort = selection;
Config::Save(cfg);
FS::GetDirList(cfg.cwd, item->entries);
}
else if (Utils::IsButtonPressed(PSP_CTRL_CANCEL)) {
selection = 0;
settings_state = GENERAL_SETTINGS;
}
Utils::SetBounds(&selection, 0, 3);
}
static void DisplayGeneralSettings(void) {
intraFontPrint(font, 40, 40, "Settings");
G2D::FontSetStyle(font, 1.0f, cfg.dark_theme? WHITE : BLACK, INTRAFONT_ALIGN_LEFT);
intraFontPrint(font, 40, 72, "FTP connection");
intraFontPrint(font, 40, 86, "Wireless connection");
intraFontPrint(font, 40, 116, "Sorting options");
intraFontPrint(font, 40, 130, "Select between various sorting options.");
intraFontPrint(font, 40, 160, "Dark theme");
intraFontPrint(font, 40, 174, "Enables dark theme mode.");
intraFontPrint(font, 40, 204, "Developer options");
intraFontPrint(font, 40, 218, "Enable logging and fs access to NAND.");
intraFontPrint(font, 40, 248, "About");
intraFontPrint(font, 40, 262, "Application and device info");
if (cfg.dark_theme)
G2D::DrawImage(cfg.dark_theme? icon_toggle_dark_on : icon_toggle_on, 415, 143);
else
G2D::DrawImage(icon_toggle_off, 415, 143);
G2D::DrawImage(cfg.dev_options? (cfg.dark_theme? icon_toggle_dark_on : icon_toggle_on) : icon_toggle_off, 415, 187);
}
static void ControlGeneralSettings(MenuItem *item, int *ctrl) {
if (Utils::IsButtonPressed(PSP_CTRL_ENTER)) {
switch(selection) {
case 1:
settings_state = SORT_SETTINGS;
selection = 0;
break;
case 2:
cfg.dark_theme = !cfg.dark_theme;
Colours::Get();
Config::Save(cfg);
break;
case 3:
cfg.dev_options = !cfg.dev_options;
Config::Save(cfg);
break;
default:
break;
}
}
else if (Utils::IsButtonPressed(PSP_CTRL_CANCEL)) {
selection = 0;
item->state = MENU_STATE_FILEBROWSER;
}
Utils::SetBounds(&selection, 0, 4);
}
void DisplaySettings(MenuItem *item) {
G2D::DrawRect(0, 18, 480, 34, MENU_BAR_COLOUR);
G2D::DrawRect(0, 52, 480, 220, BG_COLOUR);
G2D::DrawImage(icon_back, 5, 20);
G2D::DrawRect(0, 52 + (selection * sel_dist), 480, sel_dist, SELECTOR_COLOUR);
G2D::FontSetStyle(font, 1.0f, WHITE, INTRAFONT_ALIGN_LEFT);
switch(settings_state) {
case GENERAL_SETTINGS:
DisplayGeneralSettings();
break;
case SORT_SETTINGS:
DisplaySortSettings();
break;
default:
break;
}
}
void ControlSettings(MenuItem *item, int *ctrl) {
if (*ctrl & PSP_CTRL_UP)
selection--;
else if (*ctrl & PSP_CTRL_DOWN)
selection++;
switch(settings_state) {
case GENERAL_SETTINGS:
ControlGeneralSettings(item, ctrl);
break;
case SORT_SETTINGS:
ControlSortSettings(item, ctrl);
break;
default:
break;
}
}
}

View File

@ -0,0 +1,27 @@
#include "kernel_functions.h"
// audio_driver functions
int pspAudioSetFrequency(int frequency);
// display driver functions
int pspGetBrightness(int *brightness);
int pspSetBrightness(int brightness);
int pspDisplayEnable(void);
int pspDisplayDisable(void);
// fs_driver functions
int pspOpenDir(const char *dirname);
int pspReadDir(SceUID dir, SceIoDirent *dirent);
int pspCloseDir(SceUID dir);
// impose_driver functions
int pspGetVolume(void);
int pspSetVolume(int volume);
int pspGetMute(void);
int pspSetMute(int mute);
int pspGetEqualizerMode(void);
int pspSetEqualizerMode(int mode);
int pspSetHomePopup(int popup);
// input_driver functions
unsigned int pspGetButtons(void);

47
app/source/log.cpp Normal file
View File

@ -0,0 +1,47 @@
#include <pspiofilemgr.h>
#include <cstdarg>
#include <cstdio>
#include <cstring>
#include "config.h"
#include "utils.h"
namespace Log {
SceUID log_handle = 0;
int OpenHande(void) {
if (R_FAILED(log_handle = sceIoOpen("debug.log", PSP_O_WRONLY | PSP_O_CREAT | PSP_O_APPEND, 0777)))
return log_handle;
return 0;
}
int CloseHandle(void) {
int ret = 0;
if (R_FAILED(ret = sceIoClose(log_handle)))
return ret;
return 0;
}
int Error(const char *format, ...) {
if (!cfg.dev_options)
return -1;
va_list list;
char string[512] = {0};
va_start(list, format);
std::vsprintf(string, format, list);
va_end(list);
std::printf("%s", string);
int ret = 0;
if (R_FAILED(ret = sceIoWrite(log_handle, string, std::strlen(string))))
return ret;
return 0;
}
}

64
app/source/main.cpp Normal file
View File

@ -0,0 +1,64 @@
#include <pspctrl.h>
#include <pspkernel.h>
#include "config.h"
#include "g2d.h"
#include "gui.h"
#include "log.h"
#include "textures.h"
#include "utils.h"
PSP_MODULE_INFO("CMFileManager", 0x800, VERSION_MAJOR, VERSION_MINOR);
PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU);
PSP_HEAP_SIZE_MAX();
namespace Services {
int Init(void) {
sceCtrlSetSamplingCycle(0);
sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG);
Log::OpenHande();
Utils::InitKernelDrivers();
Textures::Load();
int ret = 0;
if (R_FAILED(ret = Config::Load())) {
Log::Error("Config::Load failed: 0x%lx\n", ret);
return ret;
}
if (R_FAILED(ret = intraFontInit())) {
Log::Error("intraFontInit failed: 0x%lx\n", ret);
return ret;
}
font = intraFontLoad("flash0:/font/ltn8.pgf", 0);
jpn0 = intraFontLoad("flash0:/font/jpn0.pgf", INTRAFONT_STRING_UTF8);
chn = intraFontLoad("flash0:/font/gb3s1518.bwfon", 0);
intraFontSetAltFont(font, jpn0);
intraFontSetAltFont(jpn0, chn);
intraFontSetEncoding(font, INTRAFONT_STRING_UTF8);
Utils::IsMemCardInserted(&is_ms_inserted);
is_psp_go = Utils::IsModelPSPGo();
PSP_CTRL_ENTER = static_cast<enum PspCtrlButtons>(Utils::GetEnterButton());
PSP_CTRL_CANCEL = static_cast<enum PspCtrlButtons>(Utils::GetCancelButton());
return 0;
}
void Exit(void) {
intraFontUnload(chn);
intraFontUnload(jpn0);
intraFontUnload(font);
Textures::Free();
Log::CloseHandle();
Utils::TermKernelDrivers();
sceKernelExitGame();
}
}
int main(int argc, char* argv[]) {
Services::Init();
GUI::RenderLoop();
Services::Exit();
}

156
app/source/textures.cpp Normal file
View File

@ -0,0 +1,156 @@
#include "textures.h"
extern unsigned char ic_fso_type_app_png_start[], ic_fso_type_compress_png_start[], ic_fso_type_audio_png_start[],
ic_fso_folder_png_start[], ic_fso_folder_dark_png_start[], ic_fso_default_png_start[], ic_fso_type_image_png_start[],
ic_fso_type_text_png_start[], btn_material_light_check_on_normal_png_start[], btn_material_light_check_on_normal_dark_png_start[],
btn_material_light_check_off_normal_png_start[], btn_material_light_check_off_normal_dark_png_start[], btn_material_light_toggle_on_normal_png_start[],
btn_material_light_toggle_on_normal_dark_png_start[], btn_material_light_toggle_off_normal_png_start[], btn_material_light_radio_off_normal_png_start[],
btn_material_light_radio_on_normal_png_start[], btn_material_light_radio_off_normal_dark_png_start[], btn_material_light_radio_on_normal_dark_png_start[],
ic_material_light_navigation_drawer_png_start[], ic_arrow_back_normal_png_start[], ic_material_options_dialog_png_start[],
ic_material_options_dialog_dark_png_start[], ic_material_properties_dialog_png_start[], ic_material_properties_dialog_dark_png_start[],
ic_material_dialog_png_start[], ic_material_dialog_dark_png_start[], battery_20_png_start[], battery_20_charging_png_start[], battery_30_png_start[],
battery_30_charging_png_start[], battery_50_png_start[], battery_50_charging_png_start[], battery_60_png_start[], battery_60_charging_png_start[],
battery_80_png_start[], battery_80_charging_png_start[], battery_full_png_start[], battery_full_charging_png_start[], ic_material_light_usb_png_start[],
default_artwork_png_start[], default_artwork_blur_png_start[], btn_playback_play_png_start[], btn_playback_pause_png_start[],
btn_playback_rewind_png_start[], btn_playback_forward_png_start[], btn_playback_repeat_png_start[], btn_playback_shuffle_png_start[],
btn_playback_repeat_overlay_png_start[], btn_playback_shuffle_overlay_png_start[], bg_header_png_start[], ic_material_light_sdcard_png_start[],
ic_material_light_secure_png_start[], ic_material_light_sdcard_dark_png_start[], ic_material_light_secure_dark_png_start[], ic_play_btn_png_start[];
extern unsigned int ic_fso_type_app_png_size, ic_fso_type_compress_png_size, ic_fso_type_audio_png_size, ic_fso_folder_png_size,
ic_fso_folder_dark_png_size, ic_fso_default_png_size, ic_fso_type_image_png_size, ic_fso_type_text_png_size,
btn_material_light_check_on_normal_png_size, btn_material_light_check_on_normal_dark_png_size, btn_material_light_check_off_normal_png_size,
btn_material_light_check_off_normal_dark_png_size, btn_material_light_toggle_on_normal_png_size, btn_material_light_toggle_on_normal_dark_png_size,
btn_material_light_toggle_off_normal_png_size, btn_material_light_radio_off_normal_png_size, btn_material_light_radio_on_normal_png_size,
btn_material_light_radio_off_normal_dark_png_size, btn_material_light_radio_on_normal_dark_png_size, ic_material_light_navigation_drawer_png_size,
ic_arrow_back_normal_png_size, ic_material_options_dialog_png_size, ic_material_options_dialog_dark_png_size, ic_material_properties_dialog_png_size,
ic_material_properties_dialog_dark_png_size, ic_material_dialog_png_size, ic_material_dialog_dark_png_size, battery_20_png_size,
battery_20_charging_png_size, battery_30_png_size, battery_30_charging_png_size, battery_50_png_size, battery_50_charging_png_size,
battery_60_png_size, battery_60_charging_png_size, battery_80_png_size, battery_80_charging_png_size, battery_full_png_size,
battery_full_charging_png_size, ic_material_light_usb_png_size,
default_artwork_png_size, default_artwork_blur_png_size, btn_playback_play_png_size, btn_playback_pause_png_size, btn_playback_rewind_png_size,
btn_playback_forward_png_size, btn_playback_repeat_png_size, btn_playback_shuffle_png_size, btn_playback_repeat_overlay_png_size,
btn_playback_shuffle_overlay_png_size, bg_header_png_size, ic_material_light_sdcard_png_size, ic_material_light_secure_png_size,
ic_material_light_sdcard_dark_png_size, ic_material_light_secure_dark_png_size, ic_play_btn_png_size;
g2dTexture *file_icons[NUM_ICONS], *icon_dir, *icon_dir_dark, *icon_check, *icon_check_dark, *icon_uncheck, \
*icon_uncheck_dark, *icon_toggle_on, *icon_toggle_dark_on, *icon_toggle_off, *icon_radio_off, \
*icon_radio_on, *icon_radio_dark_off, *icon_radio_dark_on, *icon_nav_drawer, *icon_back, \
*options_dialog, *options_dialog_dark, *properties_dialog, *properties_dialog_dark, *dialog, *dialog_dark, \
*battery_charging[NUM_BATT_ICONS], *battery[NUM_BATT_ICONS], *usb_icon, \
*default_artwork, *default_artwork_blur, *btn_play, *btn_pause, *btn_rewind, *btn_forward, \
*btn_repeat, *btn_shuffle, *btn_repeat_overlay, *btn_shuffle_overlay, \
*bg_header, *icon_sd, *icon_secure, *icon_sd_dark, *icon_secure_dark, *ic_play_btn;
namespace Textures {
void Load(void) {
file_icons[0] = g2dTexLoadMemory(ic_fso_default_png_start, ic_fso_default_png_size, G2D_SWIZZLE);
file_icons[1] = g2dTexLoadMemory(ic_fso_type_app_png_start, ic_fso_type_app_png_size, G2D_SWIZZLE);
file_icons[2] = g2dTexLoadMemory(ic_fso_type_compress_png_start, ic_fso_type_compress_png_size, G2D_SWIZZLE);
file_icons[3] = g2dTexLoadMemory(ic_fso_type_audio_png_start, ic_fso_type_audio_png_size, G2D_SWIZZLE);
file_icons[4] = g2dTexLoadMemory(ic_fso_type_image_png_start, ic_fso_type_image_png_size, G2D_SWIZZLE);
file_icons[5] = g2dTexLoadMemory(ic_fso_type_text_png_start, ic_fso_type_text_png_size, G2D_SWIZZLE);
icon_dir = g2dTexLoadMemory(ic_fso_folder_png_start, ic_fso_folder_png_size, G2D_SWIZZLE);
icon_dir_dark = g2dTexLoadMemory(ic_fso_folder_dark_png_start, ic_fso_folder_dark_png_size, G2D_SWIZZLE);
icon_check = g2dTexLoadMemory(btn_material_light_check_on_normal_png_start, btn_material_light_check_on_normal_png_size, G2D_SWIZZLE);
icon_check_dark = g2dTexLoadMemory(btn_material_light_check_on_normal_dark_png_start, btn_material_light_check_on_normal_dark_png_size, G2D_SWIZZLE);
icon_uncheck = g2dTexLoadMemory(btn_material_light_check_off_normal_png_start, btn_material_light_check_off_normal_png_size, G2D_SWIZZLE);
icon_uncheck_dark = g2dTexLoadMemory(btn_material_light_check_off_normal_dark_png_start, btn_material_light_check_off_normal_dark_png_size, G2D_SWIZZLE);
icon_toggle_on = g2dTexLoadMemory(btn_material_light_toggle_on_normal_png_start, btn_material_light_toggle_on_normal_png_size, G2D_SWIZZLE);
icon_toggle_dark_on = g2dTexLoadMemory(btn_material_light_toggle_on_normal_dark_png_start, btn_material_light_toggle_on_normal_dark_png_size, G2D_SWIZZLE);
icon_toggle_off = g2dTexLoadMemory(btn_material_light_toggle_off_normal_png_start, btn_material_light_toggle_off_normal_png_size, G2D_SWIZZLE);
icon_radio_off = g2dTexLoadMemory(btn_material_light_radio_off_normal_png_start, btn_material_light_radio_off_normal_png_size, G2D_SWIZZLE);
icon_radio_on = g2dTexLoadMemory(btn_material_light_radio_on_normal_png_start, btn_material_light_radio_on_normal_png_size, G2D_SWIZZLE);
icon_radio_dark_off = g2dTexLoadMemory(btn_material_light_radio_off_normal_dark_png_start, btn_material_light_radio_off_normal_dark_png_size, G2D_SWIZZLE);
icon_radio_dark_on = g2dTexLoadMemory(btn_material_light_radio_on_normal_dark_png_start, btn_material_light_radio_on_normal_dark_png_size, G2D_SWIZZLE);
icon_nav_drawer = g2dTexLoadMemory(ic_material_light_navigation_drawer_png_start, ic_material_light_navigation_drawer_png_size, G2D_SWIZZLE);
icon_back = g2dTexLoadMemory(ic_arrow_back_normal_png_start, ic_arrow_back_normal_png_size, G2D_SWIZZLE);
options_dialog = g2dTexLoadMemory(ic_material_options_dialog_png_start, ic_material_options_dialog_png_size, G2D_SWIZZLE);
options_dialog_dark = g2dTexLoadMemory(ic_material_options_dialog_dark_png_start, ic_material_options_dialog_dark_png_size, G2D_SWIZZLE);
properties_dialog = g2dTexLoadMemory(ic_material_properties_dialog_png_start, ic_material_properties_dialog_png_size, G2D_SWIZZLE);
properties_dialog_dark = g2dTexLoadMemory(ic_material_properties_dialog_dark_png_start, ic_material_properties_dialog_dark_png_size, G2D_SWIZZLE);
dialog = g2dTexLoadMemory(ic_material_dialog_png_start, ic_material_dialog_png_size, G2D_SWIZZLE);
dialog_dark = g2dTexLoadMemory(ic_material_dialog_dark_png_start, ic_material_dialog_dark_png_size, G2D_SWIZZLE);
battery_charging[0] = g2dTexLoadMemory(battery_20_charging_png_start, battery_20_charging_png_size, G2D_SWIZZLE);
battery_charging[1] = g2dTexLoadMemory(battery_30_charging_png_start, battery_30_charging_png_size, G2D_SWIZZLE);
battery_charging[2] = g2dTexLoadMemory(battery_50_charging_png_start, battery_50_charging_png_size, G2D_SWIZZLE);
battery_charging[3] = g2dTexLoadMemory(battery_60_charging_png_start, battery_60_charging_png_size, G2D_SWIZZLE);
battery_charging[4] = g2dTexLoadMemory(battery_80_charging_png_start, battery_80_charging_png_size, G2D_SWIZZLE);
battery_charging[5] = g2dTexLoadMemory(battery_full_charging_png_start, battery_full_charging_png_size, G2D_SWIZZLE);
battery[0] = g2dTexLoadMemory(battery_20_png_start, battery_30_png_size, G2D_SWIZZLE);
battery[1] = g2dTexLoadMemory(battery_30_png_start, battery_30_png_size, G2D_SWIZZLE);
battery[2] = g2dTexLoadMemory(battery_50_png_start, battery_50_png_size, G2D_SWIZZLE);
battery[3] = g2dTexLoadMemory(battery_60_png_start, battery_60_png_size, G2D_SWIZZLE);
battery[4] = g2dTexLoadMemory(battery_80_png_start, battery_80_png_size, G2D_SWIZZLE);
battery[5] = g2dTexLoadMemory(battery_full_png_start, battery_full_png_size, G2D_SWIZZLE);
usb_icon = g2dTexLoadMemory(ic_material_light_usb_png_start, ic_material_light_usb_png_size, G2D_SWIZZLE);
default_artwork = g2dTexLoadMemory(default_artwork_png_start, default_artwork_png_size, G2D_SWIZZLE);
default_artwork_blur = g2dTexLoadMemory(default_artwork_blur_png_start, default_artwork_blur_png_size, G2D_SWIZZLE);
btn_play = g2dTexLoadMemory(btn_playback_play_png_start, btn_playback_play_png_size, G2D_SWIZZLE);
btn_pause = g2dTexLoadMemory(btn_playback_pause_png_start, btn_playback_pause_png_size, G2D_SWIZZLE);
btn_rewind = g2dTexLoadMemory(btn_playback_rewind_png_start, btn_playback_rewind_png_size, G2D_SWIZZLE);
btn_forward = g2dTexLoadMemory(btn_playback_forward_png_start, btn_playback_forward_png_size, G2D_SWIZZLE);
btn_repeat = g2dTexLoadMemory(btn_playback_repeat_png_start, btn_playback_repeat_png_size, G2D_SWIZZLE);
btn_shuffle = g2dTexLoadMemory(btn_playback_shuffle_png_start, btn_playback_shuffle_png_size, G2D_SWIZZLE);
btn_repeat_overlay = g2dTexLoadMemory(btn_playback_repeat_overlay_png_start, btn_playback_repeat_overlay_png_size, G2D_SWIZZLE);
btn_shuffle_overlay = g2dTexLoadMemory(btn_playback_shuffle_overlay_png_start, btn_playback_shuffle_overlay_png_size, G2D_SWIZZLE);
bg_header = g2dTexLoadMemory(bg_header_png_start, bg_header_png_size, G2D_SWIZZLE);
icon_sd = g2dTexLoadMemory(ic_material_light_sdcard_png_start, ic_material_light_sdcard_png_size, G2D_SWIZZLE);
icon_secure = g2dTexLoadMemory(ic_material_light_secure_png_start, ic_material_light_secure_png_size, G2D_SWIZZLE);
icon_sd_dark = g2dTexLoadMemory(ic_material_light_sdcard_dark_png_start, ic_material_light_sdcard_dark_png_size, G2D_SWIZZLE);
icon_secure_dark = g2dTexLoadMemory(ic_material_light_secure_dark_png_start, ic_material_light_secure_dark_png_size, G2D_SWIZZLE);
ic_play_btn = g2dTexLoadMemory(ic_play_btn_png_start, ic_play_btn_png_size, G2D_SWIZZLE);
}
void Free(void) {
g2dTexFree(&ic_play_btn);
g2dTexFree(&icon_secure_dark);
g2dTexFree(&icon_sd_dark);
g2dTexFree(&icon_secure);
g2dTexFree(&icon_sd);
g2dTexFree(&bg_header);
g2dTexFree(&btn_shuffle_overlay);
g2dTexFree(&btn_repeat_overlay);
g2dTexFree(&btn_shuffle);
g2dTexFree(&btn_repeat);
g2dTexFree(&btn_forward);
g2dTexFree(&btn_rewind);
g2dTexFree(&btn_pause);
g2dTexFree(&btn_play);
g2dTexFree(&default_artwork_blur);
g2dTexFree(&default_artwork);
g2dTexFree(&usb_icon);
g2dTexFree(&dialog_dark);
g2dTexFree(&dialog);
g2dTexFree(&properties_dialog_dark);
g2dTexFree(&properties_dialog);
g2dTexFree(&options_dialog_dark);
g2dTexFree(&options_dialog);
g2dTexFree(&icon_back);
g2dTexFree(&icon_nav_drawer);
g2dTexFree(&icon_radio_dark_on);
g2dTexFree(&icon_radio_dark_off);
g2dTexFree(&icon_radio_on);
g2dTexFree(&icon_radio_off);
g2dTexFree(&icon_toggle_off);
g2dTexFree(&icon_toggle_dark_on);
g2dTexFree(&icon_toggle_on);
g2dTexFree(&icon_uncheck_dark);
g2dTexFree(&icon_uncheck);
g2dTexFree(&icon_check_dark);
g2dTexFree(&icon_check);
g2dTexFree(&icon_dir_dark);
g2dTexFree(&icon_dir);
for (int i = 0; i < NUM_ICONS; i++)
g2dTexFree(&file_icons[i]);
for (int i = 0; i < NUM_BATT_ICONS; i++) {
g2dTexFree(&battery_charging[i]);
g2dTexFree(&battery[i]);
}
}
}

435
app/source/utils.cpp Normal file
View File

@ -0,0 +1,435 @@
#include <cstdio>
#include <cstring>
#include <pspkernel.h>
#include <pspreg.h>
#include <pspusb.h>
#include <pspusbstor.h>
#include <vector>
#include "config.h"
#include "kernel_functions.h"
#include "kubridge.h"
#include "log.h"
#include "pspusbdevice.h"
#include "systemctrl.h"
#include "systemctrl_se.h"
#include "utils.h"
bool psp_usb_cable_connection = false, is_ms_inserted = false, is_psp_go = false;
enum PspCtrlButtons PSP_CTRL_ENTER, PSP_CTRL_CANCEL;
BROWSE_STATE device = BROWSE_STATE_EXTERNAL;
namespace Utils {
constexpr unsigned int CTRL_DEADZONE_DELAY = 500000;
constexpr unsigned int CTRL_DELAY = 100000;
static SceCtrlData pad, kernel_pad, prev_pad;
static unsigned int last_button = 0;
static int last_button_tick = 0, deadzone_tick = 0;
static bool usb_module_loaded = false;
static bool usb_actived = false;
typedef struct {
const char *path = nullptr;
int id = 0;
} Module;
static std::vector<Module> kernel_modules {
{ "audio_driver.prx", -1, },
{ "display_driver.prx", -1, },
{ "fs_driver.prx", -1, },
{ "impose_driver.prx", -1, },
{ "input_driver.prx", -1, }
};
static std::vector<Module> usb_modules {
{ "flash0:/kd/_usbdevice.prx", -1, },
{ "flash0:/kd/semawm.prx", -1, },
{ "flash0:/kd/usbstor.prx", -1, },
{ "flash0:/kd/usbstormgr.prx", -1, },
{ "flash0:/kd/usbstorms.prx", -1, },
{ "flash0:/kd/usbstoreflash.prx", -1, },
{ "flash0:/kd/usbstorboot.prx", -1, }
};
typedef struct {
unsigned long maxclusters = 0;
unsigned long freeclusters = 0;
int unk1 = 0;
unsigned int sectorsize = 0;
u64 sectorcount = 0;
} SystemDevCtl;
typedef struct {
SystemDevCtl *pdevinf;
} SystemDevCommand;
void SetBounds(int *set, int min, int max) {
if (*set > max)
*set = min;
else if (*set < min)
*set = max;
}
void SetMax(int *set, int value, int max) {
if (*set > max)
*set = value;
}
void SetMin(int *set, int value, int min) {
if (*set < min)
*set = value;
}
void GetSizeString(char *string, double size) {
int i = 0;
const char *units[] = {"B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"};
while (size >= 1024.0f) {
size /= 1024.0f;
i++;
}
std::sprintf(string, "%.*f %s", (i == 0) ? 0 : 2, size, units[i]);
}
static int LoadStartModule(const char *path) {
int ret = 0, status = 0;
SceUID modID = 0;
if (R_FAILED(ret = modID = kuKernelLoadModule(path, 0, nullptr))) {
Log::Error("kuKernelLoadModule(%s) failed: 0x%lx\n", path, ret);
return ret;
}
if (R_FAILED(ret = sceKernelStartModule(modID, 0, nullptr, &status, nullptr))) {
Log::Error("sceKernelStartModule(%s) failed: 0x%lx\n", path, ret);
return ret;
}
return ret;
}
static void StopUnloadModules(SceUID modID) {
sceKernelStopModule(modID, 0, nullptr, nullptr, nullptr);
sceKernelUnloadModule(modID);
}
static int InitUSB(void) {
int ret = 0;
if (!usb_module_loaded) {
for (unsigned int i = 0; i < usb_modules.size(); ++i)
usb_modules[i].id = Utils::LoadStartModule(usb_modules[i].path);
usb_module_loaded = true;
}
if (R_FAILED(ret = sceUsbStart(PSP_USBBUS_DRIVERNAME, 0, 0))) {
Log::Error("sceUsbStart(PSP_USBBUS_DRIVERNAME) failed: 0x%lx\n", ret);
return ret;
}
if (R_FAILED(ret = sceUsbStart(PSP_USBSTOR_DRIVERNAME, 0, 0))) {
Log::Error("sceUsbStart(PSP_USBSTOR_DRIVERNAME) failed: 0x%lx\n", ret);
return ret;
}
if (R_FAILED(ret = sceUsbstorBootSetCapacity(0x800000))) {
Log::Error("sceUsbstorBootSetCapacity(0x800000) failed: 0x%lx\n", ret);
return ret;
}
usb_actived = true;
return 0;
}
static int StartUSBStorage(void) {
int ret = 0;
if (R_FAILED(ret = sceUsbActivate(0x1c8))) {
Log::Error("sceUsbActivate(0x1c8) failed: 0x%lx\n", ret);
return ret;
}
psp_usb_cable_connection = true;
return 0;
}
static int StopUSBStorage(void) {
int ret = 0;
if (R_FAILED(ret = sceUsbDeactivate(0x1c8))) {
Log::Error("sceUsbActivate(0x1c8) failed: 0x%lx\n", ret);
return ret;
}
if (R_FAILED(ret = sceIoDevctl("fatms0:", 0x0240D81E, nullptr, 0, nullptr, 0))) { // Avoid corrupted files
Log::Error("sceIoDevctl(\"fatms0:\", 0x0240D81E, nullptr, 0, nullptr, 0) failed: 0x%lx\n", ret);
return ret;
}
psp_usb_cable_connection = false;
return 0;
}
static int DisableUSB(void) {
int ret = 0;
if (!usb_actived)
return -1;
if (R_FAILED(ret = Utils::StopUSBStorage()))
return ret;
if (R_FAILED(ret = sceUsbStop(PSP_USBSTOR_DRIVERNAME, 0, 0))) {
Log::Error("sceUsbStop(PSP_USBSTOR_DRIVERNAME) failed: 0x%lx\n", ret);
return ret;
}
if (R_FAILED(ret = sceUsbStop(PSP_USBBUS_DRIVERNAME, 0, 0))) {
Log::Error("sceUsbStop(PSP_USBBUS_DRIVERNAME) failed: 0x%lx\n", ret);
return ret;
}
if (R_FAILED(ret = pspUsbDeviceFinishDevice())) {
Log::Error("pspUsbDeviceFinishDevice() failed: 0x%lx\n", ret);
return ret;
}
usb_actived = false;
return 0;
}
static void ExitUSB(void) {
Utils::DisableUSB();
if (usb_module_loaded) {
for (int i = usb_modules.size() - 1; i >= 0; --i) {
Utils::StopUnloadModules(usb_modules[i].id);
usb_modules[i].id = -1;
}
usb_module_loaded = false;
}
}
void InitKernelDrivers(void) {
for (unsigned int i = 0; i < kernel_modules.size(); ++i)
kernel_modules[i].id = Utils::LoadStartModule(kernel_modules[i].path);
Utils::InitUSB();
}
void TermKernelDrivers(void) {
for (int i = kernel_modules.size() - 1; i >= 0; --i) {
Utils::StopUnloadModules(kernel_modules[i].id);
kernel_modules[i].id = -1;
}
Utils::ExitUSB();
}
void UpdateUSB(void) {
if (sceUsbGetState() & PSP_USB_CABLE_CONNECTED) {
if (psp_usb_cable_connection == false)
Utils::StartUSBStorage();
}
else {
if (psp_usb_cable_connection == true)
Utils::StopUSBStorage();
}
}
bool IsModelPSPGo(void) {
return (kuKernelGetModel() == 4);
}
int IsMemCardInserted(bool *is_inserted) {
int status = 0, ret = 0;
if (R_FAILED(ret = sceIoDevctl("mscmhc0:", 0x02025806, 0, 0, &status, sizeof(status))))
return ret;
if (status != 1)
*is_inserted = false;
else
*is_inserted = true;
return 0;
}
bool IsEF0(void) {
if (is_psp_go) {
if (!is_ms_inserted)
return true;
return true;
}
return false;
}
int LaunchEboot(const char *path) {
int ret = 0;
struct SceKernelLoadExecVSHParam param;
std::memset(&param, 0, sizeof(param));
param.size = sizeof(param);
param.args = std::strlen(path) + 1;
param.argp = (void *)path;
param.key = "game";
if (R_FAILED(ret = sctrlKernelLoadExecVSHWithApitype(IsEF0()? 0x152 : 0x141, path, &param))) {
Log::Error("sctrlKernelLoadExecVSHWithApitype(%x, %s) failed: 0x%lx\n", IsEF0()? 0x152 : 0x141, path, ret);
return ret;
}
return 0;
}
u64 GetTotalStorage(void) {
int ret = 0;
SystemDevCtl devctl;
SystemDevCommand command;
command.pdevinf = &devctl;
if (R_FAILED(ret = sceIoDevctl(device == BROWSE_STATE_INTERNAL? "ef0": "ms0:", 0x02425818, &command, sizeof(SystemDevCommand), nullptr, 0)))
return 0;
u64 size = (devctl.maxclusters * devctl.sectorcount) * devctl.sectorsize;
return size;
}
u64 GetFreeStorage(void) {
int ret = 0;
SystemDevCtl devctl;
SystemDevCommand command;
command.pdevinf = &devctl;
if (R_FAILED(ret = sceIoDevctl(device == BROWSE_STATE_INTERNAL? "ef0": "ms0:", 0x02425818, &command, sizeof(SystemDevCommand), nullptr, 0)))
return 0;
u64 size = (devctl.freeclusters * devctl.sectorcount) * devctl.sectorsize;
return size;
}
u64 GetUsedStorage(void) {
return (Utils::GetTotalStorage() - Utils::GetFreeStorage());
}
static int GetRegistryValue(const char *dir, const char *name, unsigned int *value) {
int ret = 0;
struct RegParam reg;
REGHANDLE h;
std::memset(&reg, 0, sizeof(reg));
reg.regtype = 1;
reg.namelen = std::strlen("/system");
reg.unk2 = 1;
reg.unk3 = 1;
std::strcpy(reg.name, "/system");
if (R_SUCCEEDED(sceRegOpenRegistry(&reg, 2, &h))) {
REGHANDLE hd;
if (R_SUCCEEDED(sceRegOpenCategory(h, dir, 2, &hd))) {
REGHANDLE hk;
unsigned int type, size;
if (R_SUCCEEDED(sceRegGetKeyInfo(hd, name, &hk, &type, &size))) {
if (!sceRegGetKeyValue(hd, hk, value, 4)) {
ret = 1;
sceRegFlushCategory(hd);
}
}
sceRegCloseCategory(hd);
}
sceRegFlushRegistry(h);
sceRegCloseRegistry(h);
}
return ret;
}
int ReadControls(void) {
prev_pad = pad;
kernel_pad.Buttons = pspGetButtons();
sceCtrlReadBufferPositive(&pad, 1);
if (pad.Buttons == last_button) {
if (pad.TimeStamp - deadzone_tick < CTRL_DEADZONE_DELAY)
return 0;
if (pad.TimeStamp - last_button_tick < CTRL_DELAY)
return 0;
last_button_tick = pad.TimeStamp;
return last_button;
}
last_button = pad.Buttons;
deadzone_tick = last_button_tick = pad.TimeStamp;
return last_button;
}
int IsButtonPressed(enum PspCtrlButtons buttons) {
return ((pad.Buttons & buttons) == buttons) && ((prev_pad.Buttons & buttons) != buttons);
}
int IsButtonHeld(enum PspCtrlButtons buttons) {
return pad.Buttons & buttons;
}
int IsKButtonPressed(enum PspCtrlButtons buttons) {
return ((kernel_pad.Buttons & buttons) == buttons) && ((prev_pad.Buttons & buttons) != buttons);
}
int IsKButtonHeld(enum PspCtrlButtons buttons) {
return kernel_pad.Buttons & buttons;
}
int GetEnterButton(void) {
unsigned int button = 0;
if (R_SUCCEEDED(GetRegistryValue("/CONFIG/SYSTEM/XMB", "button_assign", &button))) {
if (button == 0)
return 0x002000; // PSP_CTRL_CIRCLE
else
return 0x004000; // PSP_CTRL_CROSS
}
return 0x004000; // By default return PSP_CTRL_CROSS
}
// Basically the opposite of GetEnterButton()
int GetCancelButton(void) {
unsigned int button = 0;
if (R_SUCCEEDED(GetRegistryValue("/CONFIG/SYSTEM/XMB", "button_assign", &button))) {
if (button == 0)
return 0x004000; // PSP_CTRL_CROSS
else
return 0x002000; // PSP_CTRL_CIRCLE
}
return 0x002000; // By default return PSP_CTRL_CIRCLE
}
float GetAnalogX(void) {
return ((static_cast<float>(pad.Lx - 122.5f)) / 122.5f);
}
float GetAnalogY(void) {
return ((static_cast<float>(pad.Ly - 122.5f)) / 122.5f);
}
bool IsCancelButtonPressed(void) {
Utils::ReadControls();
if (Utils::IsButtonPressed(PSP_CTRL_CANCEL))
return true;
return false;
}
}

26
audio_driver/Makefile Normal file
View File

@ -0,0 +1,26 @@
TARGET = audio_driver
OBJS = audio_driver.o exports.o
PRX_EXPORTS = exports.exp
# Use the kernel's small inbuilt libc
USE_KERNEL_LIBC = 1
# Use only kernel libraries
USE_KERNEL_LIBS = 1
INCDIR =
CFLAGS = -Os -G0 -Wall -fno-builtin-printf
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
ASFLAGS = $(CFLAGS)
LIBDIR =
LDFLAGS = -nostartfiles
LIBS = -lpspaudio_driver
PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build_prx.mak
all:
psp-build-exports -s $(PRX_EXPORTS)
mv audio_driver.S "../app/drivers/"

View File

@ -0,0 +1,20 @@
#include <pspsdk.h>
#include <pspaudio_kernel.h>
PSP_MODULE_INFO("audio_driver", PSP_MODULE_KERNEL, 1, 3);
PSP_NO_CREATE_MAIN_THREAD();
int pspAudioSetFrequency(int frequency) {
u32 k1 = pspSdkSetK1(0);
int ret = sceAudioSetFrequency(frequency);
pspSdkSetK1(k1);
return ret;
}
int module_start(SceSize args, void *argp) {
return 0;
}
int module_stop(void) {
return 0;
}

16
audio_driver/exports.exp Normal file
View File

@ -0,0 +1,16 @@
# Define the exports for the prx
PSP_BEGIN_EXPORTS
# These four lines are mandatory (although you can add other functions like module_stop)
# syslib is a psynonym for the single mandatory export.
PSP_EXPORT_START(syslib, 0, 0x8000)
PSP_EXPORT_FUNC(module_start)
PSP_EXPORT_FUNC(module_stop)
PSP_EXPORT_VAR(module_info)
PSP_EXPORT_END
PSP_EXPORT_START(audio_driver, 0, 0x4001)
PSP_EXPORT_FUNC(pspAudioSetFrequency)
PSP_EXPORT_END
PSP_END_EXPORTS

26
display_driver/Makefile Normal file
View File

@ -0,0 +1,26 @@
TARGET = display_driver
OBJS = display_driver.o exports.o sceDisplay_driver.o
PRX_EXPORTS = exports.exp
# Use the kernel's small inbuilt libc
USE_KERNEL_LIBC = 1
# Use only kernel libraries
USE_KERNEL_LIBS = 1
INCDIR =
CFLAGS = -Os -G0 -Wall -fno-builtin-printf
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
ASFLAGS = $(CFLAGS)
LIBDIR =
LDFLAGS = -nostartfiles
LIBS =
PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build_prx.mak
all:
psp-build-exports -s $(PRX_EXPORTS)
mv display_driver.S "../app/drivers/"

View File

@ -0,0 +1,59 @@
#include <pspsdk.h>
#include <pspdisplay_kernel.h>
#include <pspsysmem_kernel.h>
PSP_MODULE_INFO("display_driver", PSP_MODULE_KERNEL, 1, 3);
PSP_NO_CREATE_MAIN_THREAD();
int sceDisplayEnable(void);
int sceDisplayDisable(void);
int sceDisplayEnable371(void);
int sceDisplayDisable371(void);
int pspGetBrightness(int *brightness) {
u32 k1 = pspSdkSetK1(0);
sceDisplayGetBrightness(brightness, 0);
pspSdkSetK1(k1);
return 0;
}
int pspSetBrightness(int brightness) {
u32 k1 = pspSdkSetK1(0);
sceDisplaySetBrightness(brightness, 0);
pspSdkSetK1(k1);
return 0;
}
int pspDisplayEnable(void) {
u32 k1 = pspSdkSetK1(0);
int ret = 0;
if (sceKernelDevkitVersion() < 0x03070110)
ret = sceDisplayEnable();
else
ret = sceDisplayEnable371();
pspSdkSetK1(k1);
return ret;
}
int pspDisplayDisable(void) {
u32 k1 = pspSdkSetK1(0);
int ret = 0;
if (sceKernelDevkitVersion() < 0x03070110)
ret = sceDisplayDisable();
else
ret = sceDisplayDisable371();
pspSdkSetK1(k1);
return ret;
}
int module_start(SceSize args, void *argp) {
return 0;
}
int module_stop(void) {
return 0;
}

View File

@ -0,0 +1,19 @@
# Define the exports for the prx
PSP_BEGIN_EXPORTS
# These four lines are mandatory (although you can add other functions like module_stop)
# syslib is a psynonym for the single mandatory export.
PSP_EXPORT_START(syslib, 0, 0x8000)
PSP_EXPORT_FUNC(module_start)
PSP_EXPORT_FUNC(module_stop)
PSP_EXPORT_VAR(module_info)
PSP_EXPORT_END
PSP_EXPORT_START(display_driver, 0, 0x4001)
PSP_EXPORT_FUNC(pspGetBrightness)
PSP_EXPORT_FUNC(pspSetBrightness)
PSP_EXPORT_FUNC(pspDisplayEnable)
PSP_EXPORT_FUNC(pspDisplayDisable)
PSP_EXPORT_END
PSP_END_EXPORTS

Some files were not shown because too many files have changed in this diff Show More