#pragma once

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

// These help returning a known-sized sized array.
#define define_array(type, size)                                               \
  typedef struct {                                                             \
    type array[size];                                                          \
  } type##_##size
#define define_ptrarray(type, size)                                            \
  typedef struct {                                                             \
    type *array[size];                                                         \
  } type##_p_##size

typedef void (*func)(void);

typedef void string;

typedef struct __attribute__((packed)) {
  int32_t i32 : 24;
} int24_t;

typedef struct __attribute__((packed)) {
  uint32_t u32 : 24;
} uint24_t;

typedef uint8_t undefined;
typedef uint8_t undefined1;
typedef uint16_t undefined2;
typedef uint24_t undefined3;
typedef uint32_t undefined4;

typedef int8_t int1;
typedef int16_t int2;
typedef int24_t int3;
typedef int32_t int4;
// typedef int32_t int;

typedef uint8_t uint1;
typedef uint16_t uint2;
typedef uint24_t uint3;
typedef uint32_t uint4;
typedef uint32_t uint;

typedef uint8_t byte;
typedef uint16_t word;

typedef uint16_t pointer16;
typedef uint24_t pointer24;
typedef uint32_t pointer;

typedef uint32_t ulong;

bool CARRY1(uint8_t left, uint8_t right) {
  uint8_t tmp;
  return ckd_add(&tmp, left, right);
}

bool CARRY4(uint32_t left, uint32_t right) {
  uint32_t tmp;
  return ckd_add(&tmp, left, right);
}

uint16_t CONCAT11(uint8_t left, uint8_t right) {
  uint16_t result = 0;
  result |= (((uint16_t)left) << 8);
  result |= right;
  return result;
}

uint32_t CONCAT31(uint24_t left, uint8_t right) {
  uint32_t result = 0;
  result |= left.u32 << 8;
  result |= right;
  return result;
}

uint32_t CONCAT22(uint16_t left, uint16_t right) {
  uint32_t result = 0;
  result |= (((uint32_t)left) << 16);
  result |= right;
  return result;
}
