serialize game cmds
This commit is contained in:
parent
7d0826b57b
commit
a1a1430fd8
15
src/ase.c
15
src/ase.c
@ -647,7 +647,10 @@ struct ase_decode_image_result ase_decode_image(struct arena *arena, struct buff
|
|||||||
br_seek(&br, sizeof(u8) * 3);
|
br_seek(&br, sizeof(u8) * 3);
|
||||||
|
|
||||||
u16 str_len = br_read_u16(&br);
|
u16 str_len = br_read_u16(&br);
|
||||||
u8 *str_bytes = br_read_raw(&br, str_len);
|
u8 *str_bytes = br_seek(&br, str_len);
|
||||||
|
if (!str_bytes) {
|
||||||
|
str_len = 0;
|
||||||
|
}
|
||||||
layer->name = (struct string) {
|
layer->name = (struct string) {
|
||||||
str_len,
|
str_len,
|
||||||
arena_push_array(scratch.arena, u8, str_len)
|
arena_push_array(scratch.arena, u8, str_len)
|
||||||
@ -898,7 +901,10 @@ struct ase_decode_sheet_result ase_decode_sheet(struct arena *arena, struct buff
|
|||||||
br_seek(&br, 13);
|
br_seek(&br, 13);
|
||||||
|
|
||||||
u16 str_len = br_read_u16(&br);
|
u16 str_len = br_read_u16(&br);
|
||||||
u8 *str_bytes = br_read_raw(&br, str_len);
|
u8 *str_bytes = br_seek(&br, str_len);
|
||||||
|
if (!str_bytes) {
|
||||||
|
str_len = 0;
|
||||||
|
}
|
||||||
span->name = (struct string) {
|
span->name = (struct string) {
|
||||||
str_len,
|
str_len,
|
||||||
arena_push_array(arena, u8, str_len)
|
arena_push_array(arena, u8, str_len)
|
||||||
@ -923,7 +929,10 @@ struct ase_decode_sheet_result ase_decode_sheet(struct arena *arena, struct buff
|
|||||||
struct string name;
|
struct string name;
|
||||||
{
|
{
|
||||||
u16 str_len = br_read_u16(&br);
|
u16 str_len = br_read_u16(&br);
|
||||||
u8 *str_bytes = br_read_raw(&br, str_len);
|
u8 *str_bytes = br_seek(&br, str_len);
|
||||||
|
if (!str_bytes) {
|
||||||
|
str_len = 0;
|
||||||
|
}
|
||||||
name = (struct string) {
|
name = (struct string) {
|
||||||
str_len,
|
str_len,
|
||||||
arena_push_array(arena, u8, str_len)
|
arena_push_array(arena, u8, str_len)
|
||||||
|
|||||||
246
src/byteio.c
246
src/byteio.c
@ -6,37 +6,73 @@
|
|||||||
* Writer
|
* Writer
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INTERNAL b32 write_check_overflow(struct byte_writer *bw, u64 amount)
|
INTERNAL b32 write_check_overflow(struct byte_writer *bw, i64 amount)
|
||||||
{
|
{
|
||||||
b32 overflowed = bw->overflowed;
|
b32 overflowed = bw->overflowed;
|
||||||
i64 new_space_left = (bw->at + amount) - (bw->buff.data + bw->buff.size);
|
if (overflowed || amount < 0) {
|
||||||
if (!overflowed && new_space_left < 0) {
|
overflowed = true;
|
||||||
if (bw->arena) {
|
bw->overflowed = true;
|
||||||
arena_push_array(bw->arena, u8, -new_space_left);
|
} else {
|
||||||
bw->buff.size += -new_space_left;
|
u8 *end = bw->buff.data + bw->buff.size;
|
||||||
/* Writer memory should be contiguous in arena */
|
u8 *new_pos = bw->at + amount;
|
||||||
ASSERT((bw->buff.data + bw->buff.size) == (bw->arena->base + bw->arena->pos));
|
i64 new_space_left = end - new_pos;
|
||||||
} else {
|
if (new_space_left < 0) {
|
||||||
bw->overflowed = true;
|
struct arena *arena = bw->arena;
|
||||||
overflowed = true;
|
if (arena) {
|
||||||
|
if ((arena->base + arena->pos) == end) {
|
||||||
|
arena_push_array(arena, u8, -new_space_left);
|
||||||
|
bw->buff.size += -new_space_left;
|
||||||
|
} else {
|
||||||
|
/* Writer memory must be contiguous in arena */
|
||||||
|
overflowed = true;
|
||||||
|
bw->overflowed = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
overflowed = true;
|
||||||
|
bw->overflowed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ASSERT(!overflowed);
|
ASSERT(!overflowed);
|
||||||
return overflowed;
|
return overflowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void write_unsafe(struct byte_writer *bw, void *v, u64 size)
|
INTERNAL void write(struct byte_writer *bw, void *v, u64 size)
|
||||||
{
|
{
|
||||||
|
if (write_check_overflow(bw, size)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
MEMCPY(bw->at, v, size);
|
MEMCPY(bw->at, v, size);
|
||||||
bw->at += size;
|
bw->at += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void write(struct byte_writer *bw, void *v, u64 size)
|
struct byte_writer bw_from_buffer(struct buffer buff)
|
||||||
{
|
{
|
||||||
if (write_check_overflow(bw, sizeof(v))) {
|
struct byte_writer bw = ZI;
|
||||||
return;
|
bw.buff = buff;
|
||||||
}
|
bw.at = buff.data;
|
||||||
write_unsafe(bw, v, size);
|
return bw;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns a writer that will allocate to arena instead of overflowing (writes must stay contiguous in arena) */
|
||||||
|
struct byte_writer bw_from_arena(struct arena *arena)
|
||||||
|
{
|
||||||
|
struct byte_writer bw = ZI;
|
||||||
|
bw.arena = arena;
|
||||||
|
bw.buff.data = arena->base + arena->pos;
|
||||||
|
bw.buff.size = 0;
|
||||||
|
bw.at = bw.buff.data;
|
||||||
|
return bw;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Seeks forward and returns a new writer pointing to the skipped bytes */
|
||||||
|
struct byte_writer bw_branch(struct byte_writer *bw, u64 size)
|
||||||
|
{
|
||||||
|
struct buffer buff = BUFFER(size, bw->at);
|
||||||
|
struct byte_writer branch = bw_from_buffer(buff);
|
||||||
|
bw_seek(bw, size);
|
||||||
|
branch.overflowed = bw->overflowed;
|
||||||
|
return branch;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bw_seek(struct byte_writer *bw, u64 amount)
|
void bw_seek(struct byte_writer *bw, u64 amount)
|
||||||
@ -49,9 +85,8 @@ void bw_seek(struct byte_writer *bw, u64 amount)
|
|||||||
|
|
||||||
void bw_seek_to(struct byte_writer *bw, u64 pos)
|
void bw_seek_to(struct byte_writer *bw, u64 pos)
|
||||||
{
|
{
|
||||||
if (pos > bw->buff.size) {
|
if (write_check_overflow(bw, (i64)pos - (i64)(bw->at - bw->buff.data))) {
|
||||||
ASSERT(false);
|
return;
|
||||||
bw->overflowed = true;
|
|
||||||
}
|
}
|
||||||
bw->at = bw->buff.data + pos;
|
bw->at = bw->buff.data + pos;
|
||||||
}
|
}
|
||||||
@ -113,140 +148,137 @@ void bw_write_var_sint(struct byte_writer *bw, i64 v)
|
|||||||
bw_write_i64(bw, v);
|
bw_write_i64(bw, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bw_write_f32(struct byte_writer *bw, f32 v)
|
||||||
|
{
|
||||||
|
write(bw, &v, sizeof(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
void bw_write_f64(struct byte_writer *bw, f64 v)
|
||||||
|
{
|
||||||
|
write(bw, &v, sizeof(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
void bw_write_v2(struct byte_writer *bw, struct v2 v)
|
||||||
|
{
|
||||||
|
bw_write_f32(bw, v.x);
|
||||||
|
bw_write_f32(bw, v.y);
|
||||||
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Reader
|
* Reader
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INTERNAL b32 read_check_overflow(struct byte_reader *br, u64 amount)
|
INTERNAL b32 read_check_overflow(struct byte_reader *br, i64 amount)
|
||||||
{
|
{
|
||||||
if (br->overflowed || br->at + amount > br->buff.data + br->buff.size) {
|
b32 overflowed = br->overflowed;
|
||||||
|
if (overflowed || amount < 0 || (br->at + amount) > (br->buff.data + br->buff.size) ){
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
br->overflowed = true;
|
br->overflowed = true;
|
||||||
return true;
|
overflowed = true;
|
||||||
}
|
}
|
||||||
return false;
|
return overflowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void br_seek(struct byte_reader *br, u64 amount)
|
INTERNAL void read(struct byte_reader *br, void *dst, u64 size)
|
||||||
{
|
|
||||||
if (read_check_overflow(br, amount)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
br->at += amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void br_seek_to(struct byte_reader *br, u64 pos)
|
|
||||||
{
|
|
||||||
if (pos > br->buff.size) {
|
|
||||||
ASSERT(false);
|
|
||||||
br->overflowed = true;
|
|
||||||
}
|
|
||||||
br->at = br->buff.data + pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
INTERNAL void *read_unsafe(struct byte_reader *br, u64 size)
|
|
||||||
{
|
|
||||||
void *prev = br->at;
|
|
||||||
br->at += size;
|
|
||||||
return prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Will return NULL on overflow */
|
|
||||||
void *br_read_raw(struct byte_reader *br, u64 size)
|
|
||||||
{
|
{
|
||||||
if (read_check_overflow(br, size)) {
|
if (read_check_overflow(br, size)) {
|
||||||
return NULL;
|
MEMZERO(dst, size);
|
||||||
}
|
}
|
||||||
return read_unsafe(br, size);
|
MEMCPY(dst, br->at, size);
|
||||||
|
br->at += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Will not read any data on overflow */
|
struct byte_reader br_from_buffer(struct buffer buff)
|
||||||
|
{
|
||||||
|
struct byte_reader br = ZI;
|
||||||
|
br.buff = buff;
|
||||||
|
br.at = buff.data;
|
||||||
|
return br;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns pointer to old position, or NULL on overflow */
|
||||||
|
void *br_seek(struct byte_reader *br, u64 amount)
|
||||||
|
{
|
||||||
|
void *ptr = NULL;
|
||||||
|
if (read_check_overflow(br, amount)) {
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
ptr = br->at;
|
||||||
|
br->at += amount;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns pointer to old position, or NULL on overflow */
|
||||||
|
void *br_seek_to(struct byte_reader *br, u64 pos)
|
||||||
|
{
|
||||||
|
void *ptr = NULL;
|
||||||
|
if (read_check_overflow(br, (i64)pos - (i64)(br->at - br->buff.data))) {
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
ptr = br->at;
|
||||||
|
br->at = br->buff.data + pos;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Will fill buff with zeroes on overflow */
|
||||||
void br_read_to_buffer(struct byte_reader *br, struct buffer buff)
|
void br_read_to_buffer(struct byte_reader *br, struct buffer buff)
|
||||||
{
|
{
|
||||||
if (read_check_overflow(br, buff.size)) {
|
read(br, buff.data, buff.size);
|
||||||
return;
|
|
||||||
}
|
|
||||||
u8 *bytes = read_unsafe(br, buff.size);
|
|
||||||
MEMCPY(buff.data, bytes, buff.size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 br_read_u8(struct byte_reader *br)
|
u8 br_read_u8(struct byte_reader *br)
|
||||||
{
|
{
|
||||||
if (read_check_overflow(br, sizeof(u8))) {
|
u8 res;
|
||||||
return 0;
|
read(br, &res, sizeof(res));
|
||||||
}
|
|
||||||
u8 res = 0;
|
|
||||||
MEMCPY(&res, read_unsafe(br, sizeof(u8)), sizeof(u8));
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 br_read_u16(struct byte_reader *br)
|
u16 br_read_u16(struct byte_reader *br)
|
||||||
{
|
{
|
||||||
if (read_check_overflow(br, sizeof(u16))) {
|
u16 res;
|
||||||
return 0;
|
read(br, &res, sizeof(res));
|
||||||
}
|
|
||||||
u16 res = 0;
|
|
||||||
MEMCPY(&res, read_unsafe(br, sizeof(u16)), sizeof(u16));
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 br_read_u32(struct byte_reader *br)
|
u32 br_read_u32(struct byte_reader *br)
|
||||||
{
|
{
|
||||||
if (read_check_overflow(br, sizeof(u32))) {
|
u32 res;
|
||||||
return 0;
|
read(br, &res, sizeof(res));
|
||||||
}
|
|
||||||
u32 res = 0;
|
|
||||||
MEMCPY(&res, read_unsafe(br, sizeof(u32)), sizeof(u32));
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 br_read_u64(struct byte_reader *br)
|
u64 br_read_u64(struct byte_reader *br)
|
||||||
{
|
{
|
||||||
if (read_check_overflow(br, sizeof(u64))) {
|
u64 res;
|
||||||
return 0;
|
read(br, &res, sizeof(res));
|
||||||
}
|
|
||||||
u64 res = 0;
|
|
||||||
MEMCPY(&res, read_unsafe(br, sizeof(u64)), sizeof(u64));
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
i8 br_read_i8(struct byte_reader *br)
|
i8 br_read_i8(struct byte_reader *br)
|
||||||
{
|
{
|
||||||
if (read_check_overflow(br, sizeof(i8))) {
|
i8 res;
|
||||||
return 0;
|
read(br, &res, sizeof(res));
|
||||||
}
|
|
||||||
i8 res = 0;
|
|
||||||
MEMCPY(&res, read_unsafe(br, sizeof(i8)), sizeof(i8));
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
i16 br_read_i16(struct byte_reader *br)
|
i16 br_read_i16(struct byte_reader *br)
|
||||||
{
|
{
|
||||||
if (read_check_overflow(br, sizeof(i16))) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
i16 res = 0;
|
i16 res = 0;
|
||||||
MEMCPY(&res, read_unsafe(br, sizeof(i16)), sizeof(i16));
|
read(br, &res, sizeof(res));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 br_read_i32(struct byte_reader *br)
|
i32 br_read_i32(struct byte_reader *br)
|
||||||
{
|
{
|
||||||
if (read_check_overflow(br, sizeof(i32))) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
i32 res = 0;
|
i32 res = 0;
|
||||||
MEMCPY(&res, read_unsafe(br, sizeof(i32)), sizeof(i32));
|
read(br, &res, sizeof(res));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
i64 br_read_i64(struct byte_reader *br)
|
i64 br_read_i64(struct byte_reader *br)
|
||||||
{
|
{
|
||||||
if (read_check_overflow(br, sizeof(i64))) {
|
i64 res;
|
||||||
return 0;
|
read(br, &res, sizeof(res));
|
||||||
}
|
|
||||||
i64 res = 0;
|
|
||||||
MEMCPY(&res, read_unsafe(br, sizeof(i64)), sizeof(i64));
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,3 +293,25 @@ i64 br_read_var_sint(struct byte_reader *br)
|
|||||||
/* TODO: real varint read */
|
/* TODO: real varint read */
|
||||||
return br_read_i64(br);
|
return br_read_i64(br);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
f32 br_read_f32(struct byte_reader *br)
|
||||||
|
{
|
||||||
|
f32 res;
|
||||||
|
read(br, &res, sizeof(res));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
f64 br_read_f64(struct byte_reader *br)
|
||||||
|
{
|
||||||
|
f64 res;
|
||||||
|
read(br, &res, sizeof(res));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct v2 br_read_v2(struct byte_reader *br)
|
||||||
|
{
|
||||||
|
struct v2 res;
|
||||||
|
res.x = br_read_f32(br);
|
||||||
|
res.y = br_read_f32(br);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|||||||
91
src/byteio.h
91
src/byteio.h
@ -15,62 +15,12 @@ struct byte_reader {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Constructor utils
|
* Writer
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INLINE struct byte_writer bw_from_buffer(struct buffer buff)
|
struct byte_writer bw_from_buffer(struct buffer buff);
|
||||||
{
|
struct byte_writer bw_from_arena(struct arena *arena);
|
||||||
struct byte_writer bw = ZI;
|
struct byte_writer bw_branch(struct byte_writer *bw, u64 size);
|
||||||
bw.buff = buff;
|
|
||||||
bw.at = buff.data;
|
|
||||||
return bw;
|
|
||||||
}
|
|
||||||
|
|
||||||
INLINE struct byte_writer bw_from_arena(struct arena *arena)
|
|
||||||
{
|
|
||||||
struct byte_writer bw = ZI;
|
|
||||||
bw.arena = arena;
|
|
||||||
bw.buff.data = arena->base;
|
|
||||||
bw.buff.size = 0;
|
|
||||||
bw.at = bw.buff.data;
|
|
||||||
return bw;
|
|
||||||
}
|
|
||||||
|
|
||||||
INLINE struct byte_reader br_from_buffer(struct buffer buff)
|
|
||||||
{
|
|
||||||
struct byte_reader br = ZI;
|
|
||||||
br.buff = buff;
|
|
||||||
br.at = buff.data;
|
|
||||||
return br;
|
|
||||||
}
|
|
||||||
|
|
||||||
INLINE struct byte_writer bw_copy(struct byte_writer *bw)
|
|
||||||
{
|
|
||||||
return *bw;
|
|
||||||
}
|
|
||||||
|
|
||||||
INLINE struct byte_reader br_copy(struct byte_reader *br)
|
|
||||||
{
|
|
||||||
return *br;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Generate a buffer struct containing written bytes only */
|
|
||||||
INLINE struct buffer bw_get_written_buffer(struct byte_writer *bw)
|
|
||||||
{
|
|
||||||
struct buffer buff = ZI;
|
|
||||||
buff.data = bw->buff.data;
|
|
||||||
buff.size = bw->at - bw->buff.data;
|
|
||||||
return buff;
|
|
||||||
}
|
|
||||||
|
|
||||||
INLINE u64 bw_pos(struct byte_reader *bw)
|
|
||||||
{
|
|
||||||
return bw->at - bw->buff.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ========================== *
|
|
||||||
* Write
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
void bw_seek(struct byte_writer *bw, u64 amount);
|
void bw_seek(struct byte_writer *bw, u64 amount);
|
||||||
void bw_seek_to(struct byte_writer *bw, u64 pos);
|
void bw_seek_to(struct byte_writer *bw, u64 pos);
|
||||||
@ -86,18 +36,36 @@ void bw_write_i32(struct byte_writer *bw, i32 v);
|
|||||||
void bw_write_i64(struct byte_writer *bw, i64 v);
|
void bw_write_i64(struct byte_writer *bw, i64 v);
|
||||||
void bw_write_var_uint(struct byte_writer *bw, u64 v);
|
void bw_write_var_uint(struct byte_writer *bw, u64 v);
|
||||||
void bw_write_var_sint(struct byte_writer *bw, i64 v);
|
void bw_write_var_sint(struct byte_writer *bw, i64 v);
|
||||||
|
void bw_write_f32(struct byte_writer *bw, f32 v);
|
||||||
|
void bw_write_f64(struct byte_writer *bw, f64 v);
|
||||||
|
void bw_write_v2(struct byte_writer *bw, struct v2 v);
|
||||||
|
|
||||||
|
/* Returns a buffer containing written bytes only */
|
||||||
|
INLINE struct buffer bw_get_written(struct byte_writer *bw)
|
||||||
|
{
|
||||||
|
struct buffer buff = ZI;
|
||||||
|
buff.data = bw->buff.data;
|
||||||
|
buff.size = bw->at - bw->buff.data;
|
||||||
|
return buff;
|
||||||
|
}
|
||||||
|
|
||||||
|
INLINE u64 bw_pos(struct byte_writer *bw)
|
||||||
|
{
|
||||||
|
return bw->at - bw->buff.data;
|
||||||
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Read
|
* Reader
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
void br_seek(struct byte_reader *br, u64 amount);
|
/* Will fill struct with zeroes on overflow */
|
||||||
void br_seek_to(struct byte_reader *br, u64 pos);
|
|
||||||
|
|
||||||
/* Will not read any data on overflow */
|
|
||||||
#define br_read_to_struct(br_ptr, var_ptr) (br_read_to_buffer(br_ptr, BUFFER(sizeof(*var_ptr), (u8 *)var_ptr)))
|
#define br_read_to_struct(br_ptr, var_ptr) (br_read_to_buffer(br_ptr, BUFFER(sizeof(*var_ptr), (u8 *)var_ptr)))
|
||||||
|
|
||||||
void *br_read_raw(struct byte_reader *br, u64 size);
|
struct byte_reader br_from_buffer(struct buffer buff);
|
||||||
|
|
||||||
|
void *br_seek(struct byte_reader *br, u64 amount);
|
||||||
|
void *br_seek_to(struct byte_reader *br, u64 pos);
|
||||||
|
|
||||||
void br_read_to_buffer(struct byte_reader *br, struct buffer buff);
|
void br_read_to_buffer(struct byte_reader *br, struct buffer buff);
|
||||||
u8 br_read_u8(struct byte_reader *br);
|
u8 br_read_u8(struct byte_reader *br);
|
||||||
u16 br_read_u16(struct byte_reader *br);
|
u16 br_read_u16(struct byte_reader *br);
|
||||||
@ -109,6 +77,9 @@ i32 br_read_i32(struct byte_reader *br);
|
|||||||
i64 br_read_i64(struct byte_reader *br);
|
i64 br_read_i64(struct byte_reader *br);
|
||||||
u64 br_read_var_uint(struct byte_reader *br);
|
u64 br_read_var_uint(struct byte_reader *br);
|
||||||
i64 br_read_var_sint(struct byte_reader *br);
|
i64 br_read_var_sint(struct byte_reader *br);
|
||||||
|
f32 br_read_f32(struct byte_reader *br);
|
||||||
|
f64 br_read_f64(struct byte_reader *br);
|
||||||
|
struct v2 br_read_v2(struct byte_reader *br);
|
||||||
|
|
||||||
INLINE u64 br_bytes_left(const struct byte_reader *br)
|
INLINE u64 br_bytes_left(const struct byte_reader *br)
|
||||||
{
|
{
|
||||||
|
|||||||
263
src/game.c
263
src/game.c
@ -14,6 +14,7 @@
|
|||||||
#include "collider.h"
|
#include "collider.h"
|
||||||
#include "rng.h"
|
#include "rng.h"
|
||||||
#include "space.h"
|
#include "space.h"
|
||||||
|
#include "byteio.h"
|
||||||
|
|
||||||
GLOBAL struct {
|
GLOBAL struct {
|
||||||
struct atomic_i32 game_thread_shutdown;
|
struct atomic_i32 game_thread_shutdown;
|
||||||
@ -31,9 +32,10 @@ GLOBAL struct {
|
|||||||
b32 extra_spawn;
|
b32 extra_spawn;
|
||||||
b32 should_reset_level;
|
b32 should_reset_level;
|
||||||
|
|
||||||
/* Game thread input */
|
/* Game input */
|
||||||
struct sys_mutex game_cmds_mutex;
|
struct sys_mutex game_input_mutex;
|
||||||
struct arena game_cmds_arena;
|
struct arena game_input_arena;
|
||||||
|
|
||||||
struct entity *root;
|
struct entity *root;
|
||||||
|
|
||||||
/* Bookkeeping structures */
|
/* Bookkeeping structures */
|
||||||
@ -69,9 +71,9 @@ struct game_startup_receipt game_startup(struct mixer_startup_receipt *mixer_sr,
|
|||||||
(UNUSED)sound_sr;
|
(UNUSED)sound_sr;
|
||||||
(UNUSED)phys_sr;
|
(UNUSED)phys_sr;
|
||||||
|
|
||||||
/* Initialize game cmd storage */
|
/* Initialize game input storage */
|
||||||
G.game_cmds_mutex = sys_mutex_alloc();
|
G.game_input_mutex = sys_mutex_alloc();
|
||||||
G.game_cmds_arena = arena_alloc(GIGABYTE(64));
|
G.game_input_arena = arena_alloc(GIGABYTE(64));
|
||||||
|
|
||||||
/* Initialize empty world */
|
/* Initialize empty world */
|
||||||
reset_world();
|
reset_world();
|
||||||
@ -95,34 +97,6 @@ INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(game_shutdown)
|
|||||||
sys_thread_wait_release(&G.game_thread);
|
sys_thread_wait_release(&G.game_thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
|
||||||
* Game cmd
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
INTERNAL void push_cmds(struct game_cmd_array cmd_array)
|
|
||||||
{
|
|
||||||
struct sys_lock lock = sys_mutex_lock_e(&G.game_cmds_mutex);
|
|
||||||
struct game_cmd *cmds = arena_push_array(&G.game_cmds_arena, struct game_cmd, cmd_array.count);
|
|
||||||
MEMCPY(cmds, cmd_array.cmds, cmd_array.count * sizeof(*cmds));
|
|
||||||
sys_mutex_unlock(&lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
INTERNAL struct game_cmd_array pop_cmds(struct arena *arena)
|
|
||||||
{
|
|
||||||
struct game_cmd_array array = ZI;
|
|
||||||
if (G.game_cmds_arena.pos > 0) {
|
|
||||||
struct sys_lock lock = sys_mutex_lock_e(&G.game_cmds_mutex);
|
|
||||||
struct buffer game_cmds_buff = arena_to_buffer(&G.game_cmds_arena);
|
|
||||||
arena_align(arena, alignof(struct game_cmd));
|
|
||||||
array.cmds = (struct game_cmd *)arena_push_array(arena, u8, game_cmds_buff.size);
|
|
||||||
array.count = game_cmds_buff.size / sizeof(struct game_cmd);
|
|
||||||
MEMCPY(array.cmds, game_cmds_buff.data, game_cmds_buff.size);
|
|
||||||
arena_reset(&G.game_cmds_arena);
|
|
||||||
sys_mutex_unlock(&lock);
|
|
||||||
}
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Reset
|
* Reset
|
||||||
* ========================== */
|
* ========================== */
|
||||||
@ -480,7 +454,7 @@ INTERNAL void publish_game_tick(void)
|
|||||||
sys_mutex_unlock(&lock);
|
sys_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void game_update(struct game_cmd_array game_cmds)
|
INTERNAL void game_update(struct game_cmd_list game_cmds)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
|
|
||||||
@ -537,14 +511,12 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
|||||||
* Process global game cmds
|
* Process global game cmds
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
for (u64 cmd_index = 0; cmd_index < game_cmds.count; ++cmd_index) {
|
for (struct game_cmd *cmd = game_cmds.first; cmd; cmd = cmd->next) {
|
||||||
struct game_cmd cmd = game_cmds.cmds[cmd_index];
|
switch (cmd->kind) {
|
||||||
|
|
||||||
switch (cmd.kind) {
|
|
||||||
/* Cursor */
|
/* Cursor */
|
||||||
case GAME_CMD_KIND_CURSOR_MOVE:
|
case GAME_CMD_KIND_CURSOR_MOVE:
|
||||||
{
|
{
|
||||||
G.user_cursor = cmd.cursor_pos;
|
G.user_cursor = cmd->cursor_pos;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
/* Clear level */
|
/* Clear level */
|
||||||
@ -735,19 +707,18 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
|||||||
struct v2 focus = ent->control.focus;
|
struct v2 focus = ent->control.focus;
|
||||||
b32 firing = entity_has_prop(ent, ENTITY_PROP_TRIGGERING_EQUIPPED);
|
b32 firing = entity_has_prop(ent, ENTITY_PROP_TRIGGERING_EQUIPPED);
|
||||||
|
|
||||||
for (u64 i = 0; i < game_cmds.count; ++i) {
|
for (struct game_cmd *cmd = game_cmds.first; cmd; cmd = cmd->next) {
|
||||||
struct game_cmd cmd = game_cmds.cmds[i];
|
b32 start = cmd->state == GAME_CMD_STATE_START;
|
||||||
b32 start = cmd.state == GAME_CMD_STATE_START;
|
b32 stop = cmd->state == GAME_CMD_STATE_STOP;
|
||||||
b32 stop = cmd.state == GAME_CMD_STATE_STOP;
|
|
||||||
|
|
||||||
/* TODO: Combine movement from multiple inputs? E.G. a sudden
|
/* TODO: Combine movement from multiple inputs? E.G. a sudden
|
||||||
* start and immediate stop cmd should still move the player a
|
* start and immediate stop cmd should still move the player a
|
||||||
* tad. */
|
* tad. */
|
||||||
switch (cmd.kind) {
|
switch (cmd->kind) {
|
||||||
case GAME_CMD_KIND_PLAYER_MOVE:
|
case GAME_CMD_KIND_PLAYER_MOVE:
|
||||||
{
|
{
|
||||||
move = cmd.move_dir;
|
move = cmd->move_dir;
|
||||||
focus = cmd.aim_dir;
|
focus = cmd->aim_dir;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case GAME_CMD_KIND_PLAYER_FIRE:
|
case GAME_CMD_KIND_PLAYER_FIRE:
|
||||||
@ -1094,12 +1065,11 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
|||||||
|
|
||||||
/* Mouse drag */
|
/* Mouse drag */
|
||||||
ctx.dbg_cursor_pos = G.user_cursor;
|
ctx.dbg_cursor_pos = G.user_cursor;
|
||||||
for (u64 i = 0; i < game_cmds.count; ++i) {
|
for (struct game_cmd *cmd = game_cmds.first; cmd; cmd = cmd->next) {
|
||||||
struct game_cmd cmd = game_cmds.cmds[i];
|
if (cmd->kind == GAME_CMD_KIND_DRAG_OBJECT) {
|
||||||
if (cmd.kind == GAME_CMD_KIND_DRAG_OBJECT) {
|
if (cmd->state == GAME_CMD_STATE_START) {
|
||||||
if (cmd.state == GAME_CMD_STATE_START) {
|
|
||||||
ctx.dbg_start_dragging = true;
|
ctx.dbg_start_dragging = true;
|
||||||
} else if (cmd.state == GAME_CMD_STATE_STOP) {
|
} else if (cmd->state == GAME_CMD_STATE_STOP) {
|
||||||
ctx.dbg_stop_dragging = true;
|
ctx.dbg_stop_dragging = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1342,50 +1312,116 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Game thread
|
* Game cmd
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(game_thread_entry_point, arg)
|
struct buffer game_string_from_cmds(struct arena *arena, struct game_cmd_list *cmds)
|
||||||
{
|
{
|
||||||
struct temp_arena scratch = scratch_begin_no_conflict();
|
struct byte_writer bw = bw_from_arena(arena);
|
||||||
|
|
||||||
(UNUSED)arg;
|
for (struct game_cmd *cmd = cmds->first; cmd; cmd = cmd->next) {
|
||||||
i64 last_frame_ns = 0;
|
struct byte_writer bw_size = bw_branch(&bw, sizeof(u64));
|
||||||
i64 target_dt_ns = NS_FROM_SECONDS(GAME_FPS > (0) ? (1.0 / GAME_FPS) : 0);
|
u64 start = bw_pos(&bw);
|
||||||
while (!atomic_i32_eval(&G.game_thread_shutdown)) {
|
|
||||||
__profscope(game_update_w_sleep);
|
|
||||||
struct temp_arena temp = arena_temp_begin(scratch.arena);
|
|
||||||
sleep_frame(last_frame_ns, target_dt_ns);
|
|
||||||
last_frame_ns = sys_time_ns();
|
|
||||||
{
|
|
||||||
struct game_cmd_array game_cmds = pop_cmds(temp.arena);
|
|
||||||
if (!G.paused) {
|
|
||||||
game_update(game_cmds);
|
|
||||||
}
|
|
||||||
/* Check for pause / next frame cmds */
|
|
||||||
for (u64 i = 0; i < game_cmds.count; ++i) {
|
|
||||||
struct game_cmd cmd = game_cmds.cmds[i];
|
|
||||||
switch (cmd.kind) {
|
|
||||||
case GAME_CMD_KIND_PAUSE: {
|
|
||||||
G.paused = !G.paused;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case GAME_CMD_KIND_STEP: {
|
bw_write_i8(&bw, cmd->kind);
|
||||||
if (G.paused) {
|
bw_write_i8(&bw, cmd->state);
|
||||||
G.paused = false;
|
|
||||||
game_update(game_cmds);
|
|
||||||
G.paused = true;
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
|
|
||||||
default: break;
|
#if RTC
|
||||||
}
|
bw_write_u32(&bw, cmd->collider_gjk_steps);
|
||||||
}
|
#endif
|
||||||
|
|
||||||
|
switch (cmd->kind) {
|
||||||
|
case GAME_CMD_KIND_PLAYER_MOVE:
|
||||||
|
{
|
||||||
|
bw_write_v2(&bw, cmd->move_dir);
|
||||||
|
bw_write_v2(&bw, cmd->aim_dir);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case GAME_CMD_KIND_CURSOR_MOVE:
|
||||||
|
{
|
||||||
|
bw_write_v2(&bw, cmd->cursor_pos);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default: break;
|
||||||
}
|
}
|
||||||
arena_temp_end(temp);
|
|
||||||
|
u64 size = bw_pos(&bw) - start;
|
||||||
|
if (size > 100) {
|
||||||
|
DEBUGBREAKABLE;
|
||||||
|
}
|
||||||
|
bw_write_u64(&bw_size, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
scratch_end(scratch);
|
return bw.buff;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct game_cmd_list game_cmds_from_string(struct arena *arena, struct buffer str)
|
||||||
|
{
|
||||||
|
struct game_cmd_list l = ZI;
|
||||||
|
|
||||||
|
struct byte_reader br = br_from_buffer(str);
|
||||||
|
while (br_bytes_left(&br) > 0) {
|
||||||
|
struct game_cmd *cmd = arena_push_zero(arena, struct game_cmd);
|
||||||
|
u64 cmd_size = br_read_u64(&br);
|
||||||
|
u64 cmd_pos_end = br_pos(&br) + cmd_size;
|
||||||
|
|
||||||
|
cmd->kind = br_read_i8(&br);
|
||||||
|
cmd->state = br_read_i8(&br);
|
||||||
|
|
||||||
|
#if RTC
|
||||||
|
cmd->collider_gjk_steps = br_read_u32(&br);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch (cmd->kind) {
|
||||||
|
case GAME_CMD_KIND_PLAYER_MOVE:
|
||||||
|
{
|
||||||
|
cmd->move_dir = br_read_v2(&br);
|
||||||
|
cmd->aim_dir = br_read_v2(&br);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case GAME_CMD_KIND_CURSOR_MOVE:
|
||||||
|
{
|
||||||
|
cmd->cursor_pos = br_read_v2(&br);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT(br_pos(&br) == cmd_pos_end);
|
||||||
|
br_seek_to(&br, cmd_pos_end);
|
||||||
|
|
||||||
|
if (l.last) {
|
||||||
|
l.last->next = cmd;
|
||||||
|
} else {
|
||||||
|
l.first = cmd;
|
||||||
|
}
|
||||||
|
l.last = cmd;
|
||||||
|
}
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========================== *
|
||||||
|
* Game cmd
|
||||||
|
* ========================== */
|
||||||
|
|
||||||
|
INTERNAL void push_input_string(struct buffer input)
|
||||||
|
{
|
||||||
|
struct sys_lock lock = sys_mutex_lock_e(&G.game_input_mutex);
|
||||||
|
u8 *dst = arena_push_array(&G.game_input_arena, u8, input.size);
|
||||||
|
MEMCPY(dst, input.data, input.size);
|
||||||
|
sys_mutex_unlock(&lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
INTERNAL struct buffer pop_input_string(struct arena *arena)
|
||||||
|
{
|
||||||
|
struct buffer buff = ZI;
|
||||||
|
struct sys_lock lock = sys_mutex_lock_e(&G.game_input_mutex);
|
||||||
|
buff.size = G.game_input_arena.pos;
|
||||||
|
buff.data = arena_push_array(arena, u8, buff.size);
|
||||||
|
MEMCPY(buff.data, G.game_input_arena.base, buff.size);
|
||||||
|
arena_reset(&G.game_input_arena);
|
||||||
|
sys_mutex_unlock(&lock);
|
||||||
|
return buff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -1410,7 +1446,56 @@ u64 game_get_latest_tick_continuity_gen(void)
|
|||||||
return atomic_u64_eval(&G.prev_tick_continuity_gen);
|
return atomic_u64_eval(&G.prev_tick_continuity_gen);
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_push_cmds(struct game_cmd_array cmd_array)
|
void game_push_cmds_string(struct buffer str)
|
||||||
{
|
{
|
||||||
push_cmds(cmd_array);
|
push_input_string(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========================== *
|
||||||
|
* Game thread
|
||||||
|
* ========================== */
|
||||||
|
|
||||||
|
INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(game_thread_entry_point, arg)
|
||||||
|
{
|
||||||
|
struct temp_arena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
|
(UNUSED)arg;
|
||||||
|
i64 last_frame_ns = 0;
|
||||||
|
i64 target_dt_ns = NS_FROM_SECONDS(GAME_FPS > (0) ? (1.0 / GAME_FPS) : 0);
|
||||||
|
while (!atomic_i32_eval(&G.game_thread_shutdown)) {
|
||||||
|
__profscope(game_update_w_sleep);
|
||||||
|
struct temp_arena temp = arena_temp_begin(scratch.arena);
|
||||||
|
sleep_frame(last_frame_ns, target_dt_ns);
|
||||||
|
last_frame_ns = sys_time_ns();
|
||||||
|
{
|
||||||
|
struct buffer input_str = pop_input_string(temp.arena);
|
||||||
|
struct game_cmd_list cmds = game_cmds_from_string(temp.arena, input_str);
|
||||||
|
if (!G.paused) {
|
||||||
|
game_update(cmds);
|
||||||
|
}
|
||||||
|
/* Check for pause / next frame cmds */
|
||||||
|
for (struct game_cmd *cmd = cmds.first; cmd; cmd = cmd->next) {
|
||||||
|
switch (cmd->kind) {
|
||||||
|
case GAME_CMD_KIND_PAUSE:
|
||||||
|
{
|
||||||
|
G.paused = !G.paused;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case GAME_CMD_KIND_STEP:
|
||||||
|
{
|
||||||
|
if (G.paused) {
|
||||||
|
G.paused = false;
|
||||||
|
game_update(cmds);
|
||||||
|
G.paused = true;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arena_temp_end(temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
scratch_end(scratch);
|
||||||
}
|
}
|
||||||
|
|||||||
49
src/game.h
49
src/game.h
@ -7,8 +7,25 @@ struct sprite_startup_receipt;
|
|||||||
struct sound_startup_receipt;
|
struct sound_startup_receipt;
|
||||||
struct phys_startup_receipt;
|
struct phys_startup_receipt;
|
||||||
|
|
||||||
|
/* Absolute layers */
|
||||||
|
#define GAME_LAYER_FLOOR_DECALS -300
|
||||||
|
#define GAME_LAYER_BULLETS -200
|
||||||
|
#define GAME_LAYER_TRACERS -100
|
||||||
|
#define GAME_LAYER_SHOULDERS 0
|
||||||
|
|
||||||
|
/* Relative layers */
|
||||||
|
#define GAME_LAYER_RELATIVE_DEFAULT 0
|
||||||
|
#define GAME_LAYER_RELATIVE_WEAPON 1
|
||||||
|
|
||||||
|
struct game_startup_receipt { i32 _; };
|
||||||
|
struct game_startup_receipt game_startup(struct mixer_startup_receipt *mixer_sr,
|
||||||
|
struct sprite_startup_receipt *sheet_sr,
|
||||||
|
struct sound_startup_receipt *sound_sr,
|
||||||
|
struct phys_startup_receipt *phys_sr);
|
||||||
|
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Game cmd
|
* Game CMD
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
enum game_cmd_state {
|
enum game_cmd_state {
|
||||||
@ -48,33 +65,25 @@ struct game_cmd {
|
|||||||
#if RTC
|
#if RTC
|
||||||
u32 collider_gjk_steps;
|
u32 collider_gjk_steps;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct game_cmd *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct game_cmd_array {
|
struct game_cmd_list {
|
||||||
struct game_cmd *cmds;
|
struct game_cmd *first;
|
||||||
u64 count;
|
struct game_cmd *last;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Absolute layers */
|
/* ========================== *
|
||||||
#define GAME_LAYER_FLOOR_DECALS -300
|
* Interface
|
||||||
#define GAME_LAYER_BULLETS -200
|
* ========================== */
|
||||||
#define GAME_LAYER_TRACERS -100
|
|
||||||
#define GAME_LAYER_SHOULDERS 0
|
|
||||||
|
|
||||||
/* Relative layers */
|
struct buffer game_string_from_cmds(struct arena *arena, struct game_cmd_list *cmds);
|
||||||
#define GAME_LAYER_RELATIVE_DEFAULT 0
|
struct game_cmd_list game_cmds_from_string(struct arena *arena, struct buffer str);
|
||||||
#define GAME_LAYER_RELATIVE_WEAPON 1
|
|
||||||
|
|
||||||
struct game_startup_receipt { i32 _; };
|
|
||||||
struct game_startup_receipt game_startup(struct mixer_startup_receipt *mixer_sr,
|
|
||||||
struct sprite_startup_receipt *sheet_sr,
|
|
||||||
struct sound_startup_receipt *sound_sr,
|
|
||||||
struct phys_startup_receipt *phys_sr);
|
|
||||||
|
|
||||||
void game_get_latest_tick(struct world *dest);
|
void game_get_latest_tick(struct world *dest);
|
||||||
u64 game_get_latest_tick_id(void);
|
u64 game_get_latest_tick_id(void);
|
||||||
u64 game_get_latest_tick_continuity_gen(void);
|
u64 game_get_latest_tick_continuity_gen(void);
|
||||||
|
void game_push_cmds_string(struct buffer str);
|
||||||
void game_push_cmds(struct game_cmd_array cmd_array);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -93,10 +93,11 @@ struct tar_archive tar_parse(struct arena *arena, struct buffer data, struct str
|
|||||||
struct string file_size_oct_str = { .len = 11, .text = header.file_size };
|
struct string file_size_oct_str = { .len = 11, .text = header.file_size };
|
||||||
|
|
||||||
u64 file_size = str_oct_to_u64(file_size_oct_str);
|
u64 file_size = str_oct_to_u64(file_size_oct_str);
|
||||||
struct buffer file_data = {
|
u8 *file_data_ptr = br_seek(&br, file_size);
|
||||||
.size = file_size,
|
if (!file_data_ptr) {
|
||||||
.data = br_read_raw(&br, file_size)
|
file_size = 0;
|
||||||
};
|
}
|
||||||
|
struct buffer file_data = BUFFER(file_size, file_data_ptr);
|
||||||
|
|
||||||
/* Skip sector padding */
|
/* Skip sector padding */
|
||||||
u64 remaining = (512 - (file_size % 512)) % 512;
|
u64 remaining = (512 - (file_size % 512)) % 512;
|
||||||
|
|||||||
42
src/user.c
42
src/user.c
@ -360,48 +360,30 @@ INTERNAL struct interp_ticks pull_ticks(i64 blend_time_ns)
|
|||||||
* User -> game communication
|
* User -> game communication
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct game_cmd_node {
|
INTERNAL void queue_game_cmd(struct arena *arena, struct game_cmd_list *list, struct game_cmd src)
|
||||||
struct game_cmd cmd;
|
|
||||||
struct game_cmd_node *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct game_cmd_list {
|
|
||||||
struct game_cmd_node *first;
|
|
||||||
struct game_cmd_node *last;
|
|
||||||
};
|
|
||||||
|
|
||||||
INTERNAL void queue_game_cmd(struct arena *arena, struct game_cmd_list *list, struct game_cmd cmd)
|
|
||||||
{
|
{
|
||||||
struct game_cmd_node *node = arena_push_zero(arena, struct game_cmd_node);
|
struct game_cmd *cmd = arena_push(arena, struct game_cmd);
|
||||||
node->cmd = cmd;
|
*cmd = src;
|
||||||
if (list->last) {
|
if (list->last) {
|
||||||
list->last->next = node;
|
list->last->next = cmd;
|
||||||
} else {
|
} else {
|
||||||
list->first = node;
|
list->first = cmd;
|
||||||
}
|
}
|
||||||
list->last = node;
|
list->last = cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void pubilsh_game_cmds(struct game_cmd_list *list)
|
INTERNAL void pubilsh_game_cmds(struct game_cmd_list *list)
|
||||||
{
|
{
|
||||||
struct temp_arena scratch = scratch_begin_no_conflict();
|
struct temp_arena scratch = scratch_begin_no_conflict();
|
||||||
|
struct buffer buff = game_string_from_cmds(scratch.arena, list);
|
||||||
/* Construct array */
|
game_push_cmds_string(buff);
|
||||||
struct game_cmd_array array = { .cmds = arena_dry_push(scratch.arena, struct game_cmd) };
|
|
||||||
for (struct game_cmd_node *node = list->first; node; node = node->next) {
|
|
||||||
struct game_cmd *cmd = arena_push(scratch.arena, struct game_cmd);
|
|
||||||
*cmd = node->cmd;
|
|
||||||
++array.count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Push array to game thread */
|
|
||||||
if (array.count > 0) {
|
|
||||||
game_push_cmds(array);
|
|
||||||
}
|
|
||||||
|
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ========================== *
|
||||||
|
* Debug draw
|
||||||
|
* ========================== */
|
||||||
|
|
||||||
/* TODO: remove this (testing) */
|
/* TODO: remove this (testing) */
|
||||||
INTERNAL void debug_draw_xform(struct xform xf, u32 color_x, u32 color_y)
|
INTERNAL void debug_draw_xform(struct xform xf, u32 color_x, u32 color_y)
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user