tweak byteio & ase to avoid unaligned access

This commit is contained in:
jacob 2024-04-01 15:10:34 -05:00
parent 900e841228
commit ecbc0c8501
9 changed files with 91 additions and 57 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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)
{

View File

@ -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

View File

@ -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) {

View File

@ -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

View File

@ -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 {

View File

@ -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) {