/*
 * Copyright 2016 - 2024 Gary Talent (gary@drinkingtea.net). All rights reserved.
 */

#ifdef __GNUC__

#include <ox/std/heapmgr.hpp>

#include <teagba/bios.hpp>
#include <teagba/registers.hpp>

namespace mgba {
void initConsole();
}

#define MEM_HEAP_BEGIN reinterpret_cast<char*>(0x02000000)
#define MEM_HEAP_END   reinterpret_cast<char*>(0x0203FFFF)

#define HEAP_BEGIN reinterpret_cast<char*>(MEM_HEAP_BEGIN)
// set size to half of EWRAM
#define HEAP_SIZE ((MEM_HEAP_END - MEM_HEAP_BEGIN) / 2)
#define HEAP_END  reinterpret_cast<char*>(MEM_HEAP_BEGIN + HEAP_SIZE)

extern void (*__preinit_array_start[]) (void);
extern void (*__preinit_array_end[]) (void);
extern void (*__init_array_start[]) (void);
extern void (*__init_array_end[]) (void);

int main(int argc, char const **argv);

extern "C" {

void abort() {
	REG_IE = 0;
	teagba::intrwait(0, 0);
	while (true);
}

void *__gxx_personality_v0{};

void __libc_init_array() {
	auto preInits = __preinit_array_end - __preinit_array_start;
	for (decltype(preInits) i = 0; i < preInits; i++) {
		__preinit_array_start[i]();
	}
	auto inits = __init_array_end - __init_array_start;
	for (decltype(inits) i = 0; i < inits; i++) {
		__init_array_start[i]();
	}
}

int c_start() {
	char const *args[2] = {"", "rom.oxfs"};
	ox::heapmgr::initHeap(HEAP_BEGIN, HEAP_END);
	mgba::initConsole();
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
	return main(2, args);
#pragma GCC diagnostic pop
}

}

#endif
