Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 17 additions & 20 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ jobs:
defaults:
run:
shell: ${{ matrix.shell }}
env:
CMAKE_TEST: cmake-build-host-tests
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
Expand Down Expand Up @@ -135,16 +137,6 @@ jobs:
chmod +x build.sh
./build.sh

# TODO: Tests are not building properly...
# the tests target should not be cross compiled, so we can run it on the runner
# https://stackoverflow.com/a/64335131/11214013
# echo "--- Building tests ---"
# cmake \
# -B build/tests \
# -S . \
# -DBUILD_TESTS=ON
# cmake --build build/tests --target test_moonlight

# recursively list all files in build directory
ls -R build

Expand All @@ -159,34 +151,39 @@ jobs:
name: moonlight-${{ runner.os }}
path: artifacts/

- name: Configure host tests
run: cmake -S . -B ${CMAKE_TEST} -DBUILD_TESTS=ON -DBUILD_DOCS=OFF

- name: Build host tests
run: cmake --build ${CMAKE_TEST} --target test_moonlight

- name: Run tests
id: test
if: false && always()
working-directory: build/tests
run: ./test_moonlight --gtest_color=yes --gtest_output=xml:test_results.xml
working-directory: ${{ env.CMAKE_TEST }}
run: ./tests/test_moonlight --gtest_color=yes --gtest_output=xml:tests/test_results.xml

- name: Generate gcov report
id: test_report
# any except canceled or skipped
if: >-
always() &&
(steps.test.outcome == 'success' || steps.test.outcome == 'failure')
working-directory: build
run: |
${{ steps.python-path.outputs.python-path }} -m pip install gcovr
${{ steps.python-path.outputs.python-path }} -m gcovr . -r ../src \
${{ steps.python-path.outputs.python-path }} -m pip install ".[test]"
${{ steps.python-path.outputs.python-path }} -m gcovr ${CMAKE_TEST} -r . \
--filter src \
--exclude-noncode-lines \
--exclude-throw-branches \
--exclude-unreachable-branches \
--verbose \
--xml-pretty \
-o coverage.xml
-o "${CMAKE_TEST}/coverage.xml"

- name: Debug coverage file
if: >-
always() &&
steps.test_report.outcome == 'success'
run: cat build/coverage.xml
run: cat "${CMAKE_TEST}/coverage.xml"

- name: Upload coverage
# any except canceled or skipped
Expand All @@ -198,7 +195,7 @@ jobs:
with:
disable_search: true
fail_ci_if_error: true
files: ./build/coverage.xml
files: ./${{ env.CMAKE_TEST }}/coverage.xml
flags: ${{ runner.os }}
report_type: coverage
token: ${{ secrets.CODECOV_TOKEN }}
Expand All @@ -214,7 +211,7 @@ jobs:
with:
disable_search: true
fail_ci_if_error: true
files: ./build/tests/test_results.xml
files: ./${{ env.CMAKE_TEST }}/tests/test_results.xml
flags: ${{ runner.os }}
handle_no_reports_found: true
report_type: test_results
Expand Down
10 changes: 3 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,6 @@ set(MOONLIGHT_EXTERNAL_LIBRARIES
set(MOONLIGHT_INCLUDE_DIRS
)
set(MOONLIGHT_COMPILE_OPTIONS "-Wno-builtin-macro-redefined")
set(MOONLIGHT_DEFINITIONS "-DXBOX -DNXDK")

# Stop lots of warning spam
add_compile_options(${MOONLIGHT_COMPILE_OPTIONS})
add_definitions(${MOONLIGHT_DEFINITIONS})

# submodules
# moonlight common library
Expand All @@ -98,8 +93,8 @@ include_directories(SYSTEM
target_link_libraries(${CMAKE_PROJECT_NAME} PUBLIC
${MOONLIGHT_EXTERNAL_LIBRARIES}
)

target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE "")
target_compile_options(${CMAKE_PROJECT_NAME} PRIVATE ${MOONLIGHT_COMPILE_OPTIONS})
target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE XBOX NXDK)
add_dependencies(${CMAKE_PROJECT_NAME} moonlight-common-c)

#
Expand All @@ -113,6 +108,7 @@ endif()
# tests
#
if(BUILD_TESTS)
enable_testing()
add_subdirectory(tests EXCLUDE_FROM_ALL)
endif()

