From 24bb3723534b6e6b1daea31e488e8b3d30819d1b Mon Sep 17 00:00:00 2001 From: GrapheneCt <57592952+GrapheneCt@users.noreply.github.com> Date: Wed, 11 Nov 2020 03:33:12 +0200 Subject: [PATCH] Update to v3.80: AT3 and AT3P support - AT3 and AT3P support - Fully switch to SceLibc - Fixed FLAC seeking issues --- CMakeLists.txt | 47 ++-- include/audio/at3.h | 15 + include/audio/vitaaudiolib.h | 1 + include/fios2_common.h | 10 + include/psp2_compat.h | 6 + include/utils.h | 2 + libs/include/dr_flac.h | 2 +- libs/lib/VarHelper.suprx | Bin 0 -> 10593 bytes libs/lib/libVarHelper_stub.a | Bin 0 -> 7624 bytes source/audio/at3.c | 470 ++++++++++++++++++++++++++++++++ source/audio/audio.c | 18 +- source/audio/flac.c | 22 +- source/audio/id3.c | 13 +- source/audio/mp3.c | 14 +- source/audio/ogg.c | 17 +- source/audio/vitaaudiolib.c | 9 +- source/audio/xm.c | 4 +- source/config.c | 32 ++- source/dirbrowse.c | 43 +-- source/fios2_common.c | 44 +++ source/main.c | 19 +- source/menus/menu_audioplayer.c | 35 +-- source/menus/menu_settings.c | 9 +- source/psp2_compat.c | 42 +++ source/touch.c | 4 +- source/utils.c | 6 +- 26 files changed, 750 insertions(+), 134 deletions(-) create mode 100644 include/audio/at3.h create mode 100644 include/fios2_common.h create mode 100644 include/psp2_compat.h create mode 100644 libs/lib/VarHelper.suprx create mode 100644 libs/lib/libVarHelper_stub.a create mode 100644 source/audio/at3.c create mode 100644 source/fios2_common.c create mode 100644 source/psp2_compat.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 71f1695..38f38fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,23 +10,12 @@ endif() include("$ENV{DOLCESDK}/share/dolce.cmake" REQUIRED) -add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/boot_param.bin - COMMAND dolce-make-bootparam app_memsize 0x4000 attribute 0x08 ${CMAKE_CURRENT_BINARY_DIR}/boot_param.bin -) - project(ElevenMPV) -dolce_gen_libs(SceLibc_stubs - SceLibc.yml - LIB SceLibc_stub_weak) -dolce_gen_libs(SceShellSvc_stubs - SceShellSvc.yml - LIB SceShellSvc_stub_weak) set(VITA_APP_NAME "Eleven Music Player") set(VITA_TITLEID "GRVA00008") set(VITA_VERSION "03.80") -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Os -Wl,--no-wchar-size-warning,--no-enum-size-warning -Wall") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Os -Wl,--no-wchar-size-warning,--no-enum-size-warning -nostdlib") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") include_directories( @@ -61,10 +50,13 @@ add_executable(${PROJECT_NAME} source/audio/xm.c source/audio/aac.c source/audio/at9.c + source/audio/at3.c source/audio/id3.c source/menus/menu_audioplayer.c source/menus/menu_displayfiles.c source/menus/menu_settings.c + source/psp2_compat.c + source/fios2_common.c ) target_link_libraries(${PROJECT_NAME} @@ -75,36 +67,58 @@ target_link_libraries(${PROJECT_NAME} vorbis ogg xmp-lite - png + png16v2ds z ShellAudio + SceLibKernel_stub + SceSysmem_stub + SceKernelThreadMgr_stub + SceKernelModuleMgr_stub + SceProcessMgr_stub + SceIofilemgr_stub + SceLibRng_stub taihen_stub SceAppMgr_stub + SceSharedFb_stub SceAppUtil_stub SceAudio_stub SceCtrl_stub + SceDisplayUser_stub SceDisplay_stub + SceNotificationUtilProgress_stub SceGxm_stub + SceGxmInternalForVsh_stub + SceGxmInternal_stub ScePower_stub SceShellSvc_stub SceSysmodule_stub SceTouch_stub - SceShellSvc_stub_weak + SceShellUtil_stub SceSystemGesture_stub SceIme_stub SceMotion_stub SceVshBridge_stub - SceLibc_stub_weak SceNotificationUtil_stub SceJpegArm_stub ScePvf_stub SceDbg_stub SceFios2_stub SceKernelDmacMgr_stub + SceLibm_stub + SceLibc_stub + SceRtabi_stub + SceAudiocodec_stub + VarHelper_stub + gcc ) set(DOLCE_MKSFOEX_FLAGS "${DOLCE_MKSFOEX_FLAGS} -d ATTRIBUTE=17338760 -s CATEGORY=gdc") -set(DOLCE_ELF_CREATE_FLAGS "${DOLCE_ELF_CREATE_FLAGS} -h 544288") +set(DOLCE_ELF_CREATE_FLAGS "${DOLCE_ELF_CREATE_FLAGS} -h 2097152") + +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/boot_param.bin + COMMAND dolce-make-bootparam app_memsize 0x4000 attribute 0x10 ${CMAKE_CURRENT_BINARY_DIR}/boot_param.bin +) dolce_create_self(eboot.bin ${PROJECT_NAME} UNSAFE BOOT_PARAM ${CMAKE_CURRENT_BINARY_DIR}/boot_param.bin) @@ -134,4 +148,5 @@ dolce_create_vpk(${PROJECT_NAME}.vpk ${VITA_TITLEID} eboot.bin FILE ${CMAKE_CURRENT_BINARY_DIR}/exit_module.skprx module/kernel/exit_module.skprx FILE res/tex_common.gxt tex_common.gxt FILE res/tex_dirbrowse.gxt tex_dirbrowse.gxt + FILE libs/lib/VarHelper.suprx module/user/VarHelper.suprx ) diff --git a/include/audio/at3.h b/include/audio/at3.h new file mode 100644 index 0000000..aeeff7c --- /dev/null +++ b/include/audio/at3.h @@ -0,0 +1,15 @@ +#ifndef _ELEVENMPV_AUDIO_AT3_H_ +#define _ELEVENMPV_AUDIO_AT3_H_ + +#include + +int AT3_Init(const char *path); +SceUInt32 AT3_GetSampleRate(void); +SceUInt8 AT3_GetChannels(void); +void AT3_Decode(void *buf, unsigned int length, void *userdata); +SceUInt64 AT3_GetPosition(void); +SceUInt64 AT3_GetLength(void); +SceUInt64 AT3_Seek(SceUInt64 index); +void AT3_Term(void); + +#endif diff --git a/include/audio/vitaaudiolib.h b/include/audio/vitaaudiolib.h index 5bdc3e0..81cac2f 100644 --- a/include/audio/vitaaudiolib.h +++ b/include/audio/vitaaudiolib.h @@ -25,6 +25,7 @@ void vitaAudioSetChannelCallback(vitaAudioCallback_t callback, void *userdata); int vitaAudioInit(int frequency, SceAudioOutMode mode); void vitaAudioEndPre(void); void vitaAudioEnd(void); +void vitaAudioPreSetGrain(int grain); #ifdef __cplusplus } diff --git a/include/fios2_common.h b/include/fios2_common.h new file mode 100644 index 0000000..416313f --- /dev/null +++ b/include/fios2_common.h @@ -0,0 +1,10 @@ +#ifndef _ELEVENMPV_FIOS2_H_ +#define _ELEVENMPV_FIOS2_H_ + +#include +#include + +int fios2Init(void); +int fios2CommonOpDeleteCB(void *pContext, SceFiosOp op, SceFiosOpEvent event, int err); + +#endif \ No newline at end of file diff --git a/include/psp2_compat.h b/include/psp2_compat.h new file mode 100644 index 0000000..2e9c1be --- /dev/null +++ b/include/psp2_compat.h @@ -0,0 +1,6 @@ +#ifndef _ELEVENMPV_PSP2_COMPAT_H_ +#define _ELEVENMPV_PSP2_COMPAT_H_ + +void psp2CompatInit(void); + +#endif \ No newline at end of file diff --git a/include/utils.h b/include/utils.h index 036c3f5..06a53ab 100644 --- a/include/utils.h +++ b/include/utils.h @@ -5,6 +5,8 @@ #include #include +#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1)) + #define JPEGDEC_SIZE_LIMIT 262144 //500x500 #define SCE_KERNEL_ATTR_MULTI (0x00001000U) diff --git a/libs/include/dr_flac.h b/libs/include/dr_flac.h index 0d34426..2b86800 100644 --- a/libs/include/dr_flac.h +++ b/libs/include/dr_flac.h @@ -242,7 +242,7 @@ typedef drflac_uint32 drflac_bool32; #define DRFLAC_FALSE 0 #define DRFLAC_DEPRECATED -#define DR_FLAC_NO_STDIO +//#define DR_FLAC_NO_STDIO int module_stop(SceSize argc, const void *args) { sceClibPrintf("ShellAudio module stop\n"); diff --git a/libs/lib/VarHelper.suprx b/libs/lib/VarHelper.suprx new file mode 100644 index 0000000000000000000000000000000000000000..66b03d329929f7310014281244612cc1d73cb2b8 GIT binary patch literal 10593 zcmeHN4Qx}_6+X{#NJ0a0!p{g8FpyPQ6&$MtE$!%JCxkzRl0ilT4a>6~Q#-$I{6al# z9X6r`O-v1CnqZ?^q!3MlVM9fU&oI#YIRoX= z4?7H_8**G!i-F+`jDObfi?A|oRj_H(Q+O4JyO-qQ2I*W4#rqVT9`=oc6c9y1r2E{BmUGW_y$$>iO3gO}sZ+_O>OQGi8y&NXad}0PB zW?*6lCT3t_1}0`;Vg@E=U}6S7)fxCCzpwS*D8>(!I1lds?l-k*M#IP4L-mm}Lo}^u zw-P%LjfW2e%UxBl|b#k zJRLY4I1@M%I14xnIJ;`v)#oe;VE<)%)uRg%IQCzjSJgipQxm{fhj+RXu)BdTTql?E zaBTQFSc=PX)nbVa?{d*q3tjCCpWri9@0l}gyeH1oJyaLQwQHkbc%^%&+H5}se?hLw z{uO zul${2*>=lfOS06il+NlCJ=iGq%R!9K7)P+wUN<_bAf;X!EVUcsq5+5f#9%6J!&OZd z=vvmL$hz<->sq0hog7s>IH;7`(3Yw-V>C7WOce(!+D_${s zaT)K|rSFRHrGV1+F2^J8B2fBHBAI<}0Nrdu?=9i`wP?R9+82Q`@6W>bfyp<34~(_m z2mb5Y$o8I|AIJVQY~bnZ1|GV>*c1Daz@G?wMc`2#kHnt&C&wL*{Yv0R0!IYq-5lAD z)1ccS=gkMtxK!X;9eZLm0_y~-0)qm>0;53IFQCWyuN<20@6cQgt?iASErEteoBxrl z$EjdWOUReL2pS?eX(Ru-;U(TzF67vK%`k~50`}_;RnmY9qmm4 zzZNM=uMlN58#abCZ^QaPOTZfmj1taBXSgFuz#U|eDM}eFs>e%v+*(AiRoHw#v)u@r?_;*H z{t@55Y-7#U?^|i}JHswvX*{!>(X^4d=PkrRKcd%tIG6eOuTZ`+bvr(G>F+lm8zk+kqshQz~rM zDL2_`Om;n!=ojB9q_0Vq#Ad>udWwafAes$yKS41@+Cnsk+gk{Kx+#{#SEyUZ1`6Am zSIIS((ML)4;}Yy*zuQkW>~~}7=XN4M4n2M=4e0z<>Sl~>B~{OFqCNLOZ*-$t%Q%txq) z^%4AD)ZbY7z{V@#tS#)L-rlM?xz6rK-scT$2e)=6FLPjphZKJIOl($8}nxlMm+ zI<-JlBWFjT#VgE+Kd@F`8&|h&ZFhFGH+nU%2)I23FTO9Gfi|gQb_kmn)KL)*H$0%L zqT%)q?Us%*+z4FVIwlaF6_2f6o=!x2V@7+$26USa(9e;x#&|hxj6;Tv^&)J2U~A+S zu`y21`nAqLG}IUsr)p{&rsm~Y5L0TJSi|&1BIHCz+ps8x@buxtg4g(DLu&vloDsn) zUQO!=`8u@#2L~fs2aA5(q9Bl~{_u(CBX00s0a^HVe=S;Q#n*I1zft#%eja)UWfD-vwHiKEQoYct6AhjV8Mhs_)Z^!E4WuTMOmTY+pDHOE_CWCW z9v9y3AoUKzmU{gBJqSGqe6q;6<8a70es0dq#dC}d0?N3zOmY1DZbzKh;-E*%xQnJZ zeg-ceM-R`@TvYvtLloyxA{sE${qhzRIX?c)P(4n+g&btk>xM|V?!xy1P>!#}q{q+6 zLFnD?b1To#JI{j>g|AJix7N_px7pygRNRUW;S6{qeKfA_4thM_QZH!e>DMX$emHB| z!@}K5-N(BnNe zl7lO4?-l*Bj|<1iy)4`|x+8iqBaZjvggHPI{_ME?6mjS?O(hWbv_a`dsdv(dOEY{P zXCw)4+Dsd=hjfZzq6yqZA;)hO8@HV%6u@6dzYVJW_BCoJ zI>E$Wz|si`iGiVi0s{jbIy15|z{Up8vCpy77&}zpAwJ2uckiCxS@-hGJHL!g^KyA( zCLE1eTRas@#@WPVaw-yuHKxp;kw_ww(r+k+0bl?iSOMre00{jA7@P(e+5_)6Xax}EU@#6R819#ELNYg)taQ_>R=e){DN32b7ity6OOADQW0di ztzN9QRZH8%qAxt(6p4@*2&XipBu9j;8dnizp-d!s*TJ|h$ciXgm(pAo>|H{%b(5`I zer&|Dtg*){bnm#Ps4O_sG}mRh;Anz9d2b!Gzx1l1zl1o7oKXh5NGufzYYzfjj0EG-p=L zk6-2`f|e)3UjjH~p2l&oW!wY97EKSF$MI=H*JDVk5QJVBF=>VY=kvKmZZ(&^$K}?R z9xOjBz<345d2qu70Hf?~5x#^yk+pt)o)&1<#&9vAx@1c7=rrXiov$MN~c52j}>~84(=(@8w z9>R+@D(6vwzG_szgo3&TZS?un-W=&29Pi`Rk5>pUHHxZFRi@8|B8=dTw^TuI)ZZB# zo9!Oq#40typ4vrIR-hbtN;h+r6HoivB91(*f0-|J15fSqgx3TC_zVF=+py8fP~MKA zc#J~P$TVIsbm4Vzyek>f&#xY*A)g^+Bj$pkIa`J%liE2=`!pD8d1o@tb^jm_9TkTU zyOkk)*Yg@7pCM%9WO*o)@tUEr(a+zyl_9k-;x$D6S?+{+D8aTr%h}~2Q|->_edqxB z#^(4w^p=&*bsIxY)hDmP^0@-Yxj5fFwmaWp1-zr&lu793&UL#FF1dR7Zmr+viq_k` z&QyNgL9N}*xL|6 +#include +#include +#include +#include +#include +#include + +#include "audio.h" +#include "config.h" +#include "touch.h" +#include "id3.h" +#include "utils.h" +#include "vitaaudiolib.h" +#include "menu_audioplayer.h" + +static SceAudiocodecCtrl codecCtrl; +static void* streamBuffer[2]; +static SceUInt32 codecType; +static SceUInt32 bufindex = 0; +static SceUInt32 callCount = 0; + +static SceUID file_fd; +static SceUID opHandle; +static SceUID adecWorkMem; + +static SceIoAsyncParam asyncParam; + +static SceUInt64 totalEsSamples = 0; +static SceUInt64 totalEsPlayed = 0; + +static SceSize dataBeginOffset = 0; +static SceSize readOffset = 0; +static SceSize current_offset; + +#define EA3_HEADER_SIZE 96 +#define GROUP_SIZE 64 +#define AT3P_ES_GRAIN 2048 +#define AT3_ES_GRAIN 1024 + +typedef enum At3Types { + OMA_CODECID_ATRAC3 = 0, + OMA_CODECID_ATRAC3P = 1, +} At3Types; + +SceInt32 sceAudiocodecGetAt3ConfigPSP2(SceUInt32 cmode, SceUInt32 nbytes) +{ + if ((cmode == 0) && (nbytes == 0xc0)) { + return 4; + } + if ((cmode == 0) && (nbytes == 0x98)) { + return 6; + } + if ((cmode == 1) && (nbytes == 0x60)) { + return 0xb; + } + if ((cmode == 2) && (nbytes == 0xc0)) { + return 0xe; + } + if ((cmode == 2) && (nbytes == 0x98)) { + return 0xf; + } + return -1; +} + +static int AT3_Init_common(const char *path, SceUInt8 type, SceUInt8 param1, SceUInt8 param2, SceSize dataOffset) { + + int ret; + + //Initialize SceAudiocodec + sceClibMemset(&asyncParam, 0, sizeof(SceIoAsyncParam)); + sceClibMemset(&codecCtrl, 0, sizeof(SceAudiocodecCtrl)); + switch (type) { + case OMA_CODECID_ATRAC3P: + codecType = SCE_AUDIOCODEC_ATX; + codecCtrl.atx.codecParam1 = param1; + codecCtrl.atx.codecParam2 = param2; + break; + case OMA_CODECID_ATRAC3: + codecType = SCE_AUDIOCODEC_AT3; + codecCtrl.at3.codecParam = sceAudiocodecGetAt3ConfigPSP2(param1, param2); + break; + } + + ret = sceAudiocodecQueryMemSize(&codecCtrl, codecType); + if (-1 < ret) { + + SceSize memsize = 0x8000; + if (codecCtrl.neededWorkMem > memsize) + memsize = 0x10000; + adecWorkMem = sceKernelAllocMemBlock("ElevenMPV_adec-work", SCE_KERNEL_MEMBLOCK_TYPE_USER_RW, memsize, NULL); + sceKernelGetMemBlockBase(adecWorkMem, &codecCtrl.pWorkMem); + + if (codecType == SCE_AUDIOCODEC_ATX) + codecCtrl.unk_atx_0C = 1; + + ret = sceAudiocodecInit(&codecCtrl, codecType); + if ((ret < 0) && (codecCtrl.pWorkMem != NULL)) { + free(codecCtrl.pWorkMem); + codecCtrl.pWorkMem = NULL; + return -1; + } + else if (ret < 0) { + return -1; + } + } + else { + return -1; + } + + //Allocate stream buffer, read first es streams to buffer, set output grain + file_fd = sceIoOpen(path, SCE_O_RDONLY, 0); + SceIoStat stat; + sceIoGetstatByFd(file_fd, &stat); + SceSize atDataSize; + + switch (type) { + case OMA_CODECID_ATRAC3P: + streamBuffer[0] = malloc(codecCtrl.atx.inputEsSize * GROUP_SIZE); + streamBuffer[1] = malloc(codecCtrl.atx.inputEsSize * GROUP_SIZE); + current_offset += sceIoPread(file_fd, streamBuffer[0], codecCtrl.atx.inputEsSize * GROUP_SIZE, (SceOff)dataOffset); + //Calculate total samples + atDataSize = (SceSize)stat.st_size - dataOffset; + totalEsSamples = atDataSize / codecCtrl.atx.inputEsSize; + vitaAudioPreSetGrain(AT3P_ES_GRAIN); + break; + case OMA_CODECID_ATRAC3: + switch (codecCtrl.at3.codecParam) { + case 4: + codecCtrl.inputEsSize = 384; + break; + case 6: + codecCtrl.inputEsSize = 304; + break; + case 0xB: + codecCtrl.inputEsSize = 192; + break; + case 0xE: + return -1; //unsupported + break; + case 0xF: + return -1; //unsupported + break; + } + streamBuffer[0] = malloc(codecCtrl.inputEsSize * GROUP_SIZE); + streamBuffer[1] = malloc(codecCtrl.inputEsSize * GROUP_SIZE); + current_offset += sceIoPread(file_fd, streamBuffer[0], codecCtrl.inputEsSize * GROUP_SIZE, (SceOff)dataOffset); + //Calculate total samples + atDataSize = (SceSize)stat.st_size - dataOffset; + totalEsSamples = atDataSize / codecCtrl.inputEsSize; + vitaAudioPreSetGrain(AT3_ES_GRAIN); + break; + } + + current_offset += dataOffset; + dataBeginOffset = dataOffset; + bufindex = 0; + + return 0; +} + +static int AT3_Init_OMA(const char *path) { + + SceUID fd; + + ID3Tag *ID3 = malloc(sizeof(ID3Tag)); + ParseID3(path, ID3); + + char* meta_ptr = (char *)ID3; + + for (int i = 0; i < 792; i++) { + if (meta_ptr[i] != '\0') { + metadata.has_meta = SCE_TRUE; + break; + } + } + + if (metadata.has_meta) { + sceClibStrncpy(metadata.title, ID3->ID3Title, 260); + sceClibStrncpy(metadata.artist, ID3->ID3Artist, 260); + sceClibStrncpy(metadata.album, ID3->ID3Album, 64); + sceClibStrncpy(metadata.year, ID3->ID3Year, 5); + sceClibStrncpy(metadata.genre, ID3->ID3GenreText, 64); + } + + if (ID3->ID3EncapsulatedPictureType == JPEG_IMAGE) { + Menu_UnloadExternalCover(); + fd = sceIoOpen(path, SCE_O_RDONLY, 0); + if (fd >= 0) { + char *buffer = malloc(ID3->ID3EncapsulatedPictureLength); + if (buffer) { + sceIoLseek32(fd, ID3->ID3EncapsulatedPictureOffset, SCE_SEEK_SET); + sceIoRead(fd, buffer, ID3->ID3EncapsulatedPictureLength); + sceIoClose(fd); + + vita2d_JPEG_ARM_decoder_initialize(); + metadata.cover_image = vita2d_load_JPEG_ARM_buffer(buffer, ID3->ID3EncapsulatedPictureLength, 0, 0, 0); + vita2d_JPEG_ARM_decoder_finish(); + + free(buffer); + } + } + } + else if (ID3->ID3EncapsulatedPictureType == PNG_IMAGE) { + Menu_UnloadExternalCover(); + fd = sceIoOpen(path, SCE_O_RDONLY, 0); + if (fd >= 0) { + char *buffer = malloc(ID3->ID3EncapsulatedPictureLength); + if (buffer) { + sceIoLseek32(fd, ID3->ID3EncapsulatedPictureOffset, SCE_SEEK_SET); + sceIoRead(fd, buffer, ID3->ID3EncapsulatedPictureLength); + sceIoClose(fd); + + metadata.cover_image = vita2d_load_PNG_buffer(buffer); + + free(buffer); + } + } + } + + SceSize offset = ID3v2TagSize(path); + + free(ID3); + + //Locate EA3 header + int index = 0; + char* ea3Header_init = malloc(1024); + char* ea3Header = ea3Header_init; + sceClibMemset(ea3Header, 0, 1024); + + fd = sceIoOpen(path, SCE_O_RDONLY, 0); + sceIoPread(fd, ea3Header, 1024, (SceOff)offset); + sceIoClose(fd); + + while (*ea3Header == '\0' && index < 1024) { + index++; + ea3Header++; + } + + if (sceClibMemcmp(ea3Header, "EA3", 3)) + return -1; + + SceUInt8 codecType = ea3Header[32]; + SceUInt8 param1; + SceUInt8 param2; + + if (codecType == OMA_CODECID_ATRAC3P) { + param1 = ea3Header[34]; + param2 = ea3Header[35]; + } + else if (codecType == OMA_CODECID_ATRAC3) { + //Everything here is hardcoded: no ATRAC3 header documentation anywhere + param1 = ea3Header[33]; + if (param1 == 2) + param1 = 1; + + param2 = ea3Header[35]; + switch (param2) { + case 0x18: + param2 = 0x60; + break; + case 0x26: + param2 = 0x98; + break; + case 0x30: + param2 = 0xC0; + break; + default: + return -1; + break; + } + } + else + return -1; + + free(ea3Header_init); + return AT3_Init_common(path, codecType, param1, param2, offset + index + EA3_HEADER_SIZE); +} + +static int AT3_Init_RIFF(const char *path) { + + //Locate AT3 info header + SceSize index = 0; + char* ea3Header = malloc(1024); + char* dataStart = ea3Header; + sceClibMemset(ea3Header, 0, 1024); + + SceUID fd = sceIoOpen(path, SCE_O_RDONLY, 0); + sceIoRead(fd, ea3Header, 1024); + sceIoClose(fd); + + //"data" + while (*(int *)dataStart != 0x61746164 && index < 1024) { + index++; + dataStart++; + } + index += 8; + + SceUInt8 codecType = ea3Header[60]; + SceUInt8 param1; + SceUInt8 param2; + + if (codecType == OMA_CODECID_ATRAC3P) { + param1 = ea3Header[62]; + param2 = ea3Header[63]; + } + else if (codecType == OMA_CODECID_ATRAC3) { + //Everything here is hardcoded: no ATRAC3 header documentation anywhere + param1 = ea3Header[61]; + if (param1 == 2) + param1 = 1; + + param2 = ea3Header[63]; + switch (param2) { + case 0x18: + param2 = 0x60; + break; + case 0x26: + param2 = 0x98; + break; + case 0x30: + param2 = 0xC0; + break; + default: + return -1; + break; + } + } + else + return -1; + + free(ea3Header); + return AT3_Init_common(path, codecType, param1, param2, index); +} + +int AT3_Init(const char *path) { + + //Check ATRAC3 file header type + char* ext = sceClibStrrchr(path, '.'); + if (!sceClibStrncasecmp(ext, ".oma", 4) || !sceClibStrncasecmp(ext, ".aa3", 4)) + return AT3_Init_OMA(path); + else if (!sceClibStrncasecmp(ext, ".at3", 4)) + return AT3_Init_RIFF(path); + else + return -1; +} + +SceUInt32 AT3_GetSampleRate(void) { + return 44100; +} + +SceUInt8 AT3_GetChannels(void) { + //TODO: actually check from header + return 2; +} + +void AT3_Decode(void *buf, unsigned int length, void *userdata) { + + if (callCount == GROUP_SIZE) { + bufindex ^= 1; + readOffset = 0; + callCount = 0; + } + + //Wait until we are done with previous call, issue next read call + if (callCount == 0) { + if (sceKernelWaitEvent(opHandle, 1, NULL, NULL, NULL) == 0) + sceIoComplete(opHandle); + current_offset += asyncParam.result; + sceClibMemset(&asyncParam, 0, sizeof(SceIoAsyncParam)); + bufindex ^= 1; + switch (codecType) { + case SCE_AUDIOCODEC_ATX: + opHandle = sceIoPreadAsync(file_fd, streamBuffer[bufindex], codecCtrl.atx.inputEsSize * GROUP_SIZE, (SceOff)current_offset, &asyncParam); + break; + case SCE_AUDIOCODEC_AT3: + opHandle = sceIoPreadAsync(file_fd, streamBuffer[bufindex], codecCtrl.inputEsSize * GROUP_SIZE, (SceOff)current_offset, &asyncParam); + break; + } + bufindex ^= 1; + } + + //Decode current ES samples + + codecCtrl.pEs = streamBuffer[bufindex] + readOffset; + codecCtrl.pPcm = buf; + if (sceAudiocodecDecode(&codecCtrl, codecType) < 0) {} + //playing = SCE_FALSE; + readOffset += codecCtrl.inputEsSize; + + callCount++; + totalEsPlayed++; + + if (totalEsPlayed >= totalEsSamples) + playing = SCE_FALSE; +} + +SceUInt64 AT3_GetPosition(void) { + switch (codecType) { + case SCE_AUDIOCODEC_ATX: + return totalEsPlayed * AT3P_ES_GRAIN; + break; + case SCE_AUDIOCODEC_AT3: + return totalEsPlayed * AT3_ES_GRAIN; + break; + } + + return 0; +} + +SceUInt64 AT3_GetLength(void) { + switch (codecType) { + case SCE_AUDIOCODEC_ATX: + return totalEsSamples * AT3P_ES_GRAIN; + break; + case SCE_AUDIOCODEC_AT3: + return totalEsSamples * AT3_ES_GRAIN; + break; + } + + return 0; +} + +SceUInt64 AT3_Seek(SceUInt64 index) { + + SceSize esGrain = AT3P_ES_GRAIN; + if (codecType == SCE_AUDIOCODEC_AT3) + esGrain = AT3_ES_GRAIN; + + SceUInt64 seekSamples = ((totalEsSamples * esGrain) * (index / SEEK_WIDTH_FLOAT)); + SceUInt32 seekEsNum = (SceUInt32)floorf(seekSamples / esGrain); + seekSamples = (SceUInt64)(seekEsNum * esGrain); + + totalEsPlayed = seekEsNum; + bufindex = 0; + readOffset = 0; + callCount = 0; + sceClibMemset(&asyncParam, 0, sizeof(SceIoAsyncParam)); + + SceSize newOffset = dataBeginOffset + (seekEsNum * codecCtrl.inputEsSize); + current_offset = newOffset; + current_offset += sceIoPread(file_fd, streamBuffer[0], codecCtrl.inputEsSize * GROUP_SIZE, (SceOff)(newOffset)); + + return seekSamples; +} + +void AT3_Term(void) { + + if (sceKernelWaitEvent(opHandle, 1, NULL, NULL, NULL) == 0) + sceIoComplete(opHandle); + + bufindex = 0; + callCount = 0; + readOffset = 0; + current_offset = 0; + totalEsSamples = 0; + totalEsPlayed = 0; + dataBeginOffset = 0; + sceKernelFreeMemBlock(adecWorkMem); + free(streamBuffer[0]); + free(streamBuffer[1]); + sceClibMemset(&codecCtrl, 0, sizeof(SceAudiocodecCtrl)); + sceClibMemset(&asyncParam, 0, sizeof(SceIoAsyncParam)); + + if (metadata.has_meta) + metadata.has_meta = SCE_FALSE; + + vitaAudioPreSetGrain(VITA_NUM_AUDIO_SAMPLES); + sceIoClose(file_fd); +} diff --git a/source/audio/audio.c b/source/audio/audio.c index 8fb3ed5..adf39b5 100644 --- a/source/audio/audio.c +++ b/source/audio/audio.c @@ -16,6 +16,7 @@ #include "xm.h" #include "at9.h" #include "aac.h" +#include "at3.h" enum Audio_FileType { FILE_TYPE_NONE, @@ -26,7 +27,8 @@ enum Audio_FileType { FILE_TYPE_WAV, FILE_TYPE_XM, FILE_TYPE_ATRAC9, - FILE_TYPE_AAC + FILE_TYPE_AAC, + FILE_TYPE_AT3 }; typedef struct { @@ -84,6 +86,8 @@ int Audio_Init(const char *path) { file_type = FILE_TYPE_ATRAC9; else if ((!sceClibStrncasecmp(FS_GetFileExt(path), "m4a", 3)) || (!sceClibStrncasecmp(FS_GetFileExt(path), "aac", 3))) file_type = FILE_TYPE_AAC; + else if ((!sceClibStrncasecmp(FS_GetFileExt(path), "oma", 3)) || (!sceClibStrncasecmp(FS_GetFileExt(path), "aa3", 3)) || (!sceClibStrncasecmp(FS_GetFileExt(path), "at3", 3))) + file_type = FILE_TYPE_AT3; switch(file_type) { case FILE_TYPE_FLAC: @@ -182,6 +186,18 @@ int Audio_Init(const char *path) { sceKernelClearEventFlag(event_flag_uid, ~FLAG_ELEVENMPVA_IS_DECODER_USED); break; + case FILE_TYPE_AT3: + decoder.init = AT3_Init; + decoder.rate = AT3_GetSampleRate; + decoder.channels = AT3_GetChannels; + decoder.decode = AT3_Decode; + decoder.position = AT3_GetPosition; + decoder.length = AT3_GetLength; + decoder.seek = AT3_Seek; + decoder.term = AT3_Term; + sceKernelSetEventFlag(event_flag_uid, FLAG_ELEVENMPVA_IS_DECODER_USED); + break; + default: break; } diff --git a/source/audio/flac.c b/source/audio/flac.c index a20ee0b..710243e 100644 --- a/source/audio/flac.c +++ b/source/audio/flac.c @@ -1,6 +1,6 @@ #include -#include -#include +#include +#include #include "audio.h" #include "config.h" @@ -10,7 +10,6 @@ static drflac *flac; static drflac_uint64 frames_read = 0; -static SceUID flac_fd = 0; void metadata_cb(void* pUserData, drflac_metadata* pMetadata) { @@ -70,22 +69,10 @@ void metadata_cb(void* pUserData, drflac_metadata* pMetadata) { } } -size_t dr_flac_read(void* pUserData, void* pBufferOut, size_t bytesToRead) { - return sceIoRead(flac_fd, pBufferOut, bytesToRead); -} - -drflac_bool32 dr_flac_seek(void* pUserData, int offset, drflac_seek_origin origin) { - if (sceIoLseek32(flac_fd, offset, origin) < 0) - return DRFLAC_FALSE; - else - return DRFLAC_TRUE; -} - int FLAC_Init(const char *path) { - flac_fd = sceIoOpen(path, SCE_O_RDONLY, 0777); - - flac = drflac_open_with_metadata(dr_flac_read, dr_flac_seek, metadata_cb, NULL, NULL); + //SceLibc is the fastest sync IO available on Vita, so we just use stdio here + flac = drflac_open_file_with_metadata(path, metadata_cb, NULL, NULL); if (flac == NULL) return -1; @@ -132,6 +119,5 @@ void FLAC_Term(void) { if (metadata.has_meta) metadata.has_meta = SCE_FALSE; - sceIoClose(flac_fd); drflac_close(flac); } diff --git a/source/audio/id3.c b/source/audio/id3.c index 654f345..63e17e8 100644 --- a/source/audio/id3.c +++ b/source/audio/id3.c @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -39,7 +38,7 @@ int searchJPGstart(int fp, int delta){ int retValue = -1; int i = 0; - unsigned char *tBuffer = sceLibcMalloc(sizeof(unsigned char) * (delta + 2)); + unsigned char *tBuffer = malloc(sizeof(unsigned char) * (delta + 2)); if (tBuffer == NULL) return -1; @@ -54,7 +53,7 @@ int searchJPGstart(int fp, int delta){ break; } } - sceLibcFree(tBuffer); + free(tBuffer); return retValue; } @@ -64,7 +63,7 @@ int searchPNGstart(int fp, int delta){ int retValue = -1; int i = 0; - unsigned char *tBuffer = sceLibcMalloc(sizeof(unsigned char) * (delta + 15)); + unsigned char *tBuffer = malloc(sizeof(unsigned char) * (delta + 15)); if (tBuffer == NULL) return -1; @@ -79,7 +78,7 @@ int searchPNGstart(int fp, int delta){ break; } } - sceLibcFree(tBuffer); + free(tBuffer); return retValue; } @@ -201,7 +200,7 @@ int ID3v2TagSize(const char *mp3path) if (fp < 0) return 0; sceIoRead(fp, sig, sizeof(sig)); - if (sceClibStrncmp("ID3",sig,3) != 0) { + if (sceClibStrncmp("ID3",sig,3) != 0 && sceClibStrncmp("ea3", sig, 3) != 0) { //ATRAC3 compat sceIoClose(fp); return 0; } @@ -230,7 +229,7 @@ int ID3v2(const char *mp3path) if (fp < 0) return 0; sceIoRead(fp, sig, sizeof(sig)); - if (!sceClibStrncmp("ID3",sig,3)) { + if (!sceClibStrncmp("ID3",sig,3) || !sceClibStrncmp("ea3", sig, 3)) { //ATRAC3 compat sceIoRead(fp, &version, sizeof(unsigned short int)); version = (unsigned short int) swapInt16BigToHost((short int)version); version /= 256; diff --git a/source/audio/mp3.c b/source/audio/mp3.c index 64e9f99..183d2b4 100644 --- a/source/audio/mp3.c +++ b/source/audio/mp3.c @@ -1,8 +1,8 @@ #include -#include #include #include #include +#include #include "audio.h" #include "config.h" @@ -36,7 +36,7 @@ int MP3_Init(char *path) { if (error < 0) return error; - ID3Tag *ID3 = sceLibcMalloc(sizeof(ID3Tag)); + ID3Tag *ID3 = malloc(sizeof(ID3Tag)); ParseID3(path, ID3); char* meta_ptr = (char *)ID3; @@ -64,7 +64,7 @@ int MP3_Init(char *path) { Menu_UnloadExternalCover(); SceUID fd = sceIoOpen(path, SCE_O_RDONLY, 0); if (fd >= 0) { - char *buffer = sceLibcMalloc(ID3->ID3EncapsulatedPictureLength); + char *buffer = malloc(ID3->ID3EncapsulatedPictureLength); if (buffer) { sceIoLseek32(fd, ID3->ID3EncapsulatedPictureOffset, SCE_SEEK_SET); sceIoRead(fd, buffer, ID3->ID3EncapsulatedPictureLength); @@ -74,7 +74,7 @@ int MP3_Init(char *path) { metadata.cover_image = vita2d_load_JPEG_ARM_buffer(buffer, ID3->ID3EncapsulatedPictureLength, 0, 0, 0); vita2d_JPEG_ARM_decoder_finish(); - sceLibcFree(buffer); + free(buffer); } } } @@ -82,7 +82,7 @@ int MP3_Init(char *path) { Menu_UnloadExternalCover(); SceUID fd = sceIoOpen(path, SCE_O_RDONLY, 0); if (fd >= 0) { - char *buffer = sceLibcMalloc(ID3->ID3EncapsulatedPictureLength); + char *buffer = malloc(ID3->ID3EncapsulatedPictureLength); if (buffer) { sceIoLseek32(fd, ID3->ID3EncapsulatedPictureOffset, SCE_SEEK_SET); sceIoRead(fd, buffer, ID3->ID3EncapsulatedPictureLength); @@ -90,12 +90,12 @@ int MP3_Init(char *path) { metadata.cover_image = vita2d_load_PNG_buffer(buffer); - sceLibcFree(buffer); + free(buffer); } } } - sceLibcFree(ID3); + free(ID3); //Wait until SceShell is ready while (pb_stats.currentState == SCE_SHELLAUDIO_STOP) { diff --git a/source/audio/ogg.c b/source/audio/ogg.c index f753ffb..31d13fe 100644 --- a/source/audio/ogg.c +++ b/source/audio/ogg.c @@ -8,28 +8,29 @@ #include "touch.h" static OggVorbis_File ogg; -static SceUID ogg_file = 0; +static FILE* ogg_file; static vorbis_info *ogg_info = NULL; static ogg_int64_t samples_read = 0, max_lenth = 0; static size_t ogg_callback_read(void *ptr, size_t size, size_t count, void *stream) { - return sceIoRead(*(SceUID *)stream, ptr, size * count); + return fread(ptr, size, count, *(FILE **)stream); } static int ogg_callback_seek(void *stream, ogg_int64_t offset, int whence) { - return sceIoLseek32(*(SceUID *)stream, (unsigned int) offset, whence); + return fseek(*(FILE **)stream, (long) offset, whence); } static int ogg_callback_close(void *stream) { - return sceIoClose(*(SceUID *)stream); + return fclose(*(FILE **)stream); } static long ogg_callback_tell(void *stream) { - return sceIoLseek32(*(SceUID *)stream, 0, SCE_SEEK_CUR); + return ftell(*(FILE **)stream); } int OGG_Init(const char *path) { - if (R_FAILED(ogg_file = sceIoOpen(path, SCE_O_RDONLY, 0777))) + ogg_file = fopen(path, "r"); + if (ogg_file == NULL) return -1; ov_callbacks ogg_callbacks; @@ -39,7 +40,7 @@ int OGG_Init(const char *path) { ogg_callbacks.tell_func = ogg_callback_tell; if (R_FAILED(ov_open_callbacks(&ogg_file, &ogg, NULL, 0, ogg_callbacks))) { - sceIoClose(ogg_file); + fclose(ogg_file); return -1; } @@ -141,5 +142,5 @@ void OGG_Term(void) { metadata.has_meta = SCE_FALSE; ov_clear(&ogg); - sceIoClose(ogg_file); + fclose(ogg_file); } diff --git a/source/audio/vitaaudiolib.c b/source/audio/vitaaudiolib.c index 366cf67..36ec68d 100644 --- a/source/audio/vitaaudiolib.c +++ b/source/audio/vitaaudiolib.c @@ -7,9 +7,10 @@ #include "config.h" static int audio_ready = 0; -static short vitaAudioSoundBuffer[2][VITA_NUM_AUDIO_SAMPLES][2]; +static short vitaAudioSoundBuffer[2][2048][2]; static VITA_audio_channelinfo vitaAudioStatus; static volatile int audio_terminate = 0; +static int grain = VITA_NUM_AUDIO_SAMPLES; extern SceUID event_flag_uid; @@ -80,7 +81,7 @@ int vitaAudioInit(int frequency, SceAudioOutMode mode) { vitaAudioStatus.callback = 0; vitaAudioStatus.userdata = 0; - if ((vitaAudioStatus.handle = sceAudioOutOpenPort(SCE_AUDIO_OUT_PORT_TYPE_BGM, VITA_NUM_AUDIO_SAMPLES, frequency, mode)) < 0) { + if ((vitaAudioStatus.handle = sceAudioOutOpenPort(SCE_AUDIO_OUT_PORT_TYPE_BGM, grain, frequency, mode)) < 0) { ret = -1; goto error; } @@ -118,6 +119,10 @@ void vitaAudioEndPre(void) { audio_terminate = 1; } +void vitaAudioPreSetGrain(int ngrain) { + grain = ngrain; +} + void vitaAudioEnd(void) { audio_ready = 0; audio_terminate = 1; diff --git a/source/audio/xm.c b/source/audio/xm.c index 14c09c6..95e528e 100644 --- a/source/audio/xm.c +++ b/source/audio/xm.c @@ -1,5 +1,5 @@ #include -#include +#include #include "audio.h" #include "xmp.h" @@ -22,7 +22,7 @@ int XM_Init(const char *path) { xmp_get_module_info(xmp, &module_info); if (module_info.mod->name[0] != '\0') { metadata.has_meta = SCE_TRUE; - sceLibcStrcpy(metadata.title, module_info.mod->name); + strcpy(metadata.title, module_info.mod->name); } return 0; diff --git a/source/config.c b/source/config.c index 09b28e7..e809d23 100644 --- a/source/config.c +++ b/source/config.c @@ -1,6 +1,8 @@ #include #include -#include +#include +#include +#include #include "common.h" #include "config.h" @@ -29,16 +31,16 @@ const char *config_file = int Config_Save(config_t config) { int ret = 0; - char *buf = sceLibcMalloc(190); + char *buf = malloc(190); int len = sceClibSnprintf(buf, 190, config_file, CONFIG_VERSION, config.sort, config.alc_mode, config.eq_mode, config.eq_volume, config.motion_mode, config.motion_timer, config.motion_degree, config.power_saving, config.power_timer, config.notify_mode, config.device); if (R_FAILED(ret = FS_WriteFile("savedata0:config.cfg", buf, len))) { - sceLibcFree(buf); + free(buf); return ret; } - sceLibcFree(buf); + free(buf); return 0; } @@ -63,18 +65,18 @@ int Config_Load(void) { SceOff size = 0; FS_GetFileSize("savedata0:config.cfg", &size); - char *buf = sceLibcMalloc(size + 1); + char *buf = malloc(size + 1); if (R_FAILED(ret = FS_ReadFile("savedata0:config.cfg", buf, size))) { - sceLibcFree(buf); + free(buf); return ret; } buf[size] = '\0'; - sceLibcSscanf(buf, config_file, &config_version_holder, &config.sort, &config.alc_mode, &config.eq_mode, + sscanf(buf, config_file, &config_version_holder, &config.sort, &config.alc_mode, &config.eq_mode, &config.eq_volume, &config.motion_mode, &config.motion_timer, &config.motion_degree, &config.power_saving, &config.power_timer, &config.notify_mode, &config.device); - sceLibcFree(buf); + free(buf); // Delete config file if config file is updated. This will rarely happen. if (config_version_holder < CONFIG_VERSION) { @@ -113,25 +115,25 @@ int Config_GetLastDirectory(void) { ret = sceClibSnprintf(root_path, 8, "ux0:/"); Utils_WriteSafeMem((void*)&ret, 4, 0); Utils_WriteSafeMem((void*)root_path, ret, 4); - sceLibcStrcpy(cwd, root_path); // Set Start Path to "sdmc:/" if lastDir.txt hasn't been created. + strcpy(cwd, root_path); // Set Start Path to "sdmc:/" if lastDir.txt hasn't been created. } else { - sceLibcStrcpy(root_path, root_paths[config.device]); + strcpy(root_path, root_paths[config.device]); - char *buf = sceLibcMalloc(exist + 1); + char *buf = malloc(exist + 1); Utils_ReadSafeMem((void *)buf, exist, 4); buf[exist] = '\0'; char path[512]; - sceLibcSscanf(buf, "%[^\n]s", path); + sscanf(buf, "%[^\n]s", path); if (FS_DirExists(path)) // Incase a directory previously visited had been deleted, set start path to sdmc:/ to avoid errors. - sceLibcStrcpy(cwd, path); + strcpy(cwd, path); else - sceLibcStrcpy(cwd, root_path); + strcpy(cwd, root_path); - sceLibcFree(buf); + free(buf); } return 0; diff --git a/source/dirbrowse.c b/source/dirbrowse.c index 0845f73..f59a209 100644 --- a/source/dirbrowse.c +++ b/source/dirbrowse.c @@ -1,7 +1,8 @@ #include #include -#include #include +#include +#include #include "common.h" #include "config.h" @@ -23,7 +24,7 @@ static void Dirbrowse_RecursiveFree(File *node) { Dirbrowse_RecursiveFree(node->next); // Nest further - sceLibcFree(node); // Free memory + free(node); // Free memory } static void Dirbrowse_SaveLastDirectory(void) { @@ -42,9 +43,9 @@ static int cmpstringp(const void *p1, const void *p2) { return 1; else { if (config.sort == 0) // Sort alphabetically (ascending - A to Z) - return sceLibcStrcasecmp(entryA->d_name, entryB->d_name); + return strcasecmp(entryA->d_name, entryB->d_name); else if (config.sort == 1) // Sort alphabetically (descending - Z to A) - return sceLibcStrcasecmp(entryB->d_name, entryA->d_name); + return strcasecmp(entryB->d_name, entryA->d_name); else if (config.sort == 2) // Sort by file size (largest first) return entryA->d_stat.st_size > entryB->d_stat.st_size ? -1 : entryA->d_stat.st_size < entryB->d_stat.st_size ? 1 : 0; else if (config.sort == 3) // Sort by file size (smallest first) @@ -64,22 +65,22 @@ int Dirbrowse_PopulateFiles(SceBool refresh) { if (R_SUCCEEDED(dir = sceIoDopen(cwd))) { int entryCount = 0; - SceIoDirent *entries = (SceIoDirent *)sceLibcCalloc(MAX_FILES, sizeof(SceIoDirent)); + SceIoDirent *entries = (SceIoDirent *)calloc(MAX_FILES, sizeof(SceIoDirent)); while (sceIoDread(dir, &entries[entryCount]) > 0) entryCount++; sceIoDclose(dir); - sceLibcQsort(entries, entryCount, sizeof(SceIoDirent), cmpstringp); + qsort(entries, entryCount, sizeof(SceIoDirent), cmpstringp); for (int i = -1; i < entryCount; i++) { // Allocate Memory - File *item = (File *)sceLibcMalloc(sizeof(File)); + File *item = (File *)malloc(sizeof(File)); sceClibMemset(item, 0, sizeof(File)); - if ((sceClibStrcmp(cwd, root_path)) && (i == -1) && (!parent_dir_set)) { - sceLibcStrcpy(item->name, ".."); + if ((strcmp(cwd, root_path)) && (i == -1) && (!parent_dir_set)) { + strcpy(item->name, ".."); item->is_dir = SCE_TRUE; parent_dir_set = SCE_TRUE; file_count++; @@ -90,8 +91,8 @@ int Dirbrowse_PopulateFiles(SceBool refresh) { item->is_dir = SCE_STM_ISDIR(entries[i].d_stat.st_mode); // Copy File Name - sceLibcStrcpy(item->name, entries[i].d_name); - sceLibcStrcpy(item->ext, FS_GetFileExt(item->name)); + strcpy(item->name, entries[i].d_name); + strcpy(item->ext, FS_GetFileExt(item->name)); file_count++; } @@ -110,7 +111,7 @@ int Dirbrowse_PopulateFiles(SceBool refresh) { } } - sceLibcFree(entries); + free(entries); } else return dir; @@ -187,7 +188,8 @@ void Dirbrowse_DisplayFiles(void) { else if ((!sceClibStrncasecmp(file->ext, "flac", 4)) || (!sceClibStrncasecmp(file->ext, "it", 4)) || (!sceClibStrncasecmp(file->ext, "mod", 4)) || (!sceClibStrncasecmp(file->ext, "mp3", 4)) || (!sceClibStrncasecmp(file->ext, "ogg", 4)) || (!sceClibStrncasecmp(file->ext, "opus", 4)) || (!sceClibStrncasecmp(file->ext, "s3m", 4))|| (!sceClibStrncasecmp(file->ext, "wav", 4)) || (!sceClibStrncasecmp(file->ext, "xm", 4)) - || (!sceClibStrncasecmp(file->ext, "at9", 4)) || (!sceClibStrncasecmp(file->ext, "m4a", 4)) || (!sceClibStrncasecmp(file->ext, "aac", 4))) + || (!sceClibStrncasecmp(file->ext, "at9", 4)) || (!sceClibStrncasecmp(file->ext, "m4a", 4)) || (!sceClibStrncasecmp(file->ext, "aac", 4)) + || (!sceClibStrncasecmp(file->ext, "oma", 4)) || (!sceClibStrncasecmp(file->ext, "aa3", 4)) || (!sceClibStrncasecmp(file->ext, "at3", 4))) vita2d_draw_texture(icon_audio, 15, 117 + (72 * printed)); else vita2d_draw_texture(icon_file, 15, 117 + (72 * printed)); @@ -261,8 +263,8 @@ void Dirbrowse_OpenFile(void) { if (file == NULL) return; - sceLibcStrcpy(path, cwd); - sceLibcStrcpy(path + sceLibcStrlen(path), file->name); + strcpy(path, cwd); + strcpy(path + strlen(path), file->name); if (file->is_dir) { // Attempt to navigate to target @@ -274,7 +276,8 @@ void Dirbrowse_OpenFile(void) { else if ((!sceClibStrncasecmp(file->ext, "flac", 4)) || (!sceClibStrncasecmp(file->ext, "it", 4)) || (!sceClibStrncasecmp(file->ext, "mod", 4)) || (!sceClibStrncasecmp(file->ext, "mp3", 4)) || (!sceClibStrncasecmp(file->ext, "ogg", 4)) || (!sceClibStrncasecmp(file->ext, "opus", 4)) || (!sceClibStrncasecmp(file->ext, "s3m", 4)) || (!sceClibStrncasecmp(file->ext, "wav", 4)) || (!sceClibStrncasecmp(file->ext, "xm", 4)) - || (!sceClibStrncasecmp(file->ext, "at9", 4)) || (!sceClibStrncasecmp(file->ext, "m4a", 4)) || (!sceClibStrncasecmp(file->ext, "aac", 4))) { + || (!sceClibStrncasecmp(file->ext, "at9", 4)) || (!sceClibStrncasecmp(file->ext, "m4a", 4)) || (!sceClibStrncasecmp(file->ext, "aac", 4)) + || (!sceClibStrncasecmp(file->ext, "oma", 4)) || (!sceClibStrncasecmp(file->ext, "aa3", 4)) || (!sceClibStrncasecmp(file->ext, "at3", 4))) { Menu_PlayAudio(path); } } @@ -292,7 +295,7 @@ int Dirbrowse_Navigate(SceBool parent) { char *slash = NULL; // Find last '/' in working directory - int i = sceLibcStrlen(cwd) - 2; + int i = strlen(cwd) - 2; for(; i >= 0; i--) { // Slash discovered if (cwd[i] == '/') { @@ -309,9 +312,9 @@ int Dirbrowse_Navigate(SceBool parent) { else { if (file->is_dir) { // Append folder to working directory - sceLibcStrcpy(cwd + sceLibcStrlen(cwd), file->name); - cwd[sceLibcStrlen(cwd) + 1] = 0; - cwd[sceLibcStrlen(cwd)] = '/'; + strcpy(cwd + strlen(cwd), file->name); + cwd[strlen(cwd) + 1] = 0; + cwd[strlen(cwd)] = '/'; } } diff --git a/source/fios2_common.c b/source/fios2_common.c new file mode 100644 index 0000000..e4aca84 --- /dev/null +++ b/source/fios2_common.c @@ -0,0 +1,44 @@ +#include +#include +#include +#include + +// FIOS2 stuff +//-------------------------------------------------------------------------------------- +#define MAX_PATH_LENGTH 256 + +static SceInt64 s_op_storage[SCE_FIOS_OP_STORAGE_SIZE(64, MAX_PATH_LENGTH) / sizeof(SceInt64) + 1]; +static SceInt64 s_chunk_storage[SCE_FIOS_CHUNK_STORAGE_SIZE(1024) / sizeof(SceInt64) + 1]; +static SceInt64 s_fh_storage[SCE_FIOS_FH_STORAGE_SIZE(32, MAX_PATH_LENGTH) / sizeof(SceInt64) + 1]; +static SceInt64 s_dh_storage[SCE_FIOS_DH_STORAGE_SIZE(32, MAX_PATH_LENGTH) / sizeof(SceInt64) + 1]; + +/*SceFiosRamCacheContext s_ramcache_context = SCE_FIOS_RAM_CACHE_CONTEXT_INITIALIZER; +static SceByte s_ramcache_work_buffer[10 * (64 * 1024)] __attribute__((aligned(8)));*/ + +int fios2Init(void) { + SceFiosParams params = SCE_FIOS_PARAMS_INITIALIZER; + params.opStorage.pPtr = s_op_storage; + params.opStorage.length = sizeof(s_op_storage); + params.chunkStorage.pPtr = s_chunk_storage; + params.chunkStorage.length = sizeof(s_chunk_storage); + params.fhStorage.pPtr = s_fh_storage; + params.fhStorage.length = sizeof(s_fh_storage); + params.dhStorage.pPtr = s_dh_storage; + params.dhStorage.length = sizeof(s_dh_storage); + params.pathMax = MAX_PATH_LENGTH; + + params.threadAffinity[0] = SCE_KERNEL_CPU_MASK_USER_3; + params.threadAffinity[1] = SCE_KERNEL_CPU_MASK_USER_3; + params.threadAffinity[2] = SCE_KERNEL_CPU_MASK_USER_3; + + return sceFiosInitialize(¶ms); +} + +int fios2CommonOpDeleteCB(void *pContext, SceFiosOp op, SceFiosOpEvent event, int err) { + + if (event == SCE_FIOS_OPEVENT_COMPLETE) { + sceFiosOpDelete(op); + } + + return 0; +} \ No newline at end of file diff --git a/source/main.c b/source/main.c index 265d04a..4bc3f1b 100644 --- a/source/main.c +++ b/source/main.c @@ -15,10 +15,8 @@ #include "textures.h" #include "touch.h" #include "utils.h" - -#define CLIB_HEAP_SIZE 1 * 1024 * 1024 // |sceClibMspace| Used for libvita2d_sys -//#define LIBC_HEAP_SIZE 1 * 1024 * 1024 // |sceLibc| Used for general memory stuff (file browser, small temp allocation etc.), this value is embedded in the module -int _newlib_heap_size_user = 1 * 1024 * 1024; // |newlib| Used for decoders +#include "psp2_compat.h" +#include "fios2_common.h" SceUID main_thread_uid; SceUID event_flag_uid; @@ -27,7 +25,7 @@ SceUID event_flag_uid; SceAppMgrBudgetInfo budget_info; #endif -int main(int argc, char *argv[]) { +void _start(int argc, char *argv[]) { #ifdef DEBUG sceClibMemset(&budget_info, 0, sizeof(SceAppMgrBudgetInfo)); @@ -37,17 +35,16 @@ int main(int argc, char *argv[]) { sceClibPrintf("LPDDR2: %d MB\n", budget_info.freeLPDDR2 / 1024 / 1024); #endif - void* clibm_base, *mspace; - SceUID clib_heap = sceKernelAllocMemBlock("ClibHeap", SCE_KERNEL_MEMBLOCK_TYPE_USER_RW, CLIB_HEAP_SIZE, NULL); - sceKernelGetMemBlockBase(clib_heap, &clibm_base); - mspace = sceClibMspaceCreate(clibm_base, CLIB_HEAP_SIZE); + psp2CompatInit(); + //fios2Init(); main_thread_uid = sceKernelGetThreadId(); sceKernelChangeThreadPriority(main_thread_uid, 160); + sceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_AUDIOCODEC); + event_flag_uid = sceKernelCreateEventFlag("ElevenMPVA_thread_event_flag", SCE_KERNEL_ATTR_MULTI, FLAG_ELEVENMPVA_IS_FG | FLAG_ELEVENMPVA_IS_DECODER_USED, NULL); - vita2d_clib_pass_mspace(mspace); vita2d_init_with_msaa_and_memsize(0, 4 * 1024, 128 * 1024, 64 * 1024, 4 * 1024, 0); vita2d_set_vblank_wait(0); @@ -74,6 +71,4 @@ int main(int argc, char *argv[]) { Utils_InitPowerTick(); Menu_DisplayFiles(); - - return 0; } diff --git a/source/menus/menu_audioplayer.c b/source/menus/menu_audioplayer.c index 1ff0a05..2e53ff3 100644 --- a/source/menus/menu_audioplayer.c +++ b/source/menus/menu_audioplayer.c @@ -9,8 +9,9 @@ #include #include #include -#include #include +#include +#include #include "audio.h" #include "common.h" @@ -67,13 +68,13 @@ static int Menu_GetMusicList(void) { if (R_SUCCEEDED(dir = sceIoDopen(cwd))) { int entryCount = 0, i = 0; - SceIoDirent *entries = (SceIoDirent *)sceLibcCalloc(MAX_FILES, sizeof(SceIoDirent)); + SceIoDirent *entries = (SceIoDirent *)calloc(MAX_FILES, sizeof(SceIoDirent)); while (sceIoDread(dir, &entries[entryCount]) > 0) entryCount++; sceIoDclose(dir); - sceLibcQsort(entries, entryCount, sizeof(SceIoDirent), Utils_Alphasort); + qsort(entries, entryCount, sizeof(SceIoDirent), Utils_Alphasort); for (i = 0; i < entryCount; i++) { if ((!sceClibStrncasecmp(FS_GetFileExt(entries[i].d_name), "flac", 4)) || (!sceClibStrncasecmp(FS_GetFileExt(entries[i].d_name), "it", 4)) || @@ -81,9 +82,11 @@ static int Menu_GetMusicList(void) { (!sceClibStrncasecmp(FS_GetFileExt(entries[i].d_name), "ogg", 4)) || (!sceClibStrncasecmp(FS_GetFileExt(entries[i].d_name), "opus", 4)) || (!sceClibStrncasecmp(FS_GetFileExt(entries[i].d_name), "s3m", 4)) || (!sceClibStrncasecmp(FS_GetFileExt(entries[i].d_name), "wav", 4)) || (!sceClibStrncasecmp(FS_GetFileExt(entries[i].d_name), "xm", 4)) || (!sceClibStrncasecmp(FS_GetFileExt(entries[i].d_name), "at9", 4)) || - (!sceClibStrncasecmp(FS_GetFileExt(entries[i].d_name), "m4a", 4)) || (!sceClibStrncasecmp(FS_GetFileExt(entries[i].d_name), "aac", 4))) { - sceLibcStrcpy(playlist[count], cwd); - sceLibcStrcpy(playlist[count] + sceLibcStrlen(playlist[count]), entries[i].d_name); + (!sceClibStrncasecmp(FS_GetFileExt(entries[i].d_name), "m4a", 4)) || (!sceClibStrncasecmp(FS_GetFileExt(entries[i].d_name), "aac", 4)) || + (!sceClibStrncasecmp(FS_GetFileExt(entries[i].d_name), "oma", 4)) || (!sceClibStrncasecmp(FS_GetFileExt(entries[i].d_name), "aa3", 4)) || + (!sceClibStrncasecmp(FS_GetFileExt(entries[i].d_name), "at3", 4))) { + strcpy(playlist[count], cwd); + strcpy(playlist[count] + strlen(playlist[count]), entries[i].d_name); count++; } @@ -99,7 +102,7 @@ static int Menu_GetMusicList(void) { } } - sceLibcFree(entries); + free(entries); } else { sceIoDclose(dir); @@ -246,10 +249,10 @@ static void Menu_InitMusic(char *path) { else shellAudioSetEQModeForMusicPlayer(config.eq_mode); - filename = sceLibcMalloc(128); + filename = malloc(128); sceClibSnprintf(filename, 128, Utils_Basename(path)); - position_time = sceLibcMalloc(35); - length_time = sceLibcMalloc(35); + position_time = malloc(35); + length_time = malloc(35); length_time_width = 0; length = Audio_GetLengthSeconds(); @@ -302,9 +305,9 @@ static void Music_HandleNext(SceBool forward, int state) { Audio_Stop(); - sceLibcFree(filename); - sceLibcFree(length_time); - sceLibcFree(position_time); + free(filename); + free(length_time); + free(position_time); if ((metadata.has_meta) && (metadata.cover_image) && !ext_cover_loaded) { vita2d_wait_rendering_done(); @@ -639,9 +642,9 @@ void Menu_PlayAudio(char *path) { Utils_NotificationEnd(); } - sceLibcFree(filename); - sceLibcFree(length_time); - sceLibcFree(position_time); + free(filename); + free(length_time); + free(position_time); Menu_UnloadExternalCover(); ext_cover_is_jpeg = SCE_FALSE; diff --git a/source/menus/menu_settings.c b/source/menus/menu_settings.c index fd3caa0..905be8d 100644 --- a/source/menus/menu_settings.c +++ b/source/menus/menu_settings.c @@ -2,9 +2,10 @@ #include #include #include -#include #include #include +#include +#include #include "config.h" #include "touch.h" @@ -89,8 +90,8 @@ static void Menu_DisplayDeviceSettings(void) { if (pressed & SCE_CTRL_ENTER) { if (FS_DirExists(menu_items[selection])) { config.device = selection; - sceLibcStrcpy(root_path, menu_items[config.device]); - sceLibcStrcpy(cwd, root_path); + strcpy(root_path, menu_items[config.device]); + strcpy(cwd, root_path); sceIoRemove("savedata0:lastdir.txt"); Dirbrowse_PopulateFiles(SCE_TRUE); } @@ -273,7 +274,7 @@ void Menu_OnImeEvent(void *arg, const SceImeEvent *e) case 2: if (motion_degree_outval_utf8[0] == '\0' || motion_degree_outval_utf8[0] == '0') motion_degree_outval_utf8[0] = '1'; - config.motion_degree = sceLibcAtoi(motion_degree_outval_utf8); + config.motion_degree = atoi(motion_degree_outval_utf8); break; } sceImeClose(); diff --git a/source/psp2_compat.c b/source/psp2_compat.c new file mode 100644 index 0000000..02ed969 --- /dev/null +++ b/source/psp2_compat.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include + +#include "psp2_compat.h" + +char* varHelperSceLibc_ctype(void); +int* _sceLibcErrnoLoc(void); + +char* __ctype_ptr__; +struct _reent *_impure_ptr; + +void psp2CompatInit(void) +{ + SceUID modid; + modid = sceKernelLoadStartModule("app0:module/user/VarHelper.suprx", 0, NULL, 0, NULL, NULL); + __ctype_ptr__ = varHelperSceLibc_ctype(); + sceKernelStopUnloadModule(modid, 0, NULL, 0, NULL, NULL); + _impure_ptr = malloc(sizeof(struct _reent)); +} + +//Fake stat() for libxmp +int stat(const char *pathname, void *statbuf) +{ + return 1; +} + +int fseeko(FILE *stream, off_t offset, int whence) +{ + return fseek(stream, offset, whence); +} + +off_t ftello(FILE *stream) +{ + return ftell(stream); +} + +int* __errno(void) +{ + return _sceLibcErrnoLoc(); +} \ No newline at end of file diff --git a/source/touch.c b/source/touch.c index 3091578..0978470 100644 --- a/source/touch.c +++ b/source/touch.c @@ -1,8 +1,8 @@ #include #include -#include #include #include +#include #include "touch.h" @@ -16,7 +16,7 @@ int Touch_Init(void) { sceSysmoduleLoadModule(SCE_SYSMODULE_SYSTEM_GESTURE); sceSystemGestureInitializePrimitiveTouchRecognizer(NULL); - touch_recognizers = (SceSystemGestureTouchRecognizer *)sceLibcCalloc(TOUCH_RECOGNIZERS_NUM, sizeof(SceSystemGestureTouchRecognizer)); + touch_recognizers = (SceSystemGestureTouchRecognizer *)calloc(TOUCH_RECOGNIZERS_NUM, sizeof(SceSystemGestureTouchRecognizer)); SceSystemGestureRectangle rect; rect.x = BTN_PLAY_X * 2; rect.y = BTN_MAIN_Y * 2; diff --git a/source/utils.c b/source/utils.c index 1bde782..f762ce2 100644 --- a/source/utils.c +++ b/source/utils.c @@ -11,9 +11,9 @@ #include #include #include -#include #include -#include +#include +#include #include "utils.h" #include "config.h" @@ -265,7 +265,7 @@ int Utils_Alphasort(const void *p1, const void *p2) { else if (!(SCE_STM_ISDIR(entryA->d_stat.st_mode)) && (SCE_STM_ISDIR(entryB->d_stat.st_mode))) return 1; - return sceLibcStrcasecmp(entryA->d_name, entryB->d_name); + return strcasecmp(entryA->d_name, entryB->d_name); } char *Utils_Basename(const char *filename) {