mirror of
https://github.com/arabine/open-story-teller.git
synced 2025-12-06 17:09:06 +01:00
fix sdcard buffer overflow, fix switch case, use of TLV index file for stories
This commit is contained in:
parent
084af988cb
commit
fea5bc9c17
12 changed files with 182 additions and 62 deletions
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "filesystem.h"
|
||||
#include "mini_qoi.h"
|
||||
#include "serializers.h"
|
||||
|
||||
#ifdef OST_USE_FF_LIBRARY
|
||||
#include "ff.h"
|
||||
|
|
@ -27,6 +28,21 @@ static FIL File[2]; /* File object */
|
|||
static DIR Dir; /* Directory object */
|
||||
static FILINFO Finfo;
|
||||
|
||||
file_t file_open(const char *filename)
|
||||
{
|
||||
#ifdef OST_USE_FF_LIBRARY
|
||||
file_t fil;
|
||||
FRESULT fr = f_open(&fil, filename, FA_READ);
|
||||
if (fr != FR_OK)
|
||||
{
|
||||
debug_printf("ERROR: f_open %d\n\r", (int)fr);
|
||||
}
|
||||
return fil;
|
||||
#else
|
||||
return fopen(filename, "r");
|
||||
#endif
|
||||
}
|
||||
|
||||
static FRESULT scan_files(
|
||||
char *path /* Pointer to the working buffer with start path */
|
||||
)
|
||||
|
|
@ -82,20 +98,6 @@ void filesystem_mount()
|
|||
scan_files("");
|
||||
}
|
||||
|
||||
// Ouvre le fichier d'index d'histoires
|
||||
// Le format est le suivant :
|
||||
// - Fichier texte, avec fin de ligne \n
|
||||
// - Une ligne par histoire
|
||||
// - la ligne contient le nom du répertoire au format UUIDv4 (36 caractères ASCII avec 4 tirets '-')
|
||||
|
||||
// Exemple: d0ad13e4-06de-4e00-877c-d922fdd37d13
|
||||
|
||||
int is_multiple_of_37(int nombre)
|
||||
{
|
||||
int plusGrandMultiple = (nombre / 37) * 37;
|
||||
return (nombre - plusGrandMultiple) == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
// Loop in all directories
|
||||
void disk_start()
|
||||
|
|
@ -138,30 +140,55 @@ void disk_start()
|
|||
}
|
||||
*/
|
||||
|
||||
static file_t IndexFile;
|
||||
|
||||
static uint8_t IndexBuf[260];
|
||||
|
||||
static const char *IndexFileName = "index.ost";
|
||||
|
||||
#define TLV_ARRAY_TYPE 0xAB
|
||||
#define TLV_OBJECT_TYPE 0xE7
|
||||
#define TLV_STRING_TYPE 0x3D
|
||||
|
||||
bool filesystem_read_index_file(ost_context_t *ctx)
|
||||
{
|
||||
FILINFO fno;
|
||||
FRESULT fr = f_stat("index.ost", &fno);
|
||||
FRESULT fr = f_stat(IndexFileName, &fno);
|
||||
|
||||
ctx->number_of_stories = 0;
|
||||
ctx->current_story = 0;
|
||||
|
||||
if (fr == FR_OK)
|
||||
{
|
||||
|
||||
ctx->index_file_size = fno.fsize;
|
||||
UINT br;
|
||||
|
||||
bool valid_file = false;
|
||||
int size = fno.fsize;
|
||||
// une ligne = 36 octets (UUID) + 1 octet (\n) = 37
|
||||
// Déjà, la taille doit être multiple de 37
|
||||
if (is_multiple_of_37(size) && (size > 0))
|
||||
|
||||
// Minimum size of TLV is type + length, so check if there is potential data
|
||||
if (ctx->index_file_size > 3)
|
||||
{
|
||||
valid_file = true;
|
||||
ctx->number_of_stories = size / 37;
|
||||
debug_printf("SUCCESS: found %d stories\r\n", ctx->number_of_stories);
|
||||
FRESULT fr = f_open(&IndexFile, IndexFileName, FA_READ);
|
||||
if (fr == FR_OK)
|
||||
{
|
||||
fr = f_read(&IndexFile, IndexBuf, 3, &br);
|
||||
if (fr == FR_OK)
|
||||
{
|
||||
if ((br == 3) && (IndexBuf[0] = TLV_ARRAY_TYPE)) // Must be an array
|
||||
{
|
||||
// nomber of stories
|
||||
ctx->number_of_stories = leu16_get(&IndexBuf[1]);
|
||||
ctx->rd = 3;
|
||||
debug_printf("SUCCESS: found %d stories\r\n", ctx->number_of_stories);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
debug_printf("ERROR: index.ost not found\r\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
debug_printf("ERROR: index.ost not found\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -172,21 +199,6 @@ static uint8_t bmpImage[256];
|
|||
|
||||
static color_t line[320];
|
||||
|
||||
file_t file_open(const char *filename)
|
||||
{
|
||||
#ifdef OST_USE_FF_LIBRARY
|
||||
file_t fil;
|
||||
FRESULT fr = f_open(&fil, filename, FA_READ);
|
||||
if (fr != FR_OK)
|
||||
{
|
||||
debug_printf("ERROR: f_open %d\n\r", (int)fr);
|
||||
}
|
||||
return fil;
|
||||
#else
|
||||
return fopen(filename, "r");
|
||||
#endif
|
||||
}
|
||||
|
||||
void filesystem_display_image(const char *filename)
|
||||
{
|
||||
file_t fil;
|
||||
|
|
|
|||
|
|
@ -2,12 +2,7 @@
|
|||
#define FILESYSTEM_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t number_of_stories;
|
||||
uint32_t current_story;
|
||||
} ost_context_t;
|
||||
#include "system.h"
|
||||
|
||||
bool filesystem_read_index_file(ost_context_t *ctx);
|
||||
void filesystem_mount();
|
||||
|
|
|
|||
|
|
@ -133,25 +133,25 @@ void FsTask(void *args)
|
|||
{
|
||||
switch (FsState)
|
||||
{
|
||||
FS_PLAY_SOUND:
|
||||
case FS_PLAY_SOUND:
|
||||
play_sound_file(fs_ev->filename);
|
||||
FsState = FS_WAIT_FOR_EVENT;
|
||||
break;
|
||||
FS_DISPLAY_IMAGE:
|
||||
case FS_DISPLAY_IMAGE:
|
||||
filesystem_display_image(fs_ev->filename);
|
||||
FsState = FS_WAIT_FOR_EVENT;
|
||||
break;
|
||||
FS_LOAD_INDEX:
|
||||
case FS_LOAD_INDEX:
|
||||
filesystem_read_index_file(&OstContext);
|
||||
FsState = FS_WAIT_FOR_EVENT;
|
||||
break;
|
||||
FS_LOAD_STORY:
|
||||
case FS_LOAD_STORY:
|
||||
filesystem_load_rom(fs_ev->mem, fs_ev->filename);
|
||||
// ROM loaded, execute story
|
||||
FsState = FS_WAIT_FOR_EVENT;
|
||||
break;
|
||||
|
||||
FS_WAIT_FOR_EVENT:
|
||||
case FS_WAIT_FOR_EVENT:
|
||||
default:
|
||||
res = qor_mbox_wait(&FsMailBox, (void **)&fs_ev, 1000);
|
||||
if (res == QOR_MBOX_OK)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#ifndef FS_TASK_H
|
||||
#define FS_TASK_H
|
||||
|
||||
void fs_task_scan_index();
|
||||
void fs_task_initialize();
|
||||
|
||||
#endif // FS_TASK_H
|
||||
|
|
|
|||
|
|
@ -31,6 +31,13 @@ typedef struct
|
|||
uint8_t ev;
|
||||
} ost_hmi_event_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
OST_SYS_WAIT_INDEX,
|
||||
OST_SYS_PLAY_STORY_TITLE,
|
||||
OST_SYS_WAIT_USER_EVENT
|
||||
} ost_system_state_t;
|
||||
|
||||
// ===========================================================================================================
|
||||
// GLOBAL STORY VARIABLES
|
||||
// ===========================================================================================================
|
||||
|
|
@ -44,6 +51,10 @@ static ost_hmi_event_t HmiEvent;
|
|||
|
||||
static ost_hmi_event_t HmiQueue[10];
|
||||
|
||||
static ost_system_state_t OstState = OST_SYS_WAIT_INDEX;
|
||||
|
||||
static ost_context_t OstContext;
|
||||
|
||||
// ===========================================================================================================
|
||||
// HMI TASK (user interface, buttons manager, LCD)
|
||||
// ===========================================================================================================
|
||||
|
|
@ -55,6 +66,7 @@ void HmiTask(void *args)
|
|||
// filesystem_display_image("/ba869e4b-03d6-4249-9202-85b4cec767a7/images/bird.qoi");
|
||||
|
||||
// Start by scanning the index file
|
||||
fs_task_scan_index();
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
|
@ -62,6 +74,18 @@ void HmiTask(void *args)
|
|||
|
||||
if (res == QOR_MBOX_OK)
|
||||
{
|
||||
switch (OstState)
|
||||
{
|
||||
case OST_SYS_PLAY_STORY_TITLE:
|
||||
break;
|
||||
|
||||
case OST_SYS_WAIT_USER_EVENT:
|
||||
break;
|
||||
|
||||
case OST_SYS_WAIT_INDEX:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -70,8 +94,19 @@ void HmiTask(void *args)
|
|||
}
|
||||
}
|
||||
|
||||
void hmi_task_ost_ready(uint32_t number_of_stories)
|
||||
{
|
||||
static ost_hmi_event_t OsReadyEv = {
|
||||
.ev = OST_SYS_PLAY_STORY_TITLE};
|
||||
|
||||
OstContext.number_of_stories = number_of_stories;
|
||||
OstContext.current_story = 0;
|
||||
qor_mbox_notify(&HmiMailBox, (void **)&OsReadyEv, QOR_MBOX_OPTION_SEND_BACK);
|
||||
}
|
||||
|
||||
void hmi_task_initialize()
|
||||
{
|
||||
OstState = OST_SYS_WAIT_INDEX;
|
||||
qor_mbox_init(&HmiMailBox, (void **)&HmiQueue, 10);
|
||||
|
||||
qor_create_thread(&HmiTcb, HmiTask, HmiStack, sizeof(HmiStack) / sizeof(HmiStack[0]), HMI_TASK_PRIORITY, "HmiTask"); // less priority is the HMI (user inputs and LCD)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
#ifndef HMI_TASK_H
|
||||
#define HMI_TASK_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void hmi_task_initialize();
|
||||
|
||||
void hmi_task_ost_ready(uint32_t number_of_stories);
|
||||
|
||||
#endif // HMI_TASK_H
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ qor_switch_context:
|
|||
|
||||
|
||||
msr psp, r0 @ new task stack top address
|
||||
str r0, [r1] @ Save the new top of stack
|
||||
// str r0, [r1] @ Save the new top of stack
|
||||
|
||||
subs r0, r0, #32
|
||||
ldmia r0!, {r4-r7}
|
||||
|
|
|
|||
|
|
@ -304,7 +304,7 @@ static SD_Error SD_ReceiveData(uint8_t *data, uint16_t len)
|
|||
/* receive the rest of data... */
|
||||
// for (i = 1; i < len; ++i)
|
||||
// data[i] = SD_SpiWriteByte(0xFF);
|
||||
ost_hal_sdcard_spi_read(&data[1], len);
|
||||
ost_hal_sdcard_spi_read(&data[1], (len - 1));
|
||||
|
||||
/* get CRC bytes (not really needed by us, but required by SD) */
|
||||
SD_SpiWriteByte(0xFF);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,20 @@
|
|||
#ifndef SYSTEM_H
|
||||
#define SYSTEM_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// On regroupe ici au les priorités des différents threads afin d'avoir une vision plus large
|
||||
#define HMI_TASK_PRIORITY 1
|
||||
#define VM_TASK_PRIORITY 2
|
||||
#define FS_TASK_PRIORITY 3 ///< High priority for audio / file system access
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t number_of_stories;
|
||||
uint32_t current_story;
|
||||
uint32_t index_file_size;
|
||||
uint32_t rd; ///!< Read index in the Index file
|
||||
|
||||
} ost_context_t;
|
||||
|
||||
#endif // SYSTEM_H
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ost_hal.h"
|
||||
#include "debug.h"
|
||||
|
|
|
|||
|
|
@ -27,7 +27,12 @@ ResourcesDock::ResourcesDock(StoryProject &project, ResourceModel &model)
|
|||
std::filesystem::copy(p, p2, std::filesystem::copy_options::overwrite_existing);
|
||||
|
||||
Resource res;
|
||||
res.format = "BMP";
|
||||
|
||||
std::string ext = p.extension();
|
||||
ext.erase(ext.begin()); // remove '.' dot sign
|
||||
std::transform(ext.begin(), ext.end(), ext.begin(), ::toupper);
|
||||
|
||||
res.format = ext;
|
||||
res.type = "image";
|
||||
res.file = p.filename().generic_string();
|
||||
m_resourcesModel.Append(res);
|
||||
|
|
@ -38,7 +43,7 @@ ResourcesDock::ResourcesDock(StoryProject &project, ResourceModel &model)
|
|||
|
||||
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
|
||||
".",
|
||||
tr("Sound files (*.wav *.mp3 *.m4a)"));
|
||||
tr("Sound files (*.wav *.mp3)"));
|
||||
|
||||
if (std::filesystem::exists(fileName.toStdString()))
|
||||
{
|
||||
|
|
@ -47,7 +52,12 @@ ResourcesDock::ResourcesDock(StoryProject &project, ResourceModel &model)
|
|||
std::filesystem::copy(p, p2, std::filesystem::copy_options::overwrite_existing);
|
||||
|
||||
Resource res;
|
||||
res.format = "WAV";
|
||||
|
||||
std::string ext = p.extension();
|
||||
ext.erase(ext.begin()); // remove '.' dot sign
|
||||
std::transform(ext.begin(), ext.end(), ext.begin(), ::toupper);
|
||||
|
||||
res.format = ext;
|
||||
res.type = "sound";
|
||||
res.file = p.filename().generic_string();
|
||||
m_resourcesModel.Append(res);
|
||||
|
|
|
|||
|
|
@ -12,18 +12,68 @@ void StoryProject::New(const std::string &uuid, const std::string &file_path)
|
|||
Initialize(file_path);
|
||||
}
|
||||
|
||||
#define TLV_ARRAY_TYPE 0xAB
|
||||
#define TLV_OBJECT_TYPE 0xE7
|
||||
#define TLV_STRING_TYPE 0x3D
|
||||
|
||||
|
||||
class Tlv
|
||||
{
|
||||
public:
|
||||
explicit Tlv(const std::string &filename)
|
||||
{
|
||||
m_file = std::ofstream(filename, std::ios::out | std::ios::binary);
|
||||
}
|
||||
|
||||
~Tlv() {
|
||||
m_file.close();
|
||||
}
|
||||
|
||||
void add_array(uint16_t size)
|
||||
{
|
||||
m_file.write(reinterpret_cast<const char*>(&m_objectType), sizeof(m_objectType));
|
||||
m_file.write(reinterpret_cast<const char*>(&size), sizeof(size));
|
||||
}
|
||||
|
||||
void add_string(const char *s, uint16_t size)
|
||||
{
|
||||
m_file.write(reinterpret_cast<const char*>(&m_stringType), sizeof(m_stringType));
|
||||
m_file.write(reinterpret_cast<const char*>(&size), sizeof(size));
|
||||
m_file.write(s, size);
|
||||
}
|
||||
|
||||
void add_object(uint16_t entries)
|
||||
{
|
||||
m_file.write(reinterpret_cast<const char*>(&m_arrayType), sizeof(m_arrayType));
|
||||
m_file.write(reinterpret_cast<const char*>(&entries), sizeof(entries));
|
||||
}
|
||||
|
||||
private:
|
||||
std::ofstream m_file;
|
||||
|
||||
uint8_t m_arrayType = TLV_ARRAY_TYPE;
|
||||
uint8_t m_objectType = TLV_OBJECT_TYPE;
|
||||
uint8_t m_stringType = TLV_STRING_TYPE;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
void StoryProject::SaveStory(const std::vector<uint8_t> &m_program)
|
||||
{
|
||||
std::ofstream o(m_working_dir + std::filesystem::path::preferred_separator + "story.c32", std::ios::out | std::ios::binary);
|
||||
o.write(reinterpret_cast<const char*>(m_program.data()), m_program.size());
|
||||
o.close();
|
||||
|
||||
// Generate title files
|
||||
std::ofstream index(m_working_dir + std::filesystem::path::preferred_separator + "index.ost");
|
||||
index << "/" << m_uuid << "/images/" << m_titleImage << "\n";
|
||||
index << "/" << m_uuid << "/sounds/" << m_titleSound << "\n";
|
||||
index.close();
|
||||
|
||||
Tlv tlv(m_working_dir + std::filesystem::path::preferred_separator + "index.ost");
|
||||
|
||||
tlv.add_array(1);
|
||||
|
||||
tlv.add_object(3);
|
||||
tlv.add_string(m_uuid.c_str(), m_uuid.size()); // uuid
|
||||
tlv.add_string(m_titleImage.c_str(), m_titleImage.size()); // title image
|
||||
tlv.add_string(m_titleSound.c_str(), m_titleSound.size()); // title sound
|
||||
}
|
||||
|
||||
void StoryProject::Initialize(const std::string &file_path)
|
||||
|
|
|
|||
Loading…
Reference in a new issue