Expand Down
29 changes: 29 additions & 0 deletions CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,19 @@
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "host-tests (mingw64)",
"displayName": "Host Tests (mingw64)",
"description": "Build host-native googletest targets under MSYS2/mingw64",
"generator": "Unix Makefiles",
"cmakeExecutable": "C:/msys64/usr/bin/cmake",
"binaryDir": "${sourceDir}/cmake-build-host-tests",
"cacheVariables": {
"BUILD_DOCS": "OFF",
"BUILD_TESTS": "ON",
"CMAKE_BUILD_TYPE": "Debug"
}
}
],
"buildPresets": [
Expand All @@ -49,6 +62,22 @@
{
"name": "nxdk-debug (mingw64)",
"configurePreset": "nxdk-debug (mingw64)"
},
{
"name": "host-tests (mingw64)",
"configurePreset": "host-tests (mingw64)",
"targets": [
"test_moonlight"
]
}
],
"testPresets": [
{
"name": "host-tests (mingw64)",
"configurePreset": "host-tests (mingw64)",
"output": {
"outputOnFailure": true
}
}
]
}
35 changes: 33 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
[![GitHub stars](https://img.shields.io/github/stars/lizardbyte/moonlight-xboxog.svg?logo=github&style=for-the-badge)](https://github.com/LizardByte/Moonlight-XboxOG)
[![GitHub Releases](https://img.shields.io/github/downloads/lizardbyte/moonlight-xboxog/total.svg?style=for-the-badge&logo=github)](https://github.com/LizardByte/Moonlight-XboxOG/releases/latest)
[![GitHub Workflow Status (CI)](https://img.shields.io/github/actions/workflow/status/lizardbyte/moonlight-xboxog/ci.yml.svg?branch=master&label=CI%20build&logo=github&style=for-the-badge)](https://github.com/LizardByte/Moonlight-XboxOG/actions/workflows/CI.yml?query=branch%3Amaster)
[![Codecov](https://img.shields.io/codecov/c/gh/LizardByte/Moonlight-XboxOG?token=DoIh5pkEzA&style=for-the-badge&logo=codecov&label=codecov)](https://codecov.io/gh/LizardByte/Moonlight-XboxOG)

Port of Moonlight for the Original Xbox. Unlikely to ever actually work. Do NOT use!

Expand Down Expand Up @@ -148,6 +149,36 @@ build-mingw64.bat
./build-mingw64.sh
```

### Host-native unit tests

The Xbox executable cannot run directly on Windows, macOS, or Linux, so unit tests are built as a separate host-native target. Keep Xbox runtime code thin and move logic you want to test into platform-neutral sources that can be linked into `test_moonlight`.

#### Windows via MSYS2/mingw64

From `cmd.exe`, configure, build, and run the host tests with:

```bat
C:\msys64\msys2_shell.cmd -defterm -here -no-start -mingw64 -c "cd /c/Users/%USERNAME%/Dev/git/Moonlight-XboxOG && cmake --preset \"host-tests (mingw64)\" && cmake --build --preset \"host-tests (mingw64)\" && ctest --preset \"host-tests (mingw64)\""
```

If you are already inside a `mingw64` shell, the equivalent commands are:

```bash
cmake --preset "host-tests (mingw64)"
cmake --build --preset "host-tests (mingw64)"
ctest --preset "host-tests (mingw64)"
```

#### Linux or macOS

```bash
cmake -S . -B cmake-build-host-tests -DBUILD_TESTS=ON -DBUILD_DOCS=OFF
cmake --build cmake-build-host-tests --target test_moonlight
ctest --test-dir cmake-build-host-tests --output-on-failure
```

Coverage should come from this host-native test build instead of the cross-compiled Xbox build.

### CLion on Windows

The repository now includes CLion-friendly nxdk wrapper scripts in `cmake/` plus shared run configurations in `.run/`.
Expand Down Expand Up @@ -184,8 +215,8 @@ scripts\setup-xemu.cmd --skip-support-files
- [x] Automatically run built xiso in Xemu
- [x] Add unit testing framework
- [x] Separate main build and unit test builds, due to cross compiling, see https://stackoverflow.com/a/64335131/11214013
- [ ] Get tests to properly compile
- [ ] Enable codecov
- [x] Get tests to properly compile
- [x] Enable codecov
- [x] Enable sonarcloud
- [x] Build moonlight-common-c
- [x] Build custom enet
Expand Down
6 changes: 4 additions & 2 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// nxdk includes
#include <windows.h>

// local includes
#include "src/nxdk/windows.h"
#include "src/splash/splash_screen.h"
#include "src/startup/memory_stats.h"
#include "src/startup/video_mode.h"
Expand All @@ -13,7 +15,7 @@ int main() {
startup::log_video_modes(videoModeSelection);
startup::log_memory_statistics();

Sleep(10000);
Sleep(4000);

XVideoSetMode(bestVideoMode.width, bestVideoMode.height, bestVideoMode.bpp, bestVideoMode.refresh);

Expand Down
6 changes: 0 additions & 6 deletions src/nxdk/hal/debug.h

This file was deleted.

7 changes: 0 additions & 7 deletions src/nxdk/hal/video.h

This file was deleted.

6 changes: 0 additions & 6 deletions src/nxdk/hal/xbox.h

This file was deleted.

6 changes: 0 additions & 6 deletions src/nxdk/windows.h

This file was deleted.

10 changes: 3 additions & 7 deletions src/os.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
#pragma once
#if defined(NXDK)
#define PATH_SEP "\\"
#define DATA_PATH "D:" PATH_SEP
#else
#define PATH_SEP "/"
#define DATA_PATH "." PATH_SEP
#endif

inline constexpr auto PATH_SEP = "\\";
inline constexpr auto DATA_PATH = "D:\\";
67 changes: 67 additions & 0 deletions src/splash/splash_layout.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#include "src/splash/splash_layout.h"

#include <algorithm>
#include <cmath>

namespace {

constexpr float SPLASH_LOGO_MAX_WIDTH_RATIO = 0.72f;
constexpr float SPLASH_LOGO_MAX_HEIGHT_RATIO = 0.32f;
constexpr float SPLASH_ASPECT_RATIO_EPSILON = 0.05f;

int clamp_scaled_dimension(float value) {
if (const auto scaledValue = static_cast<int>(value); scaledValue > 0) {
return scaledValue;
}

return 1;
}

} // namespace

namespace splash {

float get_framebuffer_aspect_ratio(const VIDEO_MODE &videoMode) {
return static_cast<float>(videoMode.width) / static_cast<float>(videoMode.height);
}

float get_display_aspect_ratio(const VIDEO_MODE &videoMode, unsigned long encoderSettings) {
const float framebufferAspectRatio = get_framebuffer_aspect_ratio(videoMode);
const float preferredDisplayAspectRatio = ((encoderSettings & VIDEO_WIDESCREEN) != 0UL) ? (16.0f / 9.0f) : (4.0f / 3.0f);
const bool isStandardDefinitionRaster = videoMode.height <= 576;

if (const bool needsAspectCorrection = isStandardDefinitionRaster && std::fabs(framebufferAspectRatio - preferredDisplayAspectRatio) > SPLASH_ASPECT_RATIO_EPSILON) {
return preferredDisplayAspectRatio;
}

return framebufferAspectRatio;
}

float get_logo_width_aspect_correction(const VIDEO_MODE &videoMode, unsigned long encoderSettings) {
return get_framebuffer_aspect_ratio(videoMode) / get_display_aspect_ratio(videoMode, encoderSettings);
}

SplashLayout calculate_logo_destination(
int screenWidth,
int screenHeight,
int logoWidth,
int logoHeight,
const VIDEO_MODE &videoMode,
unsigned long encoderSettings
) {
const float correctedLogoWidth = static_cast<float>(logoWidth) * get_logo_width_aspect_correction(videoMode, encoderSettings);
const float maxLogoWidth = static_cast<float>(screenWidth) * SPLASH_LOGO_MAX_WIDTH_RATIO;
const float maxLogoHeight = static_cast<float>(screenHeight) * SPLASH_LOGO_MAX_HEIGHT_RATIO;
const float widthScale = maxLogoWidth / correctedLogoWidth;
const float heightScale = maxLogoHeight / static_cast<float>(logoHeight);
const float scale = std::min(widthScale, heightScale);

SplashLayout layout {};
layout.width = clamp_scaled_dimension(correctedLogoWidth * scale);
layout.height = clamp_scaled_dimension(static_cast<float>(logoHeight) * scale);
layout.x = (screenWidth - layout.width) / 2;
layout.y = (screenHeight - layout.height) / 2;
return layout;
}

} // namespace splash
Loading
Loading