tweak byteio & ase to avoid unaligned access
This commit is contained in:
parent
900e841228
commit
ecbc0c8501
45
src/ase.c
45
src/ase.c
@ -9,7 +9,6 @@
|
||||
#include "scratch.h"
|
||||
#include "byteio.h"
|
||||
#include "string.h"
|
||||
#include "log.h"
|
||||
|
||||
/* ========================== *
|
||||
* Bitbuf
|
||||
@ -26,8 +25,10 @@ INTERNAL u32 peek_bits(struct bitbuf *bb, u32 nbits)
|
||||
|
||||
u64 cur_byte = bb->cur_bit >> 3;
|
||||
u8 bit_index = bb->cur_bit % 8;
|
||||
u64 nbytes = (nbits + bit_index + 7) >> 3;
|
||||
|
||||
u64 val64 = *(u64 *)&bb->data[cur_byte];
|
||||
u64 val64 = 0;
|
||||
MEMCPY(&val64, &bb->data[cur_byte], nbytes);
|
||||
u32 val32 = (u32)(val64 >> bit_index);
|
||||
val32 &= U32_MAX >> (32 - nbits);
|
||||
|
||||
@ -379,7 +380,7 @@ INTERNAL void inflate(struct arena *arena, u8 *dest, u8 *encoded)
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Decode image
|
||||
* Decoder structs
|
||||
* ========================== */
|
||||
|
||||
#define LAYER_FLAG_NONE 0x0
|
||||
@ -441,6 +442,21 @@ struct frame_header {
|
||||
u32 chunks_new;
|
||||
} PACKED;
|
||||
|
||||
INTERNAL void push_error_copy_msg(struct arena *arena, struct ase_error_list *list, struct string msg_src)
|
||||
{
|
||||
struct ase_error *e = arena_push(arena, struct ase_error);
|
||||
*e = (struct ase_error) {
|
||||
.msg = string_copy(arena, msg_src)
|
||||
};
|
||||
if (!list->first) {
|
||||
list->first = e;
|
||||
} else {
|
||||
list->last->next = e;
|
||||
}
|
||||
list->last = e;
|
||||
++list->count;
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Image decoder
|
||||
* ========================== */
|
||||
@ -544,16 +560,15 @@ struct ase_decode_image_result ase_decode_image(struct arena *arena, struct buff
|
||||
br_read_to_struct(&br, &ase_header);
|
||||
|
||||
if (ase_header.magic != 0xA5E0) {
|
||||
res.valid = false;
|
||||
res.error_msg = STR("Not a valid aseprite file");
|
||||
push_error_copy_msg(arena, &res.errors, STR("Not a valid aseprite file"));
|
||||
goto abort;
|
||||
}
|
||||
|
||||
if (ase_header.color_depth != 32) {
|
||||
res.valid = false;
|
||||
res.error_msg = string_format(arena,
|
||||
STR("Only 32 bit rgba color mode is supported (got %F)"),
|
||||
FMT_UINT(ase_header.color_depth));
|
||||
struct string msg = string_format(scratch.arena,
|
||||
STR("Only 32 bit rgba color mode is supported (got %F)"),
|
||||
FMT_UINT(ase_header.color_depth));
|
||||
push_error_copy_msg(arena, &res.errors, msg);
|
||||
goto abort;
|
||||
}
|
||||
|
||||
@ -615,8 +630,9 @@ struct ase_decode_image_result ase_decode_image(struct arena *arena, struct buff
|
||||
|
||||
layer->blend_mode = br_read_u16(&br);
|
||||
if (layer->blend_mode != 0) {
|
||||
res.valid = false;
|
||||
res.error_msg = STR("Layer has unsupported blend mode (only 'Normal' mode is supported). Tip: Try using 'merge down' to create a normal layer as a workaround");
|
||||
push_error_copy_msg(arena,
|
||||
&res.errors,
|
||||
STR("Layer has unsupported blend mode (only 'Normal' mode is supported). Tip: Try using 'merge down' to create a normal layer as a workaround"));
|
||||
goto abort;
|
||||
}
|
||||
|
||||
@ -685,8 +701,7 @@ struct ase_decode_image_result ase_decode_image(struct arena *arena, struct buff
|
||||
|
||||
case CEL_TYPE_COMPRESSED_TILEMAP: {
|
||||
/* Unsupported */
|
||||
res.valid = false;
|
||||
res.error_msg = STR("Tilemaps are not supported");
|
||||
push_error_copy_msg(arena, &res.errors, STR("Tilemaps are not supported"));
|
||||
goto abort;
|
||||
} break;
|
||||
}
|
||||
@ -781,10 +796,9 @@ struct ase_decode_image_result ase_decode_image(struct arena *arena, struct buff
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ASSERT all data was read */
|
||||
ASSERT(br_bytes_left(&br) == 0);
|
||||
res.valid = true;
|
||||
|
||||
abort:
|
||||
|
||||
scratch_end(scratch);
|
||||
@ -904,7 +918,6 @@ struct ase_decode_sheet_result ase_decode_sheet(struct arena *arena, struct buff
|
||||
|
||||
/* ASSERT all data was read */
|
||||
ASSERT(br_bytes_left(&br) == 0);
|
||||
res.valid = true;
|
||||
|
||||
scratch_end(scratch);
|
||||
|
||||
|
||||
17
src/ase.h
17
src/ase.h
@ -1,6 +1,17 @@
|
||||
#ifndef ASE_H
|
||||
#define ASE_H
|
||||
|
||||
struct ase_error {
|
||||
struct string msg;
|
||||
struct ase_error *next;
|
||||
};
|
||||
|
||||
struct ase_error_list {
|
||||
u64 count;
|
||||
struct ase_error *first;
|
||||
struct ase_error *last;
|
||||
};
|
||||
|
||||
struct ase_tag {
|
||||
struct string name;
|
||||
u32 start;
|
||||
@ -17,8 +28,7 @@ struct ase_frame {
|
||||
|
||||
struct ase_decode_image_result {
|
||||
struct image_rgba image;
|
||||
b32 valid;
|
||||
struct string error_msg;
|
||||
struct ase_error_list errors;
|
||||
};
|
||||
|
||||
struct ase_decode_sheet_result {
|
||||
@ -28,8 +38,7 @@ struct ase_decode_sheet_result {
|
||||
u32 num_tags;
|
||||
struct ase_frame *frame_head;
|
||||
struct ase_tag *tag_head;
|
||||
b32 valid;
|
||||
struct string error_msg;
|
||||
struct ase_error_list errors;
|
||||
};
|
||||
|
||||
struct ase_decode_image_result ase_decode_image(struct arena *arena, struct buffer encoded);
|
||||
|
||||
32
src/byteio.c
32
src/byteio.c
@ -145,7 +145,9 @@ u8 br_read_u8(struct byte_reader *br)
|
||||
if (br_overflow_check(br, sizeof(u8))) {
|
||||
return 0;
|
||||
}
|
||||
return *(u8 *)read_unsafe(br, sizeof(u8));
|
||||
u8 res = 0;
|
||||
MEMCPY(&res, read_unsafe(br, sizeof(u8)), sizeof(u8));
|
||||
return res;
|
||||
}
|
||||
|
||||
u16 br_read_u16(struct byte_reader *br)
|
||||
@ -153,7 +155,9 @@ u16 br_read_u16(struct byte_reader *br)
|
||||
if (br_overflow_check(br, sizeof(u16))) {
|
||||
return 0;
|
||||
}
|
||||
return *(u16 *)read_unsafe(br, sizeof(u16));
|
||||
u16 res = 0;
|
||||
MEMCPY(&res, read_unsafe(br, sizeof(u16)), sizeof(u16));
|
||||
return res;
|
||||
}
|
||||
|
||||
u32 br_read_u32(struct byte_reader *br)
|
||||
@ -161,7 +165,9 @@ u32 br_read_u32(struct byte_reader *br)
|
||||
if (br_overflow_check(br, sizeof(u32))) {
|
||||
return 0;
|
||||
}
|
||||
return *(u32 *)read_unsafe(br, sizeof(u32));
|
||||
u32 res = 0;
|
||||
MEMCPY(&res, read_unsafe(br, sizeof(u32)), sizeof(u32));
|
||||
return res;
|
||||
}
|
||||
|
||||
u64 br_read_u64(struct byte_reader *br)
|
||||
@ -169,7 +175,9 @@ u64 br_read_u64(struct byte_reader *br)
|
||||
if (br_overflow_check(br, sizeof(u64))) {
|
||||
return 0;
|
||||
}
|
||||
return *(u64 *)read_unsafe(br, sizeof(u64));
|
||||
u64 res = 0;
|
||||
MEMCPY(&res, read_unsafe(br, sizeof(u64)), sizeof(u64));
|
||||
return res;
|
||||
}
|
||||
|
||||
i8 br_read_i8(struct byte_reader *br)
|
||||
@ -177,7 +185,9 @@ i8 br_read_i8(struct byte_reader *br)
|
||||
if (br_overflow_check(br, sizeof(i8))) {
|
||||
return 0;
|
||||
}
|
||||
return *(i8 *)read_unsafe(br, sizeof(i8));
|
||||
i8 res = 0;
|
||||
MEMCPY(&res, read_unsafe(br, sizeof(i8)), sizeof(i8));
|
||||
return res;
|
||||
}
|
||||
|
||||
i16 br_read_i16(struct byte_reader *br)
|
||||
@ -185,7 +195,9 @@ i16 br_read_i16(struct byte_reader *br)
|
||||
if (br_overflow_check(br, sizeof(i16))) {
|
||||
return 0;
|
||||
}
|
||||
return *(i16 *)read_unsafe(br, sizeof(i16));
|
||||
i16 res = 0;
|
||||
MEMCPY(&res, read_unsafe(br, sizeof(i16)), sizeof(i16));
|
||||
return res;
|
||||
}
|
||||
|
||||
i32 br_read_i32(struct byte_reader *br)
|
||||
@ -193,7 +205,9 @@ i32 br_read_i32(struct byte_reader *br)
|
||||
if (br_overflow_check(br, sizeof(i32))) {
|
||||
return 0;
|
||||
}
|
||||
return *(i32 *)read_unsafe(br, sizeof(i32));
|
||||
i32 res = 0;
|
||||
MEMCPY(&res, read_unsafe(br, sizeof(i32)), sizeof(i32));
|
||||
return res;
|
||||
}
|
||||
|
||||
i64 br_read_i64(struct byte_reader *br)
|
||||
@ -201,7 +215,9 @@ i64 br_read_i64(struct byte_reader *br)
|
||||
if (br_overflow_check(br, sizeof(i64))) {
|
||||
return 0;
|
||||
}
|
||||
return *(i64 *)read_unsafe(br, sizeof(i64));
|
||||
i64 res = 0;
|
||||
MEMCPY(&res, read_unsafe(br, sizeof(i64)), sizeof(i64));
|
||||
return res;
|
||||
}
|
||||
|
||||
u64 br_read_var_uint(struct byte_reader *br)
|
||||
|
||||
11
src/common.h
11
src/common.h
@ -404,6 +404,8 @@ struct buffer {
|
||||
((struct string) { .len = ARRAY_COUNT(a), .text = (u8 *)(a) }) \
|
||||
)
|
||||
|
||||
#define STRING_FROM_BUFFER(buff) ((struct string) { buff.size, buff.data})
|
||||
|
||||
/* ========================== *
|
||||
* Math types
|
||||
* ========================== */
|
||||
@ -483,7 +485,8 @@ struct trs {
|
||||
* Common utilities
|
||||
* ========================== */
|
||||
|
||||
|
||||
INLINE u8 min_u8(u8 a, u8 b) { return a <= b ? a : b; }
|
||||
INLINE u8 max_u8(u8 a, u8 b) { return a >= b ? a : b; }
|
||||
INLINE u32 min_u32(u32 a, u32 b) { return a <= b ? a : b; }
|
||||
INLINE u32 max_u32(u32 a, u32 b) { return a >= b ? a : b; }
|
||||
INLINE u64 min_u64(u64 a, u64 b) { return a <= b ? a : b; }
|
||||
@ -497,10 +500,12 @@ INLINE f32 max_f32(f32 a, f32 b) { return a >= b ? a : b; }
|
||||
INLINE f64 min_f64(f64 a, f64 b) { return a <= b ? a : b; }
|
||||
INLINE f64 max_f64(f64 a, f64 b) { return a >= b ? a : b; }
|
||||
|
||||
INLINE f32 clamp_f32(f32 v, f32 min, f32 max) { return v < min ? min : v > max ? max : v; }
|
||||
INLINE f64 clamp_f64(f64 v, f64 min, f64 max) { return v < min ? min : v > max ? max : v; }
|
||||
INLINE u32 clamp_u32(u32 v, u32 min, u32 max) { return v < min ? min : v > max ? max : v; }
|
||||
INLINE u64 clamp_u64(u64 v, u64 min, u64 max) { return v < min ? min : v > max ? max : v; }
|
||||
INLINE i32 clamp_i32(i32 v, i32 min, i32 max) { return v < min ? min : v > max ? max : v; }
|
||||
INLINE i64 clamp_i64(i64 v, i64 min, i64 max) { return v < min ? min : v > max ? max : v; }
|
||||
INLINE f32 clamp_f32(f32 v, f32 min, f32 max) { return v < min ? min : v > max ? max : v; }
|
||||
INLINE f64 clamp_f64(f64 v, f64 min, f64 max) { return v < min ? min : v > max ? max : v; }
|
||||
|
||||
INLINE u64 cstr_len(char *cstr)
|
||||
{
|
||||
|
||||
23
src/log.c
23
src/log.c
@ -3,12 +3,6 @@
|
||||
#include "string.h"
|
||||
#include "atomic.h"
|
||||
|
||||
#if RTC
|
||||
# define ASSERT_INITIALIZED ASSERT(atomic_i32_eval(&L.initialized) == 1)
|
||||
#else
|
||||
# define ASSERT_INITIALIZED
|
||||
#endif
|
||||
|
||||
struct log_event_callback {
|
||||
log_event_callback_func *func;
|
||||
i32 level;
|
||||
@ -20,10 +14,7 @@ struct log_event_callback {
|
||||
* ========================== */
|
||||
|
||||
GLOBAL struct {
|
||||
#if RTC
|
||||
struct atomic_i32 initialized;
|
||||
#endif
|
||||
|
||||
struct sys_mutex mutex;
|
||||
struct arena arena;
|
||||
log_event_callback_func *callbacks_head;
|
||||
@ -75,11 +66,7 @@ struct log_startup_receipt log_startup(struct string logfile_path)
|
||||
L.file_valid = true;
|
||||
}
|
||||
}
|
||||
|
||||
#if RTC
|
||||
atomic_i32_eval_exchange(&L.initialized, 1);
|
||||
#endif
|
||||
|
||||
return (struct log_startup_receipt) { 0 };
|
||||
}
|
||||
|
||||
@ -89,7 +76,7 @@ struct log_startup_receipt log_startup(struct string logfile_path)
|
||||
|
||||
void log_register_callback(log_event_callback_func *func)
|
||||
{
|
||||
ASSERT_INITIALIZED;
|
||||
if (!atomic_i32_eval(&L.initialized)) { return; }
|
||||
sys_mutex_lock(&L.mutex);
|
||||
{
|
||||
/* TODO */
|
||||
@ -105,7 +92,7 @@ void log_register_callback(log_event_callback_func *func)
|
||||
INTERNAL void append_to_logfile(struct string msg)
|
||||
{
|
||||
__prof;
|
||||
ASSERT_INITIALIZED;
|
||||
if (!atomic_i32_eval(&L.initialized)) { return; }
|
||||
|
||||
if (L.file_valid) {
|
||||
struct temp_arena scratch = scratch_begin_no_conflict();
|
||||
@ -122,7 +109,7 @@ void _log(i32 level, struct string msg)
|
||||
#endif
|
||||
{
|
||||
__prof;
|
||||
ASSERT_INITIALIZED;
|
||||
if (!atomic_i32_eval(&L.initialized)) { return; }
|
||||
|
||||
if (level < 0 || level >= LOG_LEVEL_COUNT) {
|
||||
sys_panic_raw("Invalid log level");
|
||||
@ -192,7 +179,7 @@ void _logfv(i32 level, struct string file, u32 line, struct string fmt, va_list
|
||||
void _logfv(i32 level, struct string fmt, va_list args)
|
||||
#endif
|
||||
{
|
||||
ASSERT_INITIALIZED;
|
||||
if (!atomic_i32_eval(&L.initialized)) { return; }
|
||||
struct temp_arena scratch = scratch_begin_no_conflict();
|
||||
struct string msg = string_formatv(scratch.arena, fmt, args);
|
||||
#if LOG_INCLUDE_SOURCE_LOCATION
|
||||
@ -209,7 +196,7 @@ void _logf(i32 level, struct string file, u32 line, struct string fmt, ...)
|
||||
void _logf(i32 level, struct string fmt, ...)
|
||||
#endif
|
||||
{
|
||||
ASSERT_INITIALIZED;
|
||||
if (!atomic_i32_eval(&L.initialized)) { return; }
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
#if LOG_INCLUDE_SOURCE_LOCATION
|
||||
|
||||
@ -13,7 +13,7 @@ void *memcpy(void *restrict dest, const void *restrict src, u64 n)
|
||||
}
|
||||
|
||||
__attribute((section(".text.memset")))
|
||||
void *memset(void *dest, int c, u64 n)
|
||||
void *memset(void *dest, i32 c, u64 n)
|
||||
{
|
||||
/* TODO: Faster memset */
|
||||
for (u64 i = 0; i < (n); ++i) {
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
# include <memory.h>
|
||||
#else
|
||||
void *memcpy(void *__restrict dest, const void *__restrict src, u64 n);
|
||||
void *memset(void *dest, int c, u64 n);
|
||||
void *memset(void *dest, i32 c, u64 n);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@ -165,9 +165,11 @@ INTERNAL WORK_TASK_FUNC_DEF(sheet_load_asset_task, vparams)
|
||||
resource_close(sheet_rs);
|
||||
|
||||
/* Failure paths */
|
||||
if (!decoded.valid) {
|
||||
if (decoded.error_msg.len > 0) {
|
||||
error_msg = decoded.error_msg;
|
||||
if (decoded.errors.count > 0) {
|
||||
/* FIXME: Read all errors from decode */
|
||||
struct string msg = decoded.errors.first->msg;
|
||||
if (msg.len > 0) {
|
||||
error_msg = msg;
|
||||
}
|
||||
goto abort;
|
||||
} else {
|
||||
|
||||
@ -152,9 +152,11 @@ INTERNAL WORK_TASK_FUNC_DEF(texture_load_asset_task, vparams)
|
||||
resource_close(texture_rs);
|
||||
|
||||
/* Failure paths */
|
||||
if (!decoded.valid) {
|
||||
if (decoded.error_msg.len > 0) {
|
||||
error_msg = decoded.error_msg;
|
||||
if (decoded.errors.count > 0) {
|
||||
/* FIXME: Read all errors from decode */
|
||||
struct string msg = decoded.errors.first->msg;
|
||||
if (msg.len > 0) {
|
||||
error_msg = msg;
|
||||
}
|
||||
goto abort;
|
||||
} else if (decoded.image.width > RENDERER_TEXTURE_MAX_WIDTH || decoded.image.height > RENDERER_TEXTURE_MAX_HEIGHT) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user