gba-link-connection/examples/_lib/common.h
2025-02-14 06:30:38 -03:00

154 lines
3.4 KiB
C++

#ifndef LINK_EXAMPLES_COMMON_H
#define LINK_EXAMPLES_COMMON_H
#include <tonc.h>
#include <string>
#include <string_view>
#include <vector>
#include "../../lib/_link_common.hpp"
/**
* @brief This namespace contains shared code between all the examples.
*/
namespace Common {
inline std::string lastLog = "";
// Strings
static inline int firstDiffLine(std::string_view oldText,
std::string_view newText) {
int line = 0;
u32 oldPos = 0, newPos = 0;
while (true) {
u32 oldNL = oldText.find('\n', oldPos);
u32 newNL = newText.find('\n', newPos);
auto oldLine = (oldNL == std::string_view::npos)
? oldText.substr(oldPos)
: oldText.substr(oldPos, oldNL - oldPos);
auto newLine = (newNL == std::string_view::npos)
? newText.substr(newPos)
: newText.substr(newPos, newNL - newPos);
if (oldLine != newLine)
return line;
if (oldNL == std::string_view::npos && newNL == std::string_view::npos)
break;
oldPos = (oldNL == std::string_view::npos) ? oldText.size() : oldNL + 1;
newPos = (newNL == std::string_view::npos) ? newText.size() : newNL + 1;
line++;
}
return -1;
}
static inline int firstDiffLine(const std::vector<std::string>& oldLines,
const std::vector<std::string>& newLines) {
int maxLines = Link::_max(oldLines.size(), newLines.size());
for (int i = 0; i < maxLines; ++i) {
if (i >= (int)oldLines.size() || i >= (int)newLines.size() ||
oldLines[i] != newLines[i])
return i;
}
return -1;
}
// TTE
static inline void initTTE() {
REG_DISPCNT = DCNT_MODE0 | DCNT_BG0;
tte_init_se_default(0, BG_CBB(0) | BG_SBB(31));
}
static inline void log(const std::string& text) {
int diffLine = firstDiffLine(lastLog, text);
if (diffLine == -1)
return;
tte_erase_rect(0, diffLine * 8, 240, 160);
tte_write(
(std::string("#{P:0,") + std::to_string(diffLine * 8) + "}").c_str());
u32 pos = 0;
for (int i = 0; i < diffLine; ++i) {
pos = text.find('\n', pos);
if (pos == std::string::npos) {
pos = text.size();
break;
}
pos++;
}
tte_write(text.substr(pos).c_str());
lastLog = text;
}
// BIOS
static inline void ISR_reset() {
REG_IME = 0;
RegisterRamReset(RESET_REG | RESET_VRAM);
#if MULTIBOOT_BUILD == 1
*(vu8*)0x03007FFA = 0x01;
#endif
SoftReset();
}
// Input
static inline bool didPress(u16 key, bool& pressed) {
u16 keys = ~REG_KEYS & KEY_ANY;
bool isPressedNow = false;
if ((keys & key) && !pressed) {
pressed = true;
isPressedNow = true;
}
if (pressed && !(keys & key))
pressed = false;
return isPressedNow;
}
static inline void waitForKey(u16 key) {
u16 keys;
do {
keys = ~REG_KEYS & KEY_ANY;
} while (!(keys & key));
}
// Profiling
static inline u32 toMs(u32 cycles) {
// CPU Frequency * time per frame = cycles per frame
// 16780000 * (1/60) ~= 279666
return (cycles * 1000) / (279666 * 60);
}
static inline void profileStart() {
REG_TM1CNT_L = 0;
REG_TM2CNT_L = 0;
REG_TM1CNT_H = 0;
REG_TM2CNT_H = 0;
REG_TM2CNT_H = TM_ENABLE | TM_CASCADE;
REG_TM1CNT_H = TM_ENABLE | TM_FREQ_1;
}
static inline u32 profileStop() {
REG_TM1CNT_H = 0;
REG_TM2CNT_H = 0;
return (REG_TM1CNT_L | (REG_TM2CNT_L << 16));
}
// Bits
static inline bool isBitHigh(u16 data, u8 bit) {
return (data >> bit) & 1;
}
} // namespace Common
#endif // LINK_EXAMPLES_COMMON_H