56 Commits
2.4.1 ... 2.4.2

Author SHA1 Message Date
Lightos1
69703bd330 bump ams version 2026-06-17 07:37:21 +02:00
Lightos1
5956ac4dad add 6gb/8gb modules to erista::mtcIndexTable 2026-06-16 20:57:37 +02:00
Lightos1
4b65e86f2a delete old/incorrect dumps 2026-06-16 17:15:17 +02:00
Lightos1
5591e8d996 remove boot voltage 2026-06-16 13:49:34 +02:00
Lightos1
30dcf82cf3 Merge pull request #91 from tetetete-ctrl/main
Fix actions ccache
2026-06-16 10:20:03 +02:00
tetetete-ctrl
dc9a1c2f3f Update build artifact path and compression level 2026-06-15 17:47:36 -04:00
tetetete-ctrl
21f698e99a Change ccache path to use GITHUB_WORKSPACE
Updated ccache configuration to use workspace directory.
2026-06-15 15:24:46 -04:00
tetetete-ctrl
8e200a89fa Merge branch 'Horizon-OC:main' into main 2026-06-15 14:58:03 -04:00
Lightos1
f06b7ff6c3 Fuck Erista
This reverts commit 09b4e5ebae.
2026-06-15 18:03:26 +02:00
Lightos1
09b4e5ebae ldr: Fix nle mrf via pointer hack 2026-06-15 17:38:24 +02:00
Lightos1
e04a5b7fe7 remove accidental , 2026-06-14 21:32:20 +02:00
Lightos1
c18f3f1468 remove typedef 2026-06-14 21:21:05 +02:00
Lightos1
dc7fa98d19 change hoc text 2026-06-14 17:42:16 +02:00
Lightos1
54fd2eb98d delete zip after updating 2026-06-14 17:37:00 +02:00
Lightos1
bd6502f930 change text 2026-06-14 17:32:32 +02:00
Lightos1
266e56c884 change text 2026-06-14 17:31:43 +02:00
Lightos1
e429e6ad44 add builtin updater 2026-06-14 17:28:56 +02:00
Lightos1
9725b1ba8f revert default freq 2026-06-14 14:40:20 +02:00
Lightos1
01c78bf8b6 add all low timings 2026-06-14 14:39:32 +02:00
Lightos1
8e7d82156c Update COMPILING.md 2026-06-14 00:48:56 +02:00
Lightos1
e5293e0eb8 add benchmark-toolbox to build.sh 2026-06-14 00:44:46 +02:00
Lightos1
6ddabbb303 build.sh: automatically clone atmosphere 2026-06-14 00:30:14 +02:00
Lightos1
3315924356 source to uppercase 2026-06-13 23:58:52 +02:00
Lightos1
bd36eb26d7 improve build script 2026-06-13 23:51:29 +02:00
souldbminersmwc
0053b1b367 Delete dist.zip 2026-06-12 21:36:02 -04:00
souldbminersmwc
0401397e98 ldr: fix Hynix NLE RAM on Erista 2026-06-12 21:35:46 -04:00
souldbminersmwc
18e9c47941 Update main.cpp 2026-06-12 16:44:35 -04:00
souldbminersmwc
80a61fb3b7 btoolbox: focus restoration 2026-06-12 16:41:43 -04:00
souldbminersmwc
39c51e0fcc Update main.cpp 2026-06-12 16:33:53 -04:00
souldbminersmwc
afc551eb96 Update main.cpp 2026-06-12 15:33:05 -04:00
souldbminersmwc
820335f831 vddq 2026-06-11 19:35:10 -04:00
souldbminersmwc
955f73635c red logo 2026-06-11 19:28:13 -04:00
souldbminersmwc
32dbdcabca benchmark_toolbox: fps and tab reorder 2026-06-11 19:19:46 -04:00
souldbminersmwc
319fa2bf8f benchmark_toolbox: reorganize tabs 2026-06-11 19:07:14 -04:00
souldbminersmwc
65eb5f8903 benchmark_toolbox: hanoi cpu test 2026-06-11 19:01:15 -04:00
souldbminersmwc
464b7d8fff Update main.cpp 2026-06-11 18:57:34 -04:00
souldbminersmwc
da7f7a2f7c Update Makefile 2026-06-11 18:56:20 -04:00
souldbminersmwc
73fccf339f benchmark_toolbox: memtester 2026-06-11 18:56:01 -04:00
souldbminersmwc
2fdb0ee492 some changes 2026-06-07 21:14:38 -04:00
souldbminersmwc
4a5e889c40 benchmark-toolbox: add benchmark-toolbox
a unified benchmarking tool
2026-06-07 21:10:53 -04:00
tetetete-ctrl
6429556b96 Merge branch 'Horizon-OC:main' into main 2026-06-07 17:29:33 -04:00
souldbminersmwc
8ebf887956 Update Makefile 2026-06-06 17:45:54 -04:00
souldbminersmwc
7634ff767b add membench-NX - open source memory benchmark tool
also remove memtester, it doesnt really work
2026-06-06 17:33:14 -04:00
Lightos1
380f621b39 ldr: don't apply dvb shift with custom table 2026-06-06 17:50:49 +02:00
Lightos1
e7c5bd02c2 ldr: change formating 2026-06-06 14:31:46 +02:00
Lightos1
19175e5307 edit credits 2026-06-06 14:20:52 +02:00
Lightos1
4b37217077 Configurator: Adjust battery warnings
Co-Authored-By: cat130504 <231865593+cat130504@users.noreply.github.com>
2026-06-06 14:16:53 +02:00
Lightos1
b561d2f0ca add custom soc voltage table 2026-06-06 14:13:02 +02:00
souldbminersmwc
a78de5f18a bump version 2026-06-05 22:20:35 -04:00
tetetete-ctrl
a9adadd30e Update build.yml 2026-05-31 17:11:39 -04:00
tetetete-ctrl
16ac50e783 Perhaps the path of restore was wrong all along 2026-05-31 16:47:46 -04:00
tetetete-ctrl
62b3b71854 Update ccache directory path in build workflow 2026-05-31 16:31:54 -04:00
tetetete-ctrl
b460f635bd Merge pull request #1 from tetetete-ctrl/patch-1
Patch 1
2026-05-31 15:47:30 -04:00
tetetete-ctrl
52b3b6b469 Fix ccache stats step name in build workflow 2026-05-31 15:46:43 -04:00
tetetete-ctrl
f763fb70a8 Attempt to fix ccache 2026-05-31 15:43:41 -04:00
tetetete-ctrl
6a5c3b786a Update build.yml for container image and cloning options 2026-05-31 15:17:47 -04:00
1474 changed files with 360570 additions and 72534 deletions

View File

@@ -12,7 +12,7 @@ jobs:
# Minimal devkitA64 container
container:
image: devkitpro/devkita64:20251231
image: devkitpro/devkita64:20260219
steps:
- name: Checkout repository and submodules # needed for hoc-clk
@@ -55,7 +55,7 @@ jobs:
echo $GITHUB_SHA >> dist/.commit
- name: Clone Libnx
run: git clone https://github.com/switchbrew/libnx.git
run: git clone https://github.com/switchbrew/libnx.git --depth=1 --single-branch -b v4.12.0
- name: Clone Atmosphere
run: git clone --depth=1 --single-branch https://github.com/Atmosphere-NX/Atmosphere.git atmosphere -b $(cat ams_ver.txt)
@@ -70,20 +70,27 @@ jobs:
cp -rf Source/Atmosphere/stratosphere/loader/source/* build/stratosphere/loader/source/
- name: Cache ccache
uses: actions/cache@v5.0.3
uses: actions/cache@v5.0.5
with:
path: /root/.cache/ccache
key: ccache-${{ runner.os }}-devkitpro-ams-${{ hashFiles('ams_ver.txt') }} # last key was utter garbage, stick to ams versions,
path: .ccache
key: ccache-${{ runner.os }}-devkitpro-ams-${{ hashFiles('ams_ver.txt') }}
restore-keys: |
ccache-${{ runner.os }}-devkitpro-
- name: Configure ccache
run: |
export CCACHE_DIR=/root/.cache/ccache
echo "CCACHE_DIR=/root/.cache/ccache" >> $GITHUB_ENV
export CCACHE_DIR="$GITHUB_WORKSPACE/.ccache"
export CCACHE_COMPILERCHECK=content
export CCACHE_NOHASHDIR=true
echo "CCACHE_DIR=$GITHUB_WORKSPACE/.ccache" >> $GITHUB_ENV
echo "CCACHE_BASEDIR=$GITHUB_WORKSPACE" >> $GITHUB_ENV
echo "CCACHE_COMPILERCHECK=content" >> $GITHUB_ENV
echo "CCACHE_NOHASHDIR=true" >> $GITHUB_ENV
ccache --set-config=max_size=10G
ccache --set-config=compiler_check=content
ccache --zero-stats
ccache --set-config=hash_dir=false
ccache -s
ls -lah "$GITHUB_WORKSPACE/.ccache"
- name: Build Libnx
shell: bash
@@ -102,6 +109,7 @@ jobs:
ROOT_DIR="$GITHUB_WORKSPACE/Source/hoc-clk"
DIST_DIR="$ROOT_DIR/dist"
echo "DIST_DIR="$ROOT_DIR/dist"" >> $GITHUB_ENV
mkdir -p "$DIST_DIR"
@@ -162,8 +170,11 @@ jobs:
hactool -t kip1 out/nintendo_nx_arm64_armv8a/release/loader.kip --uncompress=hoc.kip
cp hoc.kip ../../../dist/atmosphere/kips/hoc.kip
- name: ccache stats
run: ccache --show-stats
- name: ccache stat
run: |
ccache --show-stats
ccache -s
ccache --show-config
# -------------------------------------------------
# Upload ZIP artifact
@@ -172,5 +183,5 @@ jobs:
uses: actions/upload-artifact@v6
with:
name: horizon-oc-zeus-dist
path: dist/
compression-level: 3
path: $DIST_DIR
compression-level: 6

2
.gitignore vendored
View File

@@ -4,3 +4,5 @@
build/
__pycache__/
build
*.dksh
Source/hekate

View File

@@ -2,8 +2,6 @@ Horizon OC Compilation Instructions
1. Install devkitpro (https://devkitpro.org/wiki/Getting_Started) with switch-dev
2. Set up a development enviorment for compiling Atmosphere (https://github.com/Atmosphere-NX/Atmosphere/blob/master/docs/building.md)
3. Git clone atmosphere (git clone https://github.com/Atmosphere-NX/Atmosphere.git)
4. Clone the Horizon OC develop branch (``git clone https://github.com/Horizon-OC/Horizon-OC.git --recurse-submodules``)
5. Create a new folder named ``build`` in the horizon oc repo
6. Copy atmosphere files into that build folder
7. Run ./build.sh in the root directory
3. Clone the Horizon OC develop branch (``git clone https://github.com/Horizon-OC/Horizon-OC.git --recurse-submodules``)
4. Run ``./build.sh`` in the root directory
- If you want to compile with extensions, append ``--ext``

View File

@@ -65,8 +65,14 @@ volatile CustomizeTable C = {
/* Frequency where non low timings gets used. */
.timingEmcTbreak = DISABLED,
.low_t6_tRTW = 0,
.low_t7_tWTR = 0,
.low_t1_tRCD = 0,
.low_t2_tRP = 0,
.low_t3_tRAS = 0,
.low_t4_tRRD = 0,
.low_t5_tRFC = 0,
.low_t6_tRTW = 0,
.low_t7_tWTR = 0,
.low_t8_tREFI = 0,
.readLatency = {
/* 1333 */ 0,
@@ -114,9 +120,8 @@ volatile CustomizeTable C = {
.eristaGpuVmin = 810,
.marikoGpuUV = 2,
/* Vmin past 795mV won't work due boot voltage being 800mV (can be adjusted though). */
/* Vmin past 795mV won't work due boot voltage being 800mV. */
.marikoGpuVmin = 610,
.marikoGpuBootVolt = 800, /* Used during boot and when temp is <20°C */
.marikoGpuVmax = 800,
.commonGpuVoltOffset = 0,
@@ -156,30 +161,60 @@ volatile CustomizeTable C = {
},
.marikoGpuVoltArray = {
AUTO /* 76 */,
AUTO /* 153 */,
AUTO /* 230 */,
AUTO /* 307 */,
AUTO /* 384 */,
AUTO /* 460 */,
AUTO /* 537 */,
AUTO /* 614 */,
AUTO /* 691 */,
AUTO /* 768 */,
AUTO /* 844 */,
AUTO /* 921 */,
AUTO /* 998 */,
AUTO /* 1075 */,
AUTO /* 1152 (SLT / HiOPT Only!) */,
AUTO /* 1228 (HiOPT Only!) */,
DEACTIVATED_GPU_FREQ /* 1267 (Disabled by default) */,
DEACTIVATED_GPU_FREQ /* 1305 (Disabled by default) */,
DEACTIVATED_GPU_FREQ /* 1344 (Disabled by default) */,
DEACTIVATED_GPU_FREQ /* 1382 (Disabled by default) */,
DEACTIVATED_GPU_FREQ /* 1420 (Disabled by default) */,
DEACTIVATED_GPU_FREQ /* 1459 (Disabled by default) */,
DEACTIVATED_GPU_FREQ /* 1497 (Disabled by default) */,
DEACTIVATED_GPU_FREQ /* 1536 (Disabled by default) */,
AUTO /* 76 */,
AUTO /* 153 */,
AUTO /* 230 */,
AUTO /* 307 */,
AUTO /* 384 */,
AUTO /* 460 */,
AUTO /* 537 */,
AUTO /* 614 */,
AUTO /* 691 */,
AUTO /* 768 */,
AUTO /* 844 */,
AUTO /* 921 */,
AUTO /* 998 */,
AUTO /* 1075 */,
AUTO /* 1152 (HioPT / High UV only!) */,
AUTO /* 1228 (High UV Only!) */,
DEACTIVATED_GPU_FREQ /* 1267 (Disabled by default) */,
DEACTIVATED_GPU_FREQ /* 1305 (Disabled by default) */,
DEACTIVATED_GPU_FREQ /* 1344 (Disabled by default) */,
DEACTIVATED_GPU_FREQ /* 1382 (Disabled by default) */,
DEACTIVATED_GPU_FREQ /* 1420 (Disabled by default) */,
DEACTIVATED_GPU_FREQ /* 1459 (Disabled by default) */,
DEACTIVATED_GPU_FREQ /* 1497 (Disabled by default) */,
DEACTIVATED_GPU_FREQ /* 1536 (Disabled by default) */,
},
/* Override soc voltage brackets. */
.marikoSocVoltArray = {
0 /* >= 1866 */,
0 /* >= 2000 */,
0 /* >= 2133 */,
0 /* >= 2200 */,
0 /* >= 2266 */,
0 /* >= 2333 */,
0 /* >= 2400 */,
0 /* >= 2433 */,
0 /* >= 2466 */,
0 /* >= 2533 */,
0 /* >= 2566 */,
0 /* >= 2600 */,
0 /* >= 2666 */,
0 /* >= 2700 */,
0 /* >= 2733 */,
0 /* >= 2766 */,
0 /* >= 2800 */,
0 /* >= 2833 */,
0 /* >= 2900 */,
0 /* >= 2933 */,
0 /* >= 3000 */,
0 /* >= 3033 */,
0 /* >= 3100 */,
0 /* >= 3133 */,
0 /* >= 3166 */,
0 /* >= 3200 */,
},
/* Advanced. */
@@ -478,7 +513,7 @@ volatile CustomizeTable C = {
},
.marikoGpuDvfsTableSLT = {
{ 76800, {}, { 590000, } },
{ 76800, {}, { 590000, } },
{ 153600, {}, { 590000, } },
{ 230400, {}, { 590000, } },
{ 307200, {}, { 590000, } },

View File

@@ -20,8 +20,8 @@
#pragma once
#define CUST_REV 4
#define KIP_VERSION 240
#define CUST_REV 5
#define KIP_VERSION 242
#include "oc_common.hpp"
#include "pcv/pcv_common.hpp"
@@ -89,8 +89,14 @@ struct CustomizeTable {
u32 t2_tRP_cap;
u32 timingEmcTbreak;
u32 low_t1_tRCD;
u32 low_t2_tRP;
u32 low_t3_tRAS;
u32 low_t4_tRRD;
u32 low_t5_tRFC;
u32 low_t6_tRTW;
u32 low_t7_tWTR;
u32 low_t8_tREFI;
u32 readLatency[4];
u32 writeLatency[4];
@@ -116,13 +122,13 @@ struct CustomizeTable {
u32 marikoGpuUV;
u32 marikoGpuVmin;
u32 marikoGpuBootVolt;
u32 marikoGpuVmax;
s32 commonGpuVoltOffset;
u32 eristaGpuVoltArray[27];
u32 marikoGpuVoltArray[24];
s32 marikoSocVoltArray[26];
u32 fineTune_t6_tRTW;
u32 fineTune_t7_tWTR;

View File

@@ -134,27 +134,32 @@ namespace ams::ldr::hoc::pcv::mariko {
/* At 1333WL, for some reason (incorrect ram timing config in mtc table?), tRP causes crashes at high reductions - 2 seems to be the most common limit. */
/* This is a lazy workaround until I find the issue... */
u32 tRPpbIndex = C.t2_tRP;
const bool lowFreq = freq < C.timingEmcTbreak;
volatile u32 tRPpbIndex = lowFreq ? C.low_t2_tRP : C.t2_tRP;
if (WL == WL_1331) {
tRPpbIndex = MIN(C.t2_tRP_cap, C.t2_tRP);
tRPpbIndex = MIN(C.t2_tRP_cap, tRPpbIndex);
}
tRCD = tRCD_values[C.t1_tRCD];
tRPpb = tRP_values[tRPpbIndex];
tRAS = tRAS_values[C.t3_tRAS];
tRRD = tRRD_values[C.t4_tRRD];
tRFCpb = tRFC_values[C.t5_tRFC];
u32 tRTW = C.t6_tRTW;
u32 tWTR = 10 - tWTR_values[C.t7_tWTR];
tRCD = tRCD_values[lowFreq ? C.low_t1_tRCD : C.t1_tRCD];
tRPpb = tRP_values[tRPpbIndex];
tRAS = tRAS_values[lowFreq ? C.low_t3_tRAS : C.t3_tRAS];
tRRD = tRRD_values[lowFreq ? C.low_t4_tRRD : C.t4_tRRD];
tRFCpb = tRFC_values[lowFreq ? C.low_t5_tRFC : C.t5_tRFC];
if (freq < C.timingEmcTbreak) {
tRTW = C.low_t6_tRTW;
tWTR = 10 - tWTR_values[C.low_t7_tWTR];
}
u32 tRTW = lowFreq ? C.low_t6_tRTW : C.t6_tRTW;
u32 tWTR = 10 - tWTR_values[lowFreq ? C.low_t7_tWTR : C.t7_tWTR];
s32 finetRTW = C.fineTune_t6_tRTW;
s32 finetWTR = C.fineTune_t7_tWTR;
u32 tREFI = lowFreq ? C.low_t8_tREFI : C.t8_tREFI;
refresh_raw = 0xFFFF;
if (tREFI != 6) {
refresh_raw = CEIL(tREFpb_values[tREFI] / tCK_avg) - 0x40;
refresh_raw = MIN(refresh_raw, static_cast<u32>(0xFFFF));
}
tRC = tRAS + tRPpb;
tRFCab = tRFCpb * 2;
tXSR = static_cast<double>(tRFCab + 7.5);

View File

@@ -130,6 +130,8 @@ namespace ams::ldr::hoc {
inline u32 tFAW;
inline double tRPab;
inline u32 refresh_raw;
inline u32 RL;
inline u32 WL;

View File

@@ -58,8 +58,8 @@ namespace ams::ldr {
namespace ams::ldr::hoc {
template<typename Pointer>
struct PatcherEntry {
using patternFn = bool(*)(Pointer* ptr);
using patcherFn = Result(*)(Pointer* ptr);
using patternFn = bool(*)(Pointer *ptr);
using patcherFn = Result(*)(Pointer *ptr);
const char* description;
patcherFn patcher_fn = nullptr;

View File

@@ -126,7 +126,7 @@ namespace ams::ldr::hoc {
SmcRebootToIramPayload();
while(true){}
while(true) { }
}
#endif
}

View File

@@ -83,6 +83,28 @@ namespace ams::ldr::hoc::pcv {
inline auto AsmBlCompareOpcodeOnly = [](u32 ins1, u32 ins2) {
return ((ins1 ^ ins2) >> 26) == 0;
};
inline auto AsmIsAdrX0 = [](u32 ins) {
return (ins & 0x9F00001Fu) == 0x10000000u;
};
inline auto AsmAdrTarget = [](u32 ins, uintptr_t pc) -> uintptr_t {
s64 imm = static_cast<s64>((((ins >> 5) & 0x7FFFFu) << 2) | ((ins >> 29) & 0x3u));
imm = (imm << 43) >> 43;
return static_cast<uintptr_t>(static_cast<s64>(pc) + imm);
};
inline auto AsmSetAdrTarget = [](u32 ins, uintptr_t pc, uintptr_t target) -> u32 {
const s64 delta = static_cast<s64>(target) - static_cast<s64>(pc);
const u32 immlo = static_cast<u32>(delta & 0x3);
const u32 immhi = static_cast<u32>((delta >> 2) & 0x7FFFF);
return (ins & ~((0x3u << 29) | (0x7FFFFu << 5))) | (immlo << 29) | (immhi << 5);
};
inline auto AsmIsLdpX = [](u32 ins) {
return (ins & 0xFE400000u) == 0xA8400000u;
};
inline bool AsmComparePrologue(u32 ins1, u32 ins2, u32 ins3, u32 cmp1, u32 cmp2, u32 cmp3) {
constexpr u32 StpImmMask = ~((((1u << 7) - 1u) << 15));

View File

@@ -73,7 +73,7 @@ namespace ams::ldr::hoc::pcv {
u32 unk_0;
struct div_nmp *div_nmp;
u32 unk_1[4];
void (*unk_fn)(u64* unk_struct); // set_defaults?
void (*unk_fn)(u64 *unk_struct); // set_defaults?
};
struct __attribute__((packed)) dvfs_rail {
@@ -90,7 +90,7 @@ namespace ams::ldr::hoc::pcv {
struct __attribute__((packed)) regulator {
u64 id;
const char* name;
const char *name;
u32 type;
union {
struct {
@@ -148,7 +148,7 @@ namespace ams::ldr::hoc::pcv {
size_t GetDvfsTableEntryCount(T *table_head) {
using NT = std::remove_const_t<std::remove_volatile_t<T>>;
auto is_empty = [](NT* entry) {
auto is_empty = [](NT *entry) {
u8 *m = reinterpret_cast<u8 *>(entry);
for (size_t i = 0; i < sizeof(NT); i++) {
if (*(m + i)) {

View File

@@ -27,6 +27,10 @@
namespace ams::ldr::hoc::pcv::erista {
std::vector<u32> newEmcList;
u32 *nsoStart;
u32 *nsoEnd;
Result CpuVoltDvfs(u32 *ptr) {
if (std::memcmp(ptr + 5, cpuVoltDvfsPattern, sizeof(cpuVoltDvfsPattern))) {
R_THROW(ldr::ResultInvalidCpuMinVolt());
@@ -364,10 +368,103 @@ namespace ams::ldr::hoc::pcv::erista {
table->emc_cfg_2 = 0x11083D;
table->min_volt = std::clamp(900 + (C.emcDvbShift * 25), 900, 1050);
}
/* TODO: Template this */
Result VerifyMtcTable(EristaMtcTable *tableStart, u32 expectedFreq) {
R_UNLESS(tableStart->rate_khz == expectedFreq, ldr::ResultInvalidMtcTable());
R_UNLESS(tableStart->rev == MTC_TABLE_REV, ldr::ResultInvalidMtcTable());
namespace {
std::vector<u32> newEmcList;
u32 *nsoStart;
R_SUCCEED();
}
/* TODO: Template this */
Result MtcValidateAllTables(EristaMtcTable *tableStart, const u32 *validationList, u32 tableCount) {
for (u32 i = 0; i < tableCount; ++i) {
R_TRY(VerifyMtcTable(&tableStart[i], validationList[i]));
}
R_SUCCEED();
}
/* TODO: Put this into common. */
DramId GetDramId() {
u64 id64;
splGetConfig(SplConfigItem_DramId, &id64);
return static_cast<DramId>(id64);
}
MtcTableIndex GetMtcDramIndex(DramId dramId) {
for (u32 i = 0; i < std::size(mtcIndexTable); ++i) {
if (mtcIndexTable[i].dramId == dramId) {
return mtcIndexTable[i].index;
}
}
return MtcTableIndex_Invalid;
}
NORETURN void AbortInvalidMtc(const char *crashMsg) {
panic::SmcError(panic::Emc);
CRASH(crashMsg);
}
u32 GetMtcOffset(MtcTableIndex index) {
if (index < T210SdevEmcDvfsTableS6gb01) {
return index * erista::MtcFullTableSize;
}
/* Account for the weird in between mariko table. */
return index * erista::MtcFullTableSize + mariko::MtcFullTableSize;
}
void PrepareMtcMemoryRegion(u8 *firstTable, EristaMtcTable *usedTable) {
/* Move the table, this is nessasary for NLE */
memmove(firstTable, usedTable, erista::MtcFullTableSize);
/* Clear all other tables. */
/* The used table is excluded. */
constexpr size_t RemainingRegionSize = (mariko::MtcFullTableSize) * (mariko::MtcFullTableCount) + (erista::MtcFullTableSize * (erista::MtcFullTableCount - 1));
memset(firstTable + erista::MtcFullTableSize, 0, RemainingRegionSize);
}
void MtcExtendTables(EristaMtcTable *table) {
for (u32 i = erista::MtcTableCountDefault; i < newEmcList.size(); ++i) {
std::memcpy(&table[i], &table[i - 1], sizeof(EristaMtcTable));
table[i].rate_khz = newEmcList[i];
}
}
/* Relocate the table */
/* Rescanning is simpler than trying to extract a bunch of data from the asm patch, performance impact is negligable */
/* Also, this is more stable :P */
u32 RepointEristaEmcTablePtr(uintptr_t fromSlot, uintptr_t toTable) {
constexpr u32 RetIns = 0xD65F03C0; /* ret */
u32 patched = 0;
for (u32 *p = nsoStart; p + 4 < nsoEnd; ++p) {
const u32 ins = *p;
if (!AsmIsAdrX0(ins)) {
continue;
}
const uintptr_t pc = reinterpret_cast<uintptr_t>(p);
if (AsmAdrTarget(ins, pc) != fromSlot) {
continue;
}
if (!(AsmIsLdpX(p[1]) && AsmIsLdpX(p[2]) && p[3] == RetIns)) {
continue;
}
/* adr only reaches +-1MB */
const s64 delta = static_cast<s64>(toTable) - static_cast<s64>(pc);
if (delta > 0xFFFFF || delta < -0x100000) {
continue;
}
PATCH_OFFSET(p, AsmSetAdrTarget(ins, pc, toTable));
++patched;
}
return patched;
}
/* The silicon instructs; the children obey... */
@@ -418,70 +515,6 @@ namespace ams::ldr::hoc::pcv::erista {
newEmcList.resize(std::min(newEmcList.size(), DvfsTableEntryLimit));
}
/* TODO: Template this */
Result VerifyMtcTable(EristaMtcTable *tableStart, u32 expectedFreq) {
R_UNLESS(tableStart->rate_khz == expectedFreq, ldr::ResultInvalidMtcTable());
R_UNLESS(tableStart->rev == MTC_TABLE_REV, ldr::ResultInvalidMtcTable());
R_SUCCEED();
}
/* TODO: Template this */
Result MtcValidateAllTables(EristaMtcTable *tableStart, const u32 *validationList, u32 tableCount) {
for (u32 i = 0; i < tableCount; ++i) {
R_TRY(VerifyMtcTable(&tableStart[i], validationList[i]));
}
R_SUCCEED();
}
/* TODO: Put this into common. */
DramId GetDramId() {
u64 id64;
splGetConfig(SplConfigItem_DramId, &id64);
return static_cast<DramId>(id64);
}
MtcTableIndex GetMtcDramIndex(DramId dramId) {
for (u32 i = 0; i < std::size(mtcIndexTable); ++i) {
if (mtcIndexTable[i].dramId == dramId) {
return mtcIndexTable[i].index;
}
}
return MtcTableIndex_Invalid;
}
NORETURN void AbortInvalidMtc(const char *crashMsg) {
panic::SmcError(panic::Emc);
CRASH(crashMsg);
}
u32 GetMtcOffset(MtcTableIndex index) {
if (index < T210SdevEmcDvfsTableS6gb01) {
return index * erista::MtcFullTableSize;
}
/* Account for the weird in between mariko table. */
return index * erista::MtcFullTableSize + mariko::MtcFullTableSize;
}
void PrepareMtcMemoryRegion(u8 *firstTable, EristaMtcTable *usedTable) {
memmove(firstTable, usedTable, erista::MtcFullTableSize);
/* Clear all other tables. */
/* The used table is excluded. */
constexpr size_t RemainingRegionSize = (mariko::MtcFullTableSize) * (mariko::MtcFullTableCount) + (erista::MtcFullTableSize * (erista::MtcFullTableCount - 1));
memset(firstTable + erista::MtcFullTableSize, 0, RemainingRegionSize);
}
void MtcExtendTables(EristaMtcTable *table) {
for (u32 i = erista::MtcTableCountDefault; i < newEmcList.size(); ++i) {
std::memcpy(&table[i], &table[i - 1], sizeof(EristaMtcTable));
table[i].rate_khz = newEmcList[i];
}
}
Result MemFreqMtcTable(u32 *ptr) {
static const DramId dramId = [] {
DramId id = GetDramId();
@@ -502,12 +535,20 @@ namespace ams::ldr::hoc::pcv::erista {
constexpr u32 StartAdjustment = offsetof(EristaMtcTable, rate_khz) + sizeof(EristaMtcTable) * (erista::MtcTableCountDefault - 1);
u8 *startPtr = reinterpret_cast<u8 *>(ptr) - StartAdjustment;
EristaMtcTable *table = reinterpret_cast<EristaMtcTable *>(startPtr + mtcOffset);
const uintptr_t usedSlot = reinterpret_cast<uintptr_t>(startPtr) + mtcOffset;
EristaMtcTable *table = reinterpret_cast<EristaMtcTable *>(usedSlot);
R_TRY(MtcValidateAllTables(table, EmcListDefault, EmcListSizeDefault));
PrepareMtcMemoryRegion(startPtr, table);
table = reinterpret_cast<EristaMtcTable *>(startPtr);
/* We must do this as the NLE tables don't have enough space past them for our extended ones */
if (usedSlot != reinterpret_cast<uintptr_t>(startPtr)) {
if (RepointEristaEmcTablePtr(usedSlot, reinterpret_cast<uintptr_t>(startPtr)) == 0) {
AbortInvalidMtc("Failed to repoint emc table");
}
}
if (R_FAILED(MtcValidateAllTables(table, EmcListDefault, EmcListSizeDefault))) {
AbortInvalidMtc("Failed mtc validation");
}
@@ -575,7 +616,7 @@ namespace ams::ldr::hoc::pcv::erista {
constexpr u32 MtcGoodBlOpcode = 0x97fe6cfc;
constexpr u32 MtcBadBlOpcode0 = 0x97ffae64; // bl nn::pcv::GetHardwareType
constexpr u32 MtcBadBlOpcode1 = 0x940036d5; // bl nn::pcv::GetHardwareType
constexpr u32 MtcBadBlOpcode1 = 0x940036d5; // bl strcmp
constexpr u32 MtcBadAdrpAsm = 0xd00000a1; // adrp x1, s_ModuleResetStatus_
constexpr s32 MtcBadBlOffset0 = 2;
@@ -616,6 +657,7 @@ namespace ams::ldr::hoc::pcv::erista {
void Patch(uintptr_t mapped_nso, size_t nso_size) {
nsoStart = reinterpret_cast<u32 *>(mapped_nso);
nsoEnd = reinterpret_cast<u32 *>(mapped_nso + nso_size);
MtcGenerateFreqTables();
u32 CpuCvbDefaultMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(CpuCvbTableDefault)->freq);
@@ -632,11 +674,11 @@ namespace ams::ldr::hoc::pcv::erista {
{"GPU Freq Asm", &GpuFreqMaxAsm, 2, &GpuMaxClockPatternFn },
{"GPU PLL Max", & GpuFreqPllMax, 1, nullptr, GpuClkPllMax },
// {"GPU PLL Limit", &GpuFreqPllLimit, 4, nullptr, GpuClkPllLimit },
{"MEM Table Asm", &MemMtcTableAsm, 4, &MemMtcGetGetTablePatternFn },
{"MEM Freq Mtc", &MemFreqMtcTable, 1, nullptr, EmcClkOSLimit },
{"MEM Freq Max", &MemFreqMax, 0, nullptr, EmcClkOSLimit },
{"MEM Freq PLLM", &MemFreqPllmLimit, 2, nullptr, EmcClkPllmLimit },
{"MEM Volt", &MemVoltHandler, 2, nullptr, MemVoltHOS },
{"MEM Table Asm", &MemMtcTableAsm, 4, &MemMtcGetGetTablePatternFn },
};
for (uintptr_t ptr = mapped_nso; ptr <= mapped_nso + nso_size - sizeof(EristaMtcTable); ptr += sizeof(u32)) {

View File

@@ -140,10 +140,12 @@ namespace ams::ldr::hoc::pcv::erista {
MtcTableIndex index;
};
/* TODO: Test 6gb and 8gb. */
const inline MtcDramIndex mtcIndexTable[] = {
{ ICOSA_4GB_SAMSUNG_K4F6E304HB_MGCH, T210SdevEmcDvfsTableS4gb01, },
{ ICOSA_4GB_MICRON_MT53B512M32D2NP_062_WTC, T210SdevEmcDvfsTableS4gb01, },
{ ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH, T210SdevEmcDvfsTableS6gb01, },
{ ICOSA_8GB_SAMSUNG_K4FBE3D4HM_MGXX, T210SdevEmcDvfsTableS6gb01, },
{ ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE, T210SdevEmcDvfsTableH4gb01, },
};
@@ -151,8 +153,8 @@ namespace ams::ldr::hoc::pcv::erista {
constexpr u32 MtcMovAsm = 0x52800148;
constexpr u32 MtcAdrpAsm = 0xD0000081;
constexpr u32 MtcBlIns = 0x97ffae64;
constexpr u32 MtcAddAsm = 0x91131821;
constexpr u32 MtcAddAsm = 0x91131821;
ALWAYS_INLINE bool MemMtcGetGetTablePatternFn(u32 *ptr) {
/* This builds an address that gets returned, so the register must be x0 by convention. */
return AsmCompareAddNoImm12(*ptr, MtcAddAsm);
@@ -160,4 +162,4 @@ namespace ams::ldr::hoc::pcv::erista {
void Patch(uintptr_t mapped_nso, size_t nso_size);
}
}

View File

@@ -52,9 +52,9 @@ namespace ams::ldr::hoc::pcv::mariko {
R_THROW(ldr::ResultInvalidGpuDvfs());
}
if (C.marikoGpuBootVolt) {
PATCH_OFFSET(ptr - 3, C.marikoGpuBootVolt);
}
// if (C.marikoGpuBootVolt) {
// PATCH_OFFSET(ptr - 3, C.marikoGpuBootVolt);
// }
if (C.marikoGpuVmin) {
PATCH_OFFSET(ptr, C.marikoGpuVmin);
@@ -375,12 +375,6 @@ namespace ams::ldr::hoc::pcv::mariko {
WRITE_PARAM_ALL_REG(table, emc_cfg, 0xF3200000);
}
u32 refresh_raw = 0xFFFF;
if (C.t8_tREFI != 6) {
refresh_raw = CEIL(tREFpb_values[C.t8_tREFI] / tCK_avg) - 0x40;
refresh_raw = MIN(refresh_raw, static_cast<u32>(0xFFFF));
}
u32 trefbw = refresh_raw + 0x40;
trefbw = MIN(trefbw, static_cast<u32>(0x3FFF));
@@ -815,7 +809,6 @@ namespace ams::ldr::hoc::pcv::mariko {
s32 max0 = 1050;
s32 max1 = 1025;
s32 max2 = 1000;
s32 voltAdd = 25 * C.emcDvbShift;
if (C.marikoSocVmax && C.marikoSocVmax > 1000) {
max0 = C.marikoSocVmax;
@@ -825,15 +818,23 @@ namespace ams::ldr::hoc::pcv::mariko {
constexpr s32 MinVolt = 637;
auto ClampVolt = [&](s32 value, s32 max) {
auto ClampVolt = [&](s32 value, s32 max, s32 voltAdd) {
return std::clamp(value + voltAdd, MinVolt, max);
};
auto DvbVolt = [&](s32 zero, s32 one, s32 two) {
auto DvbVolt = [&](s32 zero, s32 one, s32 two, u32 index) {
const s32 overrideVoltage = C.marikoSocVoltArray[index];
s32 voltAdd = 25 * C.emcDvbShift;
if (overrideVoltage) {
zero = one = two = overrideVoltage;
voltAdd = 0;
}
return std::array<s32, 3>{
ClampVolt(zero, max0),
ClampVolt(one, max1),
ClampVolt(two, max2)
ClampVolt(zero, max0, voltAdd),
ClampVolt(one, max1, voltAdd),
ClampVolt(two, max2, voltAdd)
};
};
@@ -841,39 +842,45 @@ namespace ams::ldr::hoc::pcv::mariko {
static_cast<u32>((v)[0]), \
static_cast<u32>((v)[1]), \
static_cast<u32>((v)[2])
#define DVB_OC(one, zero, two, idx) \
DVB(DvbVolt(one, zero, two, idx))
DvbEntry emcDvbOcTableBrackets[] = {
{ 204000, { 637, 637, 637, }, },
{ 1331200, { 650, 637, 637, }, },
{ 1600000, { 675, 650, 637, }, },
{ 1866000, { DVB(DvbVolt( 700, 675, 650)) }, },
{ 2000000, { DVB(DvbVolt( 712, 687, 662)) }, },
{ 2133000, { DVB(DvbVolt( 725, 700, 675)) }, },
{ 2200000, { DVB(DvbVolt( 737, 712, 687)) }, },
{ 2266000, { DVB(DvbVolt( 750, 725, 700)) }, },
{ 2333000, { DVB(DvbVolt( 762, 737, 712)) }, },
{ 2400000, { DVB(DvbVolt( 775, 750, 725)) }, },
{ 2433000, { DVB(DvbVolt( 787, 762, 737)) }, },
{ 2466000, { DVB(DvbVolt( 800, 775, 750)) }, },
{ 2533000, { DVB(DvbVolt( 812, 787, 762)) }, },
{ 2566000, { DVB(DvbVolt( 825, 800, 775)) }, },
{ 2600000, { DVB(DvbVolt( 837, 812, 787)) }, },
{ 2666000, { DVB(DvbVolt( 850, 825, 800)) }, },
{ 2700000, { DVB(DvbVolt( 875, 850, 825)) }, },
{ 2733000, { DVB(DvbVolt( 887, 862, 837)) }, },
{ 2766000, { DVB(DvbVolt( 912, 887, 862)) }, },
{ 2800000, { DVB(DvbVolt( 925, 900, 875)) }, },
{ 2833000, { DVB(DvbVolt( 937, 912, 887)) }, },
{ 2900000, { DVB(DvbVolt( 950, 925, 900)) }, },
{ 2933000, { DVB(DvbVolt( 962, 937, 912)) }, },
{ 3000000, { DVB(DvbVolt( 975, 950, 925)) }, },
{ 3033000, { DVB(DvbVolt( 987, 962, 937)) }, },
{ 3100000, { DVB(DvbVolt(1000, 975, 950)) }, },
{ 3133000, { DVB(DvbVolt(1025, 1000, 975)) }, },
{ 3166000, { DVB(DvbVolt(1037, 1012, 987)) }, },
{ 3200000, { DVB(DvbVolt(1050, 1025, 1000)) }, },
{ ~0u, { }, },
{ 204000, { 637, 637, 637, }, },
{ 1331200, { 650, 637, 637, }, },
{ 1600000, { 675, 650, 637, }, },
{ 1866000, { DVB_OC( 700, 675, 650, 0) }, },
{ 2000000, { DVB_OC( 712, 687, 662, 1) }, },
{ 2133000, { DVB_OC( 725, 700, 675, 2) }, },
{ 2200000, { DVB_OC( 737, 712, 687, 3) }, },
{ 2266000, { DVB_OC( 750, 725, 700, 4) }, },
{ 2333000, { DVB_OC( 762, 737, 712, 5) }, },
{ 2400000, { DVB_OC( 775, 750, 725, 6) }, },
{ 2433000, { DVB_OC( 787, 762, 737, 7) }, },
{ 2466000, { DVB_OC( 800, 775, 750, 8) }, },
{ 2533000, { DVB_OC( 812, 787, 762, 9) }, },
{ 2566000, { DVB_OC( 825, 800, 775, 10) }, },
{ 2600000, { DVB_OC( 837, 812, 787, 11) }, },
{ 2666000, { DVB_OC( 850, 825, 800, 12) }, },
{ 2700000, { DVB_OC( 875, 850, 825, 13) }, },
{ 2733000, { DVB_OC( 887, 862, 837, 14) }, },
{ 2766000, { DVB_OC( 912, 887, 862, 15) }, },
{ 2800000, { DVB_OC( 925, 900, 875, 16) }, },
{ 2833000, { DVB_OC( 937, 912, 887, 17) }, },
{ 2900000, { DVB_OC( 950, 925, 900, 18) }, },
{ 2933000, { DVB_OC( 962, 937, 912, 19) }, },
{ 3000000, { DVB_OC( 975, 950, 925, 20) }, },
{ 3033000, { DVB_OC( 987, 962, 937, 21) }, },
{ 3100000, { DVB_OC(1000, 975, 950, 22) }, },
{ 3133000, { DVB_OC(1025, 1000, 975, 23) }, },
{ 3166000, { DVB_OC(1037, 1012, 987, 24) }, },
{ 3200000, { DVB_OC(1050, 1025, 1000, 25) }, },
{ ~0u, { }, },
};
#undef DVB
#undef DVB_OC
DvbEntry emcDvbTableOc[newEmcList.size()];
u32 bracketIndex = 0;

View File

@@ -20,7 +20,7 @@
namespace ams::ldr::hoc::ptm {
Result CpuPtmBoost(perf_conf_entry* entry) {
Result CpuPtmBoost(perf_conf_entry *entry) {
bool isMariko = (spl::GetSocType() == spl::SocType_Mariko);
if (!C.eristaCpuBoostClock || !C.marikoCpuBoostClock) {
@@ -35,19 +35,19 @@ namespace ams::ldr::hoc::ptm {
R_SUCCEED();
}
Result MemPtm(perf_conf_entry* entry) {
Result MemPtm(perf_conf_entry *entry) {
PATCH_OFFSET(&(entry->emc_freq_1), memPtmLimit);
PATCH_OFFSET(&(entry->emc_freq_2), memPtmLimit);
R_SUCCEED();
}
bool PtmEntryIsValid(perf_conf_entry* entry) {
bool PtmEntryIsValid(perf_conf_entry *entry) {
return (entry->cpu_freq_1 == entry->cpu_freq_2 && entry->gpu_freq_1 == entry->gpu_freq_2 && entry->emc_freq_1 == entry->emc_freq_2);
}
bool PtmTablePatternFn(u32* ptr) {
perf_conf_entry* entry = reinterpret_cast<perf_conf_entry *>(ptr);
bool PtmTablePatternFn(u32 *ptr) {
perf_conf_entry *entry = reinterpret_cast<perf_conf_entry *>(ptr);
if (!PtmEntryIsValid(entry)) {
return false;
}
@@ -56,9 +56,9 @@ namespace ams::ldr::hoc::ptm {
}
void Patch(uintptr_t mapped_nso, size_t nso_size) {
perf_conf_entry* confTable = nullptr;
perf_conf_entry *confTable = nullptr;
for (uintptr_t ptr = mapped_nso; ptr <= mapped_nso + nso_size - sizeof(perf_conf_entry) * entryCnt; ptr += sizeof(u32)) {
u32* ptr32 = reinterpret_cast<u32 *>(ptr);
u32 *ptr32 = reinterpret_cast<u32 *>(ptr);
if (PtmTablePatternFn(ptr32)) {
confTable = reinterpret_cast<perf_conf_entry *>(ptr);
break;

View File

@@ -22,7 +22,7 @@
namespace ams::ldr::hoc::ptm {
typedef struct {
struct perf_conf_entry {
u32 conf_id;
u32 cpu_freq_1; // min-max pair?
u32 cpu_freq_2;
@@ -31,7 +31,7 @@ namespace ams::ldr::hoc::ptm {
u32 emc_freq_1;
u32 emc_freq_2;
u32 padding;
} perf_conf_entry;
};
constexpr u32 entryCnt = 16;
constexpr u32 cpuPtmDefault = 1020'000'000;

9
Source/Benchmark-Toolbox/.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
# build artifacts
build/
*.nro
*.elf
*.nacp
*.map
# generated nanovg shaders (regenerated by the build)
resources/shaders/

View File

@@ -0,0 +1,207 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITPRO)),)
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITPRO)/libnx/switch_rules
#---------------------------------------------------------------------------------
TARGET := Benchmark-Toolbox
BUILD := build
SOURCES := source source/furmark source/memtester source/cpustress
DATA := data
ICON := icon.jpg
INCLUDES := source source/furmark source/memtester source/cpustress ../hoc-clk/common/include
APP_TITLE := Benchmark Toolbox
APP_AUTHOR := Horizon-OC
APP_VERSION := 2.0.0
ROMFS := resources
BOREALIS_PATH := lib/borealis
# Output folder (in romfs) for borealis' autogenerated nanovg shaders
OUT_SHADERS := shaders
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE
CFLAGS := -g -Wall -O2 -ffunction-sections \
$(ARCH) $(DEFINES)
CFLAGS += $(INCLUDE) -D__SWITCH__ -pthread
# -include optional: borealis' nanovg dk_renderer.hpp uses std::optional without
# including <optional> (newer libstdc++ dropped the transitive include).
CXXFLAGS := $(CFLAGS) -std=gnu++17 -O2 -Wno-volatile -fexceptions -include optional
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) -pthread
# borealis.mk prepends -ldeko3d -lm. gpu_bw.c uses EGL/GLES; the Furmark tests
# use desktop GL via glad. Add the full GL stack.
LIBS := -lglad -lGLESv2 -lEGL -lglapi -ldrm_nouveau -lnx
#---------------------------------------------------------------------------------
LIBDIRS := $(PORTLIBS) $(LIBNX)
# Pull in borealis: appends its SOURCES / INCLUDES / LIBS / CXXFLAGS.
# Run `git submodule update --init --recursive` so lib/borealis is populated.
include $(TOPDIR)/$(BOREALIS_PATH)/library/borealis.mk
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
GLSLFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.glsl)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
export LD := $(CC)
else
export LD := $(CXX)
endif
#---------------------------------------------------------------------------------
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
ifneq ($(strip $(ROMFS)),)
ROMFS_TARGETS :=
ROMFS_FOLDERS :=
ifneq ($(strip $(OUT_SHADERS)),)
ROMFS_SHADERS := $(ROMFS)/$(OUT_SHADERS)
ROMFS_TARGETS += $(patsubst %.glsl, $(ROMFS_SHADERS)/%.dksh, $(GLSLFILES))
ROMFS_FOLDERS += $(ROMFS_SHADERS)
endif
export ROMFS_DEPS := $(foreach file,$(ROMFS_TARGETS),$(CURDIR)/$(file))
endif
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
export APP_ICON := $(TOPDIR)/$(ICON)
ifeq ($(strip $(NO_ICON)),)
export NROFLAGS += --icon=$(APP_ICON)
endif
ifeq ($(strip $(NO_NACP)),)
export NROFLAGS += --nacp=$(CURDIR)/$(TARGET).nacp
endif
ifneq ($(APP_TITLEID),)
export NACPFLAGS += --titleid=$(APP_TITLEID)
endif
ifneq ($(ROMFS),)
export NROFLAGS += --romfsdir=$(CURDIR)/$(ROMFS)
endif
.PHONY: all clean
#---------------------------------------------------------------------------------
all: $(ROMFS_TARGETS) | $(BUILD)
@MSYS2_ARG_CONV_EXCL="-D;$(MSYS2_ARG_CONV_EXCL)" $(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
$(BUILD):
@mkdir -p $@
ifneq ($(strip $(ROMFS_TARGETS)),)
$(ROMFS_TARGETS): | $(ROMFS_FOLDERS)
$(ROMFS_FOLDERS):
@mkdir -p $@
$(ROMFS_SHADERS)/%_vsh.dksh: %_vsh.glsl
@echo {vert} $(notdir $<)
@uam -s vert -o $@ $<
$(ROMFS_SHADERS)/%_tcsh.dksh: %_tcsh.glsl
@echo {tess_ctrl} $(notdir $<)
@uam -s tess_ctrl -o $@ $<
$(ROMFS_SHADERS)/%_tesh.dksh: %_tesh.glsl
@echo {tess_eval} $(notdir $<)
@uam -s tess_eval -o $@ $<
$(ROMFS_SHADERS)/%_gsh.dksh: %_gsh.glsl
@echo {geom} $(notdir $<)
@uam -s geom -o $@ $<
$(ROMFS_SHADERS)/%_fsh.dksh: %_fsh.glsl
@echo {frag} $(notdir $<)
@uam -s frag -o $@ $<
$(ROMFS_SHADERS)/%.dksh: %.glsl
@echo {comp} $(notdir $<)
@uam -s comp -o $@ $<
endif
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(ROMFS_FOLDERS) $(TARGET).nro $(TARGET).nacp $(TARGET).elf
#---------------------------------------------------------------------------------
else
.PHONY: all
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
all : $(OUTPUT).nro
ifeq ($(strip $(NO_NACP)),)
$(OUTPUT).nro : $(OUTPUT).elf $(OUTPUT).nacp $(ROMFS_DEPS)
else
$(OUTPUT).nro : $(OUTPUT).elf $(ROMFS_DEPS)
endif
$(OUTPUT).elf : $(OFILES)
$(OFILES_SRC) : $(HFILES_BIN)
#---------------------------------------------------------------------------------
%.bin.o %_bin.h : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
#---------------------------------------------------------------------------------
%.png.o %_png.h : %.png
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

Binary file not shown.

After

Width:  |  Height:  |  Size: 413 B

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 647 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

View File

@@ -0,0 +1,21 @@
---
AccessModifierOffset: -2
AlignConsecutiveAssignments: 'true'
BasedOnStyle: WebKit
BreakBeforeBraces: Allman
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^<borealis/.*\.hpp>'
Priority: 2
- Regex: '^<.*\.h>'
Priority: 1
- Regex: '^<.*'
Priority: 2
- Regex: '.*'
Priority: 3
IndentCaseLabels: 'true'
PointerAlignment: Left
SortIncludes: 'true'
Standard: Cpp11
...

View File

@@ -0,0 +1,12 @@
# List of borealis's significant contributors
#
# This does not necessarily list everyone who has contributed code.
# To see the full list of contributors, see the contributors page on GitHub
# https://github.com/natinusala/borealis/graphs/contributors
natinusala
p-sam
WerWolv
bylaws
H0neyBadger
D3fau4
Behemoth

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -37,24 +37,34 @@ include $(DEVKITPRO)/libnx/switch_rules
# of a homebrew executable (.nro). This is intended to be used for sysmodules.
# NACP building is skipped as well.
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source
TARGET := borealis_demo
BUILD := build.nx
SOURCES := demo
DATA := data
INCLUDES := include
#ROMFS := romfs
ICON := resources/img/demo_icon.jpg
INCLUDES := demo
APP_TITLE := borealis demo
APP_AUTHOR := natinusala
APP_VERSION := 1.0
ROMFS := resources
BOREALIS_PATH := .
# Output folders for autogenerated files in romfs
OUT_SHADERS := shaders
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE -fPIC
ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE
CFLAGS := -g -Wall -O2 -ffunction-sections \
$(ARCH) $(DEFINES)
CFLAGS += $(INCLUDE) -D__SWITCH__
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
CXXFLAGS := $(CFLAGS) -std=c++1z -O2 -Wno-volatile
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
@@ -67,6 +77,7 @@ LIBS := -lnx
#---------------------------------------------------------------------------------
LIBDIRS := $(PORTLIBS) $(LIBNX)
include $(TOPDIR)/library/borealis.mk
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
@@ -86,6 +97,7 @@ export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
GLSLFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.glsl)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
@@ -107,6 +119,18 @@ export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
ifneq ($(strip $(ROMFS)),)
ROMFS_TARGETS :=
ROMFS_FOLDERS :=
ifneq ($(strip $(OUT_SHADERS)),)
ROMFS_SHADERS := $(ROMFS)/$(OUT_SHADERS)
ROMFS_TARGETS += $(patsubst %.glsl, $(ROMFS_SHADERS)/%.dksh, $(GLSLFILES))
ROMFS_FOLDERS += $(ROMFS_SHADERS)
endif
export ROMFS_DEPS := $(foreach file,$(ROMFS_TARGETS),$(CURDIR)/$(file))
endif
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
@@ -155,22 +179,55 @@ ifneq ($(ROMFS),)
export NROFLAGS += --romfsdir=$(CURDIR)/$(ROMFS)
endif
.PHONY: $(BUILD) clean all
.PHONY: all clean
#---------------------------------------------------------------------------------
all: $(BUILD)
all: $(ROMFS_TARGETS) | $(BUILD)
@MSYS2_ARG_CONV_EXCL="-D;$(MSYS2_ARG_CONV_EXCL)" $(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
@mkdir -p $@
ifneq ($(strip $(ROMFS_TARGETS)),)
$(ROMFS_TARGETS): | $(ROMFS_FOLDERS)
$(ROMFS_FOLDERS):
@mkdir -p $@
$(ROMFS_SHADERS)/%_vsh.dksh: %_vsh.glsl
@echo {vert} $(notdir $<)
@uam -s vert -o $@ $<
$(ROMFS_SHADERS)/%_tcsh.dksh: %_tcsh.glsl
@echo {tess_ctrl} $(notdir $<)
@uam -s tess_ctrl -o $@ $<
$(ROMFS_SHADERS)/%_tesh.dksh: %_tesh.glsl
@echo {tess_eval} $(notdir $<)
@uam -s tess_eval -o $@ $<
$(ROMFS_SHADERS)/%_gsh.dksh: %_gsh.glsl
@echo {geom} $(notdir $<)
@uam -s geom -o $@ $<
$(ROMFS_SHADERS)/%_fsh.dksh: %_fsh.glsl
@echo {frag} $(notdir $<)
@uam -s frag -o $@ $<
$(ROMFS_SHADERS)/%.dksh: %.glsl
@echo {comp} $(notdir $<)
@uam -s comp -o $@ $<
endif
#---------------------------------------------------------------------------------
clean:
@echo clean ...
ifeq ($(strip $(APP_JSON)),)
@rm -fr $(BUILD) $(TARGET).nro $(TARGET).nacp $(TARGET).elf
@rm -fr $(BUILD) $(ROMFS_FOLDERS) $(TARGET).nro $(TARGET).nacp $(TARGET).elf
else
@rm -fr $(BUILD) $(TARGET).nsp $(TARGET).nso $(TARGET).npdm $(TARGET).elf
@rm -fr $(BUILD) $(ROMFS_FOLDERS) $(TARGET).nsp $(TARGET).nso $(TARGET).npdm $(TARGET).elf
endif
@@ -188,9 +245,9 @@ ifeq ($(strip $(APP_JSON)),)
all : $(OUTPUT).nro
ifeq ($(strip $(NO_NACP)),)
$(OUTPUT).nro : $(OUTPUT).elf $(OUTPUT).nacp
$(OUTPUT).nro : $(OUTPUT).elf $(OUTPUT).nacp $(ROMFS_DEPS)
else
$(OUTPUT).nro : $(OUTPUT).elf
$(OUTPUT).nro : $(OUTPUT).elf $(ROMFS_DEPS)
endif
else
@@ -219,4 +276,4 @@ $(OFILES_SRC) : $(HFILES_BIN)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------

View File

@@ -0,0 +1,13 @@
Copyright 2019-2021 borealis contributors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,79 @@
![borealis logo](https://github.com/natinusala/borealis/blob/main/resources/img/borealis_96.png?raw=true)
# borealis
Controller and TV oriented UI library for PC and Nintendo Switch (libnx).
⚠️ Warning: the project is a WIP - See the Projects tab to follow the journey towards a stable version!
The code for the old version is available in the `legacy` branch.
⚠️ The wiki only contains the documentation for the old version of the library, it has yet to be updated!
- Mimicks the Nintendo Switch system UI, but can also be used to make anything else painlessly
- Hardware acceleration and vector graphics with automatic scaling for TV usage (powered by nanovg)
- Can be ported to new platforms and graphics APIs by providing a nanovg implementation
- Powerful layout engine using flex box as a base for everything (powered by Yoga Layout)
- Automated navigation paths for out-of-the-box controller navigation
- Out of the box touch support
- Define user interfaces using XML and only write code when it matters
- Use and restyle built-in components or make your own from scratch
- Display large amount of data efficiently using recycling lists
- Integrated internationalization and storage systems
- Integrated toolbox (logger, animations, timers, background tasks...)
## Building the demo for Switch
To build for Switch, a standard development environment must first be set up. In order to do so, [refer to the Getting Started guide](https://devkitpro.org/wiki/Getting_Started).
```bash
(sudo) (dkp-)pacman -S switch-glfw switch-mesa switch-glm
make -j
nxlink -s borealis_demo.nro
```
## Building the demo for PC
To build for PC, the following components are required:
- meson/ninja build system
- A C++ compiler supporting the C++17 standard
- GLFW version 3.3 or higher (as a static library)
- GLM version 0.9.8 or higher
Please refer to the usual sources of information for your particular operating system. Usually the commands needed to build this project will look like this:
```bash
meson build
ninja -C build
./build/borealis_demo
```
Also, please note that the `resources` folder must be available in the working directory, otherwise the program will fail to find the shaders.
### Building the demo for Windows using msys2
msys2 provides all packages needed to build this project:
```bash
pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-meson mingw-w64-x86_64-ninja mingw-w64-x86_64-pkg-config mingw-w64-x86_64-glfw mingw-w64-x86_64-glm
meson build
ninja -C build
./build/borealis_demo
```
### Including in your project (TL;DR: see the demo makefile in this repo)
0. Your project must be built as C++17 (`-std=c++1z`). You also need to remove `-fno-rtti` and `-fno-exceptions` if you have them
1. Use a submodule (or even better, a [subrepo](https://github.com/ingydotnet/git-subrepo)) to clone this repository in your project
2. Copy the `resources` folder to the root of your project
3. For PC (meson):
1. take a standard meson file
2. use `subdir` to import the library folder
3. use the `borealis_files`, `borealis_dependencies`, `borealis_include` and `borealis_cpp_args` variables for respectively objects to build, dependencies (glfw...), includes directory and cpp args
4. add a `BRLS_RESOURCES` define pointing to the resources folder at runtime (so `resources`)
4. For Switch:
1. take a standard deko3d homebrew makefile (from the switch-examples repo)
2. add a `BOREALIS_PATH` variable containing the subfolder you put the library in
3. set `ROMFS` to the resources folder - borealis resources path is set to `romfs:/` in borealis.mk
4. use `include` to load `borealis.mk` (after `LIBDIRS` and `BOREALIS_PATH`)
5. it's important for `OUT_SHADERS` to be set to `shaders` since nanovg will look for the shaders there
6. if you have issues with the `BRLS_RESOURCES` define (missing quote terminator), change the `@$(MAKE)` line to `@MSYS2_ARG_CONV_EXCL="-D;$(MSYS2_ARG_CONV_EXCL)" $(MAKE)` in the Makefile (as in the demo Makefile)

View File

@@ -0,0 +1,65 @@
/*
Copyright 2020-2021 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "captioned_image.hpp"
CaptionedImage::CaptionedImage()
{
// Load the XML file and inflate ourself with its content
// The top-level Box in the XML corresponds to us, and every XML child
// is added to our children (and the attributes are applied)
// The CaptionedImage instance basically becomes what's written in the XML
this->inflateFromXMLRes("xml/views/captioned_image.xml");
// The label stays hidden until focused, so hide it right away
this->label->hide([] {});
// Forward Image and Label XML attributes
this->forwardXMLAttribute("scalingType", this->image);
this->forwardXMLAttribute("image", this->image);
this->forwardXMLAttribute("focusUp", this->image);
this->forwardXMLAttribute("focusRight", this->image);
this->forwardXMLAttribute("focusDown", this->image);
this->forwardXMLAttribute("focusLeft", this->image);
this->forwardXMLAttribute("imageWidth", this->image, "width");
this->forwardXMLAttribute("imageHeight", this->image, "height");
this->forwardXMLAttribute("caption", this->label, "text");
}
void CaptionedImage::onChildFocusGained(brls::View* directChild, brls::View* focusedView)
{
// Called when a child of ours gets focused, in that case it's the Image
Box::onChildFocusGained(directChild, focusedView);
this->label->show([] {});
}
void CaptionedImage::onChildFocusLost(brls::View* directChild, brls::View* focusedView)
{
// Called when a child of ours losts focused, in that case it's the Image
Box::onChildFocusLost(directChild, focusedView);
this->label->hide([] {});
}
brls::View* CaptionedImage::create()
{
// Called by the XML engine to create a new CaptionedImage
return new CaptionedImage();
}

View File

@@ -0,0 +1,34 @@
/*
Copyright 2020-2021 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <borealis.hpp>
class CaptionedImage : public brls::Box
{
public:
CaptionedImage();
void onChildFocusGained(brls::View* directChild, brls::View* focusedView) override;
void onChildFocusLost(brls::View* directChild, brls::View* focusedView) override;
static brls::View* create();
private:
BRLS_BIND(brls::Image, image, "image");
BRLS_BIND(brls::Label, label, "label");
};

View File

@@ -0,0 +1,43 @@
/*
Copyright 2021 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "components_tab.hpp"
ComponentsTab::ComponentsTab()
{
// Inflate the tab from the XML file
this->inflateFromXMLRes("xml/tabs/components.xml");
// Bind the button click to a method using the macro (just for the sake of showcasing it, it's overkill in this situation)
BRLS_REGISTER_CLICK_BY_ID("button_primary", this->onPrimaryButtonClicked);
// Get a handle to the button and register the action directly
brls::Button* highlightButton = (brls::Button*)this->getView("button_highlight");
highlightButton->registerAction(
"Honk", brls::BUTTON_A, [](brls::View* view) { return true; }, false, brls::SOUND_HONK);
}
bool ComponentsTab::onPrimaryButtonClicked(brls::View* view)
{
brls::Logger::info("Clicked");
return true;
}
brls::View* ComponentsTab::create()
{
// Called by the XML engine to create a new ComponentsTab
return new ComponentsTab();
}

View File

@@ -0,0 +1,30 @@
/*
Copyright 2021 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <borealis.hpp>
class ComponentsTab : public brls::Box
{
public:
ComponentsTab();
static brls::View* create();
private:
bool onPrimaryButtonClicked(brls::View* view);
};

View File

@@ -0,0 +1,82 @@
/*
Copyright 2020-2021 natinusala
Copyright 2019 p-sam
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Switch include only necessary for demo videos recording
#ifdef __SWITCH__
#include <switch.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <borealis.hpp>
#include <string>
#include "captioned_image.hpp"
#include "components_tab.hpp"
#include "main_activity.hpp"
#include "recycling_list_tab.hpp"
using namespace brls::literals; // for _i18n
int main(int argc, char* argv[])
{
// Enable recording for Twitter memes
#ifdef __SWITCH__
appletInitializeGamePlayRecording();
#endif
// Set log level
// We recommend to use INFO for real apps
brls::Logger::setLogLevel(brls::LogLevel::DEBUG);
// Init the app and i18n
if (!brls::Application::init())
{
brls::Logger::error("Unable to init Borealis application");
return EXIT_FAILURE;
}
brls::Application::createWindow("demo/title"_i18n);
// Have the application register an action on every activity that will quit when you press BUTTON_START
brls::Application::setGlobalQuit(true);
// Register custom views (including tabs, which are views)
brls::Application::registerXMLView("CaptionedImage", CaptionedImage::create);
brls::Application::registerXMLView("RecyclingListTab", RecyclingListTab::create);
brls::Application::registerXMLView("ComponentsTab", ComponentsTab::create);
// Add custom values to the theme
brls::getLightTheme().addColor("captioned_image/caption", nvgRGB(2, 176, 183));
brls::getDarkTheme().addColor("captioned_image/caption", nvgRGB(51, 186, 227));
// Add custom values to the style
brls::getStyle().addMetric("about/padding_top_bottom", 50);
brls::getStyle().addMetric("about/padding_sides", 75);
brls::getStyle().addMetric("about/description_margin", 50);
// Create and push the main activity to the stack
brls::Application::pushActivity(new MainActivity());
// Run the app
while (brls::Application::mainLoop())
;
// Exit
return EXIT_SUCCESS;
}

View File

@@ -0,0 +1,17 @@
/*
Copyright 2020-2021 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "main_activity.hpp"

View File

@@ -0,0 +1,26 @@
/*
Copyright 2020-2021 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <borealis.hpp>
class MainActivity : public brls::Activity
{
public:
// Declare that the content of this activity is the given XML file
CONTENT_FROM_XML_RES("activity/main.xml");
};

View File

@@ -0,0 +1,29 @@
/*
Copyright 2020-2021 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "recycling_list_tab.hpp"
RecyclingListTab::RecyclingListTab()
{
// Inflate the tab from the XML file
this->inflateFromXMLRes("xml/tabs/recycling_list.xml");
}
brls::View* RecyclingListTab::create()
{
// Called by the XML engine to create a new RecyclingListTab
return new RecyclingListTab();
}

View File

@@ -0,0 +1,27 @@
/*
Copyright 2020-2021 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <borealis.hpp>
class RecyclingListTab : public brls::Box
{
public:
RecyclingListTab();
static brls::View* create();
};

View File

@@ -0,0 +1,35 @@
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
current_dir := $(BOREALIS_PATH)/$(notdir $(patsubst %/,%,$(dir $(mkfile_path))))
LIBS := -ldeko3d -lm $(LIBS)
include $(TOPDIR)/$(current_dir)/lib/extern/switch-libpulsar/deps.mk
SOURCES := $(SOURCES) \
$(current_dir)/lib/core \
$(current_dir)/lib/views \
$(current_dir)/lib/platforms/switch \
$(current_dir)/lib/extern/glad \
$(current_dir)/lib/extern/nanovg-deko3d/source \
$(current_dir)/lib/extern/nanovg-deko3d/source/framework \
$(current_dir)/lib/extern/nanovg-deko3d/shaders \
$(current_dir)/lib/extern/libretro-common/compat \
$(current_dir)/lib/extern/libretro-common/encodings \
$(current_dir)/lib/extern/libretro-common/features \
$(current_dir)/lib/extern/nxfmtwrapper \
$(current_dir)/lib/extern/yoga/src/yoga/event \
$(current_dir)/lib/extern/yoga/src/yoga \
$(current_dir)/lib/extern/tinyxml2/ \
$(addprefix $(current_dir)/lib/extern/switch-libpulsar/, $(PLSR_SOURCES))
INCLUDES := $(INCLUDES) \
$(current_dir)/include \
$(current_dir)/lib/extern/fmt/include \
$(current_dir)/lib/extern/yoga/src \
$(current_dir)/lib/extern/nanovg-deko3d/include \
$(current_dir)/lib/extern/tweeny/include \
$(current_dir)/include/borealis/extern \
$(current_dir)/include/borealis/extern/tinyxml2 \
$(addprefix $(current_dir)/lib/extern/switch-libpulsar/, $(PLSR_INCLUDES))
CXXFLAGS := $(CXXFLAGS) -DYG_ENABLE_EVENTS -fdata-sections -DBRLS_RESOURCES="\"romfs:/\""

View File

@@ -0,0 +1,53 @@
/*
Copyright 2019-2021 natinusala
Copyright 2019 p-sam
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
// Core
#include <borealis/core/actions.hpp>
#include <borealis/core/activity.hpp>
#include <borealis/core/animation.hpp>
#include <borealis/core/application.hpp>
#include <borealis/core/assets.hpp>
#include <borealis/core/audio.hpp>
#include <borealis/core/bind.hpp>
#include <borealis/core/box.hpp>
#include <borealis/core/event.hpp>
#include <borealis/core/font.hpp>
#include <borealis/core/frame_context.hpp>
#include <borealis/core/i18n.hpp>
#include <borealis/core/input.hpp>
#include <borealis/core/logger.hpp>
#include <borealis/core/platform.hpp>
#include <borealis/core/style.hpp>
#include <borealis/core/task.hpp>
#include <borealis/core/theme.hpp>
#include <borealis/core/time.hpp>
#include <borealis/core/timer.hpp>
#include <borealis/core/video.hpp>
#include <borealis/core/view.hpp>
//Views
#include <borealis/views/applet_frame.hpp>
#include <borealis/views/button.hpp>
#include <borealis/views/header.hpp>
#include <borealis/views/image.hpp>
#include <borealis/views/label.hpp>
#include <borealis/views/rectangle.hpp>
#include <borealis/views/scrolling_frame.hpp>
#include <borealis/views/sidebar.hpp>
#include <borealis/views/tab_frame.hpp>

View File

@@ -0,0 +1,52 @@
/*
Copyright 2020 WerWolv
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <borealis/core/audio.hpp>
#include <borealis/core/input.hpp>
#include <functional>
#include <string>
namespace brls
{
class View;
typedef std::function<bool(View*)> ActionListener;
typedef int ActionIdentifier;
#define ACTION_NONE -1
struct Action
{
enum ControllerButton button;
ActionIdentifier identifier;
std::string hintText;
bool available;
bool hidden;
enum Sound sound;
ActionListener actionListener;
bool operator==(const enum ControllerButton other)
{
return this->button == other;
}
};
} // namespace brls

View File

@@ -0,0 +1,162 @@
/*
Copyright 2020 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <borealis/core/view.hpp>
namespace brls
{
#define CONTENT_FROM_XML_RES(x) \
brls::View* createContentView() override { return brls::View::createFromXMLResource(x); }
#define CONTENT_FROM_XML_FILE(x) \
brls::View* createContentView() override { return brls::View::createFromXMLFile(x); }
#define CONTENT_FROM_XML_STR(x) \
brls::View* createContentView() override { return brls::View::createFromXMLString(x); }
// An activity is a "screen" of your app in which the library adds
// the UI components. The app is made of a stack of activities, each activity
// containing a views tree.
class Activity
{
public:
Activity();
virtual ~Activity();
/**
* Sets the content view of this activity, aka
* the root view of the tree.
*
* When the activity is pushed, setContentView() is
* automatically called with the result of createContentView().
* As such, you should override createContentView() if you want
* to use XML in your activity.
*/
void setContentView(View* view);
/**
* Called when the activity is created. Should return the activity content view, if any.
*
* Returning nullptr means the content is not known when the activity is created.
*
* You can use View::createFromXMLFile(), View::createFromXMLResource() and View::createFromXMLString() to load
* a view from respectively an XML file path, an XML name in the resources/xml romfs directory and an XML string.
*
* The CONTENT_FROM_XML_FILE, CONTENT_FROM_XML_RES, CONTENT_FROM_XML_STR macros
* are made to make this process simpler: just use them in the public block of your activity
* header and it will override createContentView() with the right code for you.
*
* The onContentAvailable() method will be called once the content has been created, so that
* you can get the references to the activity views (by id).
*/
virtual View* createContentView();
/**
* Called when the content view is created, so that
* you can get the references to the activity views (by id).
*/
virtual void onContentAvailable() {};
View* getContentView();
/**
* Returns the view with the corresponding id, or nullptr
* if it hasn't been found in the activity.
*/
View* getView(std::string id);
/**
* Resizes the activity to fit the window. Called when the activity
* is created and when the window is resized (Switch dock counts as window resize).
*/
void resizeToFitWindow();
/**
* Returns the duration of the activity show / hide animation.
*/
virtual float getShowAnimationDuration(TransitionAnimation animation);
/**
* Is this activity translucent, aka can we see the
* activities under it in the stack?
*/
bool isTranslucent();
void willAppear(bool resetState = false);
void willDisappear(bool resetState = false);
/**
* If set to true, will force the activity to be translucent.
*/
void setInFadeAnimation(bool translucent);
/**
* Shows the activity with a fade in animation, or no animation at all.
*/
void show(std::function<void(void)> cb, bool animate, float animationDuration);
/**
* Hides the activity with a fade in animation, or no animation at all.
*/
void hide(std::function<void(void)> cb, bool animate, float animationDuration);
bool isHidden();
/**
* Registers an action with the given parameters on the content view. The listener will be fired
* when the user presses the key.
*
* The listener should return true if the action was consumed, false otherwise.
* The sound will only be played if the listener returned true.
*
* A hidden action will not show up in the bottom-right hints.
*
* Must be called after the content view is set.
*
* Returns the identifier for the action, so it can be unregistered later on. Returns ACTION_NONE if the
* action was not registered.
*/
ActionIdentifier registerAction(std::string hintText, enum ControllerButton button, ActionListener actionListener, bool hidden = false, enum Sound sound = SOUND_NONE);
/**
* Unregisters an action with the given identifier on the content view.
*
* Must be called after the content view is set.
*/
void unregisterAction(ActionIdentifier identifier);
/**
* Registers an action to exit the application with the default button BUTTON_START.
*
* Must be called after the content view is set.
*
* Returns the identifier for the action, so it can be unregistered later on. Returns ACTION_NONE if the
* action was not registered.
*/
ActionIdentifier registerExitAction(enum ControllerButton button = brls::BUTTON_START);
void onWindowSizeChanged();
View* getDefaultFocus();
void setAlpha(float alpha);
private:
View* contentView = nullptr;
};
} // namespace brls

View File

@@ -0,0 +1,104 @@
/*
Copyright 2021 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <tweeny.h>
#include <borealis/core/time.hpp>
namespace brls
{
using EasingFunction = tweeny::easing::enumerated;
// An animatable is a float which value can be animated from an initial value to a target value,
// during a given amount of time. An easing function can also be specified.
//
// Declare the animatable and then use reset(initialValue) to reset the animation.
// Add as many steps as you like by calling addStep(targetValue, duration, easing) one or multiple times.
// Then, start and stop the animation with start() and stop().
//
// setEndCallback() and setTickCallback() allow you to execute code as long as the animation runs and / or once when it finishes.
// Use .getValue() to get the current value at any time.
//
// An animatable has overloads for float conversion, comparison (==) and assignment operator (=) to allow
// basic usage as a simple float. Assignment operator is a shortcut to the reset() method.
class Animatable : public FiniteTicking
{
public:
/**
* Creates an animatable with the given initial value.
*/
Animatable(float value = 0.0f);
/**
* Returns the current animatable value.
*/
float getValue();
/**
* Stops and resets the animation, going back to the given initial value.
* All steps are removed.
* If an animation was already ongoing for that animatable, its end callback
* will be called.
*/
void reset(float initialValue);
/**
* Stops and resets the animation. The value will stay where it's at.
* All steps are removed.
* If an animation was already ongoing for that animatable, its end callback
* will be called.
*/
void reset();
/**
* Adds an animation step to the target value, lasting the specified duration in milliseconds.
*
* An animation can have multiple steps. Target value can be greater and lower than the previous step (it can go forwards or backwards).
* Easing function is optional, default is EasingFunction::linear.
*
* Duration is int32_t due to internal limitations, so a step cannot last for longer than 2 147 483 647ms.
* The sum of the duration of all steps cannot exceed 71582min.
*/
void addStep(float targetValue, int32_t duration, EasingFunction easing = EasingFunction::linear);
/**
* Returns the progress of the animation between 0.0f and 1.0f.
*/
float getProgress();
operator float() const;
operator float();
void operator=(const float value);
bool operator==(const float value);
protected:
bool onUpdate(Time delta) override;
void onReset() override;
void onRewind() override;
private:
float currentValue = 0.0f;
tweeny::tween<float> tween;
};
void updateHighlightAnimation();
void getHighlightAnimation(float* gradient_x, float* gradient_y, float* color);
} // namespace brls

View File

@@ -0,0 +1,246 @@
/*
Copyright 2019-2021 natinusala
Copyright 2019 p-sam
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <nanovg.h>
#include <tinyxml2.h>
#include <borealis/core/activity.hpp>
#include <borealis/core/audio.hpp>
#include <borealis/core/font.hpp>
#include <borealis/core/frame_context.hpp>
#include <borealis/core/logger.hpp>
#include <borealis/core/platform.hpp>
#include <borealis/core/style.hpp>
#include <borealis/core/theme.hpp>
#include <borealis/core/view.hpp>
#include <borealis/views/label.hpp>
#include <unordered_map>
#include <vector>
namespace brls
{
typedef std::function<View*(void)> XMLViewCreator;
class Application
{
public:
/**
* Inits the borealis application.
* Returns true if it succeeded, false otherwise.
*/
static bool init();
/**
* Creates the application window with the given title.
* Must be called after calling init().
*/
static void createWindow(std::string title);
/**
* Application main loop iteration.
* Must be called in an infinite loop until it returns false.
*/
static bool mainLoop();
static Platform* getPlatform();
static AudioPlayer* getAudioPlayer();
static NVGcontext* getNVGContext();
inline static float contentWidth, contentHeight;
/**
* Called by the video context when the content window is resized
* and when the context is ready (to setup the initial content scaling).
*/
static void onWindowResized(int width, int height);
/**
* Pushes a view on this applications's view stack.
*
* The view will automatically be resized to take
* the whole screen.
*
* The view will gain focus if applicable.
*
* The first activity to be pushed cannot be popped.
*/
static void pushActivity(Activity* view, TransitionAnimation animation = TransitionAnimation::FADE);
/**
* Pops the last pushed activity from the stack
* and gives focus back where it was before.
*/
static void popActivity(
TransitionAnimation animation = TransitionAnimation::FADE, std::function<void(void)> cb = [] {});
/**
* Gives the focus to the given view
* or clears the focus if given nullptr.
*/
static void giveFocus(View* view);
inline static Style getStyle()
{
return brls::getStyle();
}
static Theme getTheme();
static ThemeVariant getThemeVariant();
/**
* Loads a font from a given file and stores it in the font stash.
* Returns true if the operation succeeded.
*/
static bool loadFontFromFile(std::string fontName, std::string filePath);
/**
* Loads a font from a given memory buffer and stores it in the font stash.
* Returns true if the operation succeeded.
*/
static bool loadFontFromMemory(std::string fontName, void* data, size_t size, bool freeData);
/**
* Returns the nanovg handle to the given font name, or FONT_INVALID if
* no such font is currently loaded.
*/
static int getFont(std::string fontName);
static void notify(std::string text);
static void onControllerButtonPressed(enum ControllerButton button, bool repeating);
/**
* "Crashes" the app (displays a fullscreen CrashFrame)
*/
static void crash(std::string text);
static void quit();
/**
* Blocks any and all user inputs
*/
static void blockInputs();
/**
* Unblocks inputs after a call to
* blockInputs()
*/
static void unblockInputs();
static void setCommonFooter(std::string footer);
static std::string* getCommonFooter();
static void setDisplayFramerate(bool enabled);
static void toggleFramerateDisplay();
static void setMaximumFPS(unsigned fps);
inline static float windowScale;
/**
* Sets whether BUTTON_START will globally be used to close the application.
*/
static void setGlobalQuit(bool enabled);
/**
* Sets whether BUTTON_BACK will globally be used to toggle an FPS display.
*/
static void setGlobalFPSToggle(bool enabled);
static GenericEvent* getGlobalFocusChangeEvent();
static VoidEvent* getGlobalHintsUpdateEvent();
static View* getCurrentFocus();
static std::string getTitle();
/**
* Registers a view to be created from XML. You must give the name of the XML node as well
* as a function that creates the view.
*
* If you need attributes, register them with the given functions in the view
* class constructor directly. They will be called one by one after the view is instantiated.
*
* You should not add any children in the function, it is already taken care of.
*/
static void registerXMLView(std::string name, XMLViewCreator creator);
static bool XMLViewsRegisterContains(std::string name);
static XMLViewCreator getXMLViewCreator(std::string name);
/**
* Returns the current system locale.
*/
static std::string getLocale();
private:
inline static bool inited = false;
inline static bool quitRequested = false;
inline static Platform* platform = nullptr;
inline static std::string title;
inline static FontStash fontStash;
inline static std::vector<Activity*> activitiesStack;
inline static std::vector<View*> focusStack;
inline static unsigned windowWidth, windowHeight;
inline static View* currentFocus;
inline static unsigned blockInputsTokens = 0; // any value > 0 means inputs are blocked
inline static std::string commonFooter = "";
inline static bool globalQuitEnabled = false;
inline static ActionIdentifier gloablQuitIdentifier = ACTION_NONE;
inline static bool globalFPSToggleEnabled = false;
inline static ActionIdentifier gloablFPSToggleIdentifier = ACTION_NONE;
inline static View* repetitionOldFocus = nullptr;
inline static GenericEvent globalFocusChangeEvent;
inline static VoidEvent globalHintsUpdateEvent;
inline static std::unordered_map<std::string, XMLViewCreator> xmlViewsRegister;
static void navigate(FocusDirection direction);
static void onWindowSizeChanged();
static void frame();
static void clear();
static void exit();
/**
* Handles actions for the currently focused view and
* the given button
* Returns true if at least one action has been fired
*/
static bool handleAction(char button);
static void registerBuiltInXMLViews();
static ActionIdentifier registerFPSToggleAction(Activity* activity);
};
} // namespace brls

View File

@@ -0,0 +1,23 @@
/*
Copyright 2019-2021 natinusala
Copyright 2019 p-sam
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#ifndef BRLS_RESOURCES
#error BRLS_RESOURCES define missing
#endif
#define BRLS_ASSET(_str) BRLS_RESOURCES _str

View File

@@ -0,0 +1,78 @@
/*
Copyright 2021 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
namespace brls
{
enum Sound
{
SOUND_NONE = 0, // no sound
SOUND_FOCUS_CHANGE, // played when the focus changes
SOUND_FOCUS_ERROR, // played when the user wants to go somewhere impossible (while the highlight wiggles)
SOUND_CLICK, // played when the click action runs
SOUND_FOCUS_SIDEBAR, // played when the focus changes to a sidebar item
SOUND_CLICK_ERROR, // played when the user clicks a disabled button / a view focused with no click action
SOUND_HONK, // honk
SOUND_CLICK_SIDEBAR, // played when a sidebar item is clicked
_SOUND_MAX, // not an actual sound, just used to count of many sounds there are
};
// Platform agnostic Audio player
// Each platform's AudioPlayer is responsible for managing the enum Sound -> internal representation map
class AudioPlayer
{
public:
virtual ~AudioPlayer() {};
/**
* Preemptively loads the given sound so that it's ready to be played
* when needed.
*
* Returns a boolean indicating if the sound has been loaded or not.
*/
virtual bool load(enum Sound sound) = 0;
/**
* Plays the given sound.
*
* The AudioPlayer should not assume that the sound has been
* loaded already, and must load it if needed.
*
* Returns a boolean indicating if the sound has been played or not.
*/
virtual bool play(enum Sound sound) = 0;
};
// An AudioPlayer that does nothing
class NullAudioPlayer : public AudioPlayer
{
public:
bool load(enum Sound sound) override
{
return false;
}
bool play(enum Sound sound) override
{
return false;
}
};
} // namespace brls

View File

@@ -0,0 +1,126 @@
/*
Copyright 2021 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <borealis/core/activity.hpp>
#include <borealis/core/view.hpp>
namespace brls
{
// Exception thrown when using a BoundView with an unknown ID for
// the given owner.
class ViewNotFoundException : public std::exception
{
public:
ViewNotFoundException(View* owner, std::string searchedId);
ViewNotFoundException(Activity* owner, std::string searchedId);
const char* what() const noexcept;
private:
std::string errorMessage;
};
#define BRLS_BIND(type, name, id) brls::BoundView<type> name = brls::BoundView<type>(id, this)
// A BoundView represents a "child" view, bound to its "parent" view class.
// Dereferencing operator has been overridden to directly resolve the view by ID and forward the call to the view pointer for you.
// Allows easy access of child views inside the parent class when used with the BRLS_BIND macro.
// Does NOT do any type check - it assumes the type you give it is the same as the view you are trying to get.
template <typename T>
class BoundView
{
public:
BoundView(std::string id, View* owner)
: id(id)
, ownerView(owner)
{
}
BoundView(std::string id, Activity* owner)
: id(id)
, ownerActivity(owner)
{
}
T* getView()
{
this->resolve();
return this->view;
}
operator T*()
{
return this->getView();
}
T* operator->()
{
return this->getView();
}
bool operator==(const T* value)
{
return this->getView() == value;
}
private:
std::string id = "";
T* view = nullptr;
View* ownerView = nullptr;
Activity* ownerActivity = nullptr;
/**
* Resolve the view pointer by id.
*
* Not called in the constructor
* on purpose because the owner might now be ready when
* the BoundView is constructed, so wait for the first
* actual call before resolving the view.
*/
void resolve()
{
if (this->view)
return;
// Resolve by owner activity first
if (this->ownerView)
{
this->view = (T*)this->ownerView->getView(this->id);
if (!this->view)
throw ViewNotFoundException(this->ownerView, this->id);
}
// Then resolve by owner view
else if (this->ownerActivity)
{
this->view = (T*)this->ownerActivity->getView(this->id);
if (!this->view)
throw ViewNotFoundException(this->ownerActivity, this->id);
}
else
{
throw std::logic_error("No owner view or activity given to BoundView");
}
}
};
} // namespace brls

View File

@@ -0,0 +1,280 @@
/*
Copyright 2020-2021 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <borealis/core/view.hpp>
namespace brls
{
enum class JustifyContent
{
FLEX_START,
CENTER,
FLEX_END,
SPACE_BETWEEN,
SPACE_AROUND,
SPACE_EVENLY,
};
enum class AlignItems
{
AUTO,
FLEX_START,
CENTER,
FLEX_END,
STRETCH,
BASELINE,
SPACE_BETWEEN,
SPACE_AROUND,
};
enum class Axis
{
ROW,
COLUMN,
};
enum class Direction
{
INHERIT,
LEFT_TO_RIGHT,
RIGHT_TO_LEFT,
};
// Generic FlexBox layout
class Box : public View
{
public:
Box(Axis flexDirection);
Box();
void draw(NVGcontext* vg, float x, float y, float width, float height, Style style, FrameContext* ctx) override;
View* getDefaultFocus() override;
View* getNextFocus(FocusDirection direction, View* currentView) override;
void willAppear(bool resetState) override;
void willDisappear(bool resetState) override;
void onWindowSizeChanged() override;
void onFocusGained() override;
void onFocusLost() override;
void onParentFocusGained(View* focusedView) override;
void onParentFocusLost(View* focusedView) override;
bool applyXMLAttribute(std::string name, std::string value) override;
static View* create();
/**
* Adds a view to this Box.
* Returns the position the view was added at.
*/
virtual void addView(View* view);
/**
* Adds a view to this Box at the given position.
* Returns the position the view was added at.
*/
virtual void addView(View* view, size_t position);
/**
* Removes the given view from the Box. It will be freed.
*/
virtual void removeView(View* view);
/**
* Sets the padding of the view, aka the internal space to give
* between this view boundaries and its children.
*
* Only does one layout pass instead of four when using the four methods separately.
*/
virtual void setPadding(float padding);
/**
* Sets the padding of the view, aka the internal space to give
* between this view boundaries and its children.
*
* Only does one layout pass instead of four when using the four methods separately.
*/
virtual void setPadding(float top, float right, float bottom, float left);
/**
* Sets the padding of the view, aka the internal space to give
* between this view boundaries and its children.
*/
virtual void setPaddingTop(float top);
/**
* Sets the padding of the view, aka the internal space to give
* between this view boundaries and its children.
*/
virtual void setPaddingRight(float right);
/**
* Sets the padding of the view, aka the internal space to give
* between this view boundaries and its children.
*/
virtual void setPaddingBottom(float bottom);
/**
* Sets the padding of the view, aka the internal space to give
* between this view boundaries and its children.
*/
virtual void setPaddingLeft(float left);
/**
* Sets the children alignment along the Box axis.
*
* Default is FLEX_START.
*/
void setJustifyContent(JustifyContent justify);
/**
* Sets the children alignment along the Box cross axis.
*
* Default is AUTO.
*/
void setAlignItems(AlignItems alignment);
/**
* Sets the direction of the box, aka place the views
* left to right or right to left (flips the children).
*
* Default is INHERIT.
*/
void setDirection(Direction direction);
void setAxis(Axis axis);
std::vector<View*>& getChildren();
/**
* Returns the bounds used for culling children.
*/
virtual void getCullingBounds(float* top, float* right, float* bottom, float* left);
/**
* Registers an XML attribute to be forwarded to the given view. Works regardless of the target attribute type.
* Useful to expose attributes of children views in the parent box without copy pasting them individually.
*
* The forwarded attribute value will override the value of the regular attribute if it already exists in the target view.
*/
void forwardXMLAttribute(std::string attributeName, View* target);
/**
* Registers an XML attribute to be forwarded to the given view, while changing the target attribute name.
* Works regardless of the target attribute type.
* Useful to expose attributes of children views in the parent box without copy pasting them individually, but with a different name.
*
* The forwarded attribute value will override the value of the regular attribute if it already exists in the target view.
*/
void forwardXMLAttribute(std::string attributeName, View* target, std::string targetAttributeName);
/**
* Fired when focus is gained on one of this view's children, or one of the children
* of the children...
*
* directChild is guaranteed to be one of your children. It may not be the view that has been
* focused.
*
* If focusedView == directChild, then the child of yours has been focused.
* Otherwise, focusedView is a child of directChild.
*/
virtual void onChildFocusGained(View* directChild, View* focusedView);
/**
* Fired when focus is lost on one of this view's children. Works similarly to
* onChildFocusGained().
*/
virtual void onChildFocusLost(View* directChild, View* focusedView);
View* getView(std::string id) override;
private:
Axis axis;
std::vector<View*> children;
size_t defaultFocusedIndex = 0;
std::unordered_map<std::string, std::pair<std::string, View*>> forwardedAttributes;
protected:
/**
* Inflates the Box with the given XML string.
*
* The root element MUST be a brls::Box, corresponding to the inflated Box itself. Its
* attributes will be applied to the Box.
*
* Each child node in the root brls::Box will be treated as a view and added
* as a child of the Box.
*/
void inflateFromXMLString(std::string xml);
/**
* Inflates the Box with the given XML element.
*
* The root element MUST be a brls::Box, corresponding to the inflated Box itself. Its
* attributes will be applied to the Box.
*
* Each child node in the root brls::Box will be treated as a view and added
* as a child of the Box.
*/
void inflateFromXMLElement(tinyxml2::XMLElement* element);
/**
* Inflates the Box with the given XML resource.
*
* The root element MUST be a brls::Box, corresponding to the inflated Box itself. Its
* attributes will be applied to the Box.
*
* Each child node in the root brls::Box will be treated as a view and added
* as a child of the Box.
*/
void inflateFromXMLRes(std::string res);
/**
* Inflates the Box with the given XML file path.
*
* The root element MUST be a brls::Box, corresponding to the inflated Box itself. Its
* attributes will be applied to the Box.
*
* Each child node in the root brls::Box will be treated as a view and added
* as a child of the Box.
*/
void inflateFromXMLFile(std::string path);
/**
* Handles a child XML element.
*
* By default, calls createFromXMLElement() and adds the result
* to the children of the Box.
*/
void handleXMLElement(tinyxml2::XMLElement* element) override;
};
// An empty view that has auto x auto and grow=1.0 to push
// all the next views in its box to the right (or to the bottom)
class Padding : public View
{
public:
Padding();
void draw(NVGcontext* vg, float x, float y, float width, float height, Style style, FrameContext* ctx) override;
static View* create();
};
} // namespace brls

View File

@@ -0,0 +1,73 @@
/*
Copyright 2020 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <algorithm>
#include <functional>
#include <list>
namespace brls
{
// Simple observer pattern implementation
//
// Usage:
// 1. typedef your event type
// 2. create as many events as you want using that type
// 3. call subscribe on the events with your observers
// 4. call fire when you want to fire the events
// it wil return true if at least one subscriber exists
// for that event
template <typename... Ts>
class Event
{
public:
typedef std::function<void(Ts...)> Callback;
typedef std::list<Callback> CallbacksList;
typedef typename CallbacksList::iterator Subscription;
Subscription subscribe(Callback cb);
void unsubscribe(Subscription subscription);
bool fire(Ts... args);
private:
CallbacksList callbacks;
};
template <typename... Ts>
typename Event<Ts...>::Subscription Event<Ts...>::subscribe(Event<Ts...>::Callback cb)
{
this->callbacks.push_back(cb);
return --this->callbacks.end();
}
template <typename... Ts>
void Event<Ts...>::unsubscribe(Event<Ts...>::Subscription subscription)
{
this->callbacks.erase(subscription);
}
template <typename... Ts>
bool Event<Ts...>::fire(Ts... args)
{
for (Callback cb : this->callbacks)
cb(args...);
return !this->callbacks.empty();
}
}; // namespace brls

View File

@@ -0,0 +1,62 @@
/*
Copyright 2021 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <string>
#include <unordered_map>
namespace brls
{
static constexpr const int FONT_INVALID = -1;
static const std::string FONT_REGULAR = "regular"; // regular Latin font
static const std::string FONT_KOREAN_REGULAR = "korean"; // regular Korean font
static const std::string FONT_MATERIAL_ICONS = "material"; // Material icons font
static const std::string FONT_SWITCH_ICONS = "switch"; // Switch icons font (see the HOS shared symbols font for an example)
typedef std::unordered_map<std::string, int> FontStash;
// Platform interface to load fonts from disk or other sources (system / shared font...)
class FontLoader
{
public:
virtual ~FontLoader() {}
/**
* Called once on init to load every font in the font stash.
*
* The implementation must use the Application::loadFont and
* Application::loadFontFromMemory methods to load as much as possible
* of the "built-in" fonts defined in the FONT_* constants above.
*/
virtual void loadFonts() = 0;
protected:
/**
* Convenience method to load a font from a file path
* with some more logging.
*/
bool loadFontFromFile(std::string fontName, std::string filePath);
/**
* Can be called internally to load the Material icons font from resources.
* Returns true if the operation succeeds.
*/
bool loadMaterialFromResources();
};
} // namespace brls

View File

@@ -0,0 +1,38 @@
/*
Copyright 2019 natinusala
Copyright 2019 psam
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <nanovg.h>
#include <borealis/core/font.hpp>
#include <borealis/core/style.hpp>
#include <borealis/core/theme.hpp>
namespace brls
{
class FrameContext
{
public:
NVGcontext* vg = nullptr;
float pixelRatio = 0.0;
FontStash* fontStash = nullptr;
Theme theme = nullptr;
};
} // namespace brls

View File

@@ -0,0 +1,88 @@
/*
Copyright 2020-2021 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <fmt/core.h>
#include <borealis/core/logger.hpp>
#include <string>
namespace brls
{
const std::string LOCALE_JA = "ja";
const std::string LOCALE_EN_US = "en-US";
const std::string LOCALE_EN_GB = "en-GB";
const std::string LOCALE_FR = "fr";
const std::string LOCALE_FR_CA = "fr-CA";
const std::string LOCALE_DE = "de";
const std::string LOCALE_IT = "it";
const std::string LOCALE_ES = "es";
const std::string LOCALE_ZH_CN = "zh-CN";
const std::string LOCALE_ZH_HANS = "zh-Hans";
const std::string LOCALE_ZH_HANT = "zh-Hant";
const std::string LOCALE_ZH_TW = "zh-TW";
const std::string LOCALE_Ko = "ko";
const std::string LOCALE_NL = "nl";
const std::string LOCALE_PT = "pt";
const std::string LOCALE_PT_BR = "pt-BR";
const std::string LOCALE_RU = "ru";
const std::string LOCALE_ES_419 = "es-419";
const std::string LOCALE_DEFAULT = LOCALE_EN_US;
namespace internal
{
std::string getRawStr(std::string stringName);
} // namespace internal
/**
* Returns the translation for the given string,
* after injecting format parameters (if any)
*/
template <typename... Args>
std::string getStr(std::string stringName, Args&&... args)
{
std::string rawStr = internal::getRawStr(stringName);
try
{
return fmt::format(rawStr, args...);
}
catch (const std::exception& e)
{
Logger::error("Invalid format \"{}\" from string \"{}\": {}", rawStr, stringName, e.what());
return stringName;
}
}
/**
* Loads all translations of the current system locale + default locale
* Must be called before trying to get a translation!
*/
void loadTranslations();
inline namespace literals
{
/**
* Returns the translation for the given string, without
* injecting any parameters
* Shortcut to brls::getStr(stringName)
*/
std::string operator"" _i18n(const char* str, size_t len);
} // namespace literals
} // namespace brls

View File

@@ -0,0 +1,88 @@
/*
Copyright 2021 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
namespace brls
{
// Abstract buttons enum - names correspond to a generic Xbox controller
// LT and RT should not be buttons but for the sake of simplicity we'll assume they are.
// Similarly, DPAD (also called HAT) is assumed to be buttons here.
enum ControllerButton
{
BUTTON_LT = 0,
BUTTON_LB,
BUTTON_LSB,
BUTTON_UP,
BUTTON_RIGHT,
BUTTON_DOWN,
BUTTON_LEFT,
BUTTON_BACK,
BUTTON_GUIDE,
BUTTON_START,
BUTTON_RSB,
BUTTON_Y,
BUTTON_B,
BUTTON_A,
BUTTON_X,
BUTTON_RB,
BUTTON_RT,
_BUTTON_MAX,
};
// Abstract axis enum - names correspond to a generic Xbox controller
enum ControllerAxis
{
LEFT_X,
LEFT_Y,
// No Z axis, LT and RT are in the buttons enum for the sake of simplicity
RIGHT_X, // also called 5th axis
RIGHT_Y, // also called 4th axis
_AXES_MAX,
};
// Represents the state of the controller (a gamepad or a keyboard) in the current frame
typedef struct ControllerState
{
bool buttons[_BUTTON_MAX]; // true: pressed
float axes[_AXES_MAX]; // from 0.0f to 1.0f
} ControllerState;
// Interface responsible for reporting input state to the application - button presses,
// axis position and touch screen state
class InputManager
{
public:
virtual ~InputManager() {}
/**
* Called once every frame to fill the given ControllerState struct with the controller state.
*/
virtual void updateControllerState(ControllerState* state) = 0;
};
}; // namespace brls

View File

@@ -0,0 +1,91 @@
/*
Copyright 2019 natinusala
Copyright 2019 p-sam
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <fmt/core.h>
#include <string>
namespace brls
{
enum class LogLevel
{
ERROR = 0,
WARNING,
INFO,
DEBUG
};
class Logger
{
public:
static void setLogLevel(LogLevel logLevel);
template <typename... Args>
inline static void log(LogLevel logLevel, std::string prefix, std::string color, std::string format, Args&&... args)
{
if (Logger::logLevel < logLevel)
return;
try
{
fmt::print("\033{}[{}]\033[0m ", color, prefix);
fmt::print(format, args...);
fmt::print("\n");
}
catch (const std::exception& e)
{
// will be printed after the first fmt::print (so after the log tag)
printf("! Invalid log format string: \"%s\": %s\n", format.c_str(), e.what());
}
#ifdef __MINGW32__
fflush(0);
#endif
}
template <typename... Args>
inline static void error(std::string format, Args&&... args)
{
Logger::log(LogLevel::ERROR, "ERROR", "[0;31m", format, args...);
}
template <typename... Args>
inline static void warning(std::string format, Args&&... args)
{
Logger::log(LogLevel::WARNING, "WARNING", "[0;33m", format, args...);
}
template <typename... Args>
inline static void info(std::string format, Args&&... args)
{
Logger::log(LogLevel::INFO, "INFO", "[0;34m", format, args...);
}
template <typename... Args>
inline static void debug(std::string format, Args&&... args)
{
Logger::log(LogLevel::DEBUG, "DEBUG", "[0;32m", format, args...);
}
private:
inline static LogLevel logLevel = LogLevel::INFO;
};
} // namespace brls

View File

@@ -0,0 +1,106 @@
/*
Copyright 2021 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <borealis/core/audio.hpp>
#include <borealis/core/font.hpp>
#include <borealis/core/input.hpp>
#include <borealis/core/theme.hpp>
#include <borealis/core/video.hpp>
#include <string>
namespace brls
{
// Interface to provide everything platform specific required to run borealis: graphics context, inputs, audio...
// The best platform is automatically selected when the application starts, and cannot be changed by the user at the moment
class Platform
{
public:
virtual ~Platform() {};
/**
* Called on startup, right after instanciation, to create and open a window
* with the given title and size.
*/
virtual void createWindow(std::string title, uint32_t width, uint32_t height) = 0;
/**
* Returns the human-readable name of the platform.
*/
virtual std::string getName() = 0;
/**
* Called at every iteration of the main loop.
* Must return false if the app should continue running
* (for example, return false if the X button was pressed on the window).
*/
virtual bool mainLoopIteration() = 0;
/**
* Can be called at anytime to get the current system theme variant.
*
* For now, the variant is assumed to stay the same during the whole time
* the app is running (no variant hot swap).
*
* As such, the result should be cached by the platform code.
*/
virtual ThemeVariant getThemeVariant() = 0;
/**
* Can be called at anytime to get the current locale
*
* For now, the locale is assumed to stay the same during the whole time
* the app is running (no locale hot swap)
*
* As such, the result should be cached by the platform code.
* The method should return one of the locale constants
* defined in the i18n header file.
*/
virtual std::string getLocale() = 0;
/**
* Returns the AudioPlayer for the platform.
* Cannot return nullptr.
*/
virtual AudioPlayer* getAudioPlayer() = 0;
/**
* Returns the VideoContext for the platform.
* Cannot return nullptr.
*/
virtual VideoContext* getVideoContext() = 0;
/**
* Returns the InputManager for the platform.
* Cannot return nullptr.
*/
virtual InputManager* getInputManager() = 0;
/**
* Returns the FontLoader for the platform.
* Cannot return nullptr.
*/
virtual FontLoader* getFontLoader() = 0;
/**
* Selects and returns the best platform.
*/
static Platform* createPlatform();
};
} // namespace brls

View File

@@ -0,0 +1,56 @@
/*
Copyright 2019-2020 natinusala
Copyright 2019 WerWolv
Copyright 2019 p-sam
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <initializer_list>
#include <string>
#include <unordered_map>
namespace brls
{
class StyleValues
{
public:
StyleValues(std::initializer_list<std::pair<std::string, float>> list);
void addMetric(std::string name, float value);
float getMetric(std::string name);
private:
std::unordered_map<std::string, float> values;
};
// Simple wrapper around StyleValues for the array operator
class Style
{
public:
Style(StyleValues* values);
float operator[](std::string name);
void addMetric(std::string name, float value);
float getMetric(std::string name);
private:
StyleValues* values;
};
Style getStyle();
} // namespace brls

View File

@@ -0,0 +1,51 @@
/*
Copyright 2021 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <borealis/core/timer.hpp>
namespace brls
{
// A RepeatingTask is a task executed repeatedly on the main thread at a given period in ms
class RepeatingTask : private RepeatingTimer
{
public:
/**
* Create a RepeatingTask with the given period in ms.
*
* The task is guaranteed to wait for at least the given period of time between
* handler runs, but it can wait for slightly longer (usually less than a ms late)
*/
RepeatingTask(Time period);
/**
* Task handler executed repeatedly on the main thread at the given period.
*/
virtual void run() = 0;
/**
* Starts the task.
*/
void start();
/**
* Stops the task.
*/
void stop();
};
} // namespace brls

View File

@@ -0,0 +1,64 @@
/*
Copyright 2019-2020 natinusala
Copyright 2019 p-sam
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <nanovg.h>
#include <initializer_list>
#include <string>
#include <unordered_map>
namespace brls
{
enum class ThemeVariant
{
LIGHT,
DARK
};
class ThemeValues
{
public:
ThemeValues(std::initializer_list<std::pair<std::string, NVGcolor>> list);
void addColor(std::string name, NVGcolor color);
NVGcolor getColor(std::string name);
private:
std::unordered_map<std::string, NVGcolor> values;
};
// Simple wrapper around ThemeValues for the array operator
class Theme
{
public:
Theme(ThemeValues* values);
NVGcolor operator[](std::string name);
void addColor(std::string name, NVGcolor color);
NVGcolor getColor(std::string name);
private:
ThemeValues* values;
};
Theme getLightTheme();
Theme getDarkTheme();
} // namespace brls

View File

@@ -0,0 +1,157 @@
/*
Copyright 2021 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <libretro-common/features/features_cpu.h>
#include <libretro-common/libretro.h>
#include <functional>
#include <vector>
namespace brls
{
typedef retro_time_t Time;
/**
* Returns the current CPU time in microseconds.
*/
inline Time getCPUTimeUsec()
{
return cpu_features_get_time_usec();
}
typedef std::function<void()> TickingGenericCallback;
typedef std::function<void(bool)> TickingEndCallback;
typedef TickingGenericCallback TickingTickCallback;
// Interface representing something that "ticks" every frame for a certain amount of frames,
// like a timer, an animation, a background task...
// The library manages a list of running tickings. Each ticking is reponsible for managing its own
// lifetime by returning true or false in onUpdate.
class Ticking
{
public:
virtual ~Ticking();
/**
* Starts the ticking, pushing it to the list of running tickings.
* If the ticking is finished, it will be restarted.
* If the ticking is already running, this method will have no effect.
*/
void start();
/**
* Stops the ticking if it was running, and executes the end callback.
*/
void stop();
/**
* Sets a callback to be executed when the
* ticking finishes.
* The callback argument will be set to true if the ticking stopped
* on its own, false if it was stopped early by the user.
*/
void setEndCallback(TickingEndCallback endCallback);
/**
* Sets a callback to be executed at every tick
* until the ticking finishes.
*
* The last animation tick will execute the tick callback
* then the end callback.
*/
void setTickCallback(TickingTickCallback tickCallback);
/**
* Returns true if the ticking is currently running.
*/
bool isRunning();
/**
* Called internally by the main loop. Takes all running tickings
* and updates them.
*/
static void updateTickings();
inline static std::vector<Ticking*> runningTickings;
protected:
/**
* Executed every frame while the ticking lives.
* Delta is the time difference in ms between the last frame
* and the current one.
* Must return false if the ticking is finished and should be
* removed from the list of active tickings.
* The end callback will automatically be called then.
*/
virtual bool onUpdate(Time delta) = 0;
/**
* Called when the ticking becomes active.
*/
virtual void onStart() {};
/**
* Called when the ticking is stopped, either by the user
* or because it finished.
*/
virtual void onStop() {};
private:
void stop(bool finished);
bool running = false;
TickingEndCallback endCallback = [](bool finished) {};
TickingTickCallback tickCallback = [] {};
};
// Represents a "finite" ticking that runs for a known amount of time
// and can be seek / reset / rewound.
class FiniteTicking : public Ticking
{
public:
/**
* Rewinds the ticking to go back to the beginning
* without losing its state (as opposed to reset() that clears
* everything in the ticking).
* Does not start or stop it.
*/
void rewind();
/**
* Stops and resets the ticking, clearing its state
* in the process (as opposed to rewind() that just restarts
* the ticking from the beginning without losing the state).
*/
void reset();
protected:
/**
* Called when the ticking gets rewound.
*/
virtual void onRewind() {};
/**
* Called when the ticking gets reset.
*/
virtual void onReset() {};
};
} // namespace brls

View File

@@ -0,0 +1,93 @@
/*
Copyright 2021 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <borealis/core/time.hpp>
namespace brls
{
// A Timer allows to run a callback once after a given period of time, in ms
// Add the callback with setEndCallback(), set the duration with setDuration() then start the timer
class Timer : public FiniteTicking
{
public:
/**
* Starts the timer directly with a given duration, in ms.
*/
void start(Time duration);
/**
* Starts the timer with the already set duration.
*/
void start();
/**
* Sets the duration of the timer, in ms.
* Does not stop or reset it.
*/
void setDuration(Time duration);
void onStart() override;
bool onUpdate(Time delta) override;
void onReset() override;
void onRewind() override;
protected:
Time duration = 0;
Time progress = 0;
};
// A RepeatingTimer allows to run a callback repeatedly at a given time interval, in ms
// Add the callback with setCallback(), set the period with setPeriod() then start the timer
class RepeatingTimer : public Ticking
{
public:
/**
* Starts the timer directly with a given period, in ms.
*/
void start(Time period);
/**
* Starts the timer with the already set period.
*/
void start();
/**
* Sets the period of the timer, in ms.
* Does not stop or reset it.
*/
void setPeriod(Time period);
/**
* Sets the callback of the timer.
* Tick callback is still executed every tick.
* End callback is executed when the timer is stopped.
*/
void setCallback(TickingGenericCallback callback);
void onStart() override;
bool onUpdate(Time delta) override;
protected:
Time period = 0;
Time progress = 0;
TickingGenericCallback callback = [] {};
};
} // namespace brls

View File

@@ -0,0 +1,30 @@
/*
Copyright 2021 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <borealis/core/logger.hpp>
#include <stdexcept>
namespace brls
{
/**
* Prints the given error message message and throws a std::logic_error.
*/
[[noreturn]] void fatal(std::string message);
} // namespace brls

View File

@@ -0,0 +1,54 @@
/*
Copyright 2021 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <nanovg.h>
// A VideoContext is responsible for providing a nanovg context for the app
// (so by extension it manages all the graphics state as well as the window / context).
// The VideoContext implementation must also provide the nanovg implementation. As such, there
// can only be one VideoContext linked at any time in the binary.
// Context creation and teardown can be done in the constructor and destructor.
class VideoContext
{
public:
virtual ~VideoContext() {};
/**
* Called at the beginning of every frame to clear the window
*/
virtual void clear(NVGcolor color) = 0;
/**
* Called at the beginning of every frame to begin it.
*/
virtual void beginFrame() = 0;
/**
* Called at the end of every frame to end it (swap buffers...).
*/
virtual void endFrame() = 0;
/**
* Can be called by the application to reset the graphics
* state, in case there is a need to use the graphics API
* directly (for instance direct OpenGL calls).
*/
virtual void resetState() = 0;
virtual NVGcontext* getNVGContext() = 0;
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,39 @@
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (boolean.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_BOOLEAN_H
#define __LIBRETRO_SDK_BOOLEAN_H
#ifndef __cplusplus
#if defined(_MSC_VER) && _MSC_VER < 1800 && !defined(SN_TARGET_PS3)
/* Hack applied for MSVC when compiling in C89 mode as it isn't C99 compliant. */
#define bool unsigned char
#define true 1
#define false 0
#else
#include <stdbool.h>
#endif
#endif
#endif

View File

@@ -0,0 +1,59 @@
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (strl.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_COMPAT_STRL_H
#define __LIBRETRO_SDK_COMPAT_STRL_H
#include <string.h>
#include <stddef.h>
#if defined(RARCH_INTERNAL) && defined(HAVE_CONFIG_H)
#include "../../../config.h"
#endif
#include <libretro-common/retro_common_api.h>
RETRO_BEGIN_DECLS
#ifdef __MACH__
#ifndef HAVE_STRL
#define HAVE_STRL
#endif
#endif
#ifndef HAVE_STRL
/* Avoid possible naming collisions during link since
* we prefer to use the actual name. */
#define strlcpy(dst, src, size) strlcpy_retro__(dst, src, size)
#define strlcat(dst, src, size) strlcat_retro__(dst, src, size)
size_t strlcpy(char *dest, const char *source, size_t size);
size_t strlcat(char *dest, const char *source, size_t size);
#endif
char *strldup(const char *s, size_t n);
RETRO_END_DECLS
#endif

View File

@@ -0,0 +1,67 @@
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (utf.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _LIBRETRO_ENCODINGS_UTF_H
#define _LIBRETRO_ENCODINGS_UTF_H
#include <stdint.h>
#include <stddef.h>
#include <libretro-common/boolean.h>
#include <libretro-common/retro_common_api.h>
RETRO_BEGIN_DECLS
enum CodePage
{
CODEPAGE_LOCAL = 0, /* CP_ACP */
CODEPAGE_UTF8 = 65001 /* CP_UTF8 */
};
size_t utf8_conv_utf32(uint32_t *out, size_t out_chars,
const char *in, size_t in_size);
bool utf16_conv_utf8(uint8_t *out, size_t *out_chars,
const uint16_t *in, size_t in_size);
size_t utf8len(const char *string);
size_t utf8cpy(char *d, size_t d_len, const char *s, size_t chars);
const char *utf8skip(const char *str, size_t chars);
uint32_t utf8_walk(const char **string);
bool utf16_to_char_string(const uint16_t *in, char *s, size_t len);
char* utf8_to_local_string_alloc(const char *str);
char* local_to_utf8_string_alloc(const char *str);
wchar_t* utf8_to_utf16_string_alloc(const char *str);
char* utf16_to_utf8_string_alloc(const wchar_t *str);
RETRO_END_DECLS
#endif

View File

@@ -0,0 +1,75 @@
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (features_cpu.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _LIBRETRO_SDK_CPU_INFO_H
#define _LIBRETRO_SDK_CPU_INFO_H
#include <libretro-common/retro_common_api.h>
#include <stdint.h>
#include <libretro-common/libretro.h>
RETRO_BEGIN_DECLS
/**
* cpu_features_get_perf_counter:
*
* Gets performance counter.
*
* Returns: performance counter.
**/
retro_perf_tick_t cpu_features_get_perf_counter(void);
/**
* cpu_features_get_time_usec:
*
* Gets time in microseconds, from an undefined epoch.
* The epoch may change between computers or across reboots.
*
* Returns: time in microseconds
**/
retro_time_t cpu_features_get_time_usec(void);
/**
* cpu_features_get:
*
* Gets CPU features.
*
* Returns: bitmask of all CPU features available.
**/
uint64_t cpu_features_get(void);
/**
* cpu_features_get_core_amount:
*
* Gets the amount of available CPU cores.
*
* Returns: amount of CPU cores available.
**/
unsigned cpu_features_get_core_amount(void);
void cpu_features_get_model_name(char *name, int len);
RETRO_END_DECLS
#endif

View File

@@ -0,0 +1,37 @@
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_assert.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __RETRO_ASSERT_H
#define __RETRO_ASSERT_H
#include <assert.h>
#ifdef RARCH_INTERNAL
#include <stdio.h>
#define retro_assert(cond) do { \
if (!(cond)) { printf("Assertion failed at %s:%d.\n", __FILE__, __LINE__); abort(); } \
} while(0)
#else
#define retro_assert(cond) assert(cond)
#endif
#endif

View File

@@ -0,0 +1,117 @@
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_common_api.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _LIBRETRO_COMMON_RETRO_COMMON_API_H
#define _LIBRETRO_COMMON_RETRO_COMMON_API_H
/*
This file is designed to normalize the libretro-common compiling environment
for public API headers. This should be leaner than a normal compiling environment,
since it gets #included into other project's sources.
*/
/* ------------------------------------ */
/*
Ordinarily we want to put #ifdef __cplusplus extern "C" in C library
headers to enable them to get used by c++ sources.
However, we want to support building this library as C++ as well, so a
special technique is called for.
*/
#define RETRO_BEGIN_DECLS
#define RETRO_END_DECLS
#ifdef __cplusplus
#ifdef CXX_BUILD
/* build wants everything to be built as c++, so no extern "C" */
#else
#undef RETRO_BEGIN_DECLS
#undef RETRO_END_DECLS
#define RETRO_BEGIN_DECLS extern "C" {
#define RETRO_END_DECLS }
#endif
#else
/* header is included by a C source file, so no extern "C" */
#endif
/*
IMO, this non-standard ssize_t should not be used.
However, it's a good example of how to handle something like this.
*/
#ifdef _MSC_VER
#ifndef HAVE_SSIZE_T
#define HAVE_SSIZE_T
#if defined(_WIN64)
typedef __int64 ssize_t;
#elif defined(_WIN32)
typedef int ssize_t;
#endif
#endif
#elif defined(__MACH__)
#include <sys/types.h>
#endif
#ifdef _MSC_VER
#if _MSC_VER >= 1800
#include <inttypes.h>
#else
#ifndef PRId64
#define PRId64 "I64d"
#define PRIu64 "I64u"
#define PRIuPTR "Iu"
#endif
#endif
#else
/* C++11 says this one isn't needed, but apparently (some versions of) mingw require it anyways */
/* https://stackoverflow.com/questions/8132399/how-to-printf-uint64-t-fails-with-spurious-trailing-in-format */
/* https://github.com/libretro/RetroArch/issues/6009 */
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#endif
#ifndef PRId64
#error "inttypes.h is being screwy"
#endif
#define STRING_REP_INT64 "%" PRId64
#define STRING_REP_UINT64 "%" PRIu64
#define STRING_REP_USIZE "%" PRIuPTR
/*
I would like to see retro_inline.h moved in here; possibly boolean too.
rationale: these are used in public APIs, and it is easier to find problems
and write code that works the first time portably when theyre included uniformly
than to do the analysis from scratch each time you think you need it, for each feature.
Moreover it helps force you to make hard decisions: if you EVER bring in boolean.h,
then you should pay the price everywhere, so you can see how much grief it will cause.
Of course, another school of thought is that you should do as little damage as possible
in as few places as possible...
*/
/* _LIBRETRO_COMMON_RETRO_COMMON_API_H */
#endif

View File

@@ -0,0 +1,39 @@
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_inline.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_INLINE_H
#define __LIBRETRO_SDK_INLINE_H
#ifndef INLINE
#if defined(_WIN32) || defined(__INTEL_COMPILER)
#define INLINE __inline
#elif defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L
#define INLINE inline
#elif defined(__GNUC__)
#define INLINE __inline__
#else
#define INLINE
#endif
#endif
#endif

View File

@@ -0,0 +1,94 @@
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_math.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _LIBRETRO_COMMON_MATH_H
#define _LIBRETRO_COMMON_MATH_H
#include <stdint.h>
#if defined(_WIN32) && !defined(_XBOX)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#elif defined(_WIN32) && defined(_XBOX)
#include <Xtl.h>
#endif
#include <limits.h>
#ifdef _MSC_VER
#include <libretro-common/compat/msvc.h>
#endif
#include <libretro-common/retro_inline.h>
#ifndef M_PI
#if !defined(USE_MATH_DEFINES)
#define M_PI 3.14159265358979323846264338327
#endif
#endif
#ifndef MAX
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
/**
* next_pow2:
* @v : initial value
*
* Get next power of 2 value based on initial value.
*
* Returns: next power of 2 value (derived from @v).
**/
static INLINE uint32_t next_pow2(uint32_t v)
{
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;
return v;
}
/**
* prev_pow2:
* @v : initial value
*
* Get previous power of 2 value based on initial value.
*
* Returns: previous power of 2 value (derived from @v).
**/
static INLINE uint32_t prev_pow2(uint32_t v)
{
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
return v - (v >> 1);
}
#endif

View File

@@ -0,0 +1,182 @@
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_miscellaneous.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __RARCH_MISCELLANEOUS_H
#define __RARCH_MISCELLANEOUS_H
#define RARCH_MAX_SUBSYSTEMS 10
#define RARCH_MAX_SUBSYSTEM_ROMS 10
#include <stdint.h>
#include <libretro-common/boolean.h>
#include <libretro-common/retro_inline.h>
#if defined(_WIN32) && !defined(_XBOX)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#elif defined(_WIN32) && defined(_XBOX)
#include <Xtl.h>
#endif
#if defined(__CELLOS_LV2__)
#include <sys/fs_external.h>
#endif
#include <limits.h>
#ifdef _MSC_VER
#include <libretro-common/compat/msvc.h>
#endif
static INLINE void bits_or_bits(uint32_t *a, uint32_t *b, uint32_t count)
{
uint32_t i;
for (i = 0; i < count;i++)
a[i] |= b[i];
}
static INLINE void bits_clear_bits(uint32_t *a, uint32_t *b, uint32_t count)
{
uint32_t i;
for (i = 0; i < count;i++)
a[i] &= ~b[i];
}
static INLINE bool bits_any_set(uint32_t* ptr, uint32_t count)
{
uint32_t i;
for (i = 0; i < count; i++)
{
if (ptr[i] != 0)
return true;
}
return false;
}
#ifndef PATH_MAX_LENGTH
#if defined(__CELLOS_LV2__)
#define PATH_MAX_LENGTH CELL_FS_MAX_FS_PATH_LENGTH
#elif defined(_XBOX1) || defined(_3DS) || defined(PSP) || defined(PS2) || defined(GEKKO)|| defined(WIIU) || defined(ORBIS)
#define PATH_MAX_LENGTH 512
#else
#define PATH_MAX_LENGTH 4096
#endif
#endif
#ifndef MAX
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#define BITS_GET_ELEM(a, i) ((a).data[i])
#define BITS_GET_ELEM_PTR(a, i) ((a)->data[i])
#define BIT_SET(a, bit) ((a)[(bit) >> 3] |= (1 << ((bit) & 7)))
#define BIT_CLEAR(a, bit) ((a)[(bit) >> 3] &= ~(1 << ((bit) & 7)))
#define BIT_GET(a, bit) (((a)[(bit) >> 3] >> ((bit) & 7)) & 1)
#define BIT16_SET(a, bit) ((a) |= (1 << ((bit) & 15)))
#define BIT16_CLEAR(a, bit) ((a) &= ~(1 << ((bit) & 15)))
#define BIT16_GET(a, bit) (((a) >> ((bit) & 15)) & 1)
#define BIT16_CLEAR_ALL(a) ((a) = 0)
#define BIT32_SET(a, bit) ((a) |= (1 << ((bit) & 31)))
#define BIT32_CLEAR(a, bit) ((a) &= ~(1 << ((bit) & 31)))
#define BIT32_GET(a, bit) (((a) >> ((bit) & 31)) & 1)
#define BIT32_CLEAR_ALL(a) ((a) = 0)
#define BIT64_SET(a, bit) ((a) |= (UINT64_C(1) << ((bit) & 63)))
#define BIT64_CLEAR(a, bit) ((a) &= ~(UINT64_C(1) << ((bit) & 63)))
#define BIT64_GET(a, bit) (((a) >> ((bit) & 63)) & 1)
#define BIT64_CLEAR_ALL(a) ((a) = 0)
#define BIT128_SET(a, bit) ((a).data[(bit) >> 5] |= (1 << ((bit) & 31)))
#define BIT128_CLEAR(a, bit) ((a).data[(bit) >> 5] &= ~(1 << ((bit) & 31)))
#define BIT128_GET(a, bit) (((a).data[(bit) >> 5] >> ((bit) & 31)) & 1)
#define BIT128_CLEAR_ALL(a) memset(&(a), 0, sizeof(a))
#define BIT128_SET_PTR(a, bit) BIT128_SET(*a, bit)
#define BIT128_CLEAR_PTR(a, bit) BIT128_CLEAR(*a, bit)
#define BIT128_GET_PTR(a, bit) BIT128_GET(*a, bit)
#define BIT128_CLEAR_ALL_PTR(a) BIT128_CLEAR_ALL(*a)
#define BIT256_SET(a, bit) BIT128_SET(a, bit)
#define BIT256_CLEAR(a, bit) BIT128_CLEAR(a, bit)
#define BIT256_GET(a, bit) BIT128_GET(a, bit)
#define BIT256_CLEAR_ALL(a) BIT128_CLEAR_ALL(a)
#define BIT256_SET_PTR(a, bit) BIT256_SET(*a, bit)
#define BIT256_CLEAR_PTR(a, bit) BIT256_CLEAR(*a, bit)
#define BIT256_GET_PTR(a, bit) BIT256_GET(*a, bit)
#define BIT256_CLEAR_ALL_PTR(a) BIT256_CLEAR_ALL(*a)
#define BITS_COPY16_PTR(a,bits) \
{ \
BIT128_CLEAR_ALL_PTR(a); \
BITS_GET_ELEM_PTR(a, 0) = (bits) & 0xffff; \
}
#define BITS_COPY32_PTR(a,bits) \
{ \
BIT128_CLEAR_ALL_PTR(a); \
BITS_GET_ELEM_PTR(a, 0) = (bits); \
}
/* Helper macros and struct to keep track of many booleans. */
/* This struct has 256 bits. */
typedef struct
{
uint32_t data[8];
} retro_bits_t;
#ifdef _WIN32
# ifdef _WIN64
# define PRI_SIZET PRIu64
# else
# if _MSC_VER == 1800
# define PRI_SIZET PRIu32
# else
# define PRI_SIZET "u"
# endif
# endif
#elif PS2
# define PRI_SIZET "u"
#else
# if (SIZE_MAX == 0xFFFF)
# define PRI_SIZET "hu"
# elif (SIZE_MAX == 0xFFFFFFFF)
# define PRI_SIZET "u"
# elif (SIZE_MAX == 0xFFFFFFFFFFFFFFFF)
# define PRI_SIZET "lu"
# else
# error PRI_SIZET: unknown SIZE_MAX
# endif
#endif
#endif

View File

@@ -0,0 +1,116 @@
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_timers.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_COMMON_TIMERS_H
#define __LIBRETRO_COMMON_TIMERS_H
#include <stdint.h>
#if defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
#include <sys/timer.h>
#elif defined(XENON)
#include <time/time.h>
#elif defined(GEKKO) || defined(__PSL1GHT__) || defined(__QNX__)
#include <unistd.h>
#elif defined(WIIU)
#include <wiiu/os/thread.h>
#elif defined(PSP)
#include <pspthreadman.h>
#elif defined(VITA)
#include <psp2/kernel/threadmgr.h>
#elif defined(PS2)
#include <SDL/SDL_timer.h>
#elif defined(_3DS)
#include <3ds.h>
#else
#include <time.h>
#endif
#if defined(_WIN32) && !defined(_XBOX)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#elif defined(_WIN32) && defined(_XBOX)
#include <Xtl.h>
#endif
#include <limits.h>
#ifdef _MSC_VER
#include <libretro-common/compat/msvc.h>
#endif
#include <libretro-common/retro_inline.h>
#ifdef DJGPP
#define timespec timeval
#define tv_nsec tv_usec
#include <unistd.h>
extern int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
static int nanosleepDOS(const struct timespec *rqtp, struct timespec *rmtp)
{
usleep(1000000 * rqtp->tv_sec + rqtp->tv_nsec / 1000);
if (rmtp)
rmtp->tv_sec = rmtp->tv_nsec=0;
return 0;
}
#define nanosleep nanosleepDOS
#endif
/**
* retro_sleep:
* @msec : amount in milliseconds to sleep
*
* Sleeps for a specified amount of milliseconds (@msec).
**/
static INLINE void retro_sleep(unsigned msec)
{
#if defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
sys_timer_usleep(1000 * msec);
#elif defined(PSP) || defined(VITA)
sceKernelDelayThread(1000 * msec);
#elif defined(PS2)
SDL_Delay(msec);
#elif defined(_3DS)
svcSleepThread(1000000 * (s64)msec);
#elif defined(__WINRT__) || defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
SleepEx(msec, FALSE);
#elif defined(_WIN32)
Sleep(msec);
#elif defined(XENON)
udelay(1000 * msec);
#elif defined(GEKKO) || defined(__PSL1GHT__) || defined(__QNX__)
usleep(1000 * msec);
#elif defined(WIIU)
OSSleepTicks(ms_to_ticks(msec));
#else
struct timespec tv = {0};
tv.tv_sec = msec / 1000;
tv.tv_nsec = (msec % 1000) * 1000000;
nanosleep(&tv, NULL);
#endif
}
#endif

View File

@@ -0,0 +1,111 @@
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (file_stream.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_FILE_STREAM_H
#define __LIBRETRO_SDK_FILE_STREAM_H
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stddef.h>
#include <sys/types.h>
#include <libretro-common/libretro.h>
#include <libretro-common/retro_common_api.h>
#include <libretro-common/retro_inline.h>
#include <libretro-common/boolean.h>
#include <stdarg.h>
#define FILESTREAM_REQUIRED_VFS_VERSION 2
RETRO_BEGIN_DECLS
typedef struct RFILE RFILE;
#define FILESTREAM_REQUIRED_VFS_VERSION 2
void filestream_vfs_init(const struct retro_vfs_interface_info* vfs_info);
int64_t filestream_get_size(RFILE *stream);
int64_t filestream_truncate(RFILE *stream, int64_t length);
/**
* filestream_open:
* @path : path to file
* @mode : file mode to use when opening (read/write)
* @bufsize : optional buffer size (-1 or 0 to use default)
*
* Opens a file for reading or writing, depending on the requested mode.
* Returns a pointer to an RFILE if opened successfully, otherwise NULL.
**/
RFILE *filestream_open(const char *path, unsigned mode, unsigned hints);
int64_t filestream_seek(RFILE *stream, int64_t offset, int seek_position);
int64_t filestream_read(RFILE *stream, void *data, int64_t len);
int64_t filestream_write(RFILE *stream, const void *data, int64_t len);
int64_t filestream_tell(RFILE *stream);
void filestream_rewind(RFILE *stream);
int filestream_close(RFILE *stream);
int64_t filestream_read_file(const char *path, void **buf, int64_t *len);
char *filestream_gets(RFILE *stream, char *s, size_t len);
int filestream_getc(RFILE *stream);
int filestream_scanf(RFILE *stream, const char* format, ...);
int filestream_eof(RFILE *stream);
bool filestream_write_file(const char *path, const void *data, int64_t size);
int filestream_putc(RFILE *stream, int c);
int filestream_vprintf(RFILE *stream, const char* format, va_list args);
int filestream_printf(RFILE *stream, const char* format, ...);
int filestream_error(RFILE *stream);
int filestream_flush(RFILE *stream);
int filestream_delete(const char *path);
int filestream_rename(const char *old_path, const char *new_path);
const char *filestream_get_path(RFILE *stream);
bool filestream_exists(const char *path);
char *filestream_getline(RFILE *stream);
RETRO_END_DECLS
#endif

View File

@@ -0,0 +1,134 @@
/* Copyright (C) 2010-2019 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (stdstring.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_STDSTRING_H
#define __LIBRETRO_SDK_STDSTRING_H
#include <stdlib.h>
#include <stddef.h>
#include <ctype.h>
#include <string.h>
#include <libretro-common/boolean.h>
#include <libretro-common/retro_common_api.h>
#include <libretro-common/retro_inline.h>
#include <libretro-common/compat/strl.h>
RETRO_BEGIN_DECLS
static INLINE bool string_is_empty(const char *data)
{
return !data || (*data == '\0');
}
static INLINE bool string_is_equal(const char *a, const char *b)
{
return (a && b) ? !strcmp(a, b) : false;
}
#define STRLEN_CONST(x) ((sizeof((x))-1))
#define string_is_not_equal(a, b) !string_is_equal((a), (b))
#define string_add_pair_open(s, size) strlcat((s), " (", (size))
#define string_add_pair_close(s, size) strlcat((s), ")", (size))
#define string_add_bracket_open(s, size) strlcat((s), "{", (size))
#define string_add_bracket_close(s, size) strlcat((s), "}", (size))
#define string_add_single_quote(s, size) strlcat((s), "'", (size))
#define string_add_quote(s, size) strlcat((s), "\"", (size))
#define string_add_colon(s, size) strlcat((s), ":", (size))
#define string_add_glob_open(s, size) strlcat((s), "glob('*", (size))
#define string_add_glob_close(s, size) strlcat((s), "*')", (size))
#define string_is_not_equal_fast(a, b, size) (memcmp(a, b, size) != 0)
#define string_is_equal_fast(a, b, size) (memcmp(a, b, size) == 0)
static INLINE void string_add_between_pairs(char *s, const char *str,
size_t size)
{
string_add_pair_open(s, size);
strlcat(s, str, size);
string_add_pair_close(s, size);
}
static INLINE bool string_is_equal_case_insensitive(const char *a,
const char *b)
{
int result = 0;
const unsigned char *p1 = (const unsigned char*)a;
const unsigned char *p2 = (const unsigned char*)b;
if (!a || !b)
return false;
if (p1 == p2)
return true;
while ((result = tolower (*p1) - tolower (*p2++)) == 0)
if (*p1++ == '\0')
break;
return (result == 0);
}
static INLINE bool string_is_equal_noncase(const char *a, const char *b)
{
int result = 0;
const unsigned char *p1 = (const unsigned char*)a;
const unsigned char *p2 = (const unsigned char*)b;
if (!a || !b)
return false;
if (p1 == p2)
return false;
while ((result = tolower (*p1) - tolower (*p2++)) == 0)
if (*p1++ == '\0')
break;
return (result == 0);
}
char *string_to_upper(char *s);
char *string_to_lower(char *s);
char *string_ucwords(char *s);
char *string_replace_substring(const char *in, const char *pattern,
const char *by);
/* Remove leading whitespaces */
char *string_trim_whitespace_left(char *const s);
/* Remove trailing whitespaces */
char *string_trim_whitespace_right(char *const s);
/* Remove leading and trailing whitespaces */
char *string_trim_whitespace(char *const s);
/* max_lines == 0 means no limit */
char *word_wrap(char *buffer, const char *string,
int line_width, bool unicode, unsigned max_lines);
RETRO_END_DECLS
#endif

View File

@@ -0,0 +1,18 @@
Copyright (c) 2013 Mikko Mononen memon@inside.org
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,685 @@
//
// Copyright (c) 2013 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#ifndef NANOVG_H
#define NANOVG_H
#ifdef __cplusplus
extern "C" {
#endif
#define NVG_PI 3.14159265358979323846264338327f
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4201) // nonstandard extension used : nameless struct/union
#endif
typedef struct NVGcontext NVGcontext;
struct NVGcolor {
union {
float rgba[4];
struct {
float r,g,b,a;
};
};
};
typedef struct NVGcolor NVGcolor;
struct NVGpaint {
float xform[6];
float extent[2];
float radius;
float feather;
NVGcolor innerColor;
NVGcolor outerColor;
int image;
};
typedef struct NVGpaint NVGpaint;
enum NVGwinding {
NVG_CCW = 1, // Winding for solid shapes
NVG_CW = 2, // Winding for holes
};
enum NVGsolidity {
NVG_SOLID = 1, // CCW
NVG_HOLE = 2, // CW
};
enum NVGlineCap {
NVG_BUTT,
NVG_ROUND,
NVG_SQUARE,
NVG_BEVEL,
NVG_MITER,
};
enum NVGalign {
// Horizontal align
NVG_ALIGN_LEFT = 1<<0, // Default, align text horizontally to left.
NVG_ALIGN_CENTER = 1<<1, // Align text horizontally to center.
NVG_ALIGN_RIGHT = 1<<2, // Align text horizontally to right.
// Vertical align
NVG_ALIGN_TOP = 1<<3, // Align text vertically to top.
NVG_ALIGN_MIDDLE = 1<<4, // Align text vertically to middle.
NVG_ALIGN_BOTTOM = 1<<5, // Align text vertically to bottom.
NVG_ALIGN_BASELINE = 1<<6, // Default, align text vertically to baseline.
};
enum NVGblendFactor {
NVG_ZERO = 1<<0,
NVG_ONE = 1<<1,
NVG_SRC_COLOR = 1<<2,
NVG_ONE_MINUS_SRC_COLOR = 1<<3,
NVG_DST_COLOR = 1<<4,
NVG_ONE_MINUS_DST_COLOR = 1<<5,
NVG_SRC_ALPHA = 1<<6,
NVG_ONE_MINUS_SRC_ALPHA = 1<<7,
NVG_DST_ALPHA = 1<<8,
NVG_ONE_MINUS_DST_ALPHA = 1<<9,
NVG_SRC_ALPHA_SATURATE = 1<<10,
};
enum NVGcompositeOperation {
NVG_SOURCE_OVER,
NVG_SOURCE_IN,
NVG_SOURCE_OUT,
NVG_ATOP,
NVG_DESTINATION_OVER,
NVG_DESTINATION_IN,
NVG_DESTINATION_OUT,
NVG_DESTINATION_ATOP,
NVG_LIGHTER,
NVG_COPY,
NVG_XOR,
};
struct NVGcompositeOperationState {
int srcRGB;
int dstRGB;
int srcAlpha;
int dstAlpha;
};
typedef struct NVGcompositeOperationState NVGcompositeOperationState;
struct NVGglyphPosition {
const char* str; // Position of the glyph in the input string.
float x; // The x-coordinate of the logical glyph position.
float minx, maxx; // The bounds of the glyph shape.
};
typedef struct NVGglyphPosition NVGglyphPosition;
struct NVGtextRow {
const char* start; // Pointer to the input text where the row starts.
const char* end; // Pointer to the input text where the row ends (one past the last character).
const char* next; // Pointer to the beginning of the next row.
float width; // Logical width of the row.
float minx, maxx; // Actual bounds of the row. Logical with and bounds can differ because of kerning and some parts over extending.
};
typedef struct NVGtextRow NVGtextRow;
enum NVGimageFlags {
NVG_IMAGE_GENERATE_MIPMAPS = 1<<0, // Generate mipmaps during creation of the image.
NVG_IMAGE_REPEATX = 1<<1, // Repeat image in X direction.
NVG_IMAGE_REPEATY = 1<<2, // Repeat image in Y direction.
NVG_IMAGE_FLIPY = 1<<3, // Flips (inverses) image in Y direction when rendered.
NVG_IMAGE_PREMULTIPLIED = 1<<4, // Image data has premultiplied alpha.
NVG_IMAGE_NEAREST = 1<<5, // Image interpolation is Nearest instead Linear
};
// Begin drawing a new frame
// Calls to nanovg drawing API should be wrapped in nvgBeginFrame() & nvgEndFrame()
// nvgBeginFrame() defines the size of the window to render to in relation currently
// set viewport (i.e. glViewport on GL backends). Device pixel ration allows to
// control the rendering on Hi-DPI devices.
// For example, GLFW returns two dimension for an opened window: window size and
// frame buffer size. In that case you would set windowWidth/Height to the window size
// devicePixelRatio to: frameBufferWidth / windowWidth.
void nvgBeginFrame(NVGcontext* ctx, float windowWidth, float windowHeight, float devicePixelRatio);
// Cancels drawing the current frame.
void nvgCancelFrame(NVGcontext* ctx);
// Ends drawing flushing remaining render state.
void nvgEndFrame(NVGcontext* ctx);
//
// Composite operation
//
// The composite operations in NanoVG are modeled after HTML Canvas API, and
// the blend func is based on OpenGL (see corresponding manuals for more info).
// The colors in the blending state have premultiplied alpha.
// Sets the composite operation. The op parameter should be one of NVGcompositeOperation.
void nvgGlobalCompositeOperation(NVGcontext* ctx, int op);
// Sets the composite operation with custom pixel arithmetic. The parameters should be one of NVGblendFactor.
void nvgGlobalCompositeBlendFunc(NVGcontext* ctx, int sfactor, int dfactor);
// Sets the composite operation with custom pixel arithmetic for RGB and alpha components separately. The parameters should be one of NVGblendFactor.
void nvgGlobalCompositeBlendFuncSeparate(NVGcontext* ctx, int srcRGB, int dstRGB, int srcAlpha, int dstAlpha);
//
// Color utils
//
// Colors in NanoVG are stored as unsigned ints in ABGR format.
// Returns a color value from red, green, blue values. Alpha will be set to 255 (1.0f).
NVGcolor nvgRGB(unsigned char r, unsigned char g, unsigned char b);
// Returns a color value from red, green, blue values. Alpha will be set to 1.0f.
NVGcolor nvgRGBf(float r, float g, float b);
// Returns a color value from red, green, blue and alpha values.
NVGcolor nvgRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a);
// Returns a color value from red, green, blue and alpha values.
NVGcolor nvgRGBAf(float r, float g, float b, float a);
// Linearly interpolates from color c0 to c1, and returns resulting color value.
NVGcolor nvgLerpRGBA(NVGcolor c0, NVGcolor c1, float u);
// Sets transparency of a color value.
NVGcolor nvgTransRGBA(NVGcolor c0, unsigned char a);
// Sets transparency of a color value.
NVGcolor nvgTransRGBAf(NVGcolor c0, float a);
// Returns color value specified by hue, saturation and lightness.
// HSL values are all in range [0..1], alpha will be set to 255.
NVGcolor nvgHSL(float h, float s, float l);
// Returns color value specified by hue, saturation and lightness and alpha.
// HSL values are all in range [0..1], alpha in range [0..255]
NVGcolor nvgHSLA(float h, float s, float l, unsigned char a);
//
// State Handling
//
// NanoVG contains state which represents how paths will be rendered.
// The state contains transform, fill and stroke styles, text and font styles,
// and scissor clipping.
// Pushes and saves the current render state into a state stack.
// A matching nvgRestore() must be used to restore the state.
void nvgSave(NVGcontext* ctx);
// Pops and restores current render state.
void nvgRestore(NVGcontext* ctx);
// Resets current render state to default values. Does not affect the render state stack.
void nvgReset(NVGcontext* ctx);
//
// Render styles
//
// Fill and stroke render style can be either a solid color or a paint which is a gradient or a pattern.
// Solid color is simply defined as a color value, different kinds of paints can be created
// using nvgLinearGradient(), nvgBoxGradient(), nvgRadialGradient() and nvgImagePattern().
//
// Current render style can be saved and restored using nvgSave() and nvgRestore().
// Sets whether to draw antialias for nvgStroke() and nvgFill(). It's enabled by default.
void nvgShapeAntiAlias(NVGcontext* ctx, int enabled);
// Sets current stroke style to a solid color.
void nvgStrokeColor(NVGcontext* ctx, NVGcolor color);
// Sets current stroke style to a paint, which can be a one of the gradients or a pattern.
void nvgStrokePaint(NVGcontext* ctx, NVGpaint paint);
// Sets current fill style to a solid color.
void nvgFillColor(NVGcontext* ctx, NVGcolor color);
// Sets current fill style to a paint, which can be a one of the gradients or a pattern.
void nvgFillPaint(NVGcontext* ctx, NVGpaint paint);
// Sets the miter limit of the stroke style.
// Miter limit controls when a sharp corner is beveled.
void nvgMiterLimit(NVGcontext* ctx, float limit);
// Sets the stroke width of the stroke style.
void nvgStrokeWidth(NVGcontext* ctx, float size);
// Sets how the end of the line (cap) is drawn,
// Can be one of: NVG_BUTT (default), NVG_ROUND, NVG_SQUARE.
void nvgLineCap(NVGcontext* ctx, int cap);
// Sets how sharp path corners are drawn.
// Can be one of NVG_MITER (default), NVG_ROUND, NVG_BEVEL.
void nvgLineJoin(NVGcontext* ctx, int join);
// Sets the transparency applied to all rendered shapes.
// Already transparent paths will get proportionally more transparent as well.
void nvgGlobalAlpha(NVGcontext* ctx, float alpha);
//
// Transforms
//
// The paths, gradients, patterns and scissor region are transformed by an transformation
// matrix at the time when they are passed to the API.
// The current transformation matrix is a affine matrix:
// [sx kx tx]
// [ky sy ty]
// [ 0 0 1]
// Where: sx,sy define scaling, kx,ky skewing, and tx,ty translation.
// The last row is assumed to be 0,0,1 and is not stored.
//
// Apart from nvgResetTransform(), each transformation function first creates
// specific transformation matrix and pre-multiplies the current transformation by it.
//
// Current coordinate system (transformation) can be saved and restored using nvgSave() and nvgRestore().
// Resets current transform to a identity matrix.
void nvgResetTransform(NVGcontext* ctx);
// Premultiplies current coordinate system by specified matrix.
// The parameters are interpreted as matrix as follows:
// [a c e]
// [b d f]
// [0 0 1]
void nvgTransform(NVGcontext* ctx, float a, float b, float c, float d, float e, float f);
// Translates current coordinate system.
void nvgTranslate(NVGcontext* ctx, float x, float y);
// Rotates current coordinate system. Angle is specified in radians.
void nvgRotate(NVGcontext* ctx, float angle);
// Skews the current coordinate system along X axis. Angle is specified in radians.
void nvgSkewX(NVGcontext* ctx, float angle);
// Skews the current coordinate system along Y axis. Angle is specified in radians.
void nvgSkewY(NVGcontext* ctx, float angle);
// Scales the current coordinate system.
void nvgScale(NVGcontext* ctx, float x, float y);
// Stores the top part (a-f) of the current transformation matrix in to the specified buffer.
// [a c e]
// [b d f]
// [0 0 1]
// There should be space for 6 floats in the return buffer for the values a-f.
void nvgCurrentTransform(NVGcontext* ctx, float* xform);
// The following functions can be used to make calculations on 2x3 transformation matrices.
// A 2x3 matrix is represented as float[6].
// Sets the transform to identity matrix.
void nvgTransformIdentity(float* dst);
// Sets the transform to translation matrix matrix.
void nvgTransformTranslate(float* dst, float tx, float ty);
// Sets the transform to scale matrix.
void nvgTransformScale(float* dst, float sx, float sy);
// Sets the transform to rotate matrix. Angle is specified in radians.
void nvgTransformRotate(float* dst, float a);
// Sets the transform to skew-x matrix. Angle is specified in radians.
void nvgTransformSkewX(float* dst, float a);
// Sets the transform to skew-y matrix. Angle is specified in radians.
void nvgTransformSkewY(float* dst, float a);
// Sets the transform to the result of multiplication of two transforms, of A = A*B.
void nvgTransformMultiply(float* dst, const float* src);
// Sets the transform to the result of multiplication of two transforms, of A = B*A.
void nvgTransformPremultiply(float* dst, const float* src);
// Sets the destination to inverse of specified transform.
// Returns 1 if the inverse could be calculated, else 0.
int nvgTransformInverse(float* dst, const float* src);
// Transform a point by given transform.
void nvgTransformPoint(float* dstx, float* dsty, const float* xform, float srcx, float srcy);
// Converts degrees to radians and vice versa.
float nvgDegToRad(float deg);
float nvgRadToDeg(float rad);
//
// Images
//
// NanoVG allows you to load jpg, png, psd, tga, pic and gif files to be used for rendering.
// In addition you can upload your own image. The image loading is provided by stb_image.
// The parameter imageFlags is combination of flags defined in NVGimageFlags.
// Creates image by loading it from the disk from specified file name.
// Returns handle to the image.
int nvgCreateImage(NVGcontext* ctx, const char* filename, int imageFlags);
// Creates image by loading it from the specified chunk of memory.
// Returns handle to the image.
int nvgCreateImageMem(NVGcontext* ctx, int imageFlags, unsigned char* data, int ndata);
// Creates image from specified image data.
// Returns handle to the image.
int nvgCreateImageRGBA(NVGcontext* ctx, int w, int h, int imageFlags, const unsigned char* data);
// Updates image data specified by image handle.
void nvgUpdateImage(NVGcontext* ctx, int image, const unsigned char* data);
// Returns the dimensions of a created image.
void nvgImageSize(NVGcontext* ctx, int image, int* w, int* h);
// Deletes created image.
void nvgDeleteImage(NVGcontext* ctx, int image);
//
// Paints
//
// NanoVG supports four types of paints: linear gradient, box gradient, radial gradient and image pattern.
// These can be used as paints for strokes and fills.
// Creates and returns a linear gradient. Parameters (sx,sy)-(ex,ey) specify the start and end coordinates
// of the linear gradient, icol specifies the start color and ocol the end color.
// The gradient is transformed by the current transform when it is passed to nvgFillPaint() or nvgStrokePaint().
NVGpaint nvgLinearGradient(NVGcontext* ctx, float sx, float sy, float ex, float ey,
NVGcolor icol, NVGcolor ocol);
// Creates and returns a box gradient. Box gradient is a feathered rounded rectangle, it is useful for rendering
// drop shadows or highlights for boxes. Parameters (x,y) define the top-left corner of the rectangle,
// (w,h) define the size of the rectangle, r defines the corner radius, and f feather. Feather defines how blurry
// the border of the rectangle is. Parameter icol specifies the inner color and ocol the outer color of the gradient.
// The gradient is transformed by the current transform when it is passed to nvgFillPaint() or nvgStrokePaint().
NVGpaint nvgBoxGradient(NVGcontext* ctx, float x, float y, float w, float h,
float r, float f, NVGcolor icol, NVGcolor ocol);
// Creates and returns a radial gradient. Parameters (cx,cy) specify the center, inr and outr specify
// the inner and outer radius of the gradient, icol specifies the start color and ocol the end color.
// The gradient is transformed by the current transform when it is passed to nvgFillPaint() or nvgStrokePaint().
NVGpaint nvgRadialGradient(NVGcontext* ctx, float cx, float cy, float inr, float outr,
NVGcolor icol, NVGcolor ocol);
// Creates and returns an image patter. Parameters (ox,oy) specify the left-top location of the image pattern,
// (ex,ey) the size of one image, angle rotation around the top-left corner, image is handle to the image to render.
// The gradient is transformed by the current transform when it is passed to nvgFillPaint() or nvgStrokePaint().
NVGpaint nvgImagePattern(NVGcontext* ctx, float ox, float oy, float ex, float ey,
float angle, int image, float alpha);
//
// Scissoring
//
// Scissoring allows you to clip the rendering into a rectangle. This is useful for various
// user interface cases like rendering a text edit or a timeline.
// Sets the current scissor rectangle.
// The scissor rectangle is transformed by the current transform.
void nvgScissor(NVGcontext* ctx, float x, float y, float w, float h);
// Intersects current scissor rectangle with the specified rectangle.
// The scissor rectangle is transformed by the current transform.
// Note: in case the rotation of previous scissor rect differs from
// the current one, the intersection will be done between the specified
// rectangle and the previous scissor rectangle transformed in the current
// transform space. The resulting shape is always rectangle.
void nvgIntersectScissor(NVGcontext* ctx, float x, float y, float w, float h);
// Reset and disables scissoring.
void nvgResetScissor(NVGcontext* ctx);
//
// Paths
//
// Drawing a new shape starts with nvgBeginPath(), it clears all the currently defined paths.
// Then you define one or more paths and sub-paths which describe the shape. The are functions
// to draw common shapes like rectangles and circles, and lower level step-by-step functions,
// which allow to define a path curve by curve.
//
// NanoVG uses even-odd fill rule to draw the shapes. Solid shapes should have counter clockwise
// winding and holes should have counter clockwise order. To specify winding of a path you can
// call nvgPathWinding(). This is useful especially for the common shapes, which are drawn CCW.
//
// Finally you can fill the path using current fill style by calling nvgFill(), and stroke it
// with current stroke style by calling nvgStroke().
//
// The curve segments and sub-paths are transformed by the current transform.
// Clears the current path and sub-paths.
void nvgBeginPath(NVGcontext* ctx);
// Starts new sub-path with specified point as first point.
void nvgMoveTo(NVGcontext* ctx, float x, float y);
// Adds line segment from the last point in the path to the specified point.
void nvgLineTo(NVGcontext* ctx, float x, float y);
// Adds cubic bezier segment from last point in the path via two control points to the specified point.
void nvgBezierTo(NVGcontext* ctx, float c1x, float c1y, float c2x, float c2y, float x, float y);
// Adds quadratic bezier segment from last point in the path via a control point to the specified point.
void nvgQuadTo(NVGcontext* ctx, float cx, float cy, float x, float y);
// Adds an arc segment at the corner defined by the last path point, and two specified points.
void nvgArcTo(NVGcontext* ctx, float x1, float y1, float x2, float y2, float radius);
// Closes current sub-path with a line segment.
void nvgClosePath(NVGcontext* ctx);
// Sets the current sub-path winding, see NVGwinding and NVGsolidity.
void nvgPathWinding(NVGcontext* ctx, int dir);
// Creates new circle arc shaped sub-path. The arc center is at cx,cy, the arc radius is r,
// and the arc is drawn from angle a0 to a1, and swept in direction dir (NVG_CCW, or NVG_CW).
// Angles are specified in radians.
void nvgArc(NVGcontext* ctx, float cx, float cy, float r, float a0, float a1, int dir);
// Creates new rectangle shaped sub-path.
void nvgRect(NVGcontext* ctx, float x, float y, float w, float h);
// Creates new rounded rectangle shaped sub-path.
void nvgRoundedRect(NVGcontext* ctx, float x, float y, float w, float h, float r);
// Creates new rounded rectangle shaped sub-path with varying radii for each corner.
void nvgRoundedRectVarying(NVGcontext* ctx, float x, float y, float w, float h, float radTopLeft, float radTopRight, float radBottomRight, float radBottomLeft);
// Creates new ellipse shaped sub-path.
void nvgEllipse(NVGcontext* ctx, float cx, float cy, float rx, float ry);
// Creates new circle shaped sub-path.
void nvgCircle(NVGcontext* ctx, float cx, float cy, float r);
// Fills the current path with current fill style.
void nvgFill(NVGcontext* ctx);
// Fills the current path with current stroke style.
void nvgStroke(NVGcontext* ctx);
//
// Text
//
// NanoVG allows you to load .ttf files and use the font to render text.
//
// The appearance of the text can be defined by setting the current text style
// and by specifying the fill color. Common text and font settings such as
// font size, letter spacing and text align are supported. Font blur allows you
// to create simple text effects such as drop shadows.
//
// At render time the font face can be set based on the font handles or name.
//
// Font measure functions return values in local space, the calculations are
// carried in the same resolution as the final rendering. This is done because
// the text glyph positions are snapped to the nearest pixels sharp rendering.
//
// The local space means that values are not rotated or scale as per the current
// transformation. For example if you set font size to 12, which would mean that
// line height is 16, then regardless of the current scaling and rotation, the
// returned line height is always 16. Some measures may vary because of the scaling
// since aforementioned pixel snapping.
//
// While this may sound a little odd, the setup allows you to always render the
// same way regardless of scaling. I.e. following works regardless of scaling:
//
// const char* txt = "Text me up.";
// nvgTextBounds(vg, x,y, txt, NULL, bounds);
// nvgBeginPath(vg);
// nvgRoundedRect(vg, bounds[0],bounds[1], bounds[2]-bounds[0], bounds[3]-bounds[1]);
// nvgFill(vg);
//
// Note: currently only solid color fill is supported for text.
// Creates font by loading it from the disk from specified file name.
// Returns handle to the font.
int nvgCreateFont(NVGcontext* ctx, const char* name, const char* filename);
// Creates font by loading it from the specified memory chunk.
// Returns handle to the font.
int nvgCreateFontMem(NVGcontext* ctx, const char* name, unsigned char* data, int ndata, int freeData);
// Finds a loaded font of specified name, and returns handle to it, or -1 if the font is not found.
int nvgFindFont(NVGcontext* ctx, const char* name);
// Adds a fallback font by handle.
int nvgAddFallbackFontId(NVGcontext* ctx, int baseFont, int fallbackFont);
// Adds a fallback font by name.
int nvgAddFallbackFont(NVGcontext* ctx, const char* baseFont, const char* fallbackFont);
// Sets the font size of current text style.
void nvgFontSize(NVGcontext* ctx, float size);
// Sets the blur of current text style.
void nvgFontBlur(NVGcontext* ctx, float blur);
// Sets the letter spacing of current text style.
void nvgTextLetterSpacing(NVGcontext* ctx, float spacing);
// Sets the proportional line height of current text style. The line height is specified as multiple of font size.
void nvgTextLineHeight(NVGcontext* ctx, float lineHeight);
// Sets the text align of current text style, see NVGalign for options.
void nvgTextAlign(NVGcontext* ctx, int align);
// Sets the font face based on specified id of current text style.
void nvgFontFaceId(NVGcontext* ctx, int font);
// Sets the font face based on specified name of current text style.
void nvgFontFace(NVGcontext* ctx, const char* font);
// Draws text string at specified location. If end is specified only the sub-string up to the end is drawn.
float nvgText(NVGcontext* ctx, float x, float y, const char* string, const char* end);
// Draws multi-line text string at specified location wrapped at the specified width. If end is specified only the sub-string up to the end is drawn.
// White space is stripped at the beginning of the rows, the text is split at word boundaries or when new-line characters are encountered.
// Words longer than the max width are slit at nearest character (i.e. no hyphenation).
void nvgTextBox(NVGcontext* ctx, float x, float y, float breakRowWidth, const char* string, const char* end);
// Measures the specified text string. Parameter bounds should be a pointer to float[4],
// if the bounding box of the text should be returned. The bounds value are [xmin,ymin, xmax,ymax]
// Returns the horizontal advance of the measured text (i.e. where the next character should drawn).
// Measured values are returned in local coordinate space.
float nvgTextBounds(NVGcontext* ctx, float x, float y, const char* string, const char* end, float* bounds);
// Measures the specified multi-text string. Parameter bounds should be a pointer to float[4],
// if the bounding box of the text should be returned. The bounds value are [xmin,ymin, xmax,ymax]
// Measured values are returned in local coordinate space.
void nvgTextBoxBounds(NVGcontext* ctx, float x, float y, float breakRowWidth, const char* string, const char* end, float* bounds);
// Calculates the glyph x positions of the specified text. If end is specified only the sub-string will be used.
// Measured values are returned in local coordinate space.
int nvgTextGlyphPositions(NVGcontext* ctx, float x, float y, const char* string, const char* end, NVGglyphPosition* positions, int maxPositions);
// Returns the vertical metrics based on the current text style.
// Measured values are returned in local coordinate space.
void nvgTextMetrics(NVGcontext* ctx, float* ascender, float* descender, float* lineh);
// Breaks the specified text into lines. If end is specified only the sub-string will be used.
// White space is stripped at the beginning of the rows, the text is split at word boundaries or when new-line characters are encountered.
// Words longer than the max width are slit at nearest character (i.e. no hyphenation).
int nvgTextBreakLines(NVGcontext* ctx, const char* string, const char* end, float breakRowWidth, NVGtextRow* rows, int maxRows);
//
// Internal Render API
//
enum NVGtexture {
NVG_TEXTURE_ALPHA = 0x01,
NVG_TEXTURE_RGBA = 0x02,
};
struct NVGscissor {
float xform[6];
float extent[2];
};
typedef struct NVGscissor NVGscissor;
struct NVGvertex {
float x,y,u,v;
};
typedef struct NVGvertex NVGvertex;
struct NVGpath {
int first;
int count;
unsigned char closed;
int nbevel;
NVGvertex* fill;
int nfill;
NVGvertex* stroke;
int nstroke;
int winding;
int convex;
};
typedef struct NVGpath NVGpath;
struct NVGparams {
void* userPtr;
int edgeAntiAlias;
int (*renderCreate)(void* uptr);
int (*renderCreateTexture)(void* uptr, int type, int w, int h, int imageFlags, const unsigned char* data);
int (*renderDeleteTexture)(void* uptr, int image);
int (*renderUpdateTexture)(void* uptr, int image, int x, int y, int w, int h, const unsigned char* data);
int (*renderGetTextureSize)(void* uptr, int image, int* w, int* h);
void (*renderViewport)(void* uptr, float width, float height, float devicePixelRatio);
void (*renderCancel)(void* uptr);
void (*renderFlush)(void* uptr);
void (*renderFill)(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, float fringe, const float* bounds, const NVGpath* paths, int npaths);
void (*renderStroke)(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, float fringe, float strokeWidth, const NVGpath* paths, int npaths);
void (*renderTriangles)(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, const NVGvertex* verts, int nverts);
void (*renderDelete)(void* uptr);
};
typedef struct NVGparams NVGparams;
// Constructor and destructor, called by the render back-end.
NVGcontext* nvgCreateInternal(NVGparams* params);
void nvgDeleteInternal(NVGcontext* ctx);
NVGparams* nvgInternalParams(NVGcontext* ctx);
// Debug function to dump cached path data.
void nvgDebugDumpPathCache(NVGcontext* ctx);
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#define NVG_NOTUSED(v) for (;;) { (void)(1 ? (void)0 : ( (void)(v) ) ); break; }
#ifdef __cplusplus
}
#endif
#endif // NANOVG_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,154 @@
//
// Copyright (c) 2009-2013 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#ifndef NANOVG_GL_UTILS_H
#define NANOVG_GL_UTILS_H
struct NVGLUframebuffer {
NVGcontext* ctx;
GLuint fbo;
GLuint rbo;
GLuint texture;
int image;
};
typedef struct NVGLUframebuffer NVGLUframebuffer;
// Helper function to create GL frame buffer to render to.
void nvgluBindFramebuffer(NVGLUframebuffer* fb);
NVGLUframebuffer* nvgluCreateFramebuffer(NVGcontext* ctx, int w, int h, int imageFlags);
void nvgluDeleteFramebuffer(NVGLUframebuffer* fb);
#endif // NANOVG_GL_UTILS_H
#ifdef NANOVG_GL_IMPLEMENTATION
#if defined(NANOVG_GL3) || defined(NANOVG_GLES2) || defined(NANOVG_GLES3)
// FBO is core in OpenGL 3>.
# define NANOVG_FBO_VALID 1
#elif defined(NANOVG_GL2)
// On OS X including glext defines FBO on GL2 too.
# ifdef __APPLE__
# include <OpenGL/glext.h>
# define NANOVG_FBO_VALID 1
# endif
#endif
static GLint defaultFBO = -1;
NVGLUframebuffer* nvgluCreateFramebuffer(NVGcontext* ctx, int w, int h, int imageFlags)
{
#ifdef NANOVG_FBO_VALID
GLint defaultFBO;
GLint defaultRBO;
NVGLUframebuffer* fb = NULL;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO);
glGetIntegerv(GL_RENDERBUFFER_BINDING, &defaultRBO);
fb = (NVGLUframebuffer*)malloc(sizeof(NVGLUframebuffer));
if (fb == NULL) goto error;
memset(fb, 0, sizeof(NVGLUframebuffer));
fb->image = nvgCreateImageRGBA(ctx, w, h, imageFlags | NVG_IMAGE_FLIPY | NVG_IMAGE_PREMULTIPLIED, NULL);
#if defined NANOVG_GL2
fb->texture = nvglImageHandleGL2(ctx, fb->image);
#elif defined NANOVG_GL3
fb->texture = nvglImageHandleGL3(ctx, fb->image);
#elif defined NANOVG_GLES2
fb->texture = nvglImageHandleGLES2(ctx, fb->image);
#elif defined NANOVG_GLES3
fb->texture = nvglImageHandleGLES3(ctx, fb->image);
#endif
fb->ctx = ctx;
// frame buffer object
glGenFramebuffers(1, &fb->fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fb->fbo);
// render buffer object
glGenRenderbuffers(1, &fb->rbo);
glBindRenderbuffer(GL_RENDERBUFFER, fb->rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, w, h);
// combine all
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb->texture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb->rbo);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
#ifdef GL_DEPTH24_STENCIL8
// If GL_STENCIL_INDEX8 is not supported, try GL_DEPTH24_STENCIL8 as a fallback.
// Some graphics cards require a depth buffer along with a stencil.
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, w, h);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb->texture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb->rbo);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
#endif // GL_DEPTH24_STENCIL8
goto error;
}
glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
glBindRenderbuffer(GL_RENDERBUFFER, defaultRBO);
return fb;
error:
glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
glBindRenderbuffer(GL_RENDERBUFFER, defaultRBO);
nvgluDeleteFramebuffer(fb);
return NULL;
#else
NVG_NOTUSED(ctx);
NVG_NOTUSED(w);
NVG_NOTUSED(h);
NVG_NOTUSED(imageFlags);
return NULL;
#endif
}
void nvgluBindFramebuffer(NVGLUframebuffer* fb)
{
#ifdef NANOVG_FBO_VALID
if (defaultFBO == -1) glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO);
glBindFramebuffer(GL_FRAMEBUFFER, fb != NULL ? fb->fbo : defaultFBO);
#else
NVG_NOTUSED(fb);
#endif
}
void nvgluDeleteFramebuffer(NVGLUframebuffer* fb)
{
#ifdef NANOVG_FBO_VALID
if (fb == NULL) return;
if (fb->fbo != 0)
glDeleteFramebuffers(1, &fb->fbo);
if (fb->rbo != 0)
glDeleteRenderbuffers(1, &fb->rbo);
if (fb->image >= 0)
nvgDeleteImage(fb->ctx, fb->image);
fb->ctx = NULL;
fb->fbo = 0;
fb->rbo = 0;
fb->texture = 0;
fb->image = -1;
free(fb);
#else
NVG_NOTUSED(fb);
#endif
}
#endif // NANOVG_GL_IMPLEMENTATION

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,31 @@
/*
Copyright 2021 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <borealis/core/font.hpp>
namespace brls
{
// Font loader that reads everything from resources
class GLFWFontLoader : public FontLoader
{
public:
void loadFonts() override;
};
} // namespace brls

View File

@@ -0,0 +1,39 @@
/*
Copyright 2021 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <borealis/core/input.hpp>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
namespace brls
{
// Input manager for GLFW gamepad and keyboard
class GLFWInputManager : public InputManager
{
public:
GLFWInputManager(GLFWwindow* window);
void updateControllerState(ControllerState* state) override;
private:
GLFWwindow* window;
};
};

View File

@@ -0,0 +1,52 @@
/*
Copyright 2021 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <borealis/core/platform.hpp>
#include <borealis/platforms/glfw/glfw_font.hpp>
#include <borealis/platforms/glfw/glfw_input.hpp>
#include <borealis/platforms/glfw/glfw_video.hpp>
namespace brls
{
class GLFWPlatform : public Platform
{
public:
GLFWPlatform();
~GLFWPlatform();
std::string getName() override;
void createWindow(std::string windowTitle, uint32_t windowWidth, uint32_t windowHeight) override;
bool mainLoopIteration() override;
ThemeVariant getThemeVariant() override;
std::string getLocale() override;
AudioPlayer* getAudioPlayer() override;
VideoContext* getVideoContext() override;
InputManager* getInputManager() override;
FontLoader* getFontLoader() override;
private:
NullAudioPlayer* audioPlayer = nullptr;
GLFWVideoContext* videoContext = nullptr;
GLFWInputManager* inputManager = nullptr;
GLFWFontLoader* fontLoader = nullptr;
};
} // namespace brls

View File

@@ -0,0 +1,48 @@
/*
Copyright 2021 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <borealis/core/video.hpp>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
namespace brls
{
// GLFW Video Context
class GLFWVideoContext : public VideoContext
{
public:
GLFWVideoContext(std::string windowTitle, uint32_t windowWidth, uint32_t windowHeight);
~GLFWVideoContext();
NVGcontext* getNVGContext() override;
void clear(NVGcolor color) override;
void beginFrame() override;
void endFrame() override;
void resetState() override;
GLFWwindow* getGLFWWindow();
private:
GLFWwindow* window = nullptr;
NVGcontext* nvgContext = nullptr;
};
} // namespace brls

View File

@@ -0,0 +1,45 @@
/*
Copyright 2021 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <pulsar.h>
#include <borealis/core/audio.hpp>
namespace brls
{
// AudioPlayer implementation that uses libpulsar to load and play
// qlaunch sounds loaded at runtime
class SwitchAudioPlayer : public AudioPlayer
{
public:
SwitchAudioPlayer();
~SwitchAudioPlayer();
bool load(enum Sound sound) override;
bool play(enum Sound sound) override;
private:
bool init = false;
PLSR_BFSAR qlaunchBfsar;
PLSR_PlayerSoundId sounds[_SOUND_MAX];
};
} //namespace brls

View File

@@ -0,0 +1,31 @@
/*
Copyright 2021 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <borealis/core/font.hpp>
namespace brls
{
// Font loader using the pl system service
class SwitchFontLoader : public FontLoader
{
public:
void loadFonts() override;
};
} // namespace brls

View File

@@ -0,0 +1,38 @@
/*
Copyright 2021 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <switch.h>
#include <borealis/core/input.hpp>
namespace brls
{
// InputManager that uses the hid sysmodule to get inputs
class SwitchInputManager : public InputManager
{
public:
SwitchInputManager();
void updateControllerState(ControllerState* state);
private:
PadState padState;
};
} // namespace brls

View File

@@ -0,0 +1,61 @@
/*
Copyright 2021 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <borealis/platforms/glfw/glfw_platform.hpp>
#include <borealis/platforms/switch/switch_audio.hpp>
#include <borealis/platforms/switch/switch_font.hpp>
#include <borealis/platforms/switch/switch_input.hpp>
#include <borealis/platforms/switch/switch_video.hpp>
namespace brls
{
class SwitchPlatform : public Platform
{
public:
SwitchPlatform();
~SwitchPlatform();
void createWindow(std::string windowTitle, uint32_t windowWidth, uint32_t windowHeight) override;
std::string getName() override;
bool mainLoopIteration() override;
ThemeVariant getThemeVariant() override;
std::string getLocale() override;
VideoContext* getVideoContext() override;
AudioPlayer* getAudioPlayer() override;
InputManager* getInputManager() override;
FontLoader* getFontLoader() override;
void appletCallback(AppletHookType hookType);
private:
AppletHookCookie appletCookie;
ThemeVariant themeVariant;
std::string locale;
SwitchAudioPlayer* audioPlayer;
SwitchInputManager* inputManager;
SwitchVideoContext* videoContext;
SwitchFontLoader* fontLoader;
};
} // namespace brls

View File

@@ -0,0 +1,87 @@
/*
Copyright 2020 Adubbz
Copyright 2020-2021 Luis Scheurenbrand
Copyright 2021 natinusala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <nanovg/framework/CMemPool.h>
#include <switch.h>
#include <borealis/core/video.hpp>
#include <deko3d.hpp>
#include <nanovg/dk_renderer.hpp>
#include <optional>
typedef Event _LibNXEvent; // "Event" alone clashes with brls::Event
namespace brls
{
static constexpr const unsigned FRAMEBUFFERS_COUNT = 2;
// deko3d video context
class SwitchVideoContext : public VideoContext
{
public:
SwitchVideoContext();
~SwitchVideoContext();
void clear(NVGcolor color) override;
void resetState() override;
void beginFrame() override;
void endFrame() override;
virtual NVGcontext* getNVGContext() override;
void appletCallback(AppletHookType hookType);
private:
_LibNXEvent defaultDisplayResolutionChangeEvent;
bool displayResolutionChangeEventReady = true;
void resetFramebuffer(); // triggered by either display resolution change event or operation mode change event
void updateWindowSize();
void createFramebufferResources();
void recordStaticCommands();
void destroyFramebufferResources();
float framebufferWidth, framebufferHeight;
int imageSlot;
dk::UniqueDevice device;
dk::UniqueQueue queue;
dk::UniqueCmdBuf cmdbuf;
dk::UniqueSwapchain swapchain;
dk::Image depthBuffer;
CMemPool::Handle depthBufferHandle;
dk::Image framebuffers[FRAMEBUFFERS_COUNT];
CMemPool::Handle framebuffersHandles[FRAMEBUFFERS_COUNT];
DkCmdList framebuffersCmdLists[FRAMEBUFFERS_COUNT];
DkCmdList renderCmdlist;
std::optional<CMemPool> imagesPool;
std::optional<CMemPool> codePool;
std::optional<CMemPool> dataPool;
std::optional<nvg::DkRenderer> renderer;
NVGcontext* nvgContext;
};
} // namespace brls

View File

@@ -0,0 +1,33 @@
/*
Copyright 2019 WerWolv
Copyright 2019 p-sam
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <functional>
#include <string>
namespace brls
{
class Swkbd
{
public:
static bool openForText(std::function<void(std::string)> f, std::string headerText = "", std::string subText = "", int maxStringLength = 32, std::string initialText = "");
static bool openForNumber(std::function<void(int)> f, std::string headerText = "", std::string subText = "", int maxStringLength = 32, std::string initialText = "", std::string leftButton = "", std::string rightButton = "");
};
} // namespace brls

View File

@@ -0,0 +1,58 @@
/*
Copyright 2019-2021 natinusala
Copyright 2019 p-sam
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <borealis/core/bind.hpp>
#include <borealis/core/box.hpp>
#include <borealis/views/image.hpp>
#include <borealis/views/label.hpp>
namespace brls
{
// A Horizon settings-like frame, with header and footer (no sidebar)
class AppletFrame : public Box
{
public:
AppletFrame();
void handleXMLElement(tinyxml2::XMLElement* element) override;
/**
* Sets the content view for that AppletFrame.
* Will be placed between header and footer and expanded with grow factor
* and width / height to AUTO.
*/
void setContentView(View* view);
void setTitle(std::string title);
void setIconFromRes(std::string name);
void setIconFromFile(std::string path);
static View* create();
private:
BRLS_BIND(Label, title, "brls/applet_frame/title_label");
BRLS_BIND(Image, icon, "brls/applet_frame/title_icon");
protected:
View* contentView = nullptr;
};
} // namespace brls

Some files were not shown because too many files have changed in this diff Show More