diff --git a/.travis/.build.sh b/.travis/.build.sh index 7e6854b2..55877fda 100644 --- a/.travis/.build.sh +++ b/.travis/.build.sh @@ -4,5 +4,6 @@ rm -rf .git .travis common libs .gitattributes .gitignore .travis.yml ICON0.PNG 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 zip -r CMFileManager-PSP.zip PSP/ -rm -rf app audio_driver launcher PSP +rm -rf app audio_driver display_driver launcher PSP diff --git a/Makefile b/Makefile index 50070f50..99fb8dfe 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -SUBDIRS = app launcher +SUBDIRS = app audio_driver display_driver launcher all: @for dir in $(SUBDIRS); do $(MAKE) -C $$dir; done diff --git a/app/Makefile b/app/Makefile index 2acb0152..d77f01fe 100644 --- a/app/Makefile +++ b/app/Makefile @@ -1,6 +1,6 @@ TARGET = CMFileManager -SOURCES := data glib2d source source/audio source/menus +SOURCES := data drivers glib2d source source/audio source/menus CFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.c)) SFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.S)) CPPFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.cpp)) @@ -13,7 +13,7 @@ OBJS := $(addsuffix .o,$(BINFILES)) \ PSP_LARGE_MEMORY = 1 VERSION_MAJOR := 3 -VERSION_MINOR := 0 +VERSION_MINOR := 1 VERSION_MICRO := 0 INCDIR = ../libs/include ../libs/include/ogg ../libs/include/opus include include/menus glib2d diff --git a/app/drivers/audio_driver.S b/app/drivers/audio_driver.S new file mode 100644 index 00000000..213c1f16 --- /dev/null +++ b/app/drivers/audio_driver.S @@ -0,0 +1,7 @@ + .set noreorder + +#include "pspstub.s" + + STUB_START "audio_driver",0x40090000,0x00010005 + STUB_FUNC 0x37516EBF,pspAudioSetFrequency + STUB_END diff --git a/app/drivers/display_driver.S b/app/drivers/display_driver.S new file mode 100644 index 00000000..bb23405a --- /dev/null +++ b/app/drivers/display_driver.S @@ -0,0 +1,10 @@ + .set noreorder + +#include "pspstub.s" + + STUB_START "display_driver",0x40090000,0x00040005 + STUB_FUNC 0x9C096DA0,pspGetBrightness + STUB_FUNC 0x193400C8,pspSetBrightness + STUB_FUNC 0xE3CA895B,pspDisplayEnable + STUB_FUNC 0x105212A9,pspDisplayDisable + STUB_END diff --git a/app/drivers/mutex-imports.S b/app/drivers/mutex-imports.S new file mode 100644 index 00000000..ae398f1c --- /dev/null +++ b/app/drivers/mutex-imports.S @@ -0,0 +1,140 @@ +.set noreorder + +#include + +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 diff --git a/app/include/common.h b/app/include/common.h index 94a2c179..2ff6c365 100644 --- a/app/include/common.h +++ b/app/include/common.h @@ -60,3 +60,7 @@ extern char initial_cwd[128]; extern bool is_ms_inserted; extern bool is_psp_go; + +// display driver function prototypes +extern int pspDisplayEnable(void); +extern int pspDisplayDisable(void); diff --git a/app/include/utils.h b/app/include/utils.h index 6fe8b904..d8ba95cf 100644 --- a/app/include/utils.h +++ b/app/include/utils.h @@ -19,6 +19,10 @@ char *Utils_Basename(const char *filename); void Utils_GetSizeString(char *string, u64 size); void Utils_AppendArr(char subject[], const char insert[], int pos); int Utils_Alphasort(const void *p1, const void *p2); +void Utils_InitAudioDriver(void); +void Utils_ExitAudioDriver(void); +void Utils_InitDisplayDriver(void); +void Utils_ExitDisplayDriver(void); void Utils_InitUSB(void); void Utils_ExitUSB(void); void Utils_HandleUSB(void); diff --git a/app/source/audio/audio.c b/app/source/audio/audio.c index fd28ac93..85128720 100644 --- a/app/source/audio/audio.c +++ b/app/source/audio/audio.c @@ -40,6 +40,9 @@ static Audio_Metadata empty_metadata = {0}; static Audio_Decoder decoder = {0}, empty_decoder = {0}; bool playing = true, paused = false; +// audio driver function prototype +int pspAudioSetFrequency(int frequency); + static void Audio_Decode(void *buf, unsigned int length, void *userdata) { if (playing == false || paused == true) { short *buf_short = (short *)buf; @@ -142,6 +145,7 @@ void Audio_Init(const char *path) { (* decoder.init)(path); pspAudioInit((* decoder.channels)() == 2? PSP_AUDIO_FORMAT_STEREO : PSP_AUDIO_FORMAT_MONO); + pspAudioSetFrequency((* decoder.rate)() == 48000? 48000 : 44100); pspAudioSetChannelCallback(0, Audio_Decode, NULL); } diff --git a/app/source/common.c b/app/source/common.c index c57b65ac..d8edf6a8 100644 --- a/app/source/common.c +++ b/app/source/common.c @@ -13,3 +13,7 @@ char initial_cwd[128]; bool is_ms_inserted; bool is_psp_go; + +// display driver function prototypes +int pspDisplayEnable(void); +int pspDisplayDisable(void); diff --git a/app/source/main.c b/app/source/main.c index 12fb0a7c..48ba2a5a 100644 --- a/app/source/main.c +++ b/app/source/main.c @@ -86,10 +86,14 @@ static int Init_Services(void) { PSP_CTRL_CANCEL = Utils_GetCancelButton(); Utils_InitUSB(); + Utils_InitAudioDriver(); + Utils_InitDisplayDriver(); return 0; } static void Term_Services(void) { + Utils_ExitDisplayDriver(); + Utils_ExitAudioDriver(); Utils_ExitUSB(); intraFontUnload(font); diff --git a/app/source/menus/menu_archive.c b/app/source/menus/menu_archive.c index db6040c1..9437f494 100644 --- a/app/source/menus/menu_archive.c +++ b/app/source/menus/menu_archive.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "common.h" #include "config.h" @@ -126,6 +127,11 @@ int Archive_ExtractArchive(const char *path) { } ret = archive_write_disk_set_options(dst, ARCHIVE_EXTRACT_UNLINK); + if (ret != ARCHIVE_OK) { + Menu_DisplayError("archive_write_disk_set_options failed:", ret); + break; + } + ret = archive_write_header(dst, entry); if (ret != ARCHIVE_OK) { Menu_DisplayError("archive_write_header failed:", ret); @@ -146,7 +152,8 @@ int Archive_ExtractArchive(const char *path) { int Archive_ExtractFile(const char *path) { int dialog_selection = 0; - + scePowerLock(0); + while (1) { Dialog_DisplayPrompt("Extract file", "This may take a few minutes.", "Do you want to continue?", &dialog_selection, true); Utils_ReadControls(); @@ -165,11 +172,13 @@ int Archive_ExtractFile(const char *path) { if (Utils_IsButtonPressed(PSP_CTRL_ENTER)) { if (dialog_selection == 1) { return Archive_ExtractArchive(path); + scePowerUnlock(0); } else break; } } + scePowerUnlock(0); return -1; } diff --git a/app/source/menus/menu_audio.c b/app/source/menus/menu_audio.c index bf374448..20039bc0 100644 --- a/app/source/menus/menu_audio.c +++ b/app/source/menus/menu_audio.c @@ -41,6 +41,8 @@ void Menu_PlayAudio(const char *path) { intraFontSetStyle(font, 0.7f, WHITE, G2D_RGBA(0, 0, 0, 0), 0.f, INTRAFONT_ALIGN_LEFT); length_time_width = intraFontMeasureText(font, length_time); + bool screen_disabled = false; + while(playing) { g2dClear(config.dark_theme? BLACK_BG : WHITE); G2D_DrawImage(default_artwork_blur, 0, 0); @@ -92,6 +94,15 @@ void Menu_PlayAudio(const char *path) { Utils_ReadControls(); + if (Utils_IsButtonPressed(PSP_CTRL_START)) { + screen_disabled = !screen_disabled; + + if (screen_disabled) + pspDisplayDisable(); + else + pspDisplayEnable(); + } + if (Utils_IsButtonPressed(PSP_CTRL_ENTER)) Audio_Pause(); @@ -106,4 +117,8 @@ void Menu_PlayAudio(const char *path) { free(position_time); Audio_Term(); + + // If user tries to exit with screen disabled, enable it. + if (screen_disabled) + pspDisplayEnable(); } diff --git a/app/source/menus/menu_ftp.c b/app/source/menus/menu_ftp.c index 24763f1a..52fec26f 100644 --- a/app/source/menus/menu_ftp.c +++ b/app/source/menus/menu_ftp.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -105,6 +106,7 @@ void Menu_DisplayFTP(void) { unsigned short int psp_port; int ret = 0; + scePowerLock(0); sceUtilityLoadNetModule(PSP_NET_MODULE_COMMON); sceUtilityLoadNetModule(PSP_NET_MODULE_INET); @@ -136,6 +138,8 @@ void Menu_DisplayFTP(void) { int msg_width = intraFontMeasureText(font, msg); int result_width = intraFontMeasureText(font, "Press Cross/Circle to exit."); + bool screen_disabled = false; + while (1) { g2dClear(config.dark_theme? BLACK_BG : WHITE); G2D_DrawRect(0, 0, 480, 20, config.dark_theme? STATUS_BAR_DARK : STATUS_BAR_LIGHT); @@ -169,6 +173,15 @@ void Menu_DisplayFTP(void) { if (((Utils_IsButtonHeld(PSP_CTRL_LTRIGGER)) && (Utils_IsButtonPressed(PSP_CTRL_RTRIGGER))) || ((Utils_IsButtonHeld(PSP_CTRL_RTRIGGER)) && (Utils_IsButtonPressed(PSP_CTRL_LTRIGGER)))) Screenshot_Capture(); + if (Utils_IsButtonPressed(PSP_CTRL_START)) { + screen_disabled = !screen_disabled; + + if (screen_disabled) + pspDisplayDisable(); + else + pspDisplayEnable(); + } + if ((Utils_IsButtonPressed(PSP_CTRL_ENTER)) || (Utils_IsButtonPressed(PSP_CTRL_CANCEL))) { sceKernelDelayThread(100 * 1000); break; @@ -181,4 +194,9 @@ void Menu_DisplayFTP(void) { sceUtilityUnloadNetModule(PSP_NET_MODULE_INET); sceUtilityUnloadNetModule(PSP_NET_MODULE_COMMON); + scePowerUnlock(0); + + // If user tries to exit with screen disabled, enable it. + if (screen_disabled) + pspDisplayEnable(); } diff --git a/app/source/mutex-imports.S b/app/source/mutex-imports.S deleted file mode 100644 index a1923a5a..00000000 --- a/app/source/mutex-imports.S +++ /dev/null @@ -1,140 +0,0 @@ -.set noreorder - -#include - -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 diff --git a/app/source/utils.c b/app/source/utils.c index 8c402de4..4b3f6ce5 100644 --- a/app/source/utils.c +++ b/app/source/utils.c @@ -6,7 +6,6 @@ #include "common.h" #include "config.h" -#include "log.h" #include "kubridge.h" #include "pspusbdevice.h" #include "systemctrl.h" @@ -20,6 +19,7 @@ static SceCtrlData current, previous; static bool g_usb_module_loaded = false; static bool g_usb_actived = false; +static SceUID audio_driver = 0, display_driver = 0; struct UsbModule { char *path; @@ -118,6 +118,24 @@ static void Utils_StopUnloadModules(SceUID modID) { sceKernelUnloadModule(modID); } +void Utils_InitAudioDriver(void) { + audio_driver = Utils_LoadStartModule("audio_driver.prx"); +} + +void Utils_ExitAudioDriver(void) { + if (audio_driver) + Utils_StopUnloadModules(audio_driver); +} + +void Utils_InitDisplayDriver(void) { + display_driver = Utils_LoadStartModule("display_driver.prx"); +} + +void Utils_ExitDisplayDriver(void) { + if (display_driver) + Utils_StopUnloadModules(display_driver); +} + void Utils_InitUSB(void) { int i = 0; @@ -142,7 +160,7 @@ static void Utils_StartUSBStorage(void) { static void Utils_StopUSBStorage(void) { sceUsbDeactivate(0x1c8); - sceIoDevctl("fatms0:", 0x0240D81E, NULL, 0, NULL, 0 ); // Avoid corrupted files + sceIoDevctl("fatms0:", 0x0240D81E, NULL, 0, NULL, 0); // Avoid corrupted files psp_usb_cable_connection = false; } diff --git a/audio_driver/Makefile b/audio_driver/Makefile new file mode 100644 index 00000000..deeaf08a --- /dev/null +++ b/audio_driver/Makefile @@ -0,0 +1,23 @@ +TARGET = audio_driver +OBJS = audio_driver.o + +BUILD_PRX = 1 +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 = -O2 -G0 -Wall -fno-builtin-printf +CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti +ASFLAGS = $(CFLAGS) + +LIBDIR = + +LDFLAGS = -nostartfiles +LIBS = -lpspkernel -lpspaudio_driver + +PSPSDK=$(shell psp-config --pspsdk-path) +include $(PSPSDK)/lib/build.mak diff --git a/audio_driver/audio_driver.c b/audio_driver/audio_driver.c new file mode 100644 index 00000000..a89f79ae --- /dev/null +++ b/audio_driver/audio_driver.c @@ -0,0 +1,23 @@ +#include +#include + +PSP_MODULE_INFO("audio_driver", PSP_MODULE_KERNEL, 1, 0); +PSP_MAIN_THREAD_ATTR(0); + +int pspAudioSetFrequency(int frequency) { + u32 k1 = 0; + 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; +} diff --git a/audio_driver/exports.exp b/audio_driver/exports.exp new file mode 100644 index 00000000..595bc556 --- /dev/null +++ b/audio_driver/exports.exp @@ -0,0 +1,15 @@ +# 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_HASH(module_start) +PSP_EXPORT_VAR_HASH(module_info) +PSP_EXPORT_END + +PSP_EXPORT_START(audio_driver, 0, 0x4001) +PSP_EXPORT_FUNC(pspAudioSetFrequency) +PSP_EXPORT_END + +PSP_END_EXPORTS diff --git a/display_driver/Makefile b/display_driver/Makefile new file mode 100644 index 00000000..d5453efc --- /dev/null +++ b/display_driver/Makefile @@ -0,0 +1,23 @@ +TARGET = display_driver +OBJS = sceDisplay_driver.o display_driver.o + +BUILD_PRX = 1 +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 = -O2 -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.mak diff --git a/display_driver/display_driver.c b/display_driver/display_driver.c new file mode 100644 index 00000000..02a25bbe --- /dev/null +++ b/display_driver/display_driver.c @@ -0,0 +1,67 @@ +#include +#include +#include + +PSP_MODULE_INFO("display_driver", PSP_MODULE_KERNEL, 1, 0); +PSP_MAIN_THREAD_ATTR(0); + +int sceDisplayEnable(void); +int sceDisplayDisable(void); +int sceDisplayEnable371(void); +int sceDisplayDisable371(void); + +int pspGetBrightness(int *brightness) { + u32 k1 = 0; + k1 = pspSdkSetK1(0); + + sceDisplayGetBrightness(brightness, 0); + + pspSdkSetK1(k1); + return 0; +} + +int pspSetBrightness(int brightness) { + u32 k1 = 0; + k1 = pspSdkSetK1(0); + + sceDisplaySetBrightness(brightness, 0); + + pspSdkSetK1(k1); + return 0; +} + +int pspDisplayEnable(void) { + u32 k1 = 0; + k1 = pspSdkSetK1(0); + + int ret = 0; + if (sceKernelDevkitVersion() < 0x03070110) + ret = sceDisplayEnable(); + else + ret = sceDisplayEnable371(); + + pspSdkSetK1(k1); + return ret; +} + +int pspDisplayDisable(void) { + u32 k1 = 0; + 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; +} diff --git a/display_driver/exports.exp b/display_driver/exports.exp new file mode 100644 index 00000000..424a60fd --- /dev/null +++ b/display_driver/exports.exp @@ -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_HASH(module_start) +PSP_EXPORT_VAR_HASH(module_info) +PSP_EXPORT_END + +# Export our function +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 diff --git a/display_driver/sceDisplay_driver.S b/display_driver/sceDisplay_driver.S new file mode 100644 index 00000000..5073ab68 --- /dev/null +++ b/display_driver/sceDisplay_driver.S @@ -0,0 +1,14 @@ + .set noreorder + +#include "pspimport.s" + + IMPORT_START "sceDisplay_driver",0x00010000 + IMPORT_FUNC "sceDisplay_driver",0x1CB8CB47,sceDisplayGetBrightness371 + IMPORT_FUNC "sceDisplay_driver",0x776ADFDB,sceDisplaySetBrightness371 + IMPORT_FUNC "sceDisplay_driver",0x946155FD,sceDisplayEnable371 + IMPORT_FUNC "sceDisplay_driver",0x32B67781,sceDisplayDisable371 + + IMPORT_FUNC "sceDisplay_driver",0x31C4BAA8,sceDisplayGetBrightness + IMPORT_FUNC "sceDisplay_driver",0x9E3C6DC6,sceDisplaySetBrightness + IMPORT_FUNC "sceDisplay_driver",0x432D133F,sceDisplayEnable + IMPORT_FUNC "sceDisplay_driver",0x681EE6A7,sceDisplayDisable diff --git a/libs/include/dr_wav.h b/libs/include/dr_wav.h index d21a539c..ef9f50c2 100644 --- a/libs/include/dr_wav.h +++ b/libs/include/dr_wav.h @@ -1,6 +1,6 @@ /* WAV audio loader and writer. Choice of public domain or MIT-0. See license statements at the end of this file. -dr_wav - v0.10.0 - 2019-08-04 +dr_wav - v0.10.1 - 2019-08-31 David Reid - mackron@gmail.com */ @@ -2050,12 +2050,33 @@ drwav_bool32 drwav_init_ex(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc pWav->totalPCMFrameCount = dataChunkSize / drwav_get_bytes_per_pcm_frame(pWav); if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) { + drwav_uint64 totalBlockHeaderSizeInBytes; drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign; - pWav->totalPCMFrameCount = (((blockCount * (fmt.blockAlign - (6*pWav->channels))) * 2)) / fmt.channels; /* x2 because two samples per byte. */ + + /* Make sure any trailing partial block is accounted for. */ + if ((blockCount * fmt.blockAlign) < dataChunkSize) { + blockCount += 1; + } + + /* We decode two samples per byte. There will be blockCount headers in the data chunk. This is enough to know how to calculate the total PCM frame count. */ + totalBlockHeaderSizeInBytes = blockCount * (6*fmt.channels); + pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels; } if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) { + drwav_uint64 totalBlockHeaderSizeInBytes; drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign; - pWav->totalPCMFrameCount = (((blockCount * (fmt.blockAlign - (4*pWav->channels))) * 2) + (blockCount * pWav->channels)) / fmt.channels; + + /* Make sure any trailing partial block is accounted for. */ + if ((blockCount * fmt.blockAlign) < dataChunkSize) { + blockCount += 1; + } + + /* We decode two samples per byte. There will be blockCount headers in the data chunk. This is enough to know how to calculate the total PCM frame count. */ + totalBlockHeaderSizeInBytes = blockCount * (4*fmt.channels); + pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels; + + /* The header includes a decoded sample for each channel which acts as the initial predictor sample. */ + pWav->totalPCMFrameCount += blockCount; } } @@ -4465,6 +4486,9 @@ void drwav_free(void* pDataReturnedByOpenAndRead) /* REVISION HISTORY ================ +v0.10.1 - 2019-08-31 + - Correctly handle partial trailing ADPCM blocks. + v0.10.0 - 2019-08-04 - Remove deprecated APIs. - Add wchar_t variants for file loading APIs: