diff options
author | Christophe Grenier <[email protected]> | 2016-09-03 18:26:34 +0200 |
---|---|---|
committer | Christophe Grenier <[email protected]> | 2016-09-03 18:26:34 +0200 |
commit | 6e2814fc0a5b055484227ca62ac93a8d9ecbdd6d (patch) | |
tree | 205843ae4117c428cac6b0fb70a7d5b3f339946a | |
parent | 67e7ee73953da02b0ebe180544b51a2cba8b38b3 (diff) |
PhotoRec: recover Yamaha-YSFC .x4a files
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/file_list.c | 2 | ||||
-rw-r--r-- | src/file_x4a.c | 104 |
3 files changed, 107 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 4aa1a193..9095a5ca 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -328,6 +328,7 @@ file_C = filegen.c \ file_wtv.c \ file_wv.c \ file_x3f.c \ + file_x4a.c \ file_xar.c \ file_xcf.c \ file_xfi.c \ diff --git a/src/file_list.c b/src/file_list.c index 88c52af9..2d57c033 100644 --- a/src/file_list.c +++ b/src/file_list.c @@ -333,6 +333,7 @@ extern const file_hint_t file_hint_wpd; extern const file_hint_t file_hint_wtv; extern const file_hint_t file_hint_wv; extern const file_hint_t file_hint_x3f; +extern const file_hint_t file_hint_x4a; extern const file_hint_t file_hint_xar; extern const file_hint_t file_hint_xcf; extern const file_hint_t file_hint_xfi; @@ -656,6 +657,7 @@ file_enable_t list_file_enable[]= { .enable=0, .file_hint=&file_hint_wtv }, { .enable=0, .file_hint=&file_hint_wv }, { .enable=0, .file_hint=&file_hint_x3f }, + { .enable=0, .file_hint=&file_hint_x4a }, { .enable=0, .file_hint=&file_hint_xar }, { .enable=0, .file_hint=&file_hint_xcf }, { .enable=0, .file_hint=&file_hint_xfi }, diff --git a/src/file_x4a.c b/src/file_x4a.c new file mode 100644 index 00000000..91220445 --- /dev/null +++ b/src/file_x4a.c @@ -0,0 +1,104 @@ +/* + + File: file_ysfc100.c + + Copyright (C) 2016 Christophe GRENIER <[email protected]> + + This software is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#ifdef HAVE_STRING_H +#include <string.h> +#endif +#include <stdio.h> +#include "types.h" +#include "filegen.h" +#include "common.h" + +static void register_header_check_ysfc100(file_stat_t *file_stat); + +const file_hint_t file_hint_x4a= { + .extension="x4a", + .description="Yamaha-YSFC", + .max_filesize=PHOTOREC_MAX_FILE_SIZE, + .recover=1, + .enable_by_default=1, + .register_header_check=®ister_header_check_ysfc100 +}; + +struct x4a_catalog +{ + char type[4]; + uint32_t size; +} __attribute__ ((gcc_struct, __packed__)); + +static void file_check_x4a(file_recovery_t *fr) +{ + unsigned char buffer[0x200]; + unsigned int i; + unsigned int fs=0x80; + fr->file_size = 0; + fr->offset_error=0; + fr->offset_ok=0; + if(my_fseek(fr->handle, 0, SEEK_SET) < 0 || + fread(&buffer, sizeof(buffer), 1, fr->handle)!=1) + return; + for(i=0x80; i<0x200; i+=8) + { + const struct x4a_catalog *p=(const struct x4a_catalog *)&buffer[i]; + if(be32(p->size) > fs) + fs=be32(p->size); + } + if(my_fseek(fr->handle, 0, SEEK_SET) < 0 || + fread(&buffer, 8, 1, fr->handle)!=1) + return; + { + const struct x4a_catalog *p=(const struct x4a_catalog *)buffer; + fr->file_size=fs+be32(p->size); + } +} + +static int header_check_ysfc100(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new) +{ + if(memcmp(&buffer[0x10], "Ver 01.00", 8)!=0 || + memcmp(&buffer[0x30], "YSFC", 4)!=0) + return 0; + reset_file_recovery(file_recovery_new); + if(memcmp(&buffer[6], "ALL", 3)==0) + file_recovery_new->extension=file_hint_x4a.extension; + else if(memcmp(&buffer[6], "SONG", 4)==0) + file_recovery_new->extension="x4s"; + else if(memcmp(&buffer[6], "PATTERN", 7)==0) + file_recovery_new->extension="x4p"; + else if(memcmp(&buffer[6], "ARPEGGIO", 8)==0) + file_recovery_new->extension="x4g"; + else + file_recovery_new->extension=file_hint_x4a.extension; + file_recovery_new->min_filesize=0x200; + file_recovery_new->file_check=&file_check_x4a; + return 1; +} + +static void register_header_check_ysfc100(file_stat_t *file_stat) +{ + static const unsigned char ysfc100_header[8]= { + 'Y' , 'S' , 'F' , 'C' , 0xff, 0xff, 0xff, 0xff + }; + register_header_check(0x30, ysfc100_header, sizeof(ysfc100_header), &header_check_ysfc100, file_stat); +} |