From fb0df1537eb143cb55df239427562029b234da8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sandro=20Sobczy=C5=84ski?= Date: Thu, 12 Nov 2020 18:24:02 +0100 Subject: [PATCH] wip - file_service --- src/engine/engine.cpp | 3 +- src/engine/include/engine.hpp | 2 + src/engine/include/modules/audio.hpp | 11 +- src/engine/include/modules/file_service.hpp | 115 +++++++++++++++++++ src/engine/modules/audio.cpp | 7 +- src/engine/modules/file_service.cpp | 117 ++++++++++++++++++++ src/samples/ari/Makefile | 1 + 7 files changed, 246 insertions(+), 10 deletions(-) create mode 100644 src/engine/include/modules/file_service.hpp create mode 100644 src/engine/modules/file_service.cpp diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 4293d5f..15fbd94 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -85,7 +85,8 @@ void Engine::firePS2() SifInitRpc(0); srand(time(NULL)); VU1::uploadProgram(0, &VU1Draw3D_CodeStart, &VU1Draw3D_CodeEnd); - audio.startThread(); + fileService.startThread(); + audio.startThread(&fileService); isInitialized = 0; mainThreadId = GetThreadId(); } diff --git a/src/engine/include/engine.hpp b/src/engine/include/engine.hpp index 8ce1a82..5f10f65 100644 --- a/src/engine/include/engine.hpp +++ b/src/engine/include/engine.hpp @@ -19,6 +19,7 @@ #include "modules/timer.hpp" #include "modules/pad.hpp" #include "modules/audio.hpp" +#include "modules/file_service.hpp" class Engine { @@ -31,6 +32,7 @@ public: void init(Game *t_game, u32 t_gifPacketSize); void setDefaultScreen(); Renderer *renderer; + FileService fileService; Audio audio; ScreenSettings screen; Pad pad; diff --git a/src/engine/include/modules/audio.hpp b/src/engine/include/modules/audio.hpp index 4b4407b..8bfa868 100644 --- a/src/engine/include/modules/audio.hpp +++ b/src/engine/include/modules/audio.hpp @@ -12,6 +12,7 @@ #define _TYRA_AUDIO_ #include "../models/audio_listener.hpp" +#include "./file_service.hpp" #include #include #include @@ -120,17 +121,15 @@ public: * Do not call this method unless you know what you do. * Should be called by engine. */ - void startThread(); + void startThread(FileService *t_fileService); private: u8 songLoaded, volume, realVolume, songPlaying, songInLoop, songFinished; std::vector songListeners; FILE *wav; audsrv_fmt_t format; - // we have some sema problems here (sound freezing) - // this probably should be changed to smth like this: - // this thread (A) : play next chunks - // other thread (B) : load chunks (fread()) for thread A + FileService *fileService; + char wavChunk[2 * 1024] __attribute__((aligned(16))); s32 chunkReadStatus; @@ -150,7 +149,7 @@ private: void loadModules(); void initAUDSRV(); void threadLoop(); - static void audioThread(); + static void mainThread(); }; #endif diff --git a/src/engine/include/modules/file_service.hpp b/src/engine/include/modules/file_service.hpp new file mode 100644 index 0000000..995dea9 --- /dev/null +++ b/src/engine/include/modules/file_service.hpp @@ -0,0 +1,115 @@ +/* +# ______ ____ ___ +# | \/ ____| |___| +# | | | \ | | +#----------------------------------------------------------------------- +# Copyright 2020, tyra - https://github.com/h4570/tyra +# Licenced under Apache License 2.0 +# Sandro Sobczyński +*/ + +#ifndef _TYRA_FILE_SERVICE_ +#define _TYRA_FILE_SERVICE_ + +#include +#include +#include +#include + +enum FileServiceTaskType +{ + ReadChunk = 0 +}; + +struct FileServiceTask +{ + FileServiceTaskType type; + + u32 id; + + /** + * Used by types: + * - ReadChunk + */ + FILE *file; + + /** + * Used by types: + * - ReadChunk + */ + s32 readStatus; + + /** + * Used by types: + * - ReadChunk + */ + void *destination; + + /** + * Used by types: + * - ReadChunk + */ + u32 size; + + /** + * Used by types: + * - ReadChunk + */ + u32 n; +}; + +/** Class responsible for background, non-blocking file loading playing. */ +class FileService +{ + +public: + /** Constructor is called by the engine. */ + FileService(); + ~FileService(); + + /** + * Add task to read next chunk. ( fread() ) + * @returns Task id + */ + u32 addReadChunk(FILE *t_file, void *t_destination, const u32 &t_size, const u32 &t_n); + + /** + * Check if given task was done. + * When task is done, this method will return read status. + * After this, task is removed from file service, so this method + * will return something once per task. + * @returns Read status (ex. result of fread()). -2137 if task is not done. + */ + s32 isTaskDone(const u32 &t_taskId); + + /** + * Start file service thread. + * Do not call this method unless you know what you do. + * Should be called by engine. + */ + void startThread(); + + std::vector tasks; + +private: + /** Remove task by index */ + void removeByIndex(const u32 &t_index) { tasks.erase(tasks.begin() + t_index); } + + /** Remove task by id */ + const void removeById(const u32 &t_taskId); + + /** + * Get index of task. + * @returns Index of task. -1 if not found. + */ + const s32 getIndexOf(const u32 &t_taskId); + + u8 threadStack[8 * 1024] __attribute__((aligned(16))); + u32 getThreadStackSize() { return 8 * 1024; } + ee_thread_t thread; + int threadId; + void threadLoop(); + static void mainThread(); +}; + +#endif diff --git a/src/engine/modules/audio.cpp b/src/engine/modules/audio.cpp index ebb8f15..2889b00 100644 --- a/src/engine/modules/audio.cpp +++ b/src/engine/modules/audio.cpp @@ -157,11 +157,12 @@ void Audio::playADPCM(audsrv_adpcm_t *t_adpcm, const s8 &t_ch) // Other -void Audio::startThread() +void Audio::startThread(FileService *t_fileService) { PRINT_LOG("Creating audio thread"); + fileService = t_fileService; extern void *_gp; - thread.func = (void *)Audio::audioThread; + thread.func = (void *)Audio::mainThread; thread.stack = threadStack; thread.stack_size = getThreadStackSize(); thread.gp_reg = (void *)&_gp; @@ -293,7 +294,7 @@ void Audio::initAUDSRV() * Do not call this function. * This is a audio thread, runned by engine */ -void Audio::audioThread() +void Audio::mainThread() { while (true) audioRef->threadLoop(); diff --git a/src/engine/modules/file_service.cpp b/src/engine/modules/file_service.cpp new file mode 100644 index 0000000..daec879 --- /dev/null +++ b/src/engine/modules/file_service.cpp @@ -0,0 +1,117 @@ +/* +# ______ ____ ___ +# | \/ ____| |___| +# | | | \ | | +#----------------------------------------------------------------------- +# Copyright 2020, tyra - https://github.com/h4570/tyra +# Licenced under Apache License 2.0 +# Sandro Sobczyński +*/ + +#include "../include/modules/file_service.hpp" +#include "../include/utils/string.hpp" +#include "../include/utils/debug.hpp" +#include + +// ---- +// Constructors/Destructors +// ---- + +FileService *fsRef; + +FileService::FileService() {} + +FileService::~FileService() {} + +// ---- +// Methods +// ---- + +u32 FileService::addReadChunk(FILE *t_file, void *t_destination, const u32 &t_size, const u32 &t_n) +{ + FileServiceTask task; + task.id = rand() % 1000000; + task.file = t_file; + task.destination = t_destination; + task.size = t_size; + task.n = t_n; + task.readStatus = -2137; + tasks.push_back(task); + return task.id; +} + +s32 FileService::isTaskDone(const u32 &t_taskId) +{ + s32 taskIndex = getIndexOf(t_taskId); + if (taskIndex == -1) + PRINT_ERR("Task was not found!"); + s32 result = tasks[taskIndex].readStatus; + if (result != -2137) + removeByIndex(taskIndex); + return result; +} + +const void FileService::removeById(const u32 &t_taskId) +{ + s32 index = getIndexOf(t_taskId); + if (index != -1) + removeByIndex(index); + else + PRINT_ERR("Cant remove task, because it was not found!"); +} + +const s32 FileService::getIndexOf(const u32 &t_taskId) +{ + for (u32 i = 0; i < tasks.size(); i++) + if (tasks[i].id == t_taskId) + return i; + return -1; +}; + +// Other + +void FileService::startThread() +{ + PRINT_LOG("Creating file service thread"); + extern void *_gp; + thread.func = (void *)FileService::mainThread; + thread.stack = threadStack; + thread.stack_size = getThreadStackSize(); + thread.gp_reg = (void *)&_gp; + thread.initial_priority = 0x12; + if ((threadId = CreateThread(&thread)) < 0) + PRINT_ERR("Create audio thread failed!"); + PRINT_LOG("File service created"); + StartThread(threadId, NULL); + PRINT_LOG("File service started"); +} + +/** Main thread loop */ +void FileService::threadLoop() +{ + // This will cause an error + // printf("\n\n\n\n\nsize:%d\n", tasks.size()); + // for (size_t i = 0; i < tasks.size(); i++) + // { + // switch (tasks[i].type) + // { + // case ReadChunk: + // tasks[i].readStatus = fread(tasks[i].destination, tasks[i].n, tasks[i].size, tasks[i].file); + // break; + + // default: + // break; + // } + // } + SleepThread(); +} + +/** + * Do not call this function. + * This is an file service thread, runned by engine + */ +void FileService::mainThread() +{ + while (true) + fsRef->threadLoop(); +} diff --git a/src/samples/ari/Makefile b/src/samples/ari/Makefile index a941dc2..bd60f13 100644 --- a/src/samples/ari/Makefile +++ b/src/samples/ari/Makefile @@ -11,6 +11,7 @@ EE_OBJS = \ ../../engine/models/mesh_texture.o \ ../../engine/modules/audio.o \ ../../engine/modules/camera_base.o \ + ../../engine/modules/file_service.o \ ../../engine/modules/gif_sender.o \ ../../engine/modules/light.o \ ../../engine/modules/pad.o \