/* bit Generations: Orbital - Binary-Accurate Decompilation */
/* Using agbcc (GCC 2.95) for GBA */

typedef unsigned int u32;
typedef unsigned short u16;
typedef unsigned char u8;
typedef int s32;

/* Object structure offsets (word offsets) */
#define OBJ_SCREEN_X 4  /* 0x10 bytes */
#define OBJ_SCREEN_Y 5  /* 0x14 bytes */

/* GBA Hardware registers */
#define REG_DISPCNT (*(volatile u32*)0x04000000)
#define REG_KEYINPUT (*(volatile u16*)0x04000130)
#define REG_VCOUNT (*(volatile u16*)0x04000006)

/* External functions */
extern void Memory_Free(void *ptr);

/* 0x08000440 - SetObjectScreenPos */
void SetObjectScreenPos(obj, x, y)
    u32 *obj;
    u32 x;
    u32 y;
{
    obj[OBJ_SCREEN_X] = x;
    obj[OBJ_SCREEN_Y] = y;
}

/* 0x08000ABC - Object_ClearState */
void Object_ClearState(obj)
    u32 *obj;
{
    obj[0] = 0;
    obj[1] = 0;
    obj[2] = 0;
    obj[3] = 0;
    obj[4] = 0;
    obj[5] = 0;
}

/* 0x08000ACC - FreeIfFlagSet */
void FreeIfFlagSet(obj, flags)
    void *obj;
    u32 flags;
{
    if (flags & 1) {
        Memory_Free(obj);
    }
}

/* 0x08005EB8 - Return 0x0C */
u32 Return_0C()
{
    return 0x0C;
}

/* 0x08005EBC - Return 0x1E */
u32 Return_1E()
{
    return 0x1E;
}

/* 0x08005EC0 - Nop function */
void NopFunction()
{
}

/* Math utilities */
u32 Math_Min(a, b)
    u32 a;
    u32 b;
{
    if (a < b) return a;
    return b;
}

u32 Math_Max(a, b)
    u32 a;
    u32 b;
{
    if (a > b) return a;
    return b;
}

s32 Math_Abs(val)
    s32 val;
{
    if (val < 0) return -val;
    return val;
}

u32 Math_Clamp(val, min, max)
    u32 val;
    u32 min;
    u32 max;
{
    if (val < min) return min;
    if (val > max) return max;
    return val;
}

/* Compare for sorting */
s32 Compare_Int(a, b)
    u32 a;
    u32 b;
{
    if (a > b) return 1;
    if (a < b) return -1;
    return 0;
}

/* Display */
void Display_WaitVBlank()
{
    while (REG_VCOUNT < 160);
}

void Display_SetMode(mode)
    u32 mode;
{
    REG_DISPCNT = mode;
}

/* Input */
u32 Input_Read()
{
    return REG_KEYINPUT;
}

/* Timer */
u32 Timer_Get()
{
    return *(volatile u32*)0x04000100;
}

/* DMA */
void DMA_Transfer(src, dst, count)
    void *src;
    void *dst;
    u32 count;
{
    *(volatile u32*)0x040000D4 = (u32)src;
    *(volatile u32*)0x040000D8 = (u32)dst;
    *(volatile u32*)0x040000DC = count;
}

/* Palette */
void Palette_SetColor(index, color)
    u32 index;
    u16 color;
{
    *(volatile u16*)(0x05000000 + index * 2) = color;
}

/* Sound stubs */
void Sound_Play()
{
}

void Sound_StopAll()
{
}

/* Memory */
void Memory_Set(dst, val, count)
    u8 *dst;
    u8 val;
    u32 count;
{
    u32 i;
    for (i = 0; i < count; i++) {
        dst[i] = val;
    }
}

void Memory_Copy(dst, src, count)
    u8 *dst;
    u8 *src;
    u32 count;
{
    u32 i;
    for (i = 0; i < count; i++) {
        dst[i] = src[i];
    }
}

