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

#pragma once

#include "addresses.hpp"

namespace nostalgia::core {

inline auto bgSetSbb(volatile BgCtl *bgCtl, unsigned sbb) noexcept {
	*bgCtl = (*bgCtl & ~0b11111'0000'0000u) | (sbb << 8);
}

[[nodiscard]]
constexpr unsigned bgPri(BgCtl bgCtl) noexcept {
	return bgCtl & 1;
}

[[nodiscard]]
inline auto bgPri(const volatile BgCtl *bgCtl) noexcept {
	return bgPri(*bgCtl);
}

inline auto bgSetPri(volatile BgCtl *bgCtl, unsigned pri) noexcept {
	pri = pri & 0b1;
	*bgCtl = (*bgCtl & ~0b1u) | (pri << 0);
}

[[nodiscard]]
constexpr unsigned bgBpp(BgCtl bgCtl) noexcept {
	return ((bgCtl >> 7) & 1) ? 8 : 4;
}

[[nodiscard]]
inline auto bgBpp(const volatile BgCtl *bgCtl) noexcept {
	return bgBpp(*bgCtl);
}

inline auto bgSetBpp(volatile BgCtl *bgCtl, unsigned bpp) noexcept {
	constexpr auto Bpp8 = 1 << 7;
	if (bpp == 4) {
		*bgCtl = *bgCtl | ((*bgCtl | Bpp8) ^ Bpp8); // set to use 4 bits per pixel
	} else {
		*bgCtl = *bgCtl | Bpp8; // set to use 8 bits per pixel
	}
}

[[nodiscard]]
constexpr auto bgCbb(BgCtl bgCtl) noexcept {
	return (bgCtl >> 2) & 0b11u;
}

[[nodiscard]]
inline auto bgCbb(const volatile BgCtl *bgCtl) noexcept {
	return bgCbb(*bgCtl);
}

inline auto bgSetCbb(volatile BgCtl *bgCtl, unsigned cbb) noexcept {
	cbb = cbb & 0b11;
	*bgCtl = (*bgCtl & ~0b1100u) | (cbb << 2);
}

constexpr void iterateBgCtl(auto cb) noexcept {
	for (auto bgCtl = &REG_BG0CTL; bgCtl <= &REG_BG3CTL; bgCtl += 2) {
		cb(bgCtl);
	}
}

}
