15 Commits

Author SHA1 Message Date
730a0cd3d7 Add libvorbisdec to deps (closes #162) 2018-05-13 09:21:41 -04:00
fa37bcec99 Don't try and play mono ogg files 2018-05-13 09:03:16 -04:00
1c3e8809f6 Fix UB caused by using a free'd struct (actually fix QR code reader) 2018-05-11 18:01:35 -04:00
LiquidFenrir
3dad4e2a67 fix DEBUG calls 2018-05-11 15:59:17 +02:00
LiquidFenrir
403453c3fc add a loading bar (#159)
- when loading icons
- when downloading via QR
- when loading list in the browser
- when loading preview/BGM in the browser
- when downloading from the browser
2018-05-11 09:53:38 -04:00
fe58e2d938 Fixed QR code bug 2018-05-11 09:45:21 -04:00
LiquidFenrir
c28b794349 update remote.c to fix bgm preview there as well 2018-05-11 14:04:31 +02:00
d2b83659ea Fix race condition with music not being done playing 2018-05-11 07:42:05 -04:00
8189264908 Fix race condition in QR reader - slightly broken (doesn't run more than once) 2018-05-10 22:08:24 -04:00
5bb98a7fe2 Free everything when exiting theme preview 2018-05-10 21:30:41 -04:00
305c55e6b2 Disable home button 2018-05-10 17:17:54 -04:00
cb6f90adc7 Fix preview bug 2018-05-10 15:43:07 -04:00
7beb9b72db Change no-bgm install to make BGM silent 2018-05-10 13:09:27 -04:00
LiquidFenrir
8e43bb1a74 Shuffle without bgm (#157)
* add ability to shuffle without bgm
press B twice

* add license thingy for icons8, and thanks for their amazing icons
2018-05-10 12:52:14 -04:00
4dbc71489f Fix bug when bgm.ogg doesn't exist 2018-05-10 12:33:55 -04:00
14 changed files with 173 additions and 52 deletions

View File

@@ -5,7 +5,7 @@ To-do list here: https://trello.com/b/F1YSa1VK
# Dependencies
* devkitPro, which can be installed following the instructions [here](https://devkitpro.org/wiki/Getting_Started).
* zlib, jansson, and libarchive, which can be retrieved from [devkitPro pacman](https://devkitpro.org/viewtopic.php?f=13&t=8702).
* zlib, jansson, libvorbisidec, and libarchive, which can be retrieved from [devkitPro pacman](https://devkitpro.org/viewtopic.php?f=13&t=8702).
* A recent build of [makerom](https://github.com/profi200/Project_CTR) and the latest release of [bannertool](https://github.com/Steveice10/bannertool). These must be added to your PATH.
A 64-bit Windows binary of makerom is available [here](https://hm892.s-ul.eu/U0Irkqih).
* ~~[pp2d](https://github.com/BernardoGiordano/pp2d), which is included in the repo if you do a git clone --recursive.~~
@@ -25,6 +25,8 @@ This project is licensed under the GNU GPLv3. See LICENSE.md for details. Additi
# Credits
The following people contributed to Anemone3DS in some way. Without these people, Anemone3DS wouldn't exist, or wouldn't be as good as it is: [CONTRIBUTORS.md](CONTRIBUTORS.md)
Most of the icons under `romfs` are from the site [icons8.com](https://icons8.com) and are licensed under the [CC-BY-NC-SA](https://creativecommons.org/licenses/by-nc-sa/3.0/)
Special thanks go to these people who, whilst not directly contributing, helped immensely:
* [Rinnegatamante](https://github.com/Rinnegatamante), whose code served as reference on theme installation.
* [SteveIce10](https://github.com/SteveIce10), whose QR code in FBI was essential.

View File

@@ -60,6 +60,7 @@ enum TextureID {
TEXTURE_ARROW,
TEXTURE_ARROW_SIDE,
TEXTURE_SHUFFLE,
TEXTURE_SHUFFLE_NO_BGM,
TEXTURE_INSTALLED,
TEXTURE_PREVIEW_ICON,
TEXTURE_SORT,

View File

@@ -93,6 +93,7 @@ bool draw_confirm(const char* conf_msg, Entry_List_s* list);
void draw_preview(ssize_t previewID, int preview_offset);
void draw_install(InstallType type);
void draw_loading_bar(u32 current, u32 max, InstallType type);
void draw_base_interface(void);
void draw_grid_interface(Entry_List_s* list, Instructions_s instructions);

View File

@@ -71,6 +71,7 @@ typedef struct {
bool is_zip;
bool in_shuffle;
bool no_bgm_shuffle;
bool installed;
json_int_t tp_download_id;

View File

@@ -42,9 +42,11 @@ typedef struct {
float mix[12];
u8 buf_pos;
long data_read;
volatile bool stop;
char *filebuf;
u32 filesize;
volatile bool stop;
Handle finished;
} audio_s;
void play_audio(audio_s *);

View File

@@ -28,6 +28,7 @@
#define REMOTE_H
#include "common.h"
#include "draw.h"
#define THEMEPLAZA_BASE_URL "https://themeplaza.eu"
#define THEMEPLAZA_API_URL "/api/anemone/v1"
@@ -50,6 +51,6 @@
#define CACHE_PATH_FORMAT "/3ds/" APP_TITLE "/cache/%" JSON_INTEGER_FORMAT
bool themeplaza_browser(EntryMode mode);
u32 http_get(const char *url, char ** filename, char ** buf);
u32 http_get(const char *url, char ** filename, char ** buf, InstallType install_type);
#endif

BIN
romfs/shuffle_no_bgm.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 511 B

View File

@@ -46,15 +46,16 @@ static u16 * camera_buf = NULL;
void exit_qr(qr_data *data)
{
DEBUG("Exiting QR\n");
svcSignalEvent(data->cancel);
while(!data->finished)
svcSleepThread(1000000);
svcCloseHandle(data->cancel);
data->capturing = false;
free(data->camera_buffer);
free(data->texture_buffer);
quirc_destroy(data->context);
free(data);
}
void capture_cam_thread(void *arg)
@@ -87,6 +88,7 @@ void capture_cam_thread(void *arg)
svcWaitSynchronizationN(&index, events, 3, false, U64_MAX);
switch(index) {
case 0:
DEBUG("Cancel event received\n");
cancel = true;
break;
case 1:
@@ -202,7 +204,7 @@ void update_qr(qr_data *data)
draw_install(INSTALL_DOWNLOAD);
char * zip_buf = NULL;
char * filename = NULL;
u32 zip_size = http_get((char*)scan_data.payload, &filename, &zip_buf);
u32 zip_size = http_get((char*)scan_data.payload, &filename, &zip_buf, INSTALL_DOWNLOAD);
if(zip_size != 0)
{
@@ -293,7 +295,8 @@ bool init_qr(void)
data->texture_buffer = calloc(1, 400 * 240 * sizeof(u32));
while (!data->finished) update_qr(data);
bool success = data->success;
free(data);
return (bool)data->success;
}
return success;
}

View File

@@ -42,6 +42,7 @@ void init_screens(void)
pp2d_load_texture_png(TEXTURE_ARROW, "romfs:/arrow.png");
pp2d_load_texture_png(TEXTURE_ARROW_SIDE, "romfs:/arrow_side.png");
pp2d_load_texture_png(TEXTURE_SHUFFLE, "romfs:/shuffle.png");
pp2d_load_texture_png(TEXTURE_SHUFFLE_NO_BGM, "romfs:/shuffle_no_bgm.png");
pp2d_load_texture_png(TEXTURE_INSTALLED, "romfs:/installed.png");
pp2d_load_texture_png(TEXTURE_PREVIEW_ICON, "romfs:/preview.png");
pp2d_load_texture_png(TEXTURE_SORT, "romfs:/sort.png");
@@ -181,9 +182,8 @@ void draw_preview(ssize_t previewID, int preview_offset)
pp2d_draw_texture_part(previewID, 0, 0, 40 + preview_offset, 240, 320, 240);
}
void draw_install(InstallType type)
static void draw_install_handler(InstallType type)
{
draw_base_interface();
switch(type)
{
case INSTALL_LOADING_THEMES:
@@ -237,6 +237,25 @@ void draw_install(InstallType type)
default:
break;
}
}
void draw_install(InstallType type)
{
draw_base_interface();
draw_install_handler(type);
pp2d_end_draw();
}
void draw_loading_bar(u32 current, u32 max, InstallType type)
{
draw_base_interface();
draw_install_handler(type);
pp2d_draw_on(GFX_BOTTOM, GFX_LEFT);
double percent = 100*((double)current/(double)max);
u32 width = (u32)percent;
width *= 2;
pp2d_draw_rectangle(60-1, 110-1, 200+2, 20+2, COLOR_CURSOR);
pp2d_draw_rectangle(60, 110, width, 20, COLOR_ACCENT);
pp2d_end_draw();
}
@@ -478,8 +497,11 @@ void draw_interface(Entry_List_s* list, Instructions_s instructions)
pp2d_draw_wtext(list->entry_size+6, vertical_offset + 16, 0.55, 0.55, font_color, name);
if(current_entry->in_shuffle)
if(current_entry->no_bgm_shuffle)
pp2d_draw_texture_blend(TEXTURE_SHUFFLE_NO_BGM, 320-24-4, vertical_offset, font_color);
else if(current_entry->in_shuffle)
pp2d_draw_texture_blend(TEXTURE_SHUFFLE, 320-24-4, vertical_offset, font_color);
if(current_entry->installed)
pp2d_draw_texture_blend(TEXTURE_INSTALLED, 320-24-4, vertical_offset + 22, font_color);

View File

@@ -230,6 +230,9 @@ void load_icons_first(Entry_List_s * list, bool silent)
for(int i = starti; i < endi; i++, id++)
{
if(!silent)
draw_loading_bar(i - starti, endi-starti, INSTALL_LOADING_ICONS);
int offset = i;
if(offset < 0)
offset += list->entries_count;
@@ -464,39 +467,55 @@ bool load_preview(Entry_List_s list, int * preview_offset)
Result load_audio(Entry_s entry, audio_s *audio)
{
audio->filesize = load_data("/bgm.ogg", entry, &audio->filebuf);
if (audio->filesize == 0) {
free(audio);
DEBUG("File not found!\n");
return MAKERESULT(RL_FATAL, RS_NOTFOUND, RM_APPLICATION, RD_NOT_FOUND);
}
audio->mix[0] = audio->mix[1] = 1.0f; // Determines volume for the 12 (?) different outputs. See http://smealum.github.io/ctrulib/channel_8h.html#a30eb26f1972cc3ec28370263796c0444
svcCreateEvent(&audio->finished, RESET_STICKY);
ndspChnSetInterp(0, NDSP_INTERP_LINEAR);
ndspChnSetRate(0, 44100);
ndspChnSetFormat(0, NDSP_FORMAT_STEREO_PCM16); // Tremor outputs ogg files in 16 bit PCM stereo
ndspChnSetMix(0, audio->mix); // See mix comment above
FILE *file = fmemopen(audio->filebuf, audio->filesize, "rb");
DEBUG("Filesize: %lld\n", audio->filesize);
if(file != NULL)
{
int e = ov_open(file, &audio->vf, NULL, 0);
if (e < 0)
{
char error[50];
sprintf(error, "Vorbis: %d\n", e);
DEBUG(error);
DEBUG("Vorbis: %d\n", e);
free(audio->filebuf);
free(audio);
fclose(file);
return MAKERESULT(RL_FATAL, RS_INVALIDARG, RM_APPLICATION, RD_NO_DATA);
}
vorbis_info *vi = ov_info(&audio->vf, -1);
ndspChnSetRate(0, vi->rate);// Set sample rate to what's read from the ogg file
if (vi->channels == 2) {
DEBUG("Using stereo\n");
ndspChnSetFormat(0, NDSP_FORMAT_STEREO_PCM16); // 2 channels == Stereo
} else {
DEBUG("Invalid number of channels\n");
free(audio->filebuf);
free(audio);
fclose(file);
return MAKERESULT(RL_FATAL, RS_INVALIDARG, RM_APPLICATION, RD_NO_DATA);
}
audio->wave_buf[0].nsamples = audio->wave_buf[1].nsamples = vi->rate / 4; // 4 bytes per sample, samples = rate (bytes) / 4
audio->wave_buf[0].status = audio->wave_buf[1].status = NDSP_WBUF_DONE; // Used in play to stop from writing to current buffer
audio->wave_buf[0].data_vaddr = linearAlloc(BUF_TO_READ); // Most vorbis packets should only be 4 KB at most (?) Possibly dangerous assumption
audio->wave_buf[1].data_vaddr = linearAlloc(BUF_TO_READ);
DEBUG("Success!");
DEBUG("Success!\n");
return MAKERESULT(RL_SUCCESS, RS_SUCCESS, RM_APPLICATION, RD_SUCCESS);
} else {
free(audio->filebuf);
free(audio);
DEBUG("File not found!\n");
DEBUG("fmemopen failed!\n");
return MAKERESULT(RL_FATAL, RS_NOTFOUND, RM_APPLICATION, RD_NOT_FOUND);
}
}

View File

@@ -37,7 +37,7 @@
#include <time.h>
bool quit = false;
audio_s * audio;
audio_s * audio = NULL;
static bool homebrew = false;
static bool installed_themes = false;
@@ -136,6 +136,11 @@ void free_lists(void)
void exit_function(bool power_pressed)
{
if(audio)
{
audio->stop = true;
svcWaitSynchronization(audio->finished, U64_MAX);
}
free_lists();
svcCloseHandle(update_icons_handle);
exit_screens();
@@ -286,9 +291,24 @@ static void change_selected(Entry_List_s * list, int change_value)
static void toggle_shuffle(Entry_List_s * list)
{
Entry_s * current_entry = &list->entries[list->selected_entry];
if(current_entry->in_shuffle) list->shuffle_count--;
else list->shuffle_count++;
current_entry->in_shuffle = !current_entry->in_shuffle;
if(current_entry->in_shuffle)
{
if(current_entry->no_bgm_shuffle)
{
current_entry->in_shuffle = false;
current_entry->no_bgm_shuffle = false;
list->shuffle_count--;
}
else
{
current_entry->no_bgm_shuffle = true;
}
}
else
{
current_entry->in_shuffle = true;
list->shuffle_count++;
}
}
int main(void)
@@ -323,7 +343,7 @@ int main(void)
bool install_mode = false;
bool extra_mode = false;
while(aptMainLoop())
while(true)
{
if(quit)
{
@@ -438,15 +458,20 @@ int main(void)
if(current_mode == MODE_THEMES)
{
audio = calloc(1, sizeof(audio_s));
load_audio(current_list->entries[current_list->selected_entry], audio);
play_audio(audio);
Result r = load_audio(current_list->entries[current_list->selected_entry], audio);
if (R_SUCCEEDED(r)) play_audio(audio);
else audio = NULL;
}
}
else
{
preview_mode = false;
if(current_mode == MODE_THEMES && audio)
{
audio->stop = true;
svcWaitSynchronization(audio->finished, U64_MAX);
audio = NULL;
}
}
continue;
}
@@ -454,7 +479,11 @@ int main(void)
{
preview_mode = false;
if(current_mode == MODE_THEMES && audio)
{
audio->stop = true;
svcWaitSynchronization(audio->finished, U64_MAX);
audio = NULL;
}
continue;
}
}

View File

@@ -30,13 +30,14 @@
// Play a given audio struct
Result update_audio(audio_s *audio)
{
long size = audio->wave_buf[audio->buf_pos].nsamples * 4 - audio->data_read;
char size_info[50] = {0};
sprintf(size_info, "Audio Size: %ld\n", size);
DEBUG(size_info);
long size = BUF_TO_READ - audio->data_read;
DEBUG("Audio Size: %ld\n", size);
if (audio->wave_buf[audio->buf_pos].status == NDSP_WBUF_DONE) // only run if the current selected buffer has already finished playing
{
size_t read = ov_read(&audio->vf, (char*)audio->wave_buf[audio->buf_pos].data_vaddr + audio->data_read, size, NULL); // read 1 vorbis packet into wave buffer
DEBUG("Attempting ov_read\n");
int bitstream;
size_t read = ov_read(&audio->vf, (char*)audio->wave_buf[audio->buf_pos].data_vaddr + audio->data_read, size, &bitstream); // read 1 vorbis packet into wave buffer
DEBUG("ov_read successful\n");
if (read <= 0) // EoF or error
{
@@ -46,9 +47,7 @@ Result update_audio(audio_s *audio)
ov_open(fmemopen(audio->filebuf, audio->filesize, "rb"), &audio->vf, NULL, 0); // Reopen file. Don't need to reinit channel stuff since it's all the same as before
} else // Error :(
{
char error[100] = {0};
sprintf(error, "Vorbis play error: %d\n", read);
DEBUG(error);
DEBUG("Vorbis play error: %d\n", read);
ndspChnReset(0);
return MAKERESULT(RL_FATAL, RS_INVALIDARG, RM_APPLICATION, RD_NO_DATA);
}
@@ -71,6 +70,13 @@ void thread_audio(void* data) {
update_audio(audio);
}
free(audio->filebuf);
ov_clear(&audio->vf);
linearFree(audio->wave_buf[0].data_vaddr);
linearFree(audio->wave_buf[1].data_vaddr);
while (audio->wave_buf[0].status != NDSP_WBUF_DONE || audio->wave_buf[1].status != NDSP_WBUF_DONE) svcSleepThread(1e7);
svcSignalEvent(audio->finished);
svcSleepThread(1e8);
svcCloseHandle(audio->finished);
free(audio);
}

View File

@@ -26,7 +26,6 @@
#include "remote.h"
#include "loading.h"
#include "draw.h"
#include "fs.h"
#include "unicode.h"
#include "music.h"
@@ -115,7 +114,7 @@ static void load_remote_smdh(Entry_s * entry, size_t textureID, bool ignore_cach
smdh_buf = NULL;
char * api_url = NULL;
asprintf(&api_url, THEMEPLAZA_SMDH_FORMAT, entry->tp_download_id);
smdh_size = http_get(api_url, NULL, &smdh_buf);
smdh_size = http_get(api_url, NULL, &smdh_buf, INSTALL_NONE);
free(api_url);
smdh = (Icon_s *)smdh_buf;
}
@@ -164,7 +163,7 @@ static void load_remote_smdh(Entry_s * entry, size_t textureID, bool ignore_cach
free(smdh_buf);
}
static void load_remote_entries(Entry_List_s * list, json_t *ids_array, bool ignore_cache)
static void load_remote_entries(Entry_List_s * list, json_t *ids_array, bool ignore_cache, InstallType type)
{
list->entries_count = json_array_size(ids_array);
free(list->entries);
@@ -177,6 +176,7 @@ static void load_remote_entries(Entry_List_s * list, json_t *ids_array, bool ign
json_t * id = NULL;
json_array_foreach(ids_array, i, id)
{
draw_loading_bar(i, list->entries_count, type);
size_t offset = i;
Entry_s * current_entry = &list->entries[offset];
current_entry->tp_download_id = json_integer_value(id);
@@ -209,7 +209,7 @@ static void load_remote_list(Entry_List_s * list, json_int_t page, EntryMode mod
char * page_json = NULL;
char * api_url = NULL;
asprintf(&api_url, THEMEPLAZA_PAGE_FORMAT, page, mode+1, list->tp_search);
u32 json_len = http_get(api_url, NULL, &page_json);
u32 json_len = http_get(api_url, NULL, &page_json, INSTALL_NONE);
free(api_url);
if(json_len)
@@ -232,7 +232,7 @@ static void load_remote_list(Entry_List_s * list, json_int_t page, EntryMode mod
if(json_is_integer(value) && !strcmp(key, THEMEPLAZA_JSON_PAGE_COUNT))
list->tp_page_count = json_integer_value(value);
else if(json_is_array(value) && !strcmp(key, THEMEPLAZA_JSON_PAGE_IDS))
load_remote_entries(list, value, ignore_cache);
load_remote_entries(list, value, ignore_cache, loading_screen);
else if(json_is_string(value) && !strcmp(key, THEMEPLAZA_JSON_ERROR_MESSAGE) && !strcmp(json_string_value(value), THEMEPLAZA_JSON_ERROR_MESSAGE_NOT_FOUND))
throw_error("No results for this search.", ERROR_LEVEL_WARNING);
}
@@ -270,7 +270,7 @@ static bool load_remote_preview(Entry_s * entry, int * preview_offset)
draw_install(INSTALL_LOADING_REMOTE_PREVIEW);
preview_size = http_get(preview_url, NULL, &preview_png);
preview_size = http_get(preview_url, NULL, &preview_png, INSTALL_LOADING_REMOTE_PREVIEW);
free(preview_url);
}
@@ -343,7 +343,7 @@ static void load_remote_bgm(Entry_s * entry)
draw_install(INSTALL_LOADING_REMOTE_BGM);
bgm_size = http_get(bgm_url, NULL, &bgm_ogg);
bgm_size = http_get(bgm_url, NULL, &bgm_ogg, INSTALL_LOADING_REMOTE_BGM);
free(bgm_url);
u16 path[0x107] = {0};
@@ -366,7 +366,7 @@ static void download_remote_entry(Entry_s * entry, EntryMode mode)
char * zip_buf = NULL;
char * filename = NULL;
draw_install(INSTALL_DOWNLOAD);
u32 zip_size = http_get(download_url, &filename, &zip_buf);
u32 zip_size = http_get(download_url, &filename, &zip_buf, INSTALL_DOWNLOAD);
free(download_url);
char path_to_file[0x107] = {0};
@@ -522,15 +522,17 @@ bool themeplaza_browser(EntryMode mode)
u32 kHeld = hidKeysHeld();
u32 kUp = hidKeysUp();
if(kDown & KEY_START)
{
exit:
quit = true;
downloaded = false;
if(audio)
{
audio->stop = true;
svcWaitSynchronization(audio->finished, U64_MAX);
audio = NULL;
}
break;
}
@@ -588,7 +590,11 @@ bool themeplaza_browser(EntryMode mode)
{
preview_mode = false;
if(mode == MODE_THEMES && audio)
{
audio->stop = true;
svcWaitSynchronization(audio->finished, U64_MAX);
audio = NULL;
}
}
}
else if(kDown & KEY_B)
@@ -597,7 +603,11 @@ bool themeplaza_browser(EntryMode mode)
{
preview_mode = false;
if(mode == MODE_THEMES && audio)
{
audio->stop = true;
svcWaitSynchronization(audio->finished, U64_MAX);
audio = NULL;
}
}
else
break;
@@ -683,7 +693,11 @@ bool themeplaza_browser(EntryMode mode)
{
preview_mode = false;
if(mode == MODE_THEMES && audio)
{
audio->stop = true;
svcWaitSynchronization(audio->finished, U64_MAX);
audio = NULL;
}
continue;
}
else if(y < 24)
@@ -756,7 +770,7 @@ bool themeplaza_browser(EntryMode mode)
return downloaded;
}
u32 http_get(const char *url, char ** filename, char ** buf)
u32 http_get(const char *url, char ** filename, char ** buf, InstallType install_type)
{
Result ret;
httpcContext context;
@@ -880,6 +894,9 @@ u32 http_get(const char *url, char ** filename, char ** buf)
ret = httpcDownloadData(&context, (*(u8**)buf) + size, 0x1000, &read_size);
size += read_size;
if(content_size && install_type != INSTALL_NONE)
draw_loading_bar(size, content_size, install_type);
if (ret == (s32)HTTPC_RESULTCODE_DOWNLOADPENDING)
{
last_buf = *buf;

View File

@@ -100,13 +100,22 @@ static Result install_theme_internal(Entry_List_s themes, int installmode)
{
char bgm_cache_path[26] = {0};
sprintf(bgm_cache_path, "/BgmCache_%.2i.bin", shuffle_count);
music_size = load_data("/bgm.bcstm", *current_theme, &music);
if(music_size > BGM_MAX_SIZE)
if(current_theme->no_bgm_shuffle)
{
free(music);
DEBUG("bgm too big\n");
return MAKERESULT(RL_PERMANENT, RS_CANCELED, RM_APPLICATION, RD_TOO_LARGE);
music = NULL;
music_size = 0;
}
else
{
music_size = load_data("/bgm.bcstm", *current_theme, &music);
if(music_size > BGM_MAX_SIZE)
{
free(music);
DEBUG("bgm too big\n");
return MAKERESULT(RL_PERMANENT, RS_CANCELED, RM_APPLICATION, RD_TOO_LARGE);
}
}
shuffle_music_sizes[shuffle_count] = music_size;
@@ -116,8 +125,11 @@ static Result install_theme_internal(Entry_List_s themes, int installmode)
FSUSER_OpenFile(&bgm_cache_handle, ArchiveThemeExt, fsMakePath(PATH_ASCII, bgm_cache_path), FS_OPEN_WRITE, 0);
padded = calloc(BGM_MAX_SIZE, sizeof(char));
memcpy(padded, music, music_size);
free(music);
if(!current_theme->no_bgm_shuffle)
{
memcpy(padded, music, music_size);
free(music);
}
FSFILE_Write(bgm_cache_handle, NULL, 0, padded, BGM_MAX_SIZE, FS_WRITE_FLUSH);
@@ -183,6 +195,11 @@ static Result install_theme_internal(Entry_List_s themes, int installmode)
free(music);
if(R_FAILED(res)) return res;
} else
{
music = calloc(BGM_MAX_SIZE, 1);
res = buf_to_file(BGM_MAX_SIZE, fsMakePath(PATH_ASCII, "/BgmCache.bin"), ArchiveThemeExt, music);
free(music);
}
}