Implemented CAFF stuff
This commit is contained in:
parent
b42f8fe4ef
commit
cbb8da45ce
@ -3,4 +3,4 @@ project(caff_previewer C)
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
|
||||
add_executable(caff_previewer src/main.c src/magic_memory.c src/magic_memory.h src/ciff_tools.h src/ciff_tools.c src/libtarga.c src/libtarga.h src/pixeldata_utils.c src/pixeldata_utils.h src/utils.c src/utils.h)
|
||||
add_executable(caff_previewer src/main.c src/magic_memory.c src/magic_memory.h src/ciff_tools.h src/ciff_tools.c src/libtarga.c src/libtarga.h src/pixeldata_utils.c src/pixeldata_utils.h src/caff_tools.c src/caff_tools.h src/utils.c src/utils.h)
|
197
src/caff_tools.c
Normal file
197
src/caff_tools.c
Normal file
@ -0,0 +1,197 @@
|
||||
//
|
||||
// Created by marcsello on 03/11/2020.
|
||||
//
|
||||
|
||||
#include "caff_tools.h"
|
||||
#include "ciff_tools.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
// Validator = Parses data and checks it's validity, but not returning the provided data.
|
||||
// Parser = Parses data and checks it's validity, returns the parsed data.
|
||||
|
||||
uint8_t parse_caff_header(uint8_t *data, uint64_t data_len, uint64_t *num_anim) {
|
||||
|
||||
if (data_len != sizeof(caff_header_t)) {
|
||||
return CAFF_PARSE_LENGTH_ERROR;
|
||||
}
|
||||
|
||||
caff_header_t *header_info = (caff_header_t *) data;
|
||||
|
||||
if (header_info->magic != 0x46464143) {
|
||||
return CAFF_PARSE_BAD_MAGIC;
|
||||
}
|
||||
|
||||
if (header_info->header_size != 20) {
|
||||
return CAFF_PARSE_LENGTH_ERROR;
|
||||
}
|
||||
|
||||
if (header_info->num_anim == 0) {
|
||||
return CAFF_PARSE_ANIMATION_COUNT_ERROR;
|
||||
}
|
||||
|
||||
*num_anim = header_info->num_anim;
|
||||
|
||||
return CAFF_PARSE_SUCCESS; // Sikeres parsolás == Valid formátum
|
||||
|
||||
}
|
||||
|
||||
uint8_t validate_caff_credits(uint8_t *data, uint64_t data_len) {
|
||||
|
||||
if (data_len < sizeof(credits_header_t)) {
|
||||
return CAFF_PARSE_LENGTH_ERROR;
|
||||
}
|
||||
|
||||
credits_header_t *header_info = (credits_header_t *) data;
|
||||
|
||||
if (header_info->month > 12 || header_info->month == 0) {
|
||||
return CAFF_PARSE_BAD_DATE;
|
||||
}
|
||||
|
||||
uint8_t month_lengths[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||
|
||||
if (header_info->day > month_lengths[header_info->month - 1] || header_info->day == 0) {
|
||||
return CAFF_PARSE_BAD_DATE;
|
||||
}
|
||||
|
||||
if (header_info->hour > 23) {
|
||||
return CAFF_PARSE_BAD_DATE;
|
||||
}
|
||||
|
||||
if (header_info->minute > 60) {
|
||||
return CAFF_PARSE_BAD_DATE;
|
||||
}
|
||||
|
||||
uint64_t calculated_len = header_info->creator_len + sizeof(credits_header_t);
|
||||
|
||||
if (calculated_len != data_len) {
|
||||
return CAFF_PARSE_LENGTH_ERROR;
|
||||
}
|
||||
|
||||
return CAFF_PARSE_SUCCESS;
|
||||
}
|
||||
|
||||
uint8_t validate_caff_animation(uint8_t *data, uint64_t data_len) {
|
||||
|
||||
if (data_len < sizeof(animation_header_t)) {
|
||||
return CAFF_PARSE_LENGTH_ERROR;
|
||||
}
|
||||
|
||||
animation_header_t *header_info = (animation_header_t *) data;
|
||||
|
||||
|
||||
if (header_info->duration == 0) {
|
||||
return CAFF_PARSE_NO_DURATION;
|
||||
}
|
||||
|
||||
// NOTE: Ciff validation is solved in the CIFF tools
|
||||
uint8_t result = validate_ciff(data + sizeof(animation_header_t), data_len - sizeof(animation_header_t));
|
||||
|
||||
if (result != CIFF_PARSE_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return CAFF_PARSE_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
|
||||
uint8_t validate_caff_file(uint8_t *data, uint64_t data_len) {
|
||||
|
||||
uint8_t *p = data;
|
||||
|
||||
uint64_t frame_counter = 0;
|
||||
uint64_t len_remaining = data_len;
|
||||
uint64_t expected_num_anim;
|
||||
uint64_t num_anim = 0;
|
||||
bool credits_found = false;
|
||||
|
||||
while (len_remaining > 0) {
|
||||
|
||||
if (len_remaining < sizeof(caff_frame_header_t)) {
|
||||
return CAFF_PARSE_LENGTH_ERROR;
|
||||
}
|
||||
|
||||
caff_frame_header_t *frame_header = (caff_frame_header_t *) p;
|
||||
|
||||
if (!(
|
||||
frame_header->id == CAFF_FRAME_HEADER ||
|
||||
frame_header->id == CAFF_FRAME_CREDITS ||
|
||||
frame_header->id == CAFF_FRAME_ANIMATION)) {
|
||||
return CAFF_PARSE_BAD_FRAME;
|
||||
}
|
||||
|
||||
if (frame_header->length > len_remaining) {
|
||||
return CAFF_PARSE_LENGTH_ERROR;
|
||||
}
|
||||
|
||||
if ((frame_counter == 0 && frame_header->id != CAFF_FRAME_HEADER) ||
|
||||
(frame_counter > 0 && frame_header->id == CAFF_FRAME_HEADER)) {
|
||||
return CAFF_PARSE_HEADER_ERROR;
|
||||
}
|
||||
|
||||
uint8_t result;
|
||||
switch (frame_header->id) {
|
||||
case CAFF_FRAME_HEADER:
|
||||
result = parse_caff_header(p + sizeof(struct caff_frame_header_t),
|
||||
frame_header->length, &expected_num_anim);
|
||||
break;
|
||||
case CAFF_FRAME_CREDITS:
|
||||
result = validate_caff_credits(p + sizeof(struct caff_frame_header_t), frame_header->length);
|
||||
credits_found = true;
|
||||
break;
|
||||
case CAFF_FRAME_ANIMATION:
|
||||
result = validate_caff_animation(p + sizeof(struct caff_frame_header_t), frame_header->length);
|
||||
num_anim++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (result != CAFF_PARSE_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
frame_counter++;
|
||||
uint64_t seek_by = frame_header->length + sizeof(caff_frame_header_t);
|
||||
len_remaining -= seek_by;
|
||||
p += seek_by;
|
||||
}
|
||||
|
||||
if (expected_num_anim != num_anim) {
|
||||
return CAFF_PARSE_ANIMATION_COUNT_ERROR;
|
||||
}
|
||||
|
||||
if (!credits_found) {
|
||||
return CAFF_PARSE_NO_CREDITS_ERROR;
|
||||
}
|
||||
|
||||
|
||||
return CAFF_PARSE_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
uint8_t parse_caff_get_first_ciff(uint8_t *caff_data, uint64_t caff_data_len, uint8_t **ciff_ptr, uint64_t *ciff_len) {
|
||||
|
||||
uint8_t result = validate_caff_file(caff_data, caff_data_len);
|
||||
|
||||
if (result != CAFF_PARSE_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Seek for the first CIFF header
|
||||
uint8_t *p = caff_data;
|
||||
uint64_t caff_data_len_remaining = caff_data_len;
|
||||
while (caff_data_len_remaining > 0) {
|
||||
caff_frame_header_t *frame_header = (caff_frame_header_t *) p;
|
||||
|
||||
if (frame_header->id == CAFF_FRAME_ANIMATION) {
|
||||
*ciff_ptr = p + sizeof(caff_frame_header_t) + sizeof(animation_header_t);
|
||||
*ciff_len = frame_header->length - sizeof(animation_header_t);
|
||||
return CAFF_PARSE_SUCCESS;
|
||||
}
|
||||
|
||||
uint64_t seek_by = frame_header->length + sizeof(caff_frame_header_t);
|
||||
caff_data_len_remaining -= seek_by;
|
||||
p += seek_by;
|
||||
}
|
||||
|
||||
return CAFF_PARSE_ANIMATION_COUNT_ERROR;
|
||||
}
|
57
src/caff_tools.h
Normal file
57
src/caff_tools.h
Normal file
@ -0,0 +1,57 @@
|
||||
//
|
||||
// Created by marcsello on 03/11/2020.
|
||||
//
|
||||
|
||||
#ifndef CAFF_PREVIEWER_CAFF_TOOLS_H
|
||||
#define CAFF_PREVIEWER_CAFF_TOOLS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define CAFF_PARSE_SUCCESS 0
|
||||
#define CAFF_PARSE_LENGTH_ERROR 1
|
||||
#define CAFF_PARSE_BAD_FRAME 2
|
||||
#define CAFF_PARSE_HEADER_ERROR 3
|
||||
#define CAFF_PARSE_ANIMATION_COUNT_ERROR 4
|
||||
#define CAFF_PARSE_NO_CREDITS_ERROR 5
|
||||
#define CAFF_PARSE_BAD_MAGIC 6
|
||||
#define CAFF_PARSE_BAD_DATE 7
|
||||
#define CAFF_PARSE_NO_DURATION 8
|
||||
|
||||
#define CAFF_FRAME_HEADER 0x1
|
||||
#define CAFF_FRAME_CREDITS 0x2
|
||||
#define CAFF_FRAME_ANIMATION 0x3
|
||||
|
||||
|
||||
|
||||
typedef struct __attribute__ ((packed)) caff_frame_header_t {
|
||||
uint8_t id;
|
||||
uint64_t length;
|
||||
} caff_frame_header_t;
|
||||
|
||||
typedef struct __attribute__ ((packed)) caff_header_t { // Note: CAFF Header lives inside a frame
|
||||
uint32_t magic; //Should be to 0x46464143 (note the reversed order)
|
||||
uint64_t header_size; // Constant 20???
|
||||
uint64_t num_anim;
|
||||
} caff_header_t;
|
||||
|
||||
typedef struct __attribute__ ((packed)) credits_header_t { // Note: CAFF Header lives inside a frame
|
||||
uint16_t year;
|
||||
uint8_t month;
|
||||
uint8_t day;
|
||||
uint8_t hour;
|
||||
uint8_t minute;
|
||||
uint64_t creator_len;
|
||||
} credits_header_t;
|
||||
|
||||
|
||||
typedef struct __attribute__ ((packed)) animation_header_t {
|
||||
uint64_t duration;
|
||||
} animation_header_t;
|
||||
|
||||
|
||||
uint8_t validate_caff_file(uint8_t* data, uint64_t data_len);
|
||||
uint8_t parse_caff_get_first_ciff(uint8_t* caff_data, uint64_t caff_data_len, uint8_t **ciff_ptr, uint64_t* ciff_len);
|
||||
|
||||
|
||||
#endif //CAFF_PREVIEWER_CAFF_TOOLS_H
|
||||
|
27
src/main.c
27
src/main.c
@ -6,33 +6,44 @@
|
||||
#include "magic_memory.h"
|
||||
#include "pixeldata_utils.h"
|
||||
#include "ciff_tools.h"
|
||||
#include "caff_tools.h"
|
||||
#include "utils.h"
|
||||
|
||||
int main() {
|
||||
magic_memory_context_t *context = magic_memory_begin();
|
||||
|
||||
uint8_t *ciff_file;
|
||||
uint64_t ciff_size;
|
||||
uint8_t result = read_file_to_mem(context, "/home/marcsello/Documents/etyetem/szamitobiztonsag/caff/1.ciff",
|
||||
67108864, &ciff_file, &ciff_size);
|
||||
uint8_t *caff_file;
|
||||
uint64_t caff_size;
|
||||
uint8_t result = read_file_to_mem(context, "/home/marcsello/Documents/etyetem/szamitobiztonsag/caff/2.caff",
|
||||
67108864, &caff_file, &caff_size);
|
||||
|
||||
if (result != FILE_READ_SUCCESS) {
|
||||
printf("File read failure: %d", result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t* ciff_ptr;
|
||||
uint64_t ciff_size;
|
||||
|
||||
result = parse_caff_get_first_ciff(caff_file,caff_size,&ciff_ptr, &ciff_size);
|
||||
|
||||
if (result != CAFF_PARSE_SUCCESS) {
|
||||
printf("CAFF Parse failure: %d", result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint64_t width;
|
||||
uint64_t height;
|
||||
uint64_t pixel_data_starts;
|
||||
|
||||
result = get_pixel_data_from_ciff(ciff_file, ciff_size, &width, &height, &pixel_data_starts);
|
||||
result = get_pixel_data_from_ciff(ciff_ptr, ciff_size, &width, &height, &pixel_data_starts);
|
||||
|
||||
uint64_t pixel_data_size = width * height * 3;
|
||||
|
||||
if (result == CIFF_PARSE_SUCCESS) {
|
||||
|
||||
uint8_t *flipped_image = (uint8_t *) magic_malloc(context, ciff_size - pixel_data_starts);
|
||||
if (flip_image(ciff_file + pixel_data_starts, flipped_image, pixel_data_size, width, height) !=
|
||||
uint8_t *flipped_image = (uint8_t *) magic_malloc(context, caff_size - pixel_data_starts);
|
||||
if (flip_image(ciff_ptr + pixel_data_starts, flipped_image, pixel_data_size, width, height) !=
|
||||
IMAGE_FLIP_SUCCESS) {
|
||||
printf("Literally failed to flip the image");
|
||||
} else {
|
||||
@ -43,7 +54,7 @@ int main() {
|
||||
|
||||
|
||||
} else {
|
||||
printf("%d", result);
|
||||
printf("Failed to get pixel data: %d", result);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user