#ifndef CODUO_CORE_MEMORY_PRIVATE_H
#define CODUO_CORE_MEMORY_PRIVATE_H

#include <stddef.h>
#include <stdint.h>

#include "coduo_engine_structs.h"

extern coduo_hunk_state_t hunk;
extern uint8_t *hunk_base;
extern uint8_t *hunk_allocBase;

#if SIZE_MAX == UINT32_MAX
/*
 * ORIGINAL_BINARY_BUG: the stock i386 allocator adds the two hunk cursors as
 * one wrapping dword and then compares that result as signed.  Once bit 31 is
 * set, an oversized allocation can pass the check.  Preserve that behavior
 * for the original-width build; see
 * original-bugs/engine-hunk-allocation-signed-overflow-check-bypass.md.
 */
#define HUNK_USAGE_EXCEEDS_TOTAL(first, second) \
    ((int32_t)((first) + (second)) > (int32_t)hunk.totalSize)
#else
#define HUNK_USAGE_EXCEEDS_TOTAL(first, second) \
    ((first) > hunk.totalSize || (second) > hunk.totalSize - (first))
#endif

void Com_Error(int32_t code, const char *format, ...);
void Com_Memcpy(void *dest, const void *src, size_t count);
void Com_Memset(void *dest, int32_t value, size_t count);
void Com_Printf(const char *format, ...);
void Com_TouchMemory(void);
char *CopyString(const char *text);
void Hunk_MemInfo_f(void);
void Hunk_RetouchMemory(void);
void *Hunk_Alloc(size_t size);
void *Hunk_AllocLow(size_t size);
void *Hunk_AllocAlign(size_t size,
                      int32_t alignment);
void *Hunk_AllocLowAlign(size_t size,
                         int32_t alignment);
size_t Hunk_MemoryRemaining(void);
void *Hunk_AllocateTempMemory(size_t size);
void Hunk_FreeTempMemory(void *ptr);
void Hunk_SetHighTempMark(void);
void Hunk_ClearToHighTempMark(void);
void Hunk_SetLowMark(void);
void Hunk_ClearToLowMark(void);
void *Hunk_ReallocateTempMemory(size_t size);
int32_t Sys_Milliseconds(void);
void *Z_Malloc(size_t size);
void Z_Free(void *ptr);

#endif
