Compare commits
59 Commits
Author | SHA1 | Date | |
---|---|---|---|
74acbd9a5a | |||
25d1ec1789 | |||
97b46ad01a | |||
17d11647e7 | |||
48137f9665 | |||
c956151603 | |||
73b51be43f | |||
71b11b314b | |||
168b825bf4 | |||
edca3ad394 | |||
1aed33a48b | |||
177c5262a6 | |||
7969fb2127 | |||
b0aac13057 | |||
80c0f24a5d | |||
0f9da6148b | |||
ea48728a68 | |||
3e7037f621 | |||
11230c120d | |||
1f05424651 | |||
98db527a13 | |||
85e04fbcc6 | |||
018e506c80 | |||
945ce81fe1 | |||
fab66319ea | |||
99424546f8 | |||
cef22a5325 | |||
67ef365505 | |||
588eb5feb0 | |||
c711c8b019 | |||
864c096785 | |||
9ef0868889 | |||
5b792fbf3a | |||
c908d46d54 | |||
db03d964de | |||
c0cd9b8b1f | |||
a8835153b0 | |||
e1f2867d78 | |||
7a5fef7024 | |||
da9edee160 | |||
9e517f5e60 | |||
85e3cb6228 | |||
1dd0526197 | |||
7ecc6cb00b | |||
4189f3fd1d | |||
de18189b44 | |||
a622858a18 | |||
b005106b44 | |||
61add936cc | |||
d3b78acbef | |||
07a27d4dd9 | |||
6779905830 | |||
c3fda82642 | |||
e0ab968fa3 | |||
45b93534fa | |||
5273d6cdf9 | |||
06af8c821f | |||
7b4729b8ec | |||
ffad36224e |
94
.gitea/workflows/build.yml
Normal file
94
.gitea/workflows/build.yml
Normal file
|
@ -0,0 +1,94 @@
|
|||
name: 'Build'
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
tags:
|
||||
- '*'
|
||||
- '!flatpak'
|
||||
|
||||
jobs:
|
||||
# Build Project
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
mode:
|
||||
- Client
|
||||
- Server
|
||||
arch:
|
||||
- AMD64
|
||||
- ARM64
|
||||
- ARMHF
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
container: node:16-buster
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
# Dependencies
|
||||
- name: Install CMake
|
||||
run: |
|
||||
echo 'deb http://deb.debian.org/debian buster-backports main' > /etc/apt/sources.list.d/backports.list
|
||||
apt-get update
|
||||
apt-get install --no-install-recommends -y -t buster-backports cmake
|
||||
- name: Install Dependencies
|
||||
run: ./scripts/install-dependencies.sh ${{ matrix.arch }}
|
||||
# Build
|
||||
- name: Build
|
||||
run: ./scripts/package.sh ${{ matrix.mode }} ${{ matrix.arch }}
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ matrix.mode }}-${{ matrix.arch }}
|
||||
path: ./out/*.AppImage*
|
||||
# Test Project
|
||||
test:
|
||||
name: Test
|
||||
runs-on: ubuntu-latest
|
||||
container: node:16-buster
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
# Dependencies
|
||||
- name: Install CMake
|
||||
run: |
|
||||
echo 'deb http://deb.debian.org/debian buster-backports main' > /etc/apt/sources.list.d/backports.list
|
||||
apt-get update
|
||||
apt-get install --no-install-recommends -y -t buster-backports cmake
|
||||
- name: Install Dependencies
|
||||
run: ./scripts/install-dependencies.sh
|
||||
# Test
|
||||
- name: Test
|
||||
run: ./scripts/test.sh
|
||||
# Create Release
|
||||
release:
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
needs: build
|
||||
name: Release
|
||||
runs-on: ubuntu-latest
|
||||
container: node:16-buster
|
||||
steps:
|
||||
# Dependencies
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '>=1.20.1'
|
||||
# Download Artifacts
|
||||
- name: Download Artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
path: out
|
||||
# Create Release
|
||||
- name: Create Release
|
||||
uses: https://gitea.com/actions/release-action@main
|
||||
with:
|
||||
files: ./out
|
||||
api_key: ${{ secrets.RELEASE_TOKEN }}
|
||||
title: v${{ github.ref_name }}
|
||||
body: "[View Changelog](https://gitea.thebrokenrail.com/minecraft-pi-reborn/minecraft-pi-reborn/src/branch/master/docs/CHANGELOG.md)"
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -12,3 +12,4 @@
|
|||
/*.AppImage
|
||||
/core*
|
||||
/qemu_*
|
||||
/data
|
||||
|
|
25
.gitmodules
vendored
25
.gitmodules
vendored
|
@ -1,12 +1,5 @@
|
|||
[submodule "dependencies/libpng/src"]
|
||||
path = dependencies/libpng/src
|
||||
url = https://gitea.thebrokenrail.com/minecraft-pi-reborn/libpng.git
|
||||
[submodule "dependencies/zlib/src"]
|
||||
path = dependencies/libpng/zlib/src
|
||||
url = https://github.com/madler/zlib.git
|
||||
ignore = dirty
|
||||
[submodule "dependencies/glfw/src"]
|
||||
path = media-layer/core/dependencies/glfw/src
|
||||
path = dependencies/glfw/src
|
||||
url = https://github.com/glfw/glfw.git
|
||||
[submodule "dependencies/zenity/src"]
|
||||
path = dependencies/zenity/src
|
||||
|
@ -14,7 +7,15 @@
|
|||
[submodule "dependencies/LIEF/src"]
|
||||
path = dependencies/LIEF/src
|
||||
url = https://github.com/lief-project/LIEF.git
|
||||
[submodule "dependencies/qemu/src"]
|
||||
path = dependencies/qemu/src
|
||||
url = https://gitlab.com/qemu-project/qemu.git
|
||||
ignore = dirty
|
||||
[submodule "media-layer/core/gles/dependencies/gles-compatibility-layer"]
|
||||
path = dependencies/gles-compatibility-layer/src
|
||||
url = https://gitea.thebrokenrail.com/minecraft-pi-reborn/gles-compatibility-layer.git
|
||||
[submodule "dependencies/stb_image/include"]
|
||||
path = dependencies/stb_image/include
|
||||
url = https://github.com/nothings/stb.git
|
||||
[submodule "dependencies/utf8cpp/src"]
|
||||
path = dependencies/utf8cpp/src
|
||||
url = https://github.com/nemtrif/utfcpp.git
|
||||
[submodule "archives"]
|
||||
path = archives
|
||||
url = https://gitea.thebrokenrail.com/minecraft-pi-reborn/archives.git
|
||||
|
|
|
@ -22,6 +22,7 @@ endif()
|
|||
option(MCPI_IS_MIXED_BUILD "Whether The Architecture-Independent And ARM Code Are Different Architecture" FALSE)
|
||||
option(MCPI_OPEN_SOURCE_ONLY "Only Install Open-Source Code (Will Result In Broken Install)" FALSE)
|
||||
option(MCPI_IS_APPIMAGE_BUILD "AppImage Build" FALSE)
|
||||
option(MCPI_IS_FLATPAK_BUILD "Flatpak Build" FALSE)
|
||||
|
||||
# Server/Headless Builds
|
||||
option(MCPI_SERVER_MODE "Server Mode" FALSE)
|
||||
|
@ -37,6 +38,11 @@ option(MCPI_USE_MEDIA_LAYER_PROXY "Whether To Enable The Media Layer Proxy" ${DE
|
|||
if(NOT MCPI_HEADLESS_MODE)
|
||||
option(MCPI_USE_GLES1_COMPATIBILITY_LAYER "Whether To Enable The GLESv1_CM Compatibility Layer" TRUE)
|
||||
endif()
|
||||
if(MCPI_USE_MEDIA_LAYER_PROXY)
|
||||
set(BUILD_MEDIA_LAYER_CORE "${BUILD_NATIVE_COMPONENTS}")
|
||||
else()
|
||||
set(BUILD_MEDIA_LAYER_CORE "${BUILD_ARM_COMPONENTS}")
|
||||
endif()
|
||||
|
||||
# App ID
|
||||
set(DEFAULT_APP_ID "com.thebrokenrail.MCPIReborn")
|
||||
|
@ -65,6 +71,9 @@ else()
|
|||
string(APPEND MCPI_VARIANT_NAME "-client")
|
||||
endif()
|
||||
|
||||
# Skin Server
|
||||
set(MCPI_SKIN_SERVER "https://raw.githubusercontent.com/MCPI-Revival/Skins/data" CACHE STRING "Skin Server")
|
||||
|
||||
# Specify Installation Paths
|
||||
set(MCPI_INSTALL_DIR "lib/${MCPI_VARIANT_NAME}")
|
||||
set(MCPI_BIN_DIR "${MCPI_INSTALL_DIR}/bin")
|
||||
|
@ -105,22 +114,32 @@ project(minecraft-pi-reborn)
|
|||
include(cmake/util.cmake)
|
||||
|
||||
# Sanity Checks
|
||||
set(IS_ARM_TARGETING FALSE)
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "armv7l")
|
||||
set(IS_ARM_TARGETING TRUE)
|
||||
string(CONCAT ARM_SANITY_CHECK
|
||||
"set(IS_ARM_TARGETING FALSE)\n"
|
||||
"if(CMAKE_SYSTEM_PROCESSOR STREQUAL \"arm\" OR CMAKE_SYSTEM_PROCESSOR STREQUAL \"armv7l\")\n"
|
||||
" set(IS_ARM_TARGETING TRUE)\n"
|
||||
"endif()"
|
||||
)
|
||||
if(BUILD_ARM_COMPONENTS)
|
||||
string(CONCAT ARM_SANITY_CHECK
|
||||
"${ARM_SANITY_CHECK}\n"
|
||||
"if(NOT IS_ARM_TARGETING)\n"
|
||||
" message(FATAL_ERROR \"ARM-Targeting Compiler Required\")\n"
|
||||
"endif()"
|
||||
)
|
||||
endif()
|
||||
cmake_language(EVAL CODE "${ARM_SANITY_CHECK}")
|
||||
if(BUILD_NATIVE_COMPONENTS AND NOT IS_ARM_TARGETING AND NOT MCPI_IS_MIXED_BUILD)
|
||||
message(FATAL_ERROR "Project is configured as a mixed-buld, but MCPI_IS_MIXED_BUILD is disabled.")
|
||||
endif()
|
||||
if(BUILD_ARM_COMPONENTS AND NOT IS_ARM_TARGETING)
|
||||
message(FATAL_ERROR "ARM-Targeting Compiler Required")
|
||||
endif()
|
||||
|
||||
# Specify Default Installation Prefix
|
||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
set(DEFAULT_PREFIX "/usr")
|
||||
if(MCPI_IS_APPIMAGE_BUILD)
|
||||
set(DEFAULT_PREFIX "/")
|
||||
elseif(MCPI_IS_FLATPAK_BUILD)
|
||||
set(DEFAULT_PREFIX "/app")
|
||||
endif()
|
||||
set(CMAKE_INSTALL_PREFIX "${DEFAULT_PREFIX}" CACHE PATH "" FORCE)
|
||||
set(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT FALSE)
|
||||
|
@ -210,6 +229,8 @@ if(BUILD_ARM_COMPONENTS)
|
|||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/sdk.cmake"
|
||||
# Compile Flags
|
||||
"${COMPILE_FLAGS_SETUP}\n"
|
||||
# Snaity Check
|
||||
"${ARM_SANITY_CHECK}\n"
|
||||
# Log
|
||||
"message(STATUS \"Using Reborn SDK v${MCPI_VERSION}\")\n"
|
||||
# Include Targets
|
||||
|
|
19
Dockerfile
19
Dockerfile
|
@ -1,19 +0,0 @@
|
|||
FROM debian:bullseye-slim
|
||||
|
||||
# Install
|
||||
RUN \
|
||||
apt-get update && \
|
||||
apt-get install -y tini qemu-user && \
|
||||
apt-get --fix-broken install -y && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Copy
|
||||
ADD ./out/server-amd64 /app
|
||||
|
||||
# Setup Working Directory
|
||||
RUN mkdir /data
|
||||
WORKDIR /data
|
||||
|
||||
# Setup Entrypoint
|
||||
ENTRYPOINT ["/usr/bin/tini", "--"]
|
||||
CMD ["/app/usr/bin/minecraft-pi-reborn-server"]
|
30
Dockerfile.server
Normal file
30
Dockerfile.server
Normal file
|
@ -0,0 +1,30 @@
|
|||
FROM debian:buster as builder
|
||||
ADD . .
|
||||
RUN echo 'deb http://deb.debian.org/debian buster-backports main' > /etc/apt/sources.list.d/backports.list && apt-get update && apt-get install --no-install-recommends -y -t buster-backports cmake dpkg-dev wget
|
||||
RUN ./scripts/install-dependencies.sh
|
||||
ARG TARGETARCH
|
||||
#Build
|
||||
#If build fails past this stage, you're probably missing the repository submodules
|
||||
RUN ./scripts/setup.sh server $TARGETARCH
|
||||
RUN ./scripts/build.sh server $TARGETARCH
|
||||
|
||||
FROM debian:bullseye-slim as runtime
|
||||
|
||||
# Install
|
||||
RUN \
|
||||
apt-get update && \
|
||||
apt-get install -y tini qemu-user && \
|
||||
apt-get --fix-broken install -y && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
ARG TARGETARCH
|
||||
# Copy
|
||||
COPY --from=builder ./out/server-$TARGETARCH /app
|
||||
|
||||
# Setup Working Directory
|
||||
RUN mkdir /data
|
||||
WORKDIR /data
|
||||
|
||||
EXPOSE 19132/udp
|
||||
# Setup Entrypoint
|
||||
ENTRYPOINT ["/usr/bin/tini", "--"]
|
||||
CMD ["/app/usr/bin/minecraft-pi-reborn-server"]
|
37
Jenkinsfile
vendored
37
Jenkinsfile
vendored
|
@ -1,37 +0,0 @@
|
|||
pipeline {
|
||||
agent none
|
||||
stages {
|
||||
stage('Debian Buster') {
|
||||
agent {
|
||||
dockerfile {
|
||||
filename 'scripts/ci/Dockerfile'
|
||||
args '-v /var/run/docker.sock:/var/run/docker.sock --network host'
|
||||
}
|
||||
}
|
||||
stages {
|
||||
stage('Build') {
|
||||
steps {
|
||||
sh './scripts/ci/run.sh'
|
||||
}
|
||||
post {
|
||||
success {
|
||||
archiveArtifacts artifacts: 'out/*.AppImage*', fingerprint: true
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Publish') {
|
||||
steps {
|
||||
sh 'apt-get update && apt-get install -y docker.io'
|
||||
sh 'rm -rf ./out/server-amd64'
|
||||
sh './scripts/build.sh server amd64'
|
||||
sh 'docker build --no-cache --tag thebrokenrail/minecraft-pi-reborn-server .'
|
||||
withCredentials([usernamePassword(credentialsId: 'docker_hub_login', usernameVariable: 'DOCKER_HUB_USERNAME', passwordVariable: 'DOCKER_HUB_PASSWORD')]) {
|
||||
sh 'docker login -u "${DOCKER_HUB_USERNAME}" -p "${DOCKER_HUB_PASSWORD}"'
|
||||
}
|
||||
sh 'docker push thebrokenrail/minecraft-pi-reborn-server'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1
archives
Submodule
1
archives
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit f878bb1299f3c9506737f311cb01749e41e3f9dd
|
|
@ -1,25 +1,21 @@
|
|||
# Pick URL
|
||||
# Pick Archive
|
||||
set(toolchain_version "13.2.rel1")
|
||||
execute_process(COMMAND uname -m OUTPUT_VARIABLE arch OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(arch STREQUAL "x86_64")
|
||||
set(toolchain_url "https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-arm-none-linux-gnueabihf.tar.xz")
|
||||
set(toolchain_sha256 "aa074fa8371a4f73fecbd16bd62c8b1945f23289e26414794f130d6ccdf8e39c")
|
||||
set(toolchain_file "arm-gnu-toolchain-${toolchain_version}-x86_64-arm-none-linux-gnueabihf.tar.xz")
|
||||
elseif(arch STREQUAL "aarch64" OR arch STREQUAL "armv8b" OR arch STREQUAL "armv8l")
|
||||
set(toolchain_url "https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-aarch64-arm-none-linux-gnueabihf.tar.xz")
|
||||
set(toolchain_sha256 "fccd7af76988da2b077f939eb2a78baa9935810918d2bf3f837bc74f52efa825")
|
||||
set(toolchain_file "arm-gnu-toolchain-${toolchain_version}-aarch64-arm-none-linux-gnueabihf.tar.xz")
|
||||
else()
|
||||
message(FATAL_ERROR "Unable To Download Prebuilt ARMHF Toolchain")
|
||||
endif()
|
||||
|
||||
# Download If Needed
|
||||
include(FetchContent)
|
||||
set(FETCHCONTENT_QUIET FALSE)
|
||||
FetchContent_Declare(
|
||||
prebuilt-armhf-toolchain
|
||||
URL "${toolchain_url}"
|
||||
URL_HASH "SHA256=${toolchain_sha256}"
|
||||
URL "file://${CMAKE_CURRENT_LIST_DIR}/../archives/${toolchain_file}"
|
||||
)
|
||||
FetchContent_MakeAvailable(prebuilt-armhf-toolchain)
|
||||
set(FETCHCONTENT_QUIET TRUE)
|
||||
set(toolchain_dir "${prebuilt-armhf-toolchain_SOURCE_DIR}")
|
||||
|
||||
# Force Toolchain
|
||||
|
@ -50,6 +46,7 @@ if("${toolchain_dir}/bin/arm-none-linux-gnueabihf-gcc" IS_NEWER_THAN "${sysroot_
|
|||
|
||||
# Delete Unneeded Files
|
||||
file(REMOVE_RECURSE "${sysroot_dir}/usr/lib/audit")
|
||||
file(REMOVE_RECURSE "${sysroot_dir}/usr/lib/gconv")
|
||||
|
||||
# Strip Files
|
||||
file(GLOB_RECURSE files LIST_DIRECTORIES FALSE "${sysroot_dir}/*")
|
||||
|
@ -61,13 +58,6 @@ if("${toolchain_dir}/bin/arm-none-linux-gnueabihf-gcc" IS_NEWER_THAN "${sysroot_
|
|||
file(REMOVE "${file}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Setup gconv
|
||||
file(
|
||||
COPY "${toolchain_dir}/arm-none-linux-gnueabihf/libc/usr/lib/gconv/gconv-modules"
|
||||
DESTINATION "${sysroot_dir}/usr/lib/gconv"
|
||||
USE_SOURCE_PERMISSIONS
|
||||
)
|
||||
endif()
|
||||
|
||||
# Install Sysroot (Skipping Empty Directories)
|
||||
|
|
23
compose.yml
Normal file
23
compose.yml
Normal file
|
@ -0,0 +1,23 @@
|
|||
name: minecraft-pi-reborn
|
||||
services:
|
||||
server:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.server
|
||||
image: thebrokenrail/minecraft-pi-reborn-server
|
||||
networks:
|
||||
default: null
|
||||
ports:
|
||||
- mode: ingress
|
||||
target: 19132
|
||||
published: "19132"
|
||||
protocol: udp
|
||||
volumes:
|
||||
- type: bind
|
||||
source: ./data
|
||||
target: /data
|
||||
bind:
|
||||
create_host_path: true
|
||||
networks:
|
||||
default:
|
||||
name: minecraft-pi-reborn_default
|
16
dependencies/CMakeLists.txt
vendored
16
dependencies/CMakeLists.txt
vendored
|
@ -1,8 +1,8 @@
|
|||
project(dependencies)
|
||||
|
||||
# LibPNG
|
||||
if(BUILD_ARM_COMPONENTS)
|
||||
add_subdirectory(libpng)
|
||||
# stb_image
|
||||
if(BUILD_ARM_COMPONENTS AND NOT MCPI_HEADLESS_MODE)
|
||||
add_subdirectory(stb_image)
|
||||
endif()
|
||||
# Minecraft: Pi Edition
|
||||
if(BUILD_ARM_COMPONENTS AND NOT MCPI_OPEN_SOURCE_ONLY)
|
||||
|
@ -20,3 +20,13 @@ endif()
|
|||
if(BUILD_NATIVE_COMPONENTS AND NOT (CMAKE_SYSTEM_PROCESSOR MATCHES "arm*" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64"))
|
||||
add_subdirectory(qemu)
|
||||
endif()
|
||||
# GLFW
|
||||
if(BUILD_MEDIA_LAYER_CORE AND NOT MCPI_HEADLESS_MODE)
|
||||
add_subdirectory(glfw)
|
||||
endif()
|
||||
# GLES Compatibility Layer
|
||||
if(BUILD_MEDIA_LAYER_CORE AND NOT MCPI_HEADLESS_MODE AND MCPI_USE_GLES1_COMPATIBILITY_LAYER)
|
||||
add_subdirectory(gles-compatibility-layer)
|
||||
endif()
|
||||
# UTF8-CPP
|
||||
add_subdirectory(utf8cpp)
|
||||
|
|
2
dependencies/LIEF/src
vendored
2
dependencies/LIEF/src
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 2169578d46934c973fdbfa2fae23b192e3cac8a0
|
||||
Subproject commit 2d9855fc7f9d4ce6325245f8b75c98eb7663db60
|
7
dependencies/gles-compatibility-layer/CMakeLists.txt
vendored
Normal file
7
dependencies/gles-compatibility-layer/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
project(gles-compatibility-layer)
|
||||
|
||||
# GLES Compatibility Layer
|
||||
set(GLES_COMPATIBILITY_LAYER_USE_ES3 FALSE CACHE BOOL "" FORCE)
|
||||
set(GLES_COMPATIBILITY_LAYER_USE_SDL FALSE CACHE BOOL "" FORCE)
|
||||
set(GLES_COMPATIBILITY_LAYER_DEPENDENCY glfw CACHE STRING "" FORCE)
|
||||
add_subdirectory(src)
|
1
dependencies/gles-compatibility-layer/src
vendored
Submodule
1
dependencies/gles-compatibility-layer/src
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 5bf535a68fe1ca0381b4628859e642b40a166017
|
|
@ -21,20 +21,8 @@ add_subdirectory(src EXCLUDE_FROM_ALL)
|
|||
# Ensure Build
|
||||
add_custom_target(glfw-build ALL DEPENDS glfw)
|
||||
|
||||
# Remove When glfw/glfw#2192 Is Merged
|
||||
target_compile_definitions(glfw PRIVATE -D_GLFW_LINUX_JOYSTICK)
|
||||
# Remove When glfw/glfw#2198 Is Merged
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/publicize-glfw-symbol.h"
|
||||
"#pragma once\n"
|
||||
"extern __attribute__((visibility(\"default\"))) void _glfwDetectJoystickConnectionLinux(void);\n"
|
||||
)
|
||||
target_compile_options(glfw PRIVATE -include PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/publicize-glfw-symbol.h")
|
||||
|
||||
# Install
|
||||
install(TARGETS glfw DESTINATION "${MCPI_LIB_DIR}")
|
||||
if(BUILD_ARM_COMPONENTS)
|
||||
install(TARGETS glfw EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}")
|
||||
endif()
|
||||
|
||||
# License
|
||||
install(FILES src/LICENSE.md DESTINATION "${MCPI_LEGAL_DIR}/glfw")
|
1
dependencies/glfw/src
vendored
Submodule
1
dependencies/glfw/src
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 3eaf1255b29fdf5c2895856c7be7d7185ef2b241
|
33
dependencies/libpng/CMakeLists.txt
vendored
33
dependencies/libpng/CMakeLists.txt
vendored
|
@ -1,33 +0,0 @@
|
|||
project(libpng)
|
||||
|
||||
# ZLib (Needed By libpng)
|
||||
add_subdirectory(zlib)
|
||||
|
||||
# Silence Warnings
|
||||
add_compile_options(-w)
|
||||
|
||||
## LibPNG
|
||||
|
||||
# Options
|
||||
set(PNG_TESTS FALSE CACHE BOOL "" FORCE)
|
||||
set(PNG_NO_STDIO FALSE CACHE BOOL "" FORCE)
|
||||
set(PNG_BUILD_ZLIB TRUE CACHE BOOL "" FORCE)
|
||||
|
||||
# Download
|
||||
set(ZLIB_LIBRARY zlibstatic)
|
||||
set(ZLIB_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/zlib/src" "${CMAKE_CURRENT_BINARY_DIR}/zlib/src")
|
||||
add_subdirectory(src EXCLUDE_FROM_ALL)
|
||||
|
||||
# Use Symbol Versioning
|
||||
set_target_properties(png12 PROPERTIES LINK_OPTIONS "LINKER:--version-script=${CMAKE_CURRENT_SOURCE_DIR}/libpng.vers")
|
||||
|
||||
# Ensure Build
|
||||
add_custom_target(png12-build ALL DEPENDS png12)
|
||||
# Install
|
||||
install(TARGETS png12 DESTINATION "${MCPI_LIB_DIR}")
|
||||
if(BUILD_ARM_COMPONENTS)
|
||||
install(TARGETS png12 zlibstatic EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}")
|
||||
endif()
|
||||
|
||||
# License
|
||||
install(FILES src/LICENSE DESTINATION "${MCPI_LEGAL_DIR}/libpng")
|
208
dependencies/libpng/libpng.vers
vendored
208
dependencies/libpng/libpng.vers
vendored
|
@ -1,208 +0,0 @@
|
|||
PNG12_0 {global:
|
||||
png_libpng_ver;
|
||||
png_pass_start;
|
||||
png_pass_inc;
|
||||
png_pass_ystart;
|
||||
png_pass_yinc;
|
||||
png_pass_mask;
|
||||
png_pass_dsp_mask;
|
||||
png_access_version_number;
|
||||
png_set_sig_bytes;
|
||||
png_sig_cmp;
|
||||
png_check_sig;
|
||||
png_create_read_struct;
|
||||
png_create_write_struct;
|
||||
png_get_compression_buffer_size;
|
||||
png_set_compression_buffer_size;
|
||||
png_reset_zstream;
|
||||
png_create_read_struct_2;
|
||||
png_create_write_struct_2;
|
||||
png_write_chunk;
|
||||
png_write_chunk_start;
|
||||
png_write_chunk_data;
|
||||
png_write_chunk_end;
|
||||
png_create_info_struct;
|
||||
png_info_init;
|
||||
png_info_init_3;
|
||||
png_write_info_before_PLTE;
|
||||
png_write_info;
|
||||
png_read_info;
|
||||
png_convert_to_rfc1123;
|
||||
png_convert_from_struct_tm;
|
||||
png_convert_from_time_t;
|
||||
png_set_expand;
|
||||
png_set_expand_gray_1_2_4_to_8;
|
||||
png_set_palette_to_rgb;
|
||||
png_set_tRNS_to_alpha;
|
||||
png_set_gray_1_2_4_to_8;
|
||||
png_set_bgr;
|
||||
png_set_gray_to_rgb;
|
||||
png_set_rgb_to_gray;
|
||||
png_set_rgb_to_gray_fixed;
|
||||
png_get_rgb_to_gray_status;
|
||||
png_build_grayscale_palette;
|
||||
png_set_strip_alpha;
|
||||
png_set_swap_alpha;
|
||||
png_set_invert_alpha;
|
||||
png_set_filler;
|
||||
png_set_add_alpha;
|
||||
png_set_swap;
|
||||
png_set_packing;
|
||||
png_set_packswap;
|
||||
png_set_shift;
|
||||
png_set_interlace_handling;
|
||||
png_set_invert_mono;
|
||||
png_set_background;
|
||||
png_set_strip_16;
|
||||
png_set_dither;
|
||||
png_set_gamma;
|
||||
png_permit_empty_plte;
|
||||
png_set_flush;
|
||||
png_write_flush;
|
||||
png_start_read_image;
|
||||
png_read_update_info;
|
||||
png_read_rows;
|
||||
png_read_row;
|
||||
png_read_image;
|
||||
png_write_row;
|
||||
png_write_rows;
|
||||
png_write_image;
|
||||
png_write_end;
|
||||
png_read_end;
|
||||
png_destroy_info_struct;
|
||||
png_destroy_read_struct;
|
||||
png_destroy_write_struct;
|
||||
png_set_crc_action;
|
||||
png_set_filter;
|
||||
png_set_filter_heuristics;
|
||||
png_set_compression_level;
|
||||
png_set_compression_mem_level;
|
||||
png_set_compression_strategy;
|
||||
png_set_compression_window_bits;
|
||||
png_set_compression_method;
|
||||
png_init_io;
|
||||
png_set_error_fn;
|
||||
png_get_error_ptr;
|
||||
png_set_write_fn;
|
||||
png_set_read_fn;
|
||||
png_get_io_ptr;
|
||||
png_set_read_status_fn;
|
||||
png_set_write_status_fn;
|
||||
png_set_mem_fn;
|
||||
png_get_mem_ptr;
|
||||
png_set_read_user_transform_fn;
|
||||
png_set_write_user_transform_fn;
|
||||
png_set_user_transform_info;
|
||||
png_get_user_transform_ptr;
|
||||
png_set_read_user_chunk_fn;
|
||||
png_get_user_chunk_ptr;
|
||||
png_set_progressive_read_fn;
|
||||
png_get_progressive_ptr;
|
||||
png_process_data;
|
||||
png_progressive_combine_row;
|
||||
png_malloc;
|
||||
png_malloc_warn;
|
||||
png_free;
|
||||
png_free_data;
|
||||
png_data_freer;
|
||||
png_malloc_default;
|
||||
png_free_default;
|
||||
png_memcpy_check;
|
||||
png_memset_check;
|
||||
png_error;
|
||||
png_chunk_error;
|
||||
png_warning;
|
||||
png_chunk_warning;
|
||||
png_get_valid;
|
||||
png_get_rowbytes;
|
||||
png_get_rows;
|
||||
png_set_rows;
|
||||
png_get_channels;
|
||||
png_get_image_width;
|
||||
png_get_image_height;
|
||||
png_get_bit_depth;
|
||||
png_get_color_type;
|
||||
png_get_filter_type;
|
||||
png_get_interlace_type;
|
||||
png_get_compression_type;
|
||||
png_get_pixels_per_meter;
|
||||
png_get_x_pixels_per_meter;
|
||||
png_get_y_pixels_per_meter;
|
||||
png_get_pixel_aspect_ratio;
|
||||
png_get_x_offset_pixels;
|
||||
png_get_y_offset_pixels;
|
||||
png_get_x_offset_microns;
|
||||
png_get_y_offset_microns;
|
||||
png_get_signature;
|
||||
png_get_bKGD;
|
||||
png_set_bKGD;
|
||||
png_get_cHRM;
|
||||
png_get_cHRM_fixed;
|
||||
png_set_cHRM;
|
||||
png_set_cHRM_fixed;
|
||||
png_get_gAMA;
|
||||
png_get_gAMA_fixed;
|
||||
png_set_gAMA;
|
||||
png_set_gAMA_fixed;
|
||||
png_get_hIST;
|
||||
png_set_hIST;
|
||||
png_get_IHDR;
|
||||
png_set_IHDR;
|
||||
png_get_oFFs;
|
||||
png_set_oFFs;
|
||||
png_get_pCAL;
|
||||
png_set_pCAL;
|
||||
png_get_pHYs;
|
||||
png_set_pHYs;
|
||||
png_get_PLTE;
|
||||
png_set_PLTE;
|
||||
png_get_sBIT;
|
||||
png_set_sBIT;
|
||||
png_get_sRGB;
|
||||
png_set_sRGB;
|
||||
png_set_sRGB_gAMA_and_cHRM;
|
||||
png_get_iCCP;
|
||||
png_set_iCCP;
|
||||
png_get_sPLT;
|
||||
png_set_sPLT;
|
||||
png_get_text;
|
||||
png_set_text;
|
||||
png_get_tIME;
|
||||
png_set_tIME;
|
||||
png_get_tRNS;
|
||||
png_set_tRNS;
|
||||
png_get_sCAL;
|
||||
png_set_sCAL;
|
||||
png_set_keep_unknown_chunks;
|
||||
png_handle_as_unknown;
|
||||
png_set_unknown_chunks;
|
||||
png_set_unknown_chunk_location;
|
||||
png_get_unknown_chunks;
|
||||
png_set_invalid;
|
||||
png_read_png;
|
||||
png_write_png;
|
||||
png_get_copyright;
|
||||
png_get_header_ver;
|
||||
png_get_header_version;
|
||||
png_get_libpng_ver;
|
||||
png_permit_mng_features;
|
||||
png_get_mmx_flagmask;
|
||||
png_get_asm_flagmask;
|
||||
png_get_asm_flags;
|
||||
png_get_mmx_bitdepth_threshold;
|
||||
png_get_mmx_rowbytes_threshold;
|
||||
png_set_asm_flags;
|
||||
png_set_mmx_thresholds;
|
||||
png_mmx_support;
|
||||
png_set_strip_error_numbers;
|
||||
png_set_user_limits;
|
||||
png_get_user_width_max;
|
||||
png_get_user_height_max;
|
||||
png_get_uint_32;
|
||||
png_get_uint_16;
|
||||
png_get_int_32;
|
||||
png_get_uint_31;
|
||||
png_save_uint_32;
|
||||
png_save_int_32;
|
||||
png_save_uint_16;
|
||||
local: *; };
|
1
dependencies/libpng/src
vendored
1
dependencies/libpng/src
vendored
|
@ -1 +0,0 @@
|
|||
Subproject commit 6c445538879f9e916f8e62723d2ac7cd77d96191
|
16
dependencies/libpng/zlib/CMakeLists.txt
vendored
16
dependencies/libpng/zlib/CMakeLists.txt
vendored
|
@ -1,16 +0,0 @@
|
|||
project(zlib)
|
||||
|
||||
# Silence Warnings
|
||||
add_compile_options(-w)
|
||||
|
||||
## zlib
|
||||
|
||||
# Download
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0022 NEW) # Fix Error
|
||||
add_subdirectory(src EXCLUDE_FROM_ALL)
|
||||
|
||||
# Ensure Build
|
||||
add_custom_target(zlib-build ALL DEPENDS zlibstatic)
|
||||
|
||||
# License
|
||||
install(FILES src/LICENSE DESTINATION "${MCPI_LEGAL_DIR}/zlib")
|
1
dependencies/libpng/zlib/src
vendored
1
dependencies/libpng/zlib/src
vendored
|
@ -1 +0,0 @@
|
|||
Subproject commit 04f42ceca40f73e2978b50e93806c2a18c1281fc
|
8
dependencies/minecraft-pi/CMakeLists.txt
vendored
8
dependencies/minecraft-pi/CMakeLists.txt
vendored
|
@ -17,5 +17,13 @@ install(
|
|||
DESTINATION "${MCPI_INSTALL_DIR}/game"
|
||||
USE_SOURCE_PERMISSIONS
|
||||
REGEX "api" EXCLUDE
|
||||
REGEX "data" EXCLUDE
|
||||
)
|
||||
if(NOT MCPI_HEADLESS_MODE)
|
||||
install(
|
||||
DIRECTORY "${minecraft-pi_SOURCE_DIR}/data/"
|
||||
DESTINATION "${MCPI_INSTALL_DIR}/game/data"
|
||||
USE_SOURCE_PERMISSIONS
|
||||
)
|
||||
endif()
|
||||
install_symlink("game/minecraft-pi" "${MCPI_INSTALL_DIR}/minecraft-pi")
|
||||
|
|
15
dependencies/qemu/CMakeLists.txt
vendored
15
dependencies/qemu/CMakeLists.txt
vendored
|
@ -2,12 +2,21 @@ project(qemu)
|
|||
|
||||
## QEMU
|
||||
|
||||
# Version
|
||||
set(QEMU_VERSION "8.1.3")
|
||||
|
||||
# Flatpak Support
|
||||
set(QEMU_PATCH "")
|
||||
if(MCPI_IS_FLATPAK_BUILD)
|
||||
set(QEMU_PATCH "sed" "-i" "s/libdrm/libdrm-dis/g" "<SOURCE_DIR>/meson.build")
|
||||
endif()
|
||||
|
||||
# Build
|
||||
include(ProcessorCount)
|
||||
ProcessorCount(NPROC)
|
||||
include(ExternalProject)
|
||||
ExternalProject_Add(qemu
|
||||
SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src"
|
||||
URL "file://${CMAKE_CURRENT_SOURCE_DIR}/../../archives/qemu-${QEMU_VERSION}.tar.xz"
|
||||
CONFIGURE_COMMAND
|
||||
"${CMAKE_COMMAND}" "-E" "env"
|
||||
"PKG_CONFIG_LIBDIR=$ENV{PKG_CONFIG_LIBDIR}"
|
||||
|
@ -26,6 +35,7 @@ ExternalProject_Add(qemu
|
|||
USES_TERMINAL_BUILD TRUE
|
||||
INSTALL_COMMAND ""
|
||||
TEST_COMMAND ""
|
||||
PATCH_COMMAND ${QEMU_PATCH}
|
||||
BUILD_BYPRODUCTS "<BINARY_DIR>/qemu-arm"
|
||||
)
|
||||
|
||||
|
@ -34,4 +44,5 @@ ExternalProject_Get_property(qemu BINARY_DIR)
|
|||
install(PROGRAMS "${BINARY_DIR}/qemu-arm" DESTINATION "${MCPI_BIN_DIR}")
|
||||
|
||||
# License
|
||||
install(FILES src/COPYING DESTINATION "${MCPI_LEGAL_DIR}/qemu")
|
||||
ExternalProject_Get_property(qemu SOURCE_DIR)
|
||||
install(FILES "${SOURCE_DIR}/COPYING" DESTINATION "${MCPI_LEGAL_DIR}/qemu")
|
||||
|
|
1
dependencies/qemu/src
vendored
1
dependencies/qemu/src
vendored
|
@ -1 +0,0 @@
|
|||
Subproject commit 621da7789083b80d6f1ff1c0fb499334007b4f51
|
30
dependencies/stb_image/CMakeLists.txt
vendored
Normal file
30
dependencies/stb_image/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
project(stb_image)
|
||||
|
||||
# Silence Warnings
|
||||
add_compile_options(-w)
|
||||
|
||||
## stb_image
|
||||
|
||||
# Build
|
||||
add_library(stb_image SHARED src/stb_image_impl.c)
|
||||
target_include_directories(
|
||||
stb_image
|
||||
PUBLIC
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
|
||||
"$<INSTALL_INTERFACE:${MCPI_SDK_INCLUDE_DIR}/stb_image>"
|
||||
)
|
||||
target_link_libraries(stb_image PRIVATE m)
|
||||
target_compile_definitions(stb_image PUBLIC STBI_ONLY_PNG)
|
||||
|
||||
# Install
|
||||
install(TARGETS stb_image DESTINATION "${MCPI_LIB_DIR}")
|
||||
install(
|
||||
DIRECTORY "include/"
|
||||
DESTINATION "${MCPI_SDK_INCLUDE_DIR}/stb_image"
|
||||
FILES_MATCHING
|
||||
PATTERN "*.h"
|
||||
)
|
||||
install(TARGETS stb_image EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}")
|
||||
|
||||
# License
|
||||
install(FILES include/LICENSE DESTINATION "${MCPI_LEGAL_DIR}/stb_image")
|
1
dependencies/stb_image/include
vendored
Submodule
1
dependencies/stb_image/include
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit beebb24b945efdea3b9bba23affb8eb3ba8982e7
|
5
dependencies/stb_image/src/stb_image_impl.c
vendored
Normal file
5
dependencies/stb_image/src/stb_image_impl.c
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
|
||||
#include "stb_image.h"
|
||||
#include "stb_image_write.h"
|
12
dependencies/utf8cpp/CMakeLists.txt
vendored
Normal file
12
dependencies/utf8cpp/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
project(utf8cpp)
|
||||
|
||||
# Silence Warnings
|
||||
add_compile_options(-w)
|
||||
|
||||
## stb_image
|
||||
|
||||
# Build
|
||||
add_subdirectory(src EXCLUDE_FROM_ALL)
|
||||
|
||||
# License
|
||||
install(FILES src/LICENSE DESTINATION "${MCPI_LEGAL_DIR}/utf8cpp")
|
1
dependencies/utf8cpp/src
vendored
Submodule
1
dependencies/utf8cpp/src
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit f6780f77f6824aa0fbe69f9b97ef7d8aba26ed92
|
|
@ -29,7 +29,6 @@ This component configures the various environmental variables required for MCPI-
|
|||
The environmental variables configured by this component includes:
|
||||
* ``LD_PRELOAD``
|
||||
* ``LD_LIBRARY_PATH``
|
||||
* ``GCONV_PATH``
|
||||
* ``MCPI_FEATURE_FLAGS``
|
||||
* ``MCPI_RENDER_DISTANCE``
|
||||
* ``MCPI_USERNAME``
|
||||
|
|
|
@ -1,5 +1,37 @@
|
|||
# Changelog
|
||||
|
||||
**2.5.2**
|
||||
* Add ``3D Chest Model`` Feature Flag (Enabled By Default)
|
||||
* Stop Using Jenkins
|
||||
* Replace ``iconv``
|
||||
* Replace LibPNG
|
||||
|
||||
**2.5.1**
|
||||
* Allow Overriidng Custom Skin Server Using ``MCPI_SKIN_SERVER`` Environmental Variable
|
||||
* Fix Bug With SDK Generation
|
||||
|
||||
**2.5.0**
|
||||
* [Custom skin support](CUSTOM_SKINS.md)!
|
||||
* Add ``Load Custom Skins`` Feature Flag (Enabled By Default)
|
||||
|
||||
**2.4.9**
|
||||
* Allow Overriding GUI Scale With ``MCPI_GUI_SCALE`` Environmental Variable
|
||||
* Add ``Disable Block Tinting`` Feature Flag (Disabled By Default)
|
||||
* Add ``Disable Hostile AI In Creative Mode`` Feature Flag (Enabled By Default)
|
||||
* Allow Accessing Configuration At Runtime (Useful For Mods That Need To Support Multiple Versions)
|
||||
|
||||
**2.4.8**
|
||||
* Fix Bug In ``extract_from_bl_instruction``
|
||||
* Update LIEF And GLFW
|
||||
* Allow Mods To Access The Original GLFW Keycode For Key Events (But Better)
|
||||
* More Accurate Sound
|
||||
|
||||
**2.4.7**
|
||||
* Improve Server Performance
|
||||
* Add ``Add Biome Colors To Grass`` Feature Flag (Disabled By Default)
|
||||
* Add ``Generate Caves`` Feature Flag (Enabled By Default)
|
||||
* Allow Mods To Access The Original GLFW Keycode For Key Events
|
||||
|
||||
**2.4.6**
|
||||
* [Minimal Controller Support](CONTROLS.md)
|
||||
* Fix Holding Left-Click When Attacking
|
||||
|
|
6
docs/CUSTOM_SKINS.md
Normal file
6
docs/CUSTOM_SKINS.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
# Custom Skins
|
||||
MCPI-Reborn supports downloading custom skins from [a central skin server](https://github.com/MCPI-Revival/Skins). Skins are downloaded based on the current MCPI username.
|
||||
|
||||
This *does not* cache skins and *will not* work without internet access.
|
||||
|
||||
Custom skins can be disabled using the ``Load Custom Skins`` feature flag.
|
|
@ -9,11 +9,12 @@ This server is also compatible with MCPE Alpha v0.6.1[^1].
|
|||
To use, install and run ``minecraft-pi-reborn-server``. It will generate the world and ``server.properties`` in the current directory.
|
||||
|
||||
### Docker Image
|
||||
An official Docker image is also provided: [thebrokenrail/minecraft-pi-reborn-server](https://hub.docker.com/r/thebrokenrail/minecraft-pi-reborn-server).
|
||||
~~An official Docker image is also provided: [thebrokenrail/minecraft-pi-reborn-server](https://hub.docker.com/r/thebrokenrail/minecraft-pi-reborn-server).~~
|
||||
Use the provided Dockerfile.server at the root, there's a sample compose.yml file you can use with ``docker compose``
|
||||
|
||||
## Server Limitations
|
||||
* Player data is not saved because of limitations with MCPE LAN worlds
|
||||
* An easy workaround is to place your inventory in a chest before logging off
|
||||
* Player data is not saved because of limitations with MCPE LAN worlds (This means player position and inventory are both reset)
|
||||
* An easy workaround is to place your inventory in an easily reachable chest before logging off
|
||||
* Survival Mode servers are incompatible with unmodded MCPI
|
||||
|
||||
[^1]: The exception to this is buckets, those will crash MCPE players.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Installation
|
||||
|
||||
## AppImage
|
||||
Download packages [here](https://jenkins.thebrokenrail.com/job/minecraft-pi-reborn/job/master/lastSuccessfulBuild/artifact/out/).
|
||||
Download packages [here](https://gitea.thebrokenrail.com/minecraft-pi-reborn/minecraft-pi-reborn/releases).
|
||||
|
||||
### System Requirements
|
||||
* Debian Buster/Ubuntu 18.04 Or Higher
|
||||
|
@ -22,3 +22,6 @@ Follow [these](https://docs.appimage.org/introduction/quickstart.html#how-to-run
|
|||
|
||||
### Note
|
||||
Game data is stored in ``~/.var/app/com.thebrokenrail.MCPIReborn/.minecraft-pi`` instead of ``~/.minecraft-pi``.
|
||||
|
||||
## Arch User Repository (Arch Linux Only)
|
||||
The [``minecraft-pi-reborn-git``](https://aur.archlinux.org/packages/minecraft-pi-reborn-git) is available in the AUR.
|
||||
|
|
|
@ -10,4 +10,5 @@
|
|||
* [View Multiplayer](MULTIPLAYER.md)
|
||||
* [View Sound](SOUND.md)
|
||||
* [View In-Game Controls](CONTROLS.md)
|
||||
* [View Custom Skins](CUSTOM_SKINS.md)
|
||||
* [View Changelog](CHANGELOG.md)
|
||||
|
|
|
@ -9,6 +9,14 @@ if(NOT MCPI_HEADLESS_MODE)
|
|||
)
|
||||
endif()
|
||||
|
||||
# Chest Model
|
||||
if(NOT MCPI_HEADLESS_MODE)
|
||||
install(
|
||||
FILES "chest.png"
|
||||
DESTINATION "${MCPI_INSTALL_DIR}/data/images/item"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Icon
|
||||
install(
|
||||
FILES "icon.png"
|
||||
|
|
BIN
images/chest.png
Normal file
BIN
images/chest.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.8 KiB |
BIN
images/start.png
BIN
images/start.png
Binary file not shown.
Before Width: | Height: | Size: 155 KiB After Width: | Height: | Size: 164 KiB |
|
@ -1,7 +1,7 @@
|
|||
project(launcher)
|
||||
|
||||
# Launcher
|
||||
add_executable(launcher src/bootstrap.c src/patchelf.cpp src/crash-report.c)
|
||||
add_executable(launcher src/bootstrap.c src/patchelf.cpp src/util.c src/crash-report.c)
|
||||
if(MCPI_SERVER_MODE)
|
||||
target_sources(launcher PRIVATE src/server/launcher.c)
|
||||
else()
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "bootstrap.h"
|
||||
#include "patchelf.h"
|
||||
#include "crash-report.h"
|
||||
|
@ -88,6 +89,14 @@ static void load(char **ld_preload, char *folder) {
|
|||
#define MCPI_BINARY "minecraft-pi"
|
||||
#define QEMU_BINARY "qemu-arm"
|
||||
|
||||
#ifndef __ARM_ARCH
|
||||
#define USE_QEMU
|
||||
#endif
|
||||
|
||||
#define REQUIRED_PAGE_SIZE 4096
|
||||
#define _STR(x) #x
|
||||
#define STR(x) _STR(x)
|
||||
|
||||
// Exit Handler
|
||||
static void exit_handler(__attribute__((unused)) int signal_id) {
|
||||
// Pass Signal To Child
|
||||
|
@ -96,6 +105,45 @@ static void exit_handler(__attribute__((unused)) int signal_id) {
|
|||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
// Debug Information
|
||||
static void run_debug_command(const char *const command[], const char *prefix) {
|
||||
int status = 0;
|
||||
char *output = run_command(command, &status, NULL);
|
||||
if (output != NULL) {
|
||||
// Remove Newline
|
||||
size_t length = strlen(output);
|
||||
if (length > 0 && output[length - 1] == '\n') {
|
||||
output[length - 1] = '\0';
|
||||
}
|
||||
|
||||
// Print
|
||||
DEBUG("%s: %s", prefix, output);
|
||||
free(output);
|
||||
}
|
||||
if (!is_exit_status_success(status)) {
|
||||
ERR("Unable To Gather Debug Information");
|
||||
}
|
||||
}
|
||||
static void print_debug_information() {
|
||||
// System Information
|
||||
const char *const command[] = {"uname", "-a", NULL};
|
||||
run_debug_command(command, "System Information");
|
||||
|
||||
// Version
|
||||
DEBUG("Reborn Version: v%s", MCPI_VERSION);
|
||||
|
||||
// Architecture
|
||||
const char *arch = "Unknown";
|
||||
#ifdef __x86_64__
|
||||
arch = "AMD64";
|
||||
#elif defined(__aarch64__)
|
||||
arch = "ARM64";
|
||||
#elif defined(__arm__)
|
||||
arch = "ARM32";
|
||||
#endif
|
||||
DEBUG("Reborn Target Architecture: %s", arch);
|
||||
}
|
||||
|
||||
// Pre-Bootstrap
|
||||
void pre_bootstrap(int argc, char *argv[]) {
|
||||
// Set Debug Tag
|
||||
|
@ -181,19 +229,20 @@ void pre_bootstrap(int argc, char *argv[]) {
|
|||
act_sigterm.sa_flags = SA_RESTART;
|
||||
act_sigterm.sa_handler = &exit_handler;
|
||||
sigaction(SIGTERM, &act_sigterm, NULL);
|
||||
|
||||
// Check Page Size (Not Needed When Using QEMU)
|
||||
#ifndef USE_QEMU
|
||||
long page_size = sysconf(_SC_PAGESIZE);
|
||||
if (page_size != REQUIRED_PAGE_SIZE) {
|
||||
ERR("Invalid page size! A page size of %ld bytes is required, but the system size is %ld bytes.", (long) REQUIRED_PAGE_SIZE, page_size);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Debug Information
|
||||
print_debug_information();
|
||||
}
|
||||
|
||||
// Copy SDK Into ~/.minecraft-pi
|
||||
void run_simple_command(const char *const command[], const char *error) {
|
||||
int status = 0;
|
||||
char *output = run_command(command, &status);
|
||||
if (output != NULL) {
|
||||
free(output);
|
||||
}
|
||||
if (!is_exit_status_success(status)) {
|
||||
ERR("%s", error);
|
||||
}
|
||||
}
|
||||
#define HOME_SUBDIRECTORY_FOR_SDK HOME_SUBDIRECTORY_FOR_GAME_DATA "/sdk"
|
||||
static void copy_sdk(char *binary_directory) {
|
||||
// Ensure SDK Directory
|
||||
|
@ -249,6 +298,7 @@ void bootstrap(int argc, char *argv[]) {
|
|||
|
||||
// Get Binary Directory
|
||||
char *binary_directory = get_binary_directory();
|
||||
DEBUG("Binary Directory: %s", binary_directory);
|
||||
|
||||
// Copy SDK
|
||||
copy_sdk(binary_directory);
|
||||
|
@ -370,23 +420,6 @@ void bootstrap(int argc, char *argv[]) {
|
|||
set_and_print_env("MCPI_ARM_LD_LIBRARY_PATH", mcpi_ld_path);
|
||||
free(mcpi_ld_path);
|
||||
}
|
||||
|
||||
// Setup iconv
|
||||
{
|
||||
// Native Components
|
||||
char *host_gconv_path = getenv("GCONV_PATH");
|
||||
set_and_print_env("MCPI_NATIVE_GCONV_PATH", host_gconv_path);
|
||||
|
||||
// ARM Components
|
||||
#ifdef MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN
|
||||
char *gconv_path = NULL;
|
||||
safe_asprintf(&gconv_path, "%s/sysroot/usr/lib/gconv", binary_directory);
|
||||
set_and_print_env("MCPI_ARM_GCONV_PATH", gconv_path);
|
||||
free(gconv_path);
|
||||
#else
|
||||
set_and_print_env("MCPI_ARM_GCONV_PATH", host_gconv_path);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Configure Preloaded Objects
|
||||
|
@ -460,16 +493,18 @@ void bootstrap(int argc, char *argv[]) {
|
|||
new_args[argv_start] = new_mcpi_exe_path;
|
||||
|
||||
// Non-ARM Systems Need QEMU
|
||||
#ifndef __ARM_ARCH
|
||||
#ifdef USE_QEMU
|
||||
argv_start--;
|
||||
new_args[argv_start] = QEMU_BINARY;
|
||||
// Use 4k Page Size
|
||||
set_and_print_env("QEMU_PAGESIZE", STR(REQUIRED_PAGE_SIZE));
|
||||
#endif
|
||||
|
||||
// Setup Environment
|
||||
setup_exec_environment(1);
|
||||
|
||||
// Pass LD_* Variables Through QEMU
|
||||
#ifndef __ARM_ARCH
|
||||
#ifdef USE_QEMU
|
||||
char *qemu_set_env = NULL;
|
||||
#define pass_variable_through_qemu(name) string_append(&qemu_set_env, "%s%s=%s", qemu_set_env == NULL ? "" : ",", name, getenv(name));
|
||||
for_each_special_environmental_variable(pass_variable_through_qemu);
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
void run_simple_command(const char *const command[], const char *error);
|
||||
|
||||
void pre_bootstrap(int argc, char *argv[]);
|
||||
void bootstrap(int argc, char *argv[]);
|
||||
|
||||
|
|
|
@ -44,3 +44,9 @@ FALSE Force EGL
|
|||
TRUE Improved Classic Title Screen
|
||||
FALSE Disable Speed Bridging
|
||||
FALSE Disable Creative Mode Mining Delay
|
||||
FALSE Add Biome Colors To Grass
|
||||
TRUE Generate Caves
|
||||
FALSE Disable Block Tinting
|
||||
TRUE Disable Hostile AI In Creative Mode
|
||||
TRUE Load Custom Skins
|
||||
TRUE 3D Chest Model
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
#include "../util.h"
|
||||
#include "../bootstrap.h"
|
||||
#include "launcher.h"
|
||||
#include "cache.h"
|
||||
|
@ -85,7 +86,7 @@ static void run_command_and_set_env(const char *env_name, const char *command[])
|
|||
if (getenv(env_name) == NULL) {
|
||||
// Run
|
||||
int return_code;
|
||||
char *output = run_command(command, &return_code);
|
||||
char *output = run_command(command, &return_code, NULL);
|
||||
if (output != NULL) {
|
||||
// Trim
|
||||
int length = strlen(output);
|
||||
|
|
39
launcher/src/util.c
Normal file
39
launcher/src/util.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
#include <libreborn/libreborn.h>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
// Simpler Version Of run_command()
|
||||
void run_simple_command(const char *const command[], const char *error) {
|
||||
int status = 0;
|
||||
char *output = run_command(command, &status, NULL);
|
||||
if (output != NULL) {
|
||||
free(output);
|
||||
}
|
||||
if (!is_exit_status_success(status)) {
|
||||
ERR("%s", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Chop Off Last Component
|
||||
void chop_last_component(char **str) {
|
||||
size_t length = strlen(*str);
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
size_t j = length - i - 1;
|
||||
if ((*str)[j] == '/') {
|
||||
(*str)[j] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Get Binary Directory (Remember To Free)
|
||||
char *get_binary_directory() {
|
||||
// Get Path To Current Executable
|
||||
char *exe = realpath("/proc/self/exe", NULL);
|
||||
ALLOC_CHECK(exe);
|
||||
|
||||
// Chop Off Last Component
|
||||
chop_last_component(&exe);
|
||||
|
||||
// Return
|
||||
return exe;
|
||||
}
|
14
launcher/src/util.h
Normal file
14
launcher/src/util.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void run_simple_command(const char *const command[], const char *error);
|
||||
|
||||
void chop_last_component(char **str);
|
||||
char *get_binary_directory();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -5,7 +5,7 @@ file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/include/libreborn")
|
|||
configure_file(include/libreborn/config.h.in "${CMAKE_CURRENT_BINARY_DIR}/include/libreborn/config.h" ESCAPE_QUOTES @ONLY)
|
||||
|
||||
# Util
|
||||
add_library(reborn-util SHARED src/util/elf.c src/util/exec.c src/util/string.c src/util/util.c src/util/log.c)
|
||||
add_library(reborn-util SHARED src/util/elf.c src/util/exec.c src/util/string.c src/util/util.c src/util/log.c src/util/cp437.cpp)
|
||||
target_include_directories(
|
||||
reborn-util
|
||||
PUBLIC
|
||||
|
@ -13,6 +13,7 @@ target_include_directories(
|
|||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>"
|
||||
"$<INSTALL_INTERFACE:${MCPI_SDK_INCLUDE_DIR}/libreborn>"
|
||||
)
|
||||
target_link_libraries(reborn-util PRIVATE utf8cpp)
|
||||
# Install
|
||||
install(TARGETS reborn-util DESTINATION "${MCPI_LIB_DIR}")
|
||||
# SDK
|
||||
|
@ -32,3 +33,17 @@ if(BUILD_ARM_COMPONENTS)
|
|||
# SDK
|
||||
install(TARGETS reborn-patch EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}")
|
||||
endif()
|
||||
|
||||
# Fake LibPNG To Satisy Symbol Versioning Requirement
|
||||
if(BUILD_ARM_COMPONENTS)
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/fake-libpng.c" "")
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/fake-libpng.vers" "PNG12_0 { global: *; };")
|
||||
add_library(fake-libpng SHARED "${CMAKE_CURRENT_BINARY_DIR}/fake-libpng.c")
|
||||
set_target_properties(fake-libpng PROPERTIES
|
||||
OUTPUT_NAME "png12"
|
||||
SOVERSION 0
|
||||
LINK_OPTIONS "LINKER:--version-script=${CMAKE_CURRENT_BINARY_DIR}/fake-libpng.vers"
|
||||
)
|
||||
# Install
|
||||
install(TARGETS fake-libpng DESTINATION "${MCPI_LIB_DIR}")
|
||||
endif()
|
||||
|
|
|
@ -11,3 +11,4 @@
|
|||
#cmakedefine MCPI_VERSION "@MCPI_VERSION@"
|
||||
#cmakedefine MCPI_VARIANT_NAME "@MCPI_VARIANT_NAME@"
|
||||
#cmakedefine MCPI_SDK_DIR "@MCPI_SDK_DIR@"
|
||||
#cmakedefine MCPI_SKIN_SERVER "@MCPI_SKIN_SERVER@"
|
||||
|
|
|
@ -22,21 +22,15 @@ void set_and_print_env(const char *name, const char *value);
|
|||
// Safe execvpe()
|
||||
#define for_each_special_environmental_variable(handle) \
|
||||
handle("LD_LIBRARY_PATH"); \
|
||||
handle("GCONV_PATH"); \
|
||||
handle("LD_PRELOAD");
|
||||
void setup_exec_environment(int is_arm_component);
|
||||
__attribute__((noreturn)) void safe_execvpe(const char *const argv[], const char *const envp[]);
|
||||
|
||||
// Chop Off Last Component
|
||||
void chop_last_component(char **str);
|
||||
// Get Binary Directory (Remember To Free)
|
||||
char *get_binary_directory();
|
||||
|
||||
// Debug Tag
|
||||
#define CHILD_PROCESS_TAG "(Child Process) "
|
||||
|
||||
// Run Command And Get Output
|
||||
char *run_command(const char *const command[], int *exit_status);
|
||||
char *run_command(const char *const command[], int *exit_status, size_t *output_size);
|
||||
#define is_exit_status_success(status) (WIFEXITED(status) && WEXITSTATUS(status) == 0)
|
||||
|
||||
// Get Exit Status String
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <iconv.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "util.h"
|
||||
|
@ -36,7 +35,6 @@ extern "C" {
|
|||
void sanitize_string(char **str, int max_length, unsigned int allow_newlines);
|
||||
|
||||
// CP437
|
||||
void safe_iconv(iconv_t cd, char *input, size_t input_size, char *output, size_t output_size);
|
||||
char *to_cp437(const char *input);
|
||||
char *from_cp437(const char *input);
|
||||
|
||||
|
|
|
@ -45,6 +45,11 @@ int is_progress_difference_significant(int32_t new_val, int32_t old_val);
|
|||
int lock_file(const char *file);
|
||||
void unlock_file(const char *file, int fd);
|
||||
|
||||
// Access Configuration At Runtime
|
||||
const char *reborn_get_version();
|
||||
int reborn_is_headless();
|
||||
int reborn_is_server();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
|
||||
// Generate A BL Instruction
|
||||
static uint32_t generate_bl_instruction(void *from, void *to, int use_b_instruction) {
|
||||
if (abs(((int32_t) to) - ((int32_t) from)) > 32000000) {
|
||||
IMPOSSIBLE();
|
||||
}
|
||||
|
||||
uint32_t instruction;
|
||||
unsigned char *instruction_array = (unsigned char *) &instruction;
|
||||
|
||||
|
@ -140,11 +144,8 @@ void _overwrite_calls(const char *file, int line, void *start, void *target) {
|
|||
void *extract_from_bl_instruction(unsigned char *from) {
|
||||
unsigned char *pc = ((unsigned char *) from) + 8;
|
||||
|
||||
int32_t target = 0;
|
||||
unsigned char *target_array = (unsigned char *) ⌖
|
||||
target_array[0] = from[0];
|
||||
target_array[1] = from[1];
|
||||
target_array[2] = from[2];
|
||||
int32_t target = *(int32_t *) from;
|
||||
target = (target << 8) >> 8;
|
||||
|
||||
int32_t offset = target << 2;
|
||||
|
||||
|
|
91
libreborn/src/util/cp437.cpp
Normal file
91
libreborn/src/util/cp437.cpp
Normal file
|
@ -0,0 +1,91 @@
|
|||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "utf8.h"
|
||||
|
||||
#include <libreborn/string.h>
|
||||
|
||||
// Conversion Functions
|
||||
static std::u32string to_utf32(const std::string &s) {
|
||||
return utf8::utf8to32(s);
|
||||
}
|
||||
static std::string to_utf8(const std::u32string &s) {
|
||||
return utf8::utf32to8(s);
|
||||
}
|
||||
|
||||
// Minecraft-Flavored CP437
|
||||
#define CP437_CHARACTERS 256
|
||||
static const std::string cp437_characters_map[CP437_CHARACTERS] = {
|
||||
"\0", "☺", "☻", "♥", "♦", "♣", "♠", "•", "◘", "○", "\n", "♂", "♀", "\r", "♫", "☼",
|
||||
"►", "◄", "↕", "‼", "¶", "§", "▬", "↨", "↑", "↓", "→", "←", "∟", "↔", "▲", "▼",
|
||||
" ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/",
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", "<", "=", ">", "?",
|
||||
"@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O",
|
||||
"P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", "\\", "]", "^", "_",
|
||||
"`", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o",
|
||||
"p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "{", "|", "}", "~", "⌂",
|
||||
"Ç", "ü", "é", "â", "ä", "à", "å", "ç", "ê", "ë", "è", "ï", "î", "ì", "Ä", "Å",
|
||||
"É", "æ", "Æ", "ô", "ö", "ò", "û", "ù", "ÿ", "Ö", "Ü", "¢", "£", "¥", "₧", "ƒ",
|
||||
"á", "í", "ó", "ú", "ñ", "Ñ", "ª", "º", "¿", "⌐", "¬", "½", "¼", "¡", "«", "»",
|
||||
"░", "▒", "▓", "│", "┤", "╡", "╢", "╖", "╕", "╣", "║", "╗", "╝", "╜", "╛", "┐",
|
||||
"└", "┴", "┬", "├", "─", "┼", "╞", "╟", "╚", "╔", "╩", "╦", "╠", "═", "╬", "╧",
|
||||
"╨", "╤", "╥", "╙", "╘", "╒", "╓", "╫", "╪", "┘", "┌", "█", "▄", "▌", "▐", "▀",
|
||||
"α", "ß", "Γ", "π", "Σ", "σ", "µ", "τ", "Φ", "Θ", "Ω", "δ", "∞", "φ", "ε", "∩",
|
||||
"≡", "±", "≥", "≤", "⌠", "⌡", "÷", "≈", "°", "∙", "·", "√", "ⁿ", "²", "■", "©"
|
||||
};
|
||||
static uint32_t *get_cp437_characters_codepoint_map() {
|
||||
static uint32_t map[CP437_CHARACTERS];
|
||||
static int is_setup = 0;
|
||||
if (!is_setup) {
|
||||
// Build Map
|
||||
for (int i = 0; i < CP437_CHARACTERS; i++) {
|
||||
// Convert to UTF-32, Then Extract Codepoint
|
||||
std::u32string str = to_utf32(cp437_characters_map[i]);
|
||||
// Extract
|
||||
map[i] = str[0];
|
||||
}
|
||||
is_setup = 1;
|
||||
}
|
||||
return map;
|
||||
}
|
||||
char *to_cp437(const char *input) {
|
||||
// Convert To UTF-32 For Easier Parsing
|
||||
std::u32string utf32_str = to_utf32(input);
|
||||
|
||||
// Allocate String
|
||||
std::string cp437_str;
|
||||
|
||||
// Handle Characters
|
||||
for (size_t i = 0; i < utf32_str.length(); i++) {
|
||||
uint32_t codepoint = utf32_str[i];
|
||||
bool valid = false;
|
||||
for (int j = 0; j < CP437_CHARACTERS; j++) {
|
||||
uint32_t test_codepoint = get_cp437_characters_codepoint_map()[j];
|
||||
if (codepoint == test_codepoint) {
|
||||
valid = true;
|
||||
cp437_str += j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!valid) {
|
||||
cp437_str += '?';
|
||||
}
|
||||
}
|
||||
|
||||
// Return
|
||||
return strdup(cp437_str.c_str());
|
||||
}
|
||||
char *from_cp437(const char *raw_input) {
|
||||
// Convert To UTF-32 For Easier Parsing
|
||||
std::string input = raw_input;
|
||||
std::u32string utf32_str;
|
||||
|
||||
// Handle Characters
|
||||
for (size_t i = 0; i < input.length(); i++) {
|
||||
unsigned char c = (unsigned char) input[i];
|
||||
utf32_str += get_cp437_characters_codepoint_map()[(uint32_t) c];
|
||||
}
|
||||
|
||||
// Convert To UTF-8
|
||||
return strdup(to_utf8(utf32_str).c_str());
|
||||
}
|
|
@ -43,32 +43,8 @@ __attribute__((noreturn)) void safe_execvpe(const char *const argv[], const char
|
|||
}
|
||||
}
|
||||
|
||||
// Chop Off Last Component
|
||||
void chop_last_component(char **str) {
|
||||
size_t length = strlen(*str);
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
size_t j = length - i - 1;
|
||||
if ((*str)[j] == '/') {
|
||||
(*str)[j] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Get Binary Directory (Remember To Free)
|
||||
char *get_binary_directory() {
|
||||
// Get Path To Current Executable
|
||||
char *exe = realpath("/proc/self/exe", NULL);
|
||||
ALLOC_CHECK(exe);
|
||||
|
||||
// Chop Off Last Component
|
||||
chop_last_component(&exe);
|
||||
|
||||
// Return
|
||||
return exe;
|
||||
}
|
||||
|
||||
// Run Command And Get Output
|
||||
char *run_command(const char *const command[], int *exit_status) {
|
||||
char *run_command(const char *const command[], int *exit_status, size_t *output_size) {
|
||||
// Store Output
|
||||
int output_pipe[2];
|
||||
safe_pipe2(output_pipe, 0);
|
||||
|
@ -107,16 +83,55 @@ char *run_command(const char *const command[], int *exit_status) {
|
|||
|
||||
// Read stdout
|
||||
close(output_pipe[1]);
|
||||
char *output = NULL;
|
||||
#define BUFFER_SIZE 1024
|
||||
size_t size = BUFFER_SIZE;
|
||||
char *output = malloc(size);
|
||||
char buf[BUFFER_SIZE];
|
||||
size_t position = 0;
|
||||
ssize_t bytes_read = 0;
|
||||
while ((bytes_read = read(output_pipe[0], (void *) buf, BUFFER_SIZE - 1 /* Account For NULL-Terminator */)) > 0) {
|
||||
buf[bytes_read] = '\0';
|
||||
string_append(&output, "%s", buf);
|
||||
while ((bytes_read = read(output_pipe[0], (void *) buf, BUFFER_SIZE)) > 0) {
|
||||
// Grow Output If Needed
|
||||
size_t needed_size = position + bytes_read;
|
||||
if (needed_size > size) {
|
||||
// More Memeory Needed
|
||||
size_t new_size = size;
|
||||
while (new_size < needed_size) {
|
||||
new_size += BUFFER_SIZE;
|
||||
}
|
||||
char *new_output = realloc(output, new_size);
|
||||
if (new_output == NULL) {
|
||||
ERR("Unable To Grow Output Buffer");
|
||||
} else {
|
||||
output = new_output;
|
||||
size = new_size;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy Data To Output
|
||||
memcpy(output + position, buf, bytes_read);
|
||||
position += bytes_read;
|
||||
}
|
||||
close(output_pipe[0]);
|
||||
|
||||
// Add NULL-Terminator To Output
|
||||
size_t needed_size = position + 1;
|
||||
if (needed_size > size) {
|
||||
// More Memeory Needed
|
||||
size_t new_size = size + 1;
|
||||
char *new_output = realloc(output, new_size);
|
||||
if (new_output == NULL) {
|
||||
ERR("Unable To Grow Output Buffer (For NULL-Terminator)");
|
||||
} else {
|
||||
output = new_output;
|
||||
}
|
||||
}
|
||||
output[position++] = '\0';
|
||||
|
||||
// Return Output Size
|
||||
if (output_size != NULL) {
|
||||
*output_size = position;
|
||||
}
|
||||
|
||||
// Get Return Code
|
||||
int status;
|
||||
waitpid(ret, &status, 0);
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#include <iconv.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <libreborn/string.h>
|
||||
|
@ -23,125 +22,6 @@ void sanitize_string(char **str, int max_length, unsigned int allow_newlines) {
|
|||
}
|
||||
}
|
||||
|
||||
// Minecraft-Flavored CP437
|
||||
void safe_iconv(iconv_t cd, char *input, size_t input_size, char *output, size_t output_size) {
|
||||
iconv(cd, &input, &input_size, &output, &output_size);
|
||||
}
|
||||
#define CP437_CHARACTERS 256
|
||||
static const char *cp437_characters_map[CP437_CHARACTERS] = {
|
||||
"\0", "☺", "☻", "♥", "♦", "♣", "♠", "•", "◘", "○", "\n", "♂", "♀", "\r", "♫", "☼",
|
||||
"►", "◄", "↕", "‼", "¶", "§", "▬", "↨", "↑", "↓", "→", "←", "∟", "↔", "▲", "▼",
|
||||
" ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/",
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", "<", "=", ">", "?",
|
||||
"@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O",
|
||||
"P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", "\\", "]", "^", "_",
|
||||
"`", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o",
|
||||
"p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "{", "|", "}", "~", "⌂",
|
||||
"Ç", "ü", "é", "â", "ä", "à", "å", "ç", "ê", "ë", "è", "ï", "î", "ì", "Ä", "Å",
|
||||
"É", "æ", "Æ", "ô", "ö", "ò", "û", "ù", "ÿ", "Ö", "Ü", "¢", "£", "¥", "₧", "ƒ",
|
||||
"á", "í", "ó", "ú", "ñ", "Ñ", "ª", "º", "¿", "⌐", "¬", "½", "¼", "¡", "«", "»",
|
||||
"░", "▒", "▓", "│", "┤", "╡", "╢", "╖", "╕", "╣", "║", "╗", "╝", "╜", "╛", "┐",
|
||||
"└", "┴", "┬", "├", "─", "┼", "╞", "╟", "╚", "╔", "╩", "╦", "╠", "═", "╬", "╧",
|
||||
"╨", "╤", "╥", "╙", "╘", "╒", "╓", "╫", "╪", "┘", "┌", "█", "▄", "▌", "▐", "▀",
|
||||
"α", "ß", "Γ", "π", "Σ", "σ", "µ", "τ", "Φ", "Θ", "Ω", "δ", "∞", "φ", "ε", "∩",
|
||||
"≡", "±", "≥", "≤", "⌠", "⌡", "÷", "≈", "°", "∙", "·", "√", "ⁿ", "²", "■", "©"
|
||||
};
|
||||
static uint32_t *get_cp437_characters_codepoint_map() {
|
||||
static uint32_t map[CP437_CHARACTERS];
|
||||
static int is_setup = 0;
|
||||
if (!is_setup) {
|
||||
// Build Map
|
||||
iconv_t cd = iconv_open("UTF-32LE", "UTF-8");
|
||||
if (cd != (iconv_t) -1) {
|
||||
size_t str_size = 4;
|
||||
uint32_t *str = (uint32_t *) malloc(str_size);
|
||||
ALLOC_CHECK(str);
|
||||
for (int i = 0; i < CP437_CHARACTERS; i++) {
|
||||
// Convert to UTF-32, Then Extract Codepoint
|
||||
safe_iconv(cd, (char *) cp437_characters_map[i], strlen(cp437_characters_map[i]), (char *) str, str_size);
|
||||
// Extract
|
||||
map[i] = str[0];
|
||||
}
|
||||
// Free
|
||||
free(str);
|
||||
iconv_close(cd);
|
||||
} else {
|
||||
IMPOSSIBLE();
|
||||
}
|
||||
is_setup = 1;
|
||||
}
|
||||
return map;
|
||||
}
|
||||
char *to_cp437(const char *input) {
|
||||
// Convert To UTF-32 For Easier Parsing
|
||||
size_t in_size = strlen(input);
|
||||
size_t utf32_str_size = in_size * 4;
|
||||
size_t real_utf32_str_size = utf32_str_size + 4 /* NULL-terminator */;
|
||||
uint32_t *utf32_str = (uint32_t *) malloc(real_utf32_str_size);
|
||||
ALLOC_CHECK(utf32_str);
|
||||
memset(utf32_str, 0, real_utf32_str_size);
|
||||
iconv_t cd = iconv_open("UTF-32LE", "UTF-8");
|
||||
if (cd != (iconv_t) -1) {
|
||||
safe_iconv(cd, (char *) input, in_size, (char *) utf32_str, utf32_str_size);
|
||||
iconv_close(cd);
|
||||
} else {
|
||||
IMPOSSIBLE();
|
||||
}
|
||||
// Allocate String
|
||||
size_t cp437_str_size;
|
||||
for (cp437_str_size = 0; utf32_str[cp437_str_size] != 0; cp437_str_size++);
|
||||
size_t real_cp437_str_size = cp437_str_size + 1 /* NULL-terminator */;
|
||||
char *cp437_str = (char *) malloc(real_cp437_str_size);
|
||||
ALLOC_CHECK(cp437_str);
|
||||
memset(cp437_str, 0, real_cp437_str_size);
|
||||
// Handle Characters
|
||||
for (size_t i = 0; utf32_str[i] != 0; i++) {
|
||||
uint32_t codepoint = utf32_str[i];
|
||||
for (int j = 0; j < CP437_CHARACTERS; j++) {
|
||||
uint32_t test_codepoint = get_cp437_characters_codepoint_map()[j];
|
||||
if (codepoint == test_codepoint) {
|
||||
cp437_str[i] = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cp437_str[i] == '\0') {
|
||||
cp437_str[i] = '?';
|
||||
}
|
||||
}
|
||||
// Free
|
||||
free(utf32_str);
|
||||
// Return
|
||||
return cp437_str;
|
||||
}
|
||||
char *from_cp437(const char *input) {
|
||||
// Convert To UTF-32 For Easier Parsing
|
||||
size_t in_size = strlen(input);
|
||||
size_t utf32_str_size = in_size * 4;
|
||||
size_t real_utf32_str_size = utf32_str_size + 4 /* NULL-terminator */;
|
||||
uint32_t *utf32_str = (uint32_t *) malloc(real_utf32_str_size);
|
||||
ALLOC_CHECK(utf32_str);
|
||||
memset(utf32_str, 0, real_utf32_str_size);
|
||||
// Handle Characters
|
||||
for (size_t i = 0; input[i] != '\0'; i++) {
|
||||
utf32_str[i] = get_cp437_characters_codepoint_map()[(uint32_t) input[i]];
|
||||
}
|
||||
// Convert To UTF-8
|
||||
size_t out_size = utf32_str_size;
|
||||
size_t real_out_size = utf32_str_size + 1 /* NULL-terminator */;
|
||||
char *output = (char *) malloc(real_out_size);
|
||||
ALLOC_CHECK(output);
|
||||
memset(output, 0, real_out_size);
|
||||
iconv_t cd = iconv_open("UTF-8", "UTF-32LE");
|
||||
if (cd != (iconv_t) -1) {
|
||||
safe_iconv(cd, (char *) utf32_str, utf32_str_size, output, out_size);
|
||||
iconv_close(cd);
|
||||
} else {
|
||||
IMPOSSIBLE();
|
||||
}
|
||||
// Return
|
||||
return output;
|
||||
}
|
||||
|
||||
// Starts With
|
||||
int starts_with(const char *str, const char *prefix) {
|
||||
return strncmp(prefix, str, strlen(prefix)) == 0;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include <sys/file.h>
|
||||
|
||||
#include <libreborn/util.h>
|
||||
#include <libreborn/config.h>
|
||||
|
||||
// Safe Version Of pipe()
|
||||
void safe_pipe2(int pipefd[2], int flags) {
|
||||
|
@ -43,3 +44,22 @@ void unlock_file(const char *file, int fd) {
|
|||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
// Access Configuration At Runtime
|
||||
const char *reborn_get_version() {
|
||||
return MCPI_VERSION;
|
||||
}
|
||||
int reborn_is_headless() {
|
||||
#ifdef MCPI_HEADLESS_MODE
|
||||
return 1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
int reborn_is_server() {
|
||||
#ifdef MCPI_SERVER_MODE
|
||||
return 1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -11,18 +11,29 @@ target_include_directories(
|
|||
# SDK
|
||||
if(BUILD_ARM_COMPONENTS)
|
||||
install(TARGETS media-layer-headers EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}")
|
||||
install(DIRECTORY "include/" DESTINATION "${MCPI_SDK_INCLUDE_DIR}/media-layer")
|
||||
# Copy Headers
|
||||
set(GLES_HEADERS "include/GLES")
|
||||
install(
|
||||
DIRECTORY "include/"
|
||||
DESTINATION "${MCPI_SDK_INCLUDE_DIR}/media-layer"
|
||||
PATTERN "${GLES_HEADERS}" EXCLUDE
|
||||
)
|
||||
get_filename_component(GLES_HEADERS "${GLES_HEADERS}" REALPATH)
|
||||
install(
|
||||
DIRECTORY "${GLES_HEADERS}/"
|
||||
DESTINATION "${MCPI_SDK_INCLUDE_DIR}/media-layer/GLES"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Add Extras
|
||||
add_subdirectory(extras)
|
||||
|
||||
# Add Core
|
||||
if((BUILD_NATIVE_COMPONENTS AND MCPI_USE_MEDIA_LAYER_PROXY) OR (BUILD_ARM_COMPONENTS AND NOT MCPI_USE_MEDIA_LAYER_PROXY))
|
||||
if(BUILD_MEDIA_LAYER_CORE)
|
||||
add_subdirectory(core)
|
||||
endif()
|
||||
|
||||
# Add Proxy
|
||||
if(MCPI_USE_MEDIA_LAYER_PROXY)
|
||||
if(MCPI_USE_MEDIA_LAYER_PROXY OR BUILD_ARM_COMPONENTS)
|
||||
add_subdirectory(proxy)
|
||||
endif()
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
project(media-layer-core)
|
||||
|
||||
# Dependencies
|
||||
add_subdirectory(dependencies)
|
||||
|
||||
# OpenGL
|
||||
add_subdirectory(gles)
|
||||
|
||||
|
@ -15,18 +12,19 @@ else()
|
|||
endif()
|
||||
|
||||
# Build
|
||||
add_library(media-layer-core SHARED ${CORE_SRC}) # Dependencies Are Setup Later
|
||||
# Install
|
||||
install(TARGETS media-layer-core DESTINATION "${MCPI_LIB_DIR}")
|
||||
if(BUILD_ARM_COMPONENTS)
|
||||
install(TARGETS media-layer-core EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}")
|
||||
add_library(media-layer-core-real SHARED ${CORE_SRC}) # Dependencies Are Setup Later
|
||||
set_target_properties(media-layer-core-real PROPERTIES OUTPUT_NAME "media-layer-core")
|
||||
if(BUILD_NATIVE_COMPONENTS)
|
||||
add_library(media-layer-core ALIAS media-layer-core-real)
|
||||
endif()
|
||||
# Install
|
||||
install(TARGETS media-layer-core-real DESTINATION "${MCPI_LIB_DIR}")
|
||||
|
||||
# Link
|
||||
target_link_libraries(media-layer-core PUBLIC media-layer-headers PUBLIC reborn-util PUBLIC GLESv1_CM PUBLIC dl)
|
||||
target_link_libraries(media-layer-core-real PUBLIC media-layer-headers PUBLIC reborn-util PUBLIC GLESv1_CM PUBLIC dl)
|
||||
if(NOT MCPI_HEADLESS_MODE)
|
||||
# OpenAL
|
||||
find_library(OPENAL_LIBRARY NAMES openal REQUIRED)
|
||||
# Link
|
||||
target_link_libraries(media-layer-core PRIVATE "${OPENAL_LIBRARY}" PRIVATE m PRIVATE glfw PRIVATE LIB_LIEF)
|
||||
target_link_libraries(media-layer-core-real PRIVATE "${OPENAL_LIBRARY}" PRIVATE m PRIVATE glfw PRIVATE LIB_LIEF)
|
||||
endif()
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
project(media-layer-core-dependencies)
|
||||
|
||||
# GLFW
|
||||
if(NOT MCPI_HEADLESS_MODE)
|
||||
add_subdirectory(glfw)
|
||||
endif()
|
|
@ -1 +0,0 @@
|
|||
Subproject commit dd8a678a66f1967372e5a5e3deac41ebf65ee127
|
|
@ -3,30 +3,14 @@ project(media-layer-gles)
|
|||
# Build
|
||||
if(MCPI_HEADLESS_MODE)
|
||||
# Stubs For Headless Mode
|
||||
set(GLES_SRC src/stubs.c)
|
||||
add_library(GLESv1_CM OBJECT src/stubs.c)
|
||||
target_link_libraries(GLESv1_CM PRIVATE media-layer-headers)
|
||||
elseif(MCPI_USE_GLES1_COMPATIBILITY_LAYER)
|
||||
# GLESv1_CM Compatibility Layer
|
||||
set(GLES_SRC src/compatibility-layer/state.c src/compatibility-layer/passthrough.c src/compatibility-layer/matrix.c src/compatibility-layer/draw.c)
|
||||
add_library(GLESv1_CM INTERFACE)
|
||||
target_link_libraries(GLESv1_CM INTERFACE gles-compatibility-layer)
|
||||
else()
|
||||
# Passthrough To glfwGetProcAddress()
|
||||
set(GLES_SRC src/passthrough.c)
|
||||
endif()
|
||||
add_library(GLESv1_CM OBJECT ${GLES_SRC})
|
||||
if(NOT MCPI_HEADLESS_MODE)
|
||||
target_link_libraries(GLESv1_CM PRIVATE glfw PUBLIC reborn-util PRIVATE dl PRIVATE m)
|
||||
# Shaders
|
||||
if(MCPI_USE_GLES1_COMPATIBILITY_LAYER)
|
||||
embed_resource(GLESv1_CM src/compatibility-layer/shaders/main.vsh)
|
||||
embed_resource(GLESv1_CM src/compatibility-layer/shaders/main.fsh)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Common
|
||||
target_link_libraries(GLESv1_CM PUBLIC media-layer-headers)
|
||||
set_target_properties(GLESv1_CM PROPERTIES SOVERSION "1")
|
||||
# Install
|
||||
install(TARGETS GLESv1_CM DESTINATION "${MCPI_LIB_DIR}")
|
||||
# SDK
|
||||
if(BUILD_ARM_COMPONENTS)
|
||||
install(TARGETS GLESv1_CM EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}")
|
||||
add_library(GLESv1_CM OBJECT src/passthrough.c)
|
||||
target_link_libraries(GLESv1_CM PRIVATE glfw media-layer-headers)
|
||||
endif()
|
||||
|
|
|
@ -1,204 +0,0 @@
|
|||
#include "state.h"
|
||||
#include "../passthrough.h"
|
||||
|
||||
#include <GLES/gl.h>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
// Shaders
|
||||
#define REAL_GL_FRAGMENT_SHADER 0x8b30
|
||||
#define REAL_GL_VERTEX_SHADER 0x8b31
|
||||
#define REAL_GL_INFO_LOG_LENGTH 0x8b84
|
||||
#define REAL_GL_COMPILE_STATUS 0x8b81
|
||||
GL_FUNC(glUseProgram, void, (GLuint program));
|
||||
GL_FUNC(glGetUniformLocation, GLint, (GLuint program, const GLchar *name));
|
||||
GL_FUNC(glUniformMatrix4fv, void, (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value));
|
||||
GL_FUNC(glUniform1i, void, (GLint location, GLint v0));
|
||||
GL_FUNC(glUniform1f, void, (GLint location, GLfloat v0));
|
||||
GL_FUNC(glUniform4f, void, (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3));
|
||||
GL_FUNC(glGetAttribLocation, GLint, (GLuint program, const GLchar *name));
|
||||
GL_FUNC(glEnableVertexAttribArray, void, (GLuint index));
|
||||
GL_FUNC(glDisableVertexAttribArray, void, (GLuint index));
|
||||
GL_FUNC(glVertexAttribPointer, void, (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer));
|
||||
GL_FUNC(glVertexAttrib3f, void, (GLuint index, GLfloat v0, GLfloat v1, GLfloat v2));
|
||||
GL_FUNC(glVertexAttrib4f, void, (GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3));
|
||||
GL_FUNC(glCreateShader, GLuint, (GLenum type));
|
||||
GL_FUNC(glShaderSource, void, (GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length));
|
||||
GL_FUNC(glCompileShader, void, (GLuint shader));
|
||||
GL_FUNC(glCreateProgram, GLuint, ());
|
||||
GL_FUNC(glAttachShader, void, (GLuint program, GLuint shader));
|
||||
GL_FUNC(glLinkProgram, void, (GLuint program));
|
||||
GL_FUNC(glGetShaderiv, void, (GLuint shader, GLenum pname, GLint *params));
|
||||
GL_FUNC(glGetShaderInfoLog, void, (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog));
|
||||
|
||||
// Compile Shader
|
||||
static void log_shader(GLuint shader, const char *name) {
|
||||
// Log
|
||||
GLint log_length = 0;
|
||||
real_glGetShaderiv()(shader, REAL_GL_INFO_LOG_LENGTH, &log_length);
|
||||
GLchar *log = malloc(log_length * sizeof (GLchar));
|
||||
ALLOC_CHECK(log);
|
||||
real_glGetShaderInfoLog()(shader, log_length, &log_length, log);
|
||||
if (log_length > 0) {
|
||||
if (log_length > 1 && log[log_length - 1] == '\n') {
|
||||
log[log_length - 1] = '\0';
|
||||
}
|
||||
DEBUG("%s Shader Compile Log: %s", name, log);
|
||||
}
|
||||
free(log);
|
||||
|
||||
// Check Status
|
||||
GLint is_compiled = 0;
|
||||
real_glGetShaderiv()(shader, REAL_GL_COMPILE_STATUS, &is_compiled);
|
||||
if (!is_compiled) {
|
||||
ERR("Failed To Compile %s Shader", name);
|
||||
}
|
||||
}
|
||||
static GLuint compile_shader(const char *vertex_shader_text, const int vertex_shader_length, const char *fragment_shader_text, const int fragment_shader_length) {
|
||||
// Vertex Shader
|
||||
const GLuint vertex_shader = real_glCreateShader()(REAL_GL_VERTEX_SHADER);
|
||||
real_glShaderSource()(vertex_shader, 1, &vertex_shader_text, &vertex_shader_length);
|
||||
real_glCompileShader()(vertex_shader);
|
||||
log_shader(vertex_shader, "Vertex");
|
||||
|
||||
// Fragment Shader
|
||||
const GLuint fragment_shader = real_glCreateShader()(REAL_GL_FRAGMENT_SHADER);
|
||||
real_glShaderSource()(fragment_shader, 1, &fragment_shader_text, &fragment_shader_length);
|
||||
real_glCompileShader()(fragment_shader);
|
||||
log_shader(fragment_shader, "Fragment");
|
||||
|
||||
// Link
|
||||
GLuint program = real_glCreateProgram()();
|
||||
real_glAttachShader()(program, vertex_shader);
|
||||
real_glAttachShader()(program, fragment_shader);
|
||||
real_glLinkProgram()(program);
|
||||
|
||||
// Return
|
||||
return program;
|
||||
}
|
||||
|
||||
// Shader
|
||||
extern unsigned char main_vsh[];
|
||||
extern size_t main_vsh_len;
|
||||
extern unsigned char main_fsh[];
|
||||
extern size_t main_fsh_len;
|
||||
static GLuint get_shader() {
|
||||
static GLuint program = 0;
|
||||
if (program == 0) {
|
||||
program = compile_shader((const char *) main_vsh, main_vsh_len, (const char *) main_fsh, main_fsh_len);
|
||||
}
|
||||
return program;
|
||||
}
|
||||
|
||||
// Shader Switching
|
||||
static void use_shader(GLuint program) {
|
||||
static GLuint current_program = 0;
|
||||
if (current_program != program) {
|
||||
real_glUseProgram()(program);
|
||||
current_program = program;
|
||||
}
|
||||
}
|
||||
|
||||
// Array Pointer Drawing
|
||||
GL_FUNC(glDrawArrays, void, (GLenum mode, GLint first, GLsizei count));
|
||||
#define lazy_uniform(name) \
|
||||
static GLint name##_handle = -1; \
|
||||
if (name##_handle == -1) { \
|
||||
name##_handle = real_glGetUniformLocation()(program, #name); \
|
||||
}
|
||||
void glDrawArrays(GLenum mode, GLint first, GLsizei count) {
|
||||
// Verify
|
||||
if (gl_state.array_pointers.vertex.size != 3 || !gl_state.array_pointers.vertex.enabled || gl_state.array_pointers.vertex.type != GL_FLOAT) {
|
||||
ERR("Unsupported Vertex Conifguration");
|
||||
}
|
||||
|
||||
// Check Mode
|
||||
int use_color_pointer = gl_state.array_pointers.color.enabled;
|
||||
if (use_color_pointer && (gl_state.array_pointers.color.size != 4 || gl_state.array_pointers.color.type != GL_UNSIGNED_BYTE)) {
|
||||
ERR("Unsupported Color Conifguration");
|
||||
}
|
||||
int use_texture = gl_state.texture_2d && gl_state.array_pointers.tex_coord.enabled;
|
||||
if (use_texture && (gl_state.array_pointers.tex_coord.size != 2 || gl_state.array_pointers.tex_coord.type != GL_FLOAT)) {
|
||||
ERR("Unsupported Texture Conifguration");
|
||||
}
|
||||
|
||||
// Load Shader
|
||||
GLuint program = get_shader();
|
||||
use_shader(program);
|
||||
|
||||
// Projection Matrix
|
||||
lazy_uniform(u_projection);
|
||||
matrix_t *p = &gl_state.matrix_stacks.projection.stack[gl_state.matrix_stacks.projection.i];
|
||||
real_glUniformMatrix4fv()(u_projection_handle, 1, 0, (GLfloat *) &p->data[0][0]);
|
||||
|
||||
// Model View Matrix
|
||||
lazy_uniform(u_model_view);
|
||||
p = &gl_state.matrix_stacks.model_view.stack[gl_state.matrix_stacks.model_view.i];
|
||||
real_glUniformMatrix4fv()(u_model_view_handle, 1, 0, (GLfloat *) &p->data[0][0]);
|
||||
|
||||
// Has Texture
|
||||
lazy_uniform(u_has_texture); \
|
||||
real_glUniform1i()(u_has_texture_handle, use_texture); \
|
||||
|
||||
// Texture Matrix
|
||||
lazy_uniform(u_texture);
|
||||
p = &gl_state.matrix_stacks.texture.stack[gl_state.matrix_stacks.texture.i];
|
||||
real_glUniformMatrix4fv()(u_texture_handle, 1, 0, (GLfloat *) &p->data[0][0]);
|
||||
|
||||
// Texture Unit
|
||||
lazy_uniform(u_texture_unit);
|
||||
real_glUniform1i()(u_texture_unit_handle, 0);
|
||||
|
||||
// Alpha Test
|
||||
lazy_uniform(u_alpha_test);
|
||||
real_glUniform1i()(u_alpha_test_handle, gl_state.alpha_test);
|
||||
|
||||
// Color
|
||||
GLint a_color_handle = real_glGetAttribLocation()(program, "a_color");
|
||||
if (use_color_pointer) {
|
||||
real_glVertexAttribPointer()(a_color_handle, gl_state.array_pointers.color.size, gl_state.array_pointers.color.type, 1, gl_state.array_pointers.color.stride, gl_state.array_pointers.color.pointer);
|
||||
real_glEnableVertexAttribArray()(a_color_handle);
|
||||
} else {
|
||||
real_glVertexAttrib4f()(a_color_handle, gl_state.color.red, gl_state.color.green, gl_state.color.blue, gl_state.color.alpha);
|
||||
}
|
||||
|
||||
// Fog
|
||||
lazy_uniform(u_fog);
|
||||
real_glUniform1i()(u_fog_handle, gl_state.fog.enabled);
|
||||
if (gl_state.fog.enabled) {
|
||||
lazy_uniform(u_fog_color);
|
||||
real_glUniform4f()(u_fog_color_handle, gl_state.fog.color[0], gl_state.fog.color[1], gl_state.fog.color[2], gl_state.fog.color[3]);
|
||||
lazy_uniform(u_fog_is_linear);
|
||||
real_glUniform1i()(u_fog_is_linear_handle, gl_state.fog.mode == GL_LINEAR);
|
||||
lazy_uniform(u_fog_start);
|
||||
real_glUniform1f()(u_fog_start_handle, gl_state.fog.start);
|
||||
lazy_uniform(u_fog_end);
|
||||
real_glUniform1f()(u_fog_end_handle, gl_state.fog.end);
|
||||
}
|
||||
|
||||
// Vertices
|
||||
GLint a_vertex_coords_handle = real_glGetAttribLocation()(program, "a_vertex_coords");
|
||||
real_glVertexAttribPointer()(a_vertex_coords_handle, gl_state.array_pointers.vertex.size, gl_state.array_pointers.vertex.type, 0, gl_state.array_pointers.vertex.stride, gl_state.array_pointers.vertex.pointer);
|
||||
real_glEnableVertexAttribArray()(a_vertex_coords_handle);
|
||||
|
||||
// Texture Coordinates
|
||||
GLint a_texture_coords_handle = real_glGetAttribLocation()(program, "a_texture_coords");
|
||||
if (use_texture) {
|
||||
real_glVertexAttribPointer()(a_texture_coords_handle, gl_state.array_pointers.tex_coord.size, gl_state.array_pointers.tex_coord.type, 0, gl_state.array_pointers.tex_coord.stride, gl_state.array_pointers.tex_coord.pointer);
|
||||
real_glEnableVertexAttribArray()(a_texture_coords_handle);
|
||||
} else {
|
||||
real_glVertexAttrib3f()(a_texture_coords_handle, 0, 0, 0);
|
||||
}
|
||||
|
||||
// Draw
|
||||
real_glDrawArrays()(mode, first, count);
|
||||
|
||||
// Cleanup
|
||||
if (use_color_pointer) {
|
||||
real_glDisableVertexAttribArray()(a_color_handle);
|
||||
}
|
||||
real_glDisableVertexAttribArray()(a_vertex_coords_handle);
|
||||
if (use_texture) {
|
||||
real_glDisableVertexAttribArray()(a_texture_coords_handle);
|
||||
}
|
||||
}
|
|
@ -1,131 +0,0 @@
|
|||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
#include "state.h"
|
||||
|
||||
// Matrix Common
|
||||
static void matrix_copy(matrix_t *src, matrix_t *dst) {
|
||||
memcpy((void *) dst->data, (void *) src->data, MATRIX_DATA_SIZE);
|
||||
}
|
||||
|
||||
// Identity Matrix
|
||||
static matrix_t identity_matrix = {
|
||||
.data = {
|
||||
{1, 0, 0, 0},
|
||||
{0, 1, 0, 0},
|
||||
{0, 0, 1, 0},
|
||||
{0, 0, 0, 1}
|
||||
}
|
||||
};
|
||||
static void init_matrix_stack(matrix_stack_t *stack) {
|
||||
matrix_copy(&identity_matrix, &stack->stack[0]);
|
||||
}
|
||||
__attribute__((constructor)) static void init_matrix_stacks() {
|
||||
init_matrix_stack(&gl_state.matrix_stacks.model_view);
|
||||
init_matrix_stack(&gl_state.matrix_stacks.projection);
|
||||
init_matrix_stack(&gl_state.matrix_stacks.texture);
|
||||
}
|
||||
|
||||
// Matrix Mode
|
||||
static matrix_stack_t *get_matrix_stack() {
|
||||
switch (gl_state.matrix_stacks.mode) {
|
||||
case GL_MODELVIEW: {
|
||||
return &gl_state.matrix_stacks.model_view;
|
||||
}
|
||||
case GL_PROJECTION: {
|
||||
return &gl_state.matrix_stacks.projection;
|
||||
}
|
||||
case GL_TEXTURE: {
|
||||
return &gl_state.matrix_stacks.texture;
|
||||
}
|
||||
default: {
|
||||
ERR("Unsupported Matrix Mode: %i", gl_state.matrix_stacks.mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Matrix Functions
|
||||
void glMatrixMode(GLenum mode) {
|
||||
gl_state.matrix_stacks.mode = mode;
|
||||
}
|
||||
void glPopMatrix() {
|
||||
get_matrix_stack()->i--;
|
||||
}
|
||||
void glLoadIdentity() {
|
||||
matrix_stack_t *stack = get_matrix_stack();
|
||||
matrix_copy(&identity_matrix, &stack->stack[stack->i]);
|
||||
}
|
||||
void glPushMatrix() {
|
||||
matrix_stack_t *stack = get_matrix_stack();
|
||||
matrix_copy(&stack->stack[stack->i], &stack->stack[stack->i + 1]);
|
||||
stack->i++;
|
||||
}
|
||||
void glMultMatrixf(const GLfloat *m) {
|
||||
matrix_t new_matrix;
|
||||
matrix_stack_t *stack = get_matrix_stack();
|
||||
matrix_t *current_matrix = &stack->stack[stack->i];
|
||||
for (int x = 0; x < MATRIX_SIZE; x++) {
|
||||
for (int y = 0; y < MATRIX_SIZE; y++) {
|
||||
GLfloat result = 0;
|
||||
for (int i = 0; i < MATRIX_SIZE; i++) {
|
||||
result += (current_matrix->data[i][y] * m[(x * MATRIX_SIZE) + i]);
|
||||
}
|
||||
new_matrix.data[x][y] = result;
|
||||
}
|
||||
}
|
||||
matrix_copy(&new_matrix, current_matrix);
|
||||
}
|
||||
void glScalef(GLfloat x, GLfloat y, GLfloat z) {
|
||||
GLfloat m[] = {
|
||||
x, 0, 0, 0,
|
||||
0, y, 0, 0,
|
||||
0, 0, z, 0,
|
||||
0, 0, 0, 1
|
||||
};
|
||||
glMultMatrixf(m);
|
||||
}
|
||||
void glTranslatef(GLfloat x, GLfloat y, GLfloat z) {
|
||||
GLfloat m[] = {
|
||||
1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
x, y, z, 1
|
||||
};
|
||||
glMultMatrixf(m);
|
||||
}
|
||||
void glOrthof(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far) {
|
||||
GLfloat m[] = {
|
||||
(2.f / (right - left)), 0, 0, 0,
|
||||
0, (2.f / (top - bottom)), 0, 0,
|
||||
0, 0, (-2.f / (far - near)), 0,
|
||||
-((right + left) / (right - left)), -((top + bottom) / (top - bottom)), -((far + near) / (far - near)), 1
|
||||
};
|
||||
glMultMatrixf(m);
|
||||
}
|
||||
#define DEG2RAD (M_PI / 180.f)
|
||||
void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
|
||||
// Normalize
|
||||
GLfloat length = sqrtf((x * x) + (y * y) + (z * z));
|
||||
x /= length;
|
||||
y /= length;
|
||||
z /= length;
|
||||
|
||||
// Values
|
||||
GLfloat angle_radians = angle * DEG2RAD;
|
||||
GLfloat c = cosf(angle_radians);
|
||||
GLfloat s = sinf(angle_radians);
|
||||
GLfloat x2 = x * x;
|
||||
GLfloat y2 = y * y;
|
||||
GLfloat z2 = z * z;
|
||||
|
||||
// Multiply
|
||||
GLfloat m[] = {
|
||||
x2 * (1.f - c) + c, (x * y) * (1.f - c) + (z * s), (x * z) * (1.f - c) - (y * s), 0,
|
||||
(x * y) * (1.f - c) - (z * s), y2 * (1.f - c) + c, (y * z) * (1.f - c) + (x * s), 0,
|
||||
(x * z) * (1.f - c) + (y * s), (y * z) * (1.f - c) - (x * s), z2 * (1.f - c) + c, 0,
|
||||
0, 0, 0, 1.f
|
||||
};
|
||||
glMultMatrixf(m);
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
#include <GLES/gl.h>
|
||||
|
||||
// Matrix Common
|
||||
#define MATRIX_SIZE 4
|
||||
#define MATRIX_DATA_SIZE (sizeof (GLfloat) * MATRIX_SIZE * MATRIX_SIZE)
|
||||
// OpenGL Matrices Are Column-Major
|
||||
typedef struct {
|
||||
GLfloat data[MATRIX_SIZE][MATRIX_SIZE];
|
||||
} matrix_t;
|
|
@ -1,117 +0,0 @@
|
|||
#include <GLES/gl.h>
|
||||
|
||||
#include "../passthrough.h"
|
||||
|
||||
// Simple v1.1 -> v2.0 Passthrough Functions
|
||||
GL_FUNC(glLineWidth, void, (GLfloat width));
|
||||
void glLineWidth(GLfloat width) {
|
||||
real_glLineWidth()(width);
|
||||
}
|
||||
GL_FUNC(glBlendFunc, void, (GLenum sfactor, GLenum dfactor));
|
||||
void glBlendFunc(GLenum sfactor, GLenum dfactor) {
|
||||
real_glBlendFunc()(sfactor, dfactor);
|
||||
}
|
||||
GL_FUNC(glClear, void, (GLbitfield mask));
|
||||
void glClear(GLbitfield mask) {
|
||||
real_glClear()(mask);
|
||||
}
|
||||
GL_FUNC(glBufferData, void, (GLenum target, GLsizeiptr size, const void *data, GLenum usage));
|
||||
void glBufferData(GLenum target, GLsizeiptr size, const void *data, GLenum usage) {
|
||||
real_glBufferData()(target, size, data, usage);
|
||||
}
|
||||
GL_FUNC(glScissor, void, (GLint x, GLint y, GLsizei width, GLsizei height));
|
||||
void glScissor(GLint x, GLint y, GLsizei width, GLsizei height) {
|
||||
real_glScissor()(x, y, width, height);
|
||||
}
|
||||
GL_FUNC(glTexParameteri, void, (GLenum target, GLenum pname, GLint param));
|
||||
void glTexParameteri(GLenum target, GLenum pname, GLint param) {
|
||||
real_glTexParameteri()(target, pname, param);
|
||||
}
|
||||
GL_FUNC(glTexImage2D, void, (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels));
|
||||
void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels) {
|
||||
real_glTexImage2D()(target, level, internalformat, width, height, border, format, type, pixels);
|
||||
}
|
||||
GL_FUNC(glPolygonOffset, void, (GLfloat factor, GLfloat units));
|
||||
void glPolygonOffset(GLfloat factor, GLfloat units) {
|
||||
real_glPolygonOffset()(factor, units);
|
||||
}
|
||||
GL_FUNC(glDepthRangef, void, (GLclampf near, GLclampf far));
|
||||
void glDepthRangef(GLclampf near, GLclampf far) {
|
||||
real_glDepthRangef()(near, far);
|
||||
}
|
||||
GL_FUNC(glBindBuffer, void, (GLenum target, GLuint buffer));
|
||||
void glBindBuffer(GLenum target, GLuint buffer) {
|
||||
real_glBindBuffer()(target, buffer);
|
||||
}
|
||||
GL_FUNC(glDepthFunc, void, (GLenum func));
|
||||
void glDepthFunc(GLenum func) {
|
||||
real_glDepthFunc()(func);
|
||||
}
|
||||
GL_FUNC(glClearColor, void, (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha));
|
||||
void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
|
||||
real_glClearColor()(red, green, blue, alpha);
|
||||
}
|
||||
GL_FUNC(glDepthMask, void, (GLboolean flag));
|
||||
void glDepthMask(GLboolean flag) {
|
||||
real_glDepthMask()(flag);
|
||||
}
|
||||
GL_FUNC(glHint, void, (GLenum target, GLenum mode));
|
||||
void glHint(GLenum target, GLenum mode) {
|
||||
if (target != GL_PERSPECTIVE_CORRECTION_HINT) {
|
||||
real_glHint()(target, mode);
|
||||
}
|
||||
}
|
||||
GL_FUNC(glDeleteBuffers, void, (GLsizei n, const GLuint *buffers));
|
||||
void glDeleteBuffers(GLsizei n, const GLuint *buffers) {
|
||||
real_glDeleteBuffers()(n, buffers);
|
||||
}
|
||||
GL_FUNC(glColorMask, void, (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha));
|
||||
void glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
|
||||
real_glColorMask()(red, green, blue, alpha);
|
||||
}
|
||||
GL_FUNC(glTexSubImage2D, void, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels));
|
||||
void glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) {
|
||||
real_glTexSubImage2D()(target, level, xoffset, yoffset, width, height, format, type, pixels);
|
||||
}
|
||||
GL_FUNC(glGenTextures, void, (GLsizei n, GLuint *textures));
|
||||
void glGenTextures(GLsizei n, GLuint *textures) {
|
||||
real_glGenTextures()(n, textures);
|
||||
}
|
||||
GL_FUNC(glDeleteTextures, void, (GLsizei n, const GLuint *textures));
|
||||
void glDeleteTextures(GLsizei n, const GLuint *textures) {
|
||||
real_glDeleteTextures()(n, textures);
|
||||
}
|
||||
GL_FUNC(glBindTexture, void, (GLenum target, GLuint texture));
|
||||
void glBindTexture(GLenum target, GLuint texture) {
|
||||
real_glBindTexture()(target, texture);
|
||||
}
|
||||
GL_FUNC(glCullFace, void, (GLenum mode));
|
||||
void glCullFace(GLenum mode) {
|
||||
real_glCullFace()(mode);
|
||||
}
|
||||
GL_FUNC(glViewport, void, (GLint x, GLint y, GLsizei width, GLsizei height));
|
||||
void glViewport(GLint x, GLint y, GLsizei width, GLsizei height) {
|
||||
real_glViewport()(x, y, width, height);
|
||||
}
|
||||
GL_FUNC(glIsEnabled, GLboolean, (GLenum cap));
|
||||
GLboolean glIsEnabled(GLenum cap) {
|
||||
return real_glIsEnabled()(cap);
|
||||
}
|
||||
GL_FUNC(glGetIntegerv, void, (GLenum pname, GLint *data));
|
||||
void glGetIntegerv(GLenum pname, GLint *data) {
|
||||
real_glGetIntegerv()(pname, data);
|
||||
}
|
||||
GL_FUNC(glReadPixels, void, (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *data));
|
||||
void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *data) {
|
||||
real_glReadPixels()(x, y, width, height, format, type, data);
|
||||
}
|
||||
void glShadeModel(__attribute__((unused)) GLenum mode) {
|
||||
// Do Nothing
|
||||
}
|
||||
void glNormal3f(__attribute__((unused)) GLfloat nx, __attribute__((unused)) GLfloat ny, __attribute__((unused)) GLfloat nz) {
|
||||
// Do Nothing
|
||||
}
|
||||
GL_FUNC(glGenBuffers, void, (GLsizei n, GLuint *buffers));
|
||||
void glGenBuffers(GLsizei n, GLuint *buffers) {
|
||||
real_glGenBuffers()(n, buffers);
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
#version 100
|
||||
precision mediump float;
|
||||
// Texture
|
||||
uniform bool u_has_texture;
|
||||
uniform sampler2D u_texture_unit;
|
||||
// Color
|
||||
varying vec4 v_color;
|
||||
varying vec4 v_texture_pos;
|
||||
// Alpha Test
|
||||
uniform bool u_alpha_test;
|
||||
// Fog
|
||||
uniform bool u_fog;
|
||||
uniform vec4 u_fog_color;
|
||||
uniform bool u_fog_is_linear;
|
||||
uniform float u_fog_start;
|
||||
uniform float u_fog_end;
|
||||
varying vec4 v_fog_eye_position;
|
||||
// Main
|
||||
void main(void) {
|
||||
gl_FragColor = v_color;
|
||||
// Texture
|
||||
if (u_has_texture) {
|
||||
gl_FragColor *= texture2D(u_texture_unit, v_texture_pos.xy);
|
||||
}
|
||||
// Alpha Test
|
||||
if (u_alpha_test && gl_FragColor.a <= 0.1) {
|
||||
discard;
|
||||
}
|
||||
// Fog
|
||||
if (u_fog) {
|
||||
float fog_factor;
|
||||
if (u_fog_is_linear) {
|
||||
fog_factor = (u_fog_end - length(v_fog_eye_position)) / (u_fog_end - u_fog_start);
|
||||
} else {
|
||||
fog_factor = exp(-u_fog_start * length(v_fog_eye_position));
|
||||
}
|
||||
gl_FragColor = mix(gl_FragColor, u_fog_color, 1.0 - clamp(fog_factor, 0.0, 1.0));
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
#version 100
|
||||
precision mediump float;
|
||||
// Matrices
|
||||
uniform mat4 u_projection;
|
||||
uniform mat4 u_model_view;
|
||||
uniform mat4 u_texture;
|
||||
// Texture
|
||||
attribute vec3 a_vertex_coords;
|
||||
attribute vec2 a_texture_coords;
|
||||
varying vec4 v_texture_pos;
|
||||
// Color
|
||||
attribute vec4 a_color;
|
||||
varying vec4 v_color;
|
||||
// Fog
|
||||
varying vec4 v_fog_eye_position;
|
||||
// Main
|
||||
void main(void) {
|
||||
v_texture_pos = u_texture * vec4(a_texture_coords.xy, 0.0, 1.0);
|
||||
gl_Position = u_projection * u_model_view * vec4(a_vertex_coords.xyz, 1.0);
|
||||
v_color = a_color;
|
||||
v_fog_eye_position = u_model_view * vec4(a_vertex_coords.xyz, 1.0);
|
||||
}
|
|
@ -1,178 +0,0 @@
|
|||
#include <libreborn/libreborn.h>
|
||||
|
||||
#include "state.h"
|
||||
#include "../passthrough.h"
|
||||
|
||||
// GL State
|
||||
gl_state_t gl_state = {
|
||||
.color = {
|
||||
.red = 1,
|
||||
.green = 1,
|
||||
.blue = 1,
|
||||
.alpha = 1
|
||||
},
|
||||
.matrix_stacks = {
|
||||
.mode = GL_MODELVIEW
|
||||
},
|
||||
.alpha_test = 0,
|
||||
.texture_2d = 0,
|
||||
.fog = {
|
||||
.enabled = 0,
|
||||
.mode = GL_LINEAR,
|
||||
.color = {0, 0, 0, 0},
|
||||
.start = 0,
|
||||
.end = 1
|
||||
}
|
||||
};
|
||||
|
||||
// Change Color
|
||||
void glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
|
||||
gl_state.color.red = red;
|
||||
gl_state.color.green = green;
|
||||
gl_state.color.blue = blue;
|
||||
gl_state.color.alpha = alpha;
|
||||
}
|
||||
|
||||
// Array Pointer Storage
|
||||
#define ARRAY_POINTER_FUNC(func, name) \
|
||||
void func(GLint size, GLenum type, GLsizei stride, const void *pointer) { \
|
||||
gl_state.array_pointers.name.size = size; \
|
||||
gl_state.array_pointers.name.type = type; \
|
||||
gl_state.array_pointers.name.stride = stride; \
|
||||
gl_state.array_pointers.name.pointer = pointer; \
|
||||
}
|
||||
ARRAY_POINTER_FUNC(glVertexPointer, vertex)
|
||||
ARRAY_POINTER_FUNC(glColorPointer, color)
|
||||
ARRAY_POINTER_FUNC(glTexCoordPointer, tex_coord)
|
||||
static array_pointer_t *get_array_pointer(GLenum array) {
|
||||
switch (array) {
|
||||
case GL_VERTEX_ARRAY: {
|
||||
return &gl_state.array_pointers.vertex;
|
||||
}
|
||||
case GL_COLOR_ARRAY: {
|
||||
return &gl_state.array_pointers.color;
|
||||
}
|
||||
case GL_TEXTURE_COORD_ARRAY: {
|
||||
return &gl_state.array_pointers.tex_coord;
|
||||
}
|
||||
default: {
|
||||
ERR("Unsupported Array Pointer: %i", array);
|
||||
}
|
||||
}
|
||||
}
|
||||
void glEnableClientState(GLenum array) {
|
||||
get_array_pointer(array)->enabled = 1;
|
||||
}
|
||||
void glDisableClientState(GLenum array) {
|
||||
get_array_pointer(array)->enabled = 0;
|
||||
}
|
||||
|
||||
// Enable/Disable State
|
||||
GL_FUNC(glEnable, void, (GLenum cap));
|
||||
void glEnable(GLenum cap) {
|
||||
switch (cap) {
|
||||
case GL_ALPHA_TEST: {
|
||||
gl_state.alpha_test = 1;
|
||||
break;
|
||||
}
|
||||
case GL_TEXTURE_2D: {
|
||||
gl_state.texture_2d = 1;
|
||||
break;
|
||||
}
|
||||
case GL_COLOR_MATERIAL: {
|
||||
// Ignore
|
||||
break;
|
||||
}
|
||||
case GL_FOG: {
|
||||
gl_state.fog.enabled = 1;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
real_glEnable()(cap);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
GL_FUNC(glDisable, void, (GLenum cap));
|
||||
void glDisable(GLenum cap) {
|
||||
switch (cap) {
|
||||
case GL_ALPHA_TEST: {
|
||||
gl_state.alpha_test = 0;
|
||||
break;
|
||||
}
|
||||
case GL_TEXTURE_2D: {
|
||||
gl_state.texture_2d = 0;
|
||||
break;
|
||||
}
|
||||
case GL_COLOR_MATERIAL: {
|
||||
// Ignore
|
||||
break;
|
||||
}
|
||||
case GL_FOG: {
|
||||
gl_state.fog.enabled = 0;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
real_glDisable()(cap);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
void glAlphaFunc(GLenum func, GLclampf ref) {
|
||||
if (func != GL_GREATER && ref != 0.1f) {
|
||||
ERR("Unsupported Alpha Function");
|
||||
}
|
||||
}
|
||||
|
||||
// Fog
|
||||
#define UNSUPPORTED_FOG() ERR("Unsupported Fog Configuration")
|
||||
void glFogfv(GLenum pname, const GLfloat *params) {
|
||||
if (pname == GL_FOG_COLOR) {
|
||||
memcpy((void *) gl_state.fog.color, params, sizeof (gl_state.fog.color));
|
||||
} else {
|
||||
UNSUPPORTED_FOG();
|
||||
}
|
||||
}
|
||||
void glFogx(GLenum pname, GLfixed param) {
|
||||
if (pname == GL_FOG_MODE && (param == GL_LINEAR || param == GL_EXP)) {
|
||||
gl_state.fog.mode = param;
|
||||
} else {
|
||||
UNSUPPORTED_FOG();
|
||||
}
|
||||
}
|
||||
void glFogf(GLenum pname, GLfloat param) {
|
||||
switch (pname) {
|
||||
case GL_FOG_DENSITY:
|
||||
case GL_FOG_START: {
|
||||
gl_state.fog.start = param;
|
||||
break;
|
||||
}
|
||||
case GL_FOG_END: {
|
||||
gl_state.fog.end = param;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
UNSUPPORTED_FOG();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get Matrix Data
|
||||
GL_FUNC(glGetFloatv, void, (GLenum pname, GLfloat *params));
|
||||
void glGetFloatv(GLenum pname, GLfloat *params) {
|
||||
switch (pname) {
|
||||
case GL_MODELVIEW_MATRIX: {
|
||||
memcpy((void *) params, gl_state.matrix_stacks.model_view.stack[gl_state.matrix_stacks.model_view.i].data, MATRIX_DATA_SIZE);
|
||||
break;
|
||||
}
|
||||
case GL_PROJECTION_MATRIX: {
|
||||
memcpy((void *) params, gl_state.matrix_stacks.projection.stack[gl_state.matrix_stacks.projection.i].data, MATRIX_DATA_SIZE);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
real_glGetFloatv()(pname, params);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
#include <GLES/gl.h>
|
||||
|
||||
#include "matrix.h"
|
||||
|
||||
// Matrix Data
|
||||
#define MATRIX_STACK_DEPTH 256
|
||||
typedef struct {
|
||||
matrix_t stack[MATRIX_STACK_DEPTH];
|
||||
unsigned int i;
|
||||
} matrix_stack_t;
|
||||
|
||||
// Array Pointer Storage
|
||||
typedef struct {
|
||||
GLboolean enabled;
|
||||
GLint size;
|
||||
GLenum type;
|
||||
GLsizei stride;
|
||||
const void *pointer;
|
||||
} array_pointer_t;
|
||||
|
||||
// GL State
|
||||
typedef struct {
|
||||
struct {
|
||||
GLfloat red;
|
||||
GLfloat green;
|
||||
GLfloat blue;
|
||||
GLfloat alpha;
|
||||
} color;
|
||||
struct {
|
||||
GLenum mode;
|
||||
matrix_stack_t model_view;
|
||||
matrix_stack_t projection;
|
||||
matrix_stack_t texture;
|
||||
} matrix_stacks;
|
||||
struct {
|
||||
array_pointer_t vertex;
|
||||
array_pointer_t color;
|
||||
array_pointer_t tex_coord;
|
||||
} array_pointers;
|
||||
GLboolean alpha_test;
|
||||
GLboolean texture_2d;
|
||||
struct {
|
||||
GLboolean enabled;
|
||||
GLfixed mode;
|
||||
GLfloat color[4];
|
||||
GLfloat start;
|
||||
GLfloat end;
|
||||
} fog;
|
||||
} gl_state_t;
|
||||
extern gl_state_t gl_state;
|
|
@ -1,6 +1,6 @@
|
|||
#include <GLES/gl.h>
|
||||
|
||||
#include "passthrough.h"
|
||||
#include "../dependencies/gles-compatibility-layer/src/passthrough.h"
|
||||
|
||||
GL_FUNC(glFogfv, void, (GLenum pname, const GLfloat *params));
|
||||
void glFogfv(GLenum pname, const GLfloat *params) {
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
#define GLFW_INCLUDE_NONE
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
// Load GL Function
|
||||
#define GL_FUNC(name, return_type, args) \
|
||||
typedef return_type (*real_##name##_t)args; \
|
||||
\
|
||||
static real_##name##_t real_##name() { \
|
||||
static real_##name##_t func = NULL; \
|
||||
if (!func) { \
|
||||
func = (real_##name##_t) glfwGetProcAddress(#name); \
|
||||
if (!func) { \
|
||||
ERR("Error Resolving GL Symbol: " #name ": %s", dlerror()); \
|
||||
} \
|
||||
} \
|
||||
return func; \
|
||||
}
|
|
@ -140,11 +140,11 @@ void media_audio_play(const char *source, const char *name, float x, float y, fl
|
|||
// Set Attenuation
|
||||
alSourcei(al_source, AL_DISTANCE_MODEL, AL_LINEAR_DISTANCE_CLAMPED);
|
||||
AL_ERROR_CHECK();
|
||||
alSourcef(al_source, AL_MAX_DISTANCE, 22.0f);
|
||||
alSourcef(al_source, AL_MAX_DISTANCE, 16.0f);
|
||||
AL_ERROR_CHECK();
|
||||
alSourcef(al_source, AL_ROLLOFF_FACTOR, 1.0f);
|
||||
alSourcef(al_source, AL_ROLLOFF_FACTOR, 6.0f);
|
||||
AL_ERROR_CHECK();
|
||||
alSourcef(al_source, AL_REFERENCE_DISTANCE, 2.0f);
|
||||
alSourcef(al_source, AL_REFERENCE_DISTANCE, 5.0f);
|
||||
AL_ERROR_CHECK();
|
||||
|
||||
// Set Buffer
|
||||
|
|
|
@ -12,14 +12,14 @@
|
|||
#include "engine.h"
|
||||
|
||||
// Load Symbol From ELF File
|
||||
static void load_symbol(const char *source, const char *name, std::function<void(unsigned char *, uint32_t)> callback) {
|
||||
static void load_symbol(const char *source, const char *name, std::function<void(const unsigned char *, uint32_t)> callback) {
|
||||
static std::unique_ptr<LIEF::ELF::Binary> binary = NULL;
|
||||
if (binary == NULL) {
|
||||
binary = LIEF::ELF::Parser::parse(source);
|
||||
}
|
||||
const LIEF::ELF::Symbol *symbol = binary->get_dynamic_symbol(name);
|
||||
if (symbol != NULL) {
|
||||
std::vector<uint8_t> data = binary->get_content_from_virtual_address(symbol->value(), symbol->size(), LIEF::Binary::VA_TYPES::VA);
|
||||
LIEF::span<const uint8_t> data = binary->get_content_from_virtual_address(symbol->value(), symbol->size(), LIEF::Binary::VA_TYPES::VA);
|
||||
callback(data.data(), data.size());
|
||||
} else {
|
||||
WARN("Unable To Find Symbol: %s", name);
|
||||
|
@ -45,7 +45,7 @@ static ALuint load_sound(const char *source, const char *name) {
|
|||
ALuint buffer = 0;
|
||||
|
||||
// Load Symbol
|
||||
load_symbol(source, name, [name, &buffer](unsigned char *symbol, uint32_t size) {
|
||||
load_symbol(source, name, [name, &buffer](const unsigned char *symbol, uint32_t size) {
|
||||
// Load Metadata
|
||||
if (size < sizeof (audio_metadata)) {
|
||||
WARN("Symbol Too Small To Contain Audio Metadata: %s", name);
|
||||
|
@ -77,7 +77,7 @@ static ALuint load_sound(const char *source, const char *name) {
|
|||
WARN("Symbol Too Small To Contain Specified Audio Data: %s", name);
|
||||
return;
|
||||
}
|
||||
unsigned char *data = symbol + sizeof (audio_metadata);
|
||||
const unsigned char *data = symbol + sizeof (audio_metadata);
|
||||
|
||||
// Create Buffer
|
||||
alGenBuffers(1, &buffer);
|
||||
|
|
|
@ -55,7 +55,8 @@ static void character_event(char c) {
|
|||
// SDL_UserEvent Is Never Used In MCPI, So It Is Repurposed For Character Events
|
||||
SDL_Event event;
|
||||
event.type = SDL_USEREVENT;
|
||||
event.user.code = (int) c;
|
||||
event.user.code = USER_EVENT_CHARACTER;
|
||||
event.user.data1 = (int) c;
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
|
||||
|
@ -167,14 +168,21 @@ static SDLMod glfw_modifier_to_sdl_modifier(int mods) {
|
|||
|
||||
// Pass Key Presses To SDL
|
||||
static void glfw_key_raw(int key, int scancode, int action, int mods) {
|
||||
SDL_Event event;
|
||||
SDL_Event event1;
|
||||
int up = action == GLFW_RELEASE;
|
||||
event.type = up ? SDL_KEYUP : SDL_KEYDOWN;
|
||||
event.key.state = up ? SDL_RELEASED : SDL_PRESSED;
|
||||
event.key.keysym.scancode = scancode;
|
||||
event.key.keysym.mod = glfw_modifier_to_sdl_modifier(mods);
|
||||
event.key.keysym.sym = glfw_key_to_sdl_key(key);
|
||||
SDL_PushEvent(&event);
|
||||
event1.type = up ? SDL_KEYUP : SDL_KEYDOWN;
|
||||
event1.key.state = up ? SDL_RELEASED : SDL_PRESSED;
|
||||
event1.key.keysym.scancode = scancode;
|
||||
event1.key.keysym.mod = glfw_modifier_to_sdl_modifier(mods);
|
||||
event1.key.keysym.sym = glfw_key_to_sdl_key(key);
|
||||
SDL_PushEvent(&event1);
|
||||
// Allow MCPI To Access Original GLFW Keycode
|
||||
SDL_Event event2;
|
||||
event2.type = SDL_USEREVENT;
|
||||
event2.user.code = USER_EVENT_REAL_KEY;
|
||||
event2.user.data1 = event1.key.state;
|
||||
event2.user.data2 = key;
|
||||
SDL_PushEvent(&event2);
|
||||
}
|
||||
static void glfw_key(__attribute__((unused)) GLFWwindow *window, int key, int scancode, int action, int mods) {
|
||||
if (is_interactable) {
|
||||
|
@ -606,6 +614,12 @@ void SDL_WM_SetCaption(const char *title, __attribute__((unused)) const char *ic
|
|||
|
||||
// Make Window Context Current
|
||||
glfwMakeContextCurrent(glfw_window);
|
||||
|
||||
// Setup Compatibility Layer
|
||||
#ifdef MCPI_USE_GLES1_COMPATIBILITY_LAYER
|
||||
extern void init_gles_compatibility_layer();
|
||||
init_gles_compatibility_layer();
|
||||
#endif
|
||||
|
||||
// Debug
|
||||
glGetString_t glGetString = (glGetString_t) glfwGetProcAddress("glGetString");
|
||||
|
@ -679,12 +693,6 @@ void _media_handle_SDL_PollEvent() {
|
|||
// Process GLFW Events
|
||||
glfwPollEvents();
|
||||
|
||||
// Fix Joystick Detection While Running (Remove When glfw/glfw#2198 Is Merged)
|
||||
extern void _glfwDetectJoystickConnectionLinux(void);
|
||||
if (glfwGetPlatform() == GLFW_PLATFORM_WAYLAND) {
|
||||
_glfwDetectJoystickConnectionLinux();
|
||||
}
|
||||
|
||||
// Controller
|
||||
update_controller_state();
|
||||
|
||||
|
|
1
media-layer/include/GLES
Symbolic link
1
media-layer/include/GLES
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../dependencies/gles-compatibility-layer/src/include/GLES
|
|
@ -1,114 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define GL_FALSE 0
|
||||
#define GL_ARRAY_BUFFER_BINDING 0x8894
|
||||
#define GL_ARRAY_BUFFER 0x8892
|
||||
#define GL_TEXTURE_BINDING_2D 0x8069
|
||||
#define GL_UNSIGNED_BYTE 0x1401
|
||||
#define GL_FLOAT 0x1406
|
||||
#define GL_RGB 0x1907
|
||||
#define GL_RGBA 0x1908
|
||||
#define GL_MODELVIEW_MATRIX 0xba6
|
||||
#define GL_PROJECTION_MATRIX 0xba7
|
||||
#define GL_VIEWPORT 0xba2
|
||||
#define GL_DEPTH_TEST 0xb71
|
||||
#define GL_PACK_ALIGNMENT 0xd05
|
||||
#define GL_UNPACK_ALIGNMENT 0xcf5
|
||||
#define GL_SRC_ALPHA 0x302
|
||||
#define GL_ONE_MINUS_SRC_ALPHA 0x303
|
||||
#define GL_MODELVIEW 0x1700
|
||||
#define GL_PROJECTION 0x1701
|
||||
#define GL_TEXTURE 0x1702
|
||||
#define GL_VERTEX_ARRAY 0x8074
|
||||
#define GL_COLOR_ARRAY 0x8076
|
||||
#define GL_TEXTURE_COORD_ARRAY 0x8078
|
||||
#define GL_GREATER 0x204
|
||||
#define GL_ALPHA_TEST 0xbc0
|
||||
#define GL_TEXTURE_2D 0xde1
|
||||
#define GL_COLOR_MATERIAL 0xb57
|
||||
#define GL_PERSPECTIVE_CORRECTION_HINT 0xc50
|
||||
#define GL_FOG 0xb60
|
||||
#define GL_LINEAR 0x2601
|
||||
#define GL_EXP 0x800
|
||||
#define GL_FOG_DENSITY 0xb62
|
||||
#define GL_FOG_START 0xb63
|
||||
#define GL_FOG_END 0xb64
|
||||
#define GL_FOG_MODE 0xb65
|
||||
#define GL_FOG_COLOR 0xb66
|
||||
#define GL_BLEND 0xbe2
|
||||
|
||||
typedef float GLfloat;
|
||||
typedef float GLclampf;
|
||||
typedef int GLint;
|
||||
typedef unsigned char GLboolean;
|
||||
typedef int GLsizei;
|
||||
typedef unsigned int GLuint;
|
||||
typedef ssize_t GLsizeiptr;
|
||||
typedef intptr_t GLintptr;
|
||||
typedef int32_t GLfixed;
|
||||
typedef unsigned int GLbitfield;
|
||||
typedef unsigned int GLenum;
|
||||
typedef char GLchar;
|
||||
|
||||
void glFogfv(GLenum pname, const GLfloat *params);
|
||||
void glVertexPointer(GLint size, GLenum type, GLsizei stride, const void *pointer);
|
||||
void glLineWidth(GLfloat width);
|
||||
void glBlendFunc(GLenum sfactor, GLenum dfactor);
|
||||
void glDrawArrays(GLenum mode, GLint first, GLsizei count);
|
||||
void glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
|
||||
void glClear(GLbitfield mask);
|
||||
void glBufferData(GLenum target, GLsizeiptr size, const void *data, GLenum usage);
|
||||
void glFogx(GLenum pname, GLfixed param);
|
||||
void glFogf(GLenum pname, GLfloat param);
|
||||
void glMatrixMode(GLenum mode);
|
||||
void glColorPointer(GLint size, GLenum type, GLsizei stride, const void *pointer);
|
||||
void glScissor(GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
void glTexParameteri(GLenum target, GLenum pname, GLint param);
|
||||
void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
|
||||
void glEnable(GLenum cap);
|
||||
void glEnableClientState(GLenum array);
|
||||
void glPolygonOffset(GLfloat factor, GLfloat units);
|
||||
void glDisableClientState(GLenum array);
|
||||
void glDepthRangef(GLclampf near, GLclampf far);
|
||||
void glDepthFunc(GLenum func);
|
||||
void glBindBuffer(GLenum target, GLuint buffer);
|
||||
void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
|
||||
void glPopMatrix();
|
||||
void glLoadIdentity();
|
||||
void glScalef(GLfloat x, GLfloat y, GLfloat z);
|
||||
void glPushMatrix();
|
||||
void glDepthMask(GLboolean flag);
|
||||
void glHint(GLenum target, GLenum mode);
|
||||
void glMultMatrixf(const GLfloat *m);
|
||||
void glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const void *pointer);
|
||||
void glDeleteBuffers(GLsizei n, const GLuint *buffers);
|
||||
void glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
|
||||
void glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
|
||||
void glGenTextures(GLsizei n, GLuint *textures);
|
||||
void glDeleteTextures(GLsizei n, const GLuint *textures);
|
||||
void glAlphaFunc(GLenum func, GLclampf ref);
|
||||
void glGetFloatv(GLenum pname, GLfloat *params);
|
||||
void glBindTexture(GLenum target, GLuint texture);
|
||||
void glTranslatef(GLfloat x, GLfloat y, GLfloat z);
|
||||
void glShadeModel(GLenum mode);
|
||||
void glOrthof(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far);
|
||||
void glDisable(GLenum cap);
|
||||
void glCullFace(GLenum mode);
|
||||
void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
|
||||
void glViewport(GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
void glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz);
|
||||
GLboolean glIsEnabled(GLenum cap);
|
||||
void glGetIntegerv(GLenum pname, GLint *data);
|
||||
void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *data);
|
||||
void glGenBuffers(GLsizei n, GLuint *buffers);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -8,6 +8,10 @@ extern "C" {
|
|||
#define DEFAULT_WIDTH 840
|
||||
#define DEFAULT_HEIGHT 480
|
||||
|
||||
// SDL User Events
|
||||
#define USER_EVENT_CHARACTER 0 // data1 = 8-Bit Character
|
||||
#define USER_EVENT_REAL_KEY 1 // data1 = SDL_RELEASED/PRESSED, data2 = GLFW Key Code
|
||||
|
||||
void media_ensure_loaded();
|
||||
|
||||
void media_toggle_fullscreen();
|
||||
|
|
|
@ -17,6 +17,8 @@ elseif(BUILD_ARM_COMPONENTS)
|
|||
target_link_libraries(media-layer-core media-layer-headers reborn-util)
|
||||
target_compile_definitions(media-layer-core PRIVATE -DMEDIA_LAYER_PROXY_SERVER)
|
||||
# Install
|
||||
install(TARGETS media-layer-core DESTINATION "${MCPI_LIB_DIR}")
|
||||
if(MCPI_USE_MEDIA_LAYER_PROXY)
|
||||
install(TARGETS media-layer-core DESTINATION "${MCPI_LIB_DIR}")
|
||||
endif()
|
||||
install(TARGETS media-layer-core EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}")
|
||||
endif()
|
||||
|
|
|
@ -17,10 +17,7 @@ install(DIRECTORY "include/" DESTINATION "${MCPI_SDK_INCLUDE_DIR}/mods")
|
|||
add_library(compat SHARED src/compat/compat.c src/compat/egl.c src/compat/x11.c src/compat/bcm_host.c)
|
||||
target_link_libraries(compat mods-headers reborn-patch media-layer-core)
|
||||
if(NOT MCPI_HEADLESS_MODE)
|
||||
target_link_libraries(compat screenshot)
|
||||
endif()
|
||||
if(NOT MCPI_SERVER_MODE)
|
||||
target_link_libraries(compat input sign chat home dl)
|
||||
target_link_libraries(compat screenshot input sign chat home dl)
|
||||
endif()
|
||||
|
||||
add_library(readdir SHARED src/readdir/readdir.c)
|
||||
|
@ -33,7 +30,7 @@ target_link_libraries(version mods-headers reborn-patch symbols)
|
|||
|
||||
add_library(chat SHARED src/chat/chat.cpp src/chat/ui.c)
|
||||
target_link_libraries(chat mods-headers reborn-patch symbols feature)
|
||||
if(NOT MCPI_SERVER_MODE)
|
||||
if(NOT MCPI_HEADLESS_MODE)
|
||||
target_link_libraries(chat input media-layer-core pthread)
|
||||
endif()
|
||||
|
||||
|
@ -53,14 +50,16 @@ else()
|
|||
add_library(multiplayer SHARED src/multiplayer/multiplayer.cpp)
|
||||
target_link_libraries(multiplayer mods-headers reborn-patch symbols home feature)
|
||||
|
||||
add_library(benchmark SHARED src/benchmark/benchmark.cpp)
|
||||
target_link_libraries(benchmark mods-headers reborn-patch symbols compat misc media-layer-core)
|
||||
endif()
|
||||
|
||||
if(NOT MCPI_HEADLESS_MODE)
|
||||
add_library(sound SHARED src/sound/sound.cpp src/sound/repository.cpp)
|
||||
target_link_libraries(sound mods-headers reborn-patch symbols feature override media-layer-core)
|
||||
|
||||
add_library(camera SHARED src/camera/camera.cpp)
|
||||
target_link_libraries(camera mods-headers reborn-patch symbols feature home)
|
||||
if(NOT MCPI_HEADLESS_MODE)
|
||||
target_link_libraries(camera screenshot)
|
||||
endif()
|
||||
target_link_libraries(camera mods-headers reborn-patch symbols feature home screenshot)
|
||||
|
||||
add_library(input SHARED src/input/input.cpp src/input/bow.c src/input/attack.c src/input/toggle.c src/input/misc.c src/input/drop.cpp src/input/crafting.cpp)
|
||||
target_link_libraries(input mods-headers reborn-patch symbols creative feature misc media-layer-core)
|
||||
|
@ -71,17 +70,27 @@ else()
|
|||
add_library(touch SHARED src/touch/touch.cpp)
|
||||
target_link_libraries(touch mods-headers reborn-patch symbols feature)
|
||||
|
||||
add_library(textures SHARED src/textures/textures.cpp)
|
||||
target_link_libraries(textures mods-headers reborn-patch symbols media-layer-core feature misc)
|
||||
|
||||
add_library(atlas SHARED src/atlas/atlas.cpp)
|
||||
target_link_libraries(atlas mods-headers reborn-patch symbols feature media-layer-core)
|
||||
|
||||
add_library(title-screen SHARED src/title-screen/title-screen.cpp)
|
||||
target_link_libraries(title-screen mods-headers reborn-patch symbols feature compat)
|
||||
|
||||
add_library(benchmark SHARED src/benchmark/benchmark.cpp)
|
||||
target_link_libraries(benchmark mods-headers reborn-patch symbols compat misc media-layer-core)
|
||||
add_library(skin SHARED src/skin/skin.cpp src/skin/loader.cpp)
|
||||
target_link_libraries(skin mods-headers reborn-patch symbols feature misc textures media-layer-core stb_image)
|
||||
|
||||
add_library(screenshot SHARED src/screenshot/screenshot.c)
|
||||
target_link_libraries(screenshot mods-headers reborn-util media-layer-core stb_image)
|
||||
endif()
|
||||
|
||||
if(NOT MCPI_HEADLESS_MODE)
|
||||
add_library(textures SHARED src/textures/textures.cpp)
|
||||
else()
|
||||
add_library(textures SHARED src/textures/headless.cpp)
|
||||
endif()
|
||||
target_link_libraries(textures mods-headers reborn-patch symbols)
|
||||
if(NOT MCPI_HEADLESS_MODE)
|
||||
target_link_libraries(textures media-layer-core feature misc stb_image)
|
||||
endif()
|
||||
|
||||
add_library(override SHARED src/override/override.c)
|
||||
|
@ -99,11 +108,6 @@ target_link_libraries(options mods-headers reborn-patch symbols feature home)
|
|||
add_library(bucket SHARED src/bucket/bucket.cpp)
|
||||
target_link_libraries(bucket mods-headers reborn-patch symbols feature misc)
|
||||
|
||||
if(NOT MCPI_HEADLESS_MODE)
|
||||
add_library(screenshot SHARED src/screenshot/screenshot.c)
|
||||
target_link_libraries(screenshot mods-headers reborn-util media-layer-core png12)
|
||||
endif()
|
||||
|
||||
add_library(home SHARED src/home/home.c)
|
||||
target_link_libraries(home mods-headers reborn-patch symbols)
|
||||
|
||||
|
@ -111,22 +115,25 @@ add_library(test SHARED src/test/test.c)
|
|||
target_link_libraries(test mods-headers reborn-patch home)
|
||||
|
||||
add_library(init SHARED src/init/init.c)
|
||||
target_link_libraries(init mods-headers reborn-util compat game-mode misc death options chat creative bucket home version test media-layer-core)
|
||||
target_link_libraries(init mods-headers reborn-util compat game-mode misc death options chat creative bucket textures home version test media-layer-core)
|
||||
if(MCPI_SERVER_MODE)
|
||||
target_link_libraries(init server)
|
||||
else()
|
||||
target_link_libraries(init multiplayer sound camera input sign touch textures atlas title-screen benchmark)
|
||||
target_link_libraries(init multiplayer benchmark)
|
||||
endif()
|
||||
if(NOT MCPI_HEADLESS_MODE)
|
||||
target_link_libraries(init sound camera input sign touch atlas title-screen skin)
|
||||
endif()
|
||||
|
||||
## Install Mods
|
||||
set(MODS_TO_INSTALL init compat readdir feature game-mode misc override death options chat creative bucket home version test)
|
||||
set(MODS_TO_INSTALL init compat readdir feature game-mode misc override death options chat creative bucket textures home version test)
|
||||
if(MCPI_SERVER_MODE)
|
||||
list(APPEND MODS_TO_INSTALL server)
|
||||
else()
|
||||
list(APPEND MODS_TO_INSTALL multiplayer sound camera input sign touch textures atlas title-screen benchmark)
|
||||
list(APPEND MODS_TO_INSTALL multiplayer benchmark)
|
||||
endif()
|
||||
if(NOT MCPI_HEADLESS_MODE)
|
||||
list(APPEND MODS_TO_INSTALL screenshot)
|
||||
list(APPEND MODS_TO_INSTALL sound camera input sign touch atlas title-screen skin screenshot)
|
||||
endif()
|
||||
install(TARGETS ${MODS_TO_INSTALL} DESTINATION "${MCPI_INSTALL_DIR}/mods")
|
||||
# SDK
|
||||
|
|
|
@ -13,15 +13,19 @@ void init_compat();
|
|||
void init_server();
|
||||
#else
|
||||
void init_multiplayer();
|
||||
void init_benchmark();
|
||||
#endif
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
void init_sound();
|
||||
void init_input();
|
||||
void init_sign();
|
||||
void init_camera();
|
||||
void init_touch();
|
||||
void init_textures();
|
||||
void init_atlas();
|
||||
void init_title_screen();
|
||||
void init_skin();
|
||||
#endif
|
||||
void init_textures();
|
||||
void init_creative();
|
||||
void init_game_mode();
|
||||
void init_misc();
|
||||
|
@ -30,9 +34,6 @@ void init_options();
|
|||
void init_chat();
|
||||
void init_bucket();
|
||||
void init_home();
|
||||
#ifndef MCPI_SERVER_MODE
|
||||
void init_benchmark();
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
13
mods/include/mods/textures/textures.h
Normal file
13
mods/include/mods/textures/textures.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include <GLES/gl.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void glTexSubImage2D_with_scaling(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLsizei normal_texture_width, GLsizei normal_texture_height, GLenum format, GLenum type, const void *pixels);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -5,18 +5,18 @@
|
|||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
#ifndef MCPI_SERVER_MODE
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include <symbols/minecraft.h>
|
||||
#ifndef MCPI_SERVER_MODE
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
#include <media-layer/core.h>
|
||||
#endif
|
||||
|
||||
#include <mods/init/init.h>
|
||||
#include <mods/feature/feature.h>
|
||||
#ifndef MCPI_SERVER_MODE
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
#include <mods/input/input.h>
|
||||
#endif
|
||||
#include "chat-internal.h"
|
||||
|
@ -42,7 +42,7 @@ std::string chat_send_api_command(unsigned char *minecraft, char *str) {
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef MCPI_SERVER_MODE
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
// Send API Chat Command
|
||||
static void send_api_chat_command(unsigned char *minecraft, char *str) {
|
||||
char *command = NULL;
|
||||
|
@ -95,7 +95,7 @@ static void ServerSideNetworkHandler_handle_ChatPacket_injection(unsigned char *
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef MCPI_SERVER_MODE
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
// Message Queue
|
||||
static pthread_mutex_t queue_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static std::vector<std::string> queue;
|
||||
|
@ -144,7 +144,7 @@ void init_chat() {
|
|||
// Re-Broadcast ChatPacket
|
||||
patch_address(ServerSideNetworkHandler_handle_ChatPacket_vtable_addr, (void *) ServerSideNetworkHandler_handle_ChatPacket_injection);
|
||||
// Send Messages On Input Tick
|
||||
#ifndef MCPI_SERVER_MODE
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
input_run_on_tick(send_queued_messages);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include <libreborn/libreborn.h>
|
||||
|
||||
// Chat UI Code Is Useless In Headless Mode
|
||||
#ifndef MCPI_SERVER_MODE
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
|
@ -34,7 +34,7 @@ static void *chat_thread(__attribute__((unused)) void *nop) {
|
|||
"--text", "Enter Chat Message:",
|
||||
NULL
|
||||
};
|
||||
char *output = run_command(command, &return_code);
|
||||
char *output = run_command(command, &return_code, NULL);
|
||||
// Handle Message
|
||||
if (output != NULL) {
|
||||
// Check Return Code
|
||||
|
|
|
@ -11,6 +11,14 @@
|
|||
#include <SDL/SDL.h>
|
||||
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
#include <media-layer/core.h>
|
||||
|
||||
#include <mods/input/input.h>
|
||||
#include <mods/sign/sign.h>
|
||||
#include <mods/chat/chat.h>
|
||||
#include <mods/home/home.h>
|
||||
#endif
|
||||
|
||||
// Custom Title
|
||||
HOOK(SDL_WM_SetCaption, void, (__attribute__((unused)) const char *title, const char *icon)) {
|
||||
ensure_SDL_WM_SetCaption();
|
||||
|
@ -23,26 +31,19 @@ HOOK(SDL_ShowCursor, int, (int toggle)) {
|
|||
ensure_SDL_ShowCursor();
|
||||
return (*real_SDL_ShowCursor)(toggle == SDL_QUERY ? SDL_QUERY : SDL_DISABLE);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef MCPI_SERVER_MODE
|
||||
#include <media-layer/core.h>
|
||||
|
||||
#include <mods/input/input.h>
|
||||
#include <mods/sign/sign.h>
|
||||
#include <mods/chat/chat.h>
|
||||
#include <mods/home/home.h>
|
||||
|
||||
// Intercept SDL Events
|
||||
HOOK(SDL_PollEvent, int, (SDL_Event *event)) {
|
||||
// In Server Mode, Exit Requests Are Handled In src/server/server.cpp
|
||||
// Check If Exit Is Requested
|
||||
#ifndef MCPI_SERVER_MODE
|
||||
if (compat_check_exit_requested()) {
|
||||
// Send SDL_QUIT
|
||||
SDL_Event new_event;
|
||||
new_event.type = SDL_QUIT;
|
||||
SDL_PushEvent(&new_event);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Poll Events
|
||||
ensure_SDL_PollEvent();
|
||||
|
@ -52,6 +53,7 @@ HOOK(SDL_PollEvent, int, (SDL_Event *event)) {
|
|||
if (ret == 1 && event != NULL) {
|
||||
int handled = 0;
|
||||
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
switch (event->type) {
|
||||
case SDL_KEYDOWN: {
|
||||
// Handle Key Presses
|
||||
|
@ -59,9 +61,7 @@ HOOK(SDL_PollEvent, int, (SDL_Event *event)) {
|
|||
media_toggle_fullscreen();
|
||||
handled = 1;
|
||||
} else if (event->key.keysym.sym == SDLK_F2) {
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
screenshot_take(home_get());
|
||||
#endif
|
||||
handled = 1;
|
||||
} else if (event->key.keysym.sym == SDLK_F1) {
|
||||
input_hide_gui();
|
||||
|
@ -103,11 +103,14 @@ HOOK(SDL_PollEvent, int, (SDL_Event *event)) {
|
|||
}
|
||||
case SDL_USEREVENT: {
|
||||
// SDL_UserEvent Is Never Used In MCPI, So It Is Repurposed For Character Events
|
||||
sign_key_press((char) event->user.code);
|
||||
handled = 1;
|
||||
if (event->user.code == USER_EVENT_CHARACTER) {
|
||||
sign_key_press((char) event->user.data1);
|
||||
handled = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (handled) {
|
||||
// Event Was Handled
|
||||
|
@ -117,7 +120,6 @@ HOOK(SDL_PollEvent, int, (SDL_Event *event)) {
|
|||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Exit Handler
|
||||
static void exit_handler(__attribute__((unused)) int data) {
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
static char *run_command_proper(const char *command[], bool allow_empty) {
|
||||
// Run
|
||||
int return_code;
|
||||
char *output = run_command(command, &return_code);
|
||||
char *output = run_command(command, &return_code, NULL);
|
||||
|
||||
// Handle Message
|
||||
if (output != NULL) {
|
||||
|
|
|
@ -13,15 +13,18 @@ __attribute__((constructor)) static void init() {
|
|||
init_server();
|
||||
#else
|
||||
init_multiplayer();
|
||||
#endif
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
init_sound();
|
||||
init_input();
|
||||
init_sign();
|
||||
init_camera();
|
||||
init_touch();
|
||||
init_textures();
|
||||
init_atlas();
|
||||
init_title_screen();
|
||||
init_skin();
|
||||
#endif
|
||||
init_textures();
|
||||
init_creative();
|
||||
init_game_mode();
|
||||
init_misc();
|
||||
|
|
|
@ -45,6 +45,23 @@ static int32_t OptionsScreen_handleBackEvent_injection(unsigned char *screen, bo
|
|||
return 1;
|
||||
}
|
||||
|
||||
// Fix "Sleeping Beauty" Bug
|
||||
static int32_t InBedScreen_handleBackEvent_injection(unsigned char *screen, bool do_nothing) {
|
||||
if (!do_nothing) {
|
||||
// Close Screen
|
||||
unsigned char *minecraft = *(unsigned char **) (screen + Screen_minecraft_property_offset);
|
||||
(*Minecraft_setScreen)(minecraft, NULL);
|
||||
// Stop Sleeping
|
||||
unsigned char *player = *(unsigned char **) (minecraft + Minecraft_player_property_offset);
|
||||
if (player != NULL) {
|
||||
unsigned char *player_vtable = *(unsigned char **) player;
|
||||
Player_stopSleepInBed_t Player_stopSleepInBed = *(Player_stopSleepInBed_t *) (player_vtable + Player_stopSleepInBed_vtable_offset);
|
||||
(*Player_stopSleepInBed)(player, 1, 1, 1);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Set Mouse Grab State
|
||||
static int mouse_grab_state = 0;
|
||||
void input_set_mouse_grab_state(int state) {
|
||||
|
@ -90,6 +107,8 @@ void _init_misc() {
|
|||
if (enable_misc) {
|
||||
// Fix OptionsScreen Ignoring The Back Button
|
||||
patch_address(OptionsScreen_handleBackEvent_vtable_addr, (void *) OptionsScreen_handleBackEvent_injection);
|
||||
// Fix "Sleeping Beauty" Bug
|
||||
patch_address(InBedScreen_handleBackEvent_vtable_addr, (void *) InBedScreen_handleBackEvent_injection);
|
||||
// Disable Opening Inventory Using The Cursor When Cursor Is Hidden
|
||||
overwrite_calls((void *) Gui_handleClick, (void *) Gui_handleClick_injection);
|
||||
}
|
||||
|
|
|
@ -265,6 +265,7 @@ static int32_t FurnaceScreen_handleAddItem_injection(unsigned char *furnace_scre
|
|||
//
|
||||
// The default behavior for Touch GUI is to only render the cursor when the mouse is clicking, this fixes that.
|
||||
// This also makes the cursor always render if the mouse is unlocked, instead of just when there is a Screen showing.
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
static void GameRenderer_render_injection(unsigned char *game_renderer, float param_1) {
|
||||
// Call Original Method
|
||||
(*GameRenderer_render)(game_renderer, param_1);
|
||||
|
@ -281,6 +282,7 @@ static void GameRenderer_render_injection(unsigned char *game_renderer, float pa
|
|||
(*renderCursor)(x, y, minecraft);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Get Real Selected Slot
|
||||
int32_t misc_get_real_selected_slot(unsigned char *player) {
|
||||
|
@ -330,6 +332,167 @@ HOOK(bind, int, (int sockfd, const struct sockaddr *addr, socklen_t addrlen)) {
|
|||
return (*real_bind)(sockfd, new_addr, addrlen);
|
||||
}
|
||||
|
||||
// Change Grass Color
|
||||
static int32_t get_color(unsigned char *level_source, int32_t x, int32_t z) {
|
||||
unsigned char *level_source_vtable = *(unsigned char **) level_source;
|
||||
LevelSource_getBiome_t LevelSource_getBiome = *(LevelSource_getBiome_t *) (level_source_vtable + LevelSource_getBiome_vtable_offset);
|
||||
unsigned char *biome = (*LevelSource_getBiome)(level_source, x, z);
|
||||
if (biome == NULL) {
|
||||
return 0;
|
||||
}
|
||||
return *(int32_t *) (biome + Biome_color_property_offset);
|
||||
}
|
||||
#define BIOME_BLEND_SIZE 7
|
||||
static int32_t GrassTile_getColor_injection(__attribute__((unused)) unsigned char *tile, unsigned char *level_source, int32_t x, __attribute__((unused)) int32_t y, int32_t z) {
|
||||
int r_sum = 0;
|
||||
int g_sum = 0;
|
||||
int b_sum = 0;
|
||||
int color_sum = 0;
|
||||
int x_start = x - (BIOME_BLEND_SIZE / 2);
|
||||
int z_start = z - (BIOME_BLEND_SIZE / 2);
|
||||
for (int x_offset = 0; x_offset < BIOME_BLEND_SIZE; x_offset++) {
|
||||
for (int z_offset = 0; z_offset < BIOME_BLEND_SIZE; z_offset++) {
|
||||
int32_t color = get_color(level_source, x_start + x_offset, z_start + z_offset);
|
||||
r_sum += (color >> 16) & 0xff;
|
||||
g_sum += (color >> 8) & 0xff;
|
||||
b_sum += color & 0xff;
|
||||
color_sum++;
|
||||
}
|
||||
}
|
||||
int r_avg = r_sum / color_sum;
|
||||
int g_avg = g_sum / color_sum;
|
||||
int b_avg = b_sum / color_sum;
|
||||
return (r_avg << 16) | (g_avg << 8) | b_avg;
|
||||
}
|
||||
static int32_t TallGrass_getColor_injection(unsigned char *tile, unsigned char *level_source, int32_t x, int32_t y, int32_t z) {
|
||||
int32_t original_color = (*TallGrass_getColor)(tile, level_source, x, y, z);
|
||||
if (original_color == 0x339933) {
|
||||
return GrassTile_getColor_injection(tile, level_source, x, y, z);
|
||||
} else {
|
||||
return original_color;
|
||||
}
|
||||
}
|
||||
|
||||
// Generate Caves
|
||||
static void RandomLevelSource_buildSurface_injection(unsigned char *random_level_source, int32_t chunk_x, int32_t chunk_y, unsigned char *chunk_data, unsigned char **biomes) {
|
||||
// Call Original Method
|
||||
(*RandomLevelSource_buildSurface)(random_level_source, chunk_x, chunk_y, chunk_data, biomes);
|
||||
|
||||
// Get Level
|
||||
unsigned char *level = *(unsigned char **) (random_level_source + RandomLevelSource_level_property_offset);
|
||||
|
||||
// Get Cave Feature
|
||||
unsigned char *cave_feature = random_level_source + RandomLevelSource_cave_feature_property_offset;
|
||||
unsigned char *cave_feature_vtable = *(unsigned char **) cave_feature;
|
||||
|
||||
// Generate
|
||||
LargeFeature_apply_t LargeCaveFeature_apply = *(LargeFeature_apply_t *) (cave_feature_vtable + LargeFeature_apply_vtable_offset);
|
||||
(*LargeCaveFeature_apply)(cave_feature, random_level_source, level, chunk_x, chunk_y, chunk_data, 0);
|
||||
}
|
||||
|
||||
// No Block Tinting
|
||||
static int32_t Tile_getColor_injection() {
|
||||
return 0xffffff;
|
||||
}
|
||||
|
||||
// Disable Hostile AI In Creative Mode
|
||||
static unsigned char *PathfinderMob_findAttackTarget_injection(unsigned char *mob) {
|
||||
// Call Original Method
|
||||
unsigned char *mob_vtable = *(unsigned char **) mob;
|
||||
PathfinderMob_findAttackTarget_t PathfinderMob_findAttackTarget = *(PathfinderMob_findAttackTarget_t *) (mob_vtable + PathfinderMob_findAttackTarget_vtable_offset);
|
||||
unsigned char *target = (*PathfinderMob_findAttackTarget)(mob);
|
||||
|
||||
// Check If Creative Mode
|
||||
if (target != NULL) {
|
||||
unsigned char *inventory = *(unsigned char **) (target + Player_inventory_property_offset);
|
||||
bool is_creative = *(bool *) (inventory + FillingContainer_is_creative_property_offset);
|
||||
if (is_creative) {
|
||||
target = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Return
|
||||
return target;
|
||||
}
|
||||
|
||||
// 3D Chests
|
||||
static int32_t Tile_getRenderShape_injection(unsigned char *tile) {
|
||||
if (tile == *Tile_chest) {
|
||||
// Don't Render "Simple" Chest Model
|
||||
return -1;
|
||||
} else {
|
||||
// Call Original Method
|
||||
unsigned char *tile_vtable = *(unsigned char **) tile;
|
||||
Tile_getRenderShape_t Tile_getRenderShape = *(Tile_getRenderShape_t *) (tile_vtable + Tile_getRenderShape_vtable_offset);
|
||||
return (*Tile_getRenderShape)(tile);
|
||||
}
|
||||
}
|
||||
static unsigned char *ChestTileEntity_injection(unsigned char *tile_entity) {
|
||||
// Call Original Method
|
||||
(*ChestTileEntity)(tile_entity);
|
||||
|
||||
// Enable Renderer
|
||||
*(int32_t *) (tile_entity + TileEntity_renderer_id_property_offset) = 1;
|
||||
|
||||
// Return
|
||||
return tile_entity;
|
||||
}
|
||||
static bool is_rendering_chest = 0;
|
||||
static void ModelPart_render_injection(unsigned char *model_part, float scale) {
|
||||
// Start
|
||||
is_rendering_chest = 1;
|
||||
|
||||
// Call Original Method
|
||||
(*ModelPart_render)(model_part, scale);
|
||||
|
||||
// Stop
|
||||
is_rendering_chest = 0;
|
||||
}
|
||||
static void Tesselator_vertexUV_injection(unsigned char *tesselator, float x, float y, float z, float u, float v) {
|
||||
// Fix Chest Texture
|
||||
if (is_rendering_chest) {
|
||||
v /= 2;
|
||||
}
|
||||
|
||||
// Call Original Method
|
||||
(*Tesselator_vertexUV)(tesselator, x, y, z, u, v);
|
||||
}
|
||||
static bool ChestTileEntity_shouldSave_injection(__attribute__((unused)) unsigned char *tile_entity) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Animated 3D Chest
|
||||
static unsigned char *ContainerMenu_injection(unsigned char *container_menu, unsigned char *container, int32_t param_1) {
|
||||
// Call Original Method
|
||||
(*ContainerMenu)(container_menu, container, param_1);
|
||||
|
||||
// Play Animation
|
||||
unsigned char *tile_entity = container - ChestTileEntity_container_property_offset;
|
||||
bool is_client = *(bool *) (tile_entity + TileEntity_is_client_property_offset);
|
||||
if (!is_client) {
|
||||
unsigned char *container_vtable = *(unsigned char **) container;
|
||||
Container_startOpen_t Container_startOpen = *(Container_startOpen_t *) (container_vtable + Container_startOpen_vtable_offset);
|
||||
(*Container_startOpen)(container);
|
||||
}
|
||||
|
||||
// Return
|
||||
return container_menu;
|
||||
}
|
||||
static unsigned char *ContainerMenu_destructor_injection(unsigned char *container_menu) {
|
||||
// Play Animation
|
||||
unsigned char *container = *(unsigned char **) (container_menu + ContainerMenu_container_property_offset);
|
||||
unsigned char *tile_entity = container - ChestTileEntity_container_property_offset;
|
||||
bool is_client = *(bool *) (tile_entity + TileEntity_is_client_property_offset);
|
||||
if (!is_client) {
|
||||
unsigned char *container_vtable = *(unsigned char **) container;
|
||||
Container_stopOpen_t Container_stopOpen = *(Container_stopOpen_t *) (container_vtable + Container_stopOpen_vtable_offset);
|
||||
(*Container_stopOpen)(container);
|
||||
}
|
||||
|
||||
// Call Original Method
|
||||
return (*ContainerMenu_destructor)(container_menu);
|
||||
}
|
||||
|
||||
// Init
|
||||
static void nop() {
|
||||
}
|
||||
|
@ -388,6 +551,10 @@ void init_misc() {
|
|||
overwrite_calls((void *) FurnaceScreen_handleAddItem, (void *) FurnaceScreen_handleAddItem_injection);
|
||||
}
|
||||
|
||||
#ifdef MCPI_HEADLESS_MODE
|
||||
// Don't Render Game In Headless Mode
|
||||
overwrite_calls((void *) GameRenderer_render, (void *) nop);
|
||||
#else
|
||||
// Improved Cursor Rendering
|
||||
if (feature_has("Improved Cursor Rendering", server_disabled)) {
|
||||
// Disable Normal Cursor Rendering
|
||||
|
@ -396,6 +563,7 @@ void init_misc() {
|
|||
// Add Custom Cursor Rendering
|
||||
overwrite_calls((void *) GameRenderer_render, (void *) GameRenderer_render_injection);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Disable V-Sync
|
||||
if (feature_has("Disable V-Sync", server_enabled)) {
|
||||
|
@ -430,6 +598,63 @@ void init_misc() {
|
|||
patch((void *) 0x19fa0, nop_patch);
|
||||
}
|
||||
|
||||
// Change Grass Color
|
||||
if (feature_has("Add Biome Colors To Grass", server_disabled)) {
|
||||
patch_address((void *) GrassTile_getColor_vtable_addr, (void *) GrassTile_getColor_injection);
|
||||
patch_address((void *) TallGrass_getColor_vtable_addr, (void *) TallGrass_getColor_injection);
|
||||
}
|
||||
|
||||
// Generate Caves
|
||||
if (feature_has("Generate Caves", server_auto)) {
|
||||
overwrite_calls((void *) RandomLevelSource_buildSurface, (void *) RandomLevelSource_buildSurface_injection);
|
||||
}
|
||||
|
||||
// Disable Block Tinting
|
||||
if (feature_has("Disable Block Tinting", server_disabled)) {
|
||||
patch_address((void *) GrassTile_getColor_vtable_addr, (void *) Tile_getColor_injection);
|
||||
patch_address((void *) TallGrass_getColor_vtable_addr, (void *) Tile_getColor_injection);
|
||||
patch_address((void *) StemTile_getColor_vtable_addr, (void *) Tile_getColor_injection);
|
||||
patch_address((void *) LeafTile_getColor_vtable_addr, (void *) Tile_getColor_injection);
|
||||
overwrite((void *) LiquidTile_getColor, (void *) Tile_getColor_injection);
|
||||
}
|
||||
|
||||
// Custom GUI Scale
|
||||
const char *gui_scale_str = getenv("MCPI_GUI_SCALE");
|
||||
if (gui_scale_str != NULL) {
|
||||
unsigned char nop_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
||||
patch((void *) 0x173e8, nop_patch);
|
||||
patch((void *) 0x173f0, nop_patch);
|
||||
float gui_scale = strtof(gui_scale_str, NULL);
|
||||
uint32_t gui_scale_raw;
|
||||
memcpy(&gui_scale_raw, &gui_scale, sizeof (gui_scale_raw));
|
||||
patch_address((void *) 0x17520, (void *) gui_scale_raw);
|
||||
}
|
||||
|
||||
// Disable Hostile AI In Creative Mode
|
||||
if (feature_has("Disable Hostile AI In Creative Mode", server_enabled)) {
|
||||
overwrite_call((void *) 0x83b8c, (void *) PathfinderMob_findAttackTarget_injection);
|
||||
}
|
||||
|
||||
// 3D Chests
|
||||
if (feature_has("3D Chest Model", server_disabled)) {
|
||||
overwrite_call((void *) 0x5e830, (void *) Tile_getRenderShape_injection);
|
||||
overwrite_calls((void *) ChestTileEntity, (void *) ChestTileEntity_injection);
|
||||
overwrite_call((void *) 0x6655c, (void *) ModelPart_render_injection);
|
||||
overwrite_call((void *) 0x66568, (void *) ModelPart_render_injection);
|
||||
overwrite_call((void *) 0x66574, (void *) ModelPart_render_injection);
|
||||
overwrite_calls((void *) Tesselator_vertexUV, (void *) Tesselator_vertexUV_injection);
|
||||
unsigned char chest_model_patch[4] = {0x13, 0x20, 0xa0, 0xe3}; // "mov r2, #0x13"
|
||||
patch((void *) 0x66fc8, chest_model_patch);
|
||||
unsigned char chest_color_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
||||
patch((void *) 0x66404, chest_color_patch);
|
||||
|
||||
// Animation
|
||||
overwrite_calls((void *) ContainerMenu, (void *) ContainerMenu_injection);
|
||||
overwrite_calls((void *) ContainerMenu_destructor, (void *) ContainerMenu_destructor_injection);
|
||||
patch_address(ContainerMenu_destructor_vtable_addr, (void *) ContainerMenu_destructor_injection);
|
||||
}
|
||||
patch_address((void *) 0x115b48, (void *) ChestTileEntity_shouldSave_injection);
|
||||
|
||||
// Init C++ And Logging
|
||||
_init_misc_cpp();
|
||||
_init_misc_logging();
|
||||
|
|
|
@ -13,15 +13,25 @@
|
|||
|
||||
// Read Asset File
|
||||
static AppPlatform_readAssetFile_return_value AppPlatform_readAssetFile_injection(__attribute__((unused)) unsigned char *app_platform, std::string const& path) {
|
||||
// Open File
|
||||
std::ifstream stream("data/" + path, std::ios_base::binary | std::ios_base::ate);
|
||||
if (!stream) {
|
||||
// Does Not Exist
|
||||
AppPlatform_readAssetFile_return_value ret;
|
||||
ret.length = -1;
|
||||
ret.data = NULL;
|
||||
return ret;
|
||||
}
|
||||
// Read File
|
||||
std::string full_path("data/");
|
||||
full_path.append(path);
|
||||
std::ifstream stream(full_path);
|
||||
std::string str((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>());
|
||||
long len = stream.tellg();
|
||||
char *buf = new char[len];
|
||||
stream.seekg(0, stream.beg);
|
||||
stream.read(buf, len);
|
||||
stream.close();
|
||||
// Return String
|
||||
AppPlatform_readAssetFile_return_value ret;
|
||||
ret.length = str.length();
|
||||
ret.data = strdup(str.c_str());
|
||||
ret.length = len;
|
||||
ret.data = strdup(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ static void load_servers() {
|
|||
// Write Defaults
|
||||
std::ofstream server_list_file_output(file);
|
||||
server_list_file_output << "# External Servers File\n";
|
||||
server_list_file_output << "thebrokenrail.com\n";
|
||||
server_list_file_output << "# Example: thebrokenrail.com\n";
|
||||
server_list_file_output.close();
|
||||
// Re-Open Stream
|
||||
server_list_file = std::ifstream(file);
|
||||
|
|
|
@ -27,6 +27,12 @@ HOOK(access, int, (const char *pathname, int mode)) {
|
|||
|
||||
// Get Override Path For File (If It Exists)
|
||||
char *override_get_path(const char *filename) {
|
||||
// Custom Skin
|
||||
if (starts_with(filename, "data/images/$")) {
|
||||
// Fallback Texture
|
||||
filename = "data/images/mob/char.png";
|
||||
}
|
||||
|
||||
// Get MCPI Home Path
|
||||
char *home_path = home_get();
|
||||
// Get Asset Override Path
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <png.h>
|
||||
#include "stb_image.h"
|
||||
#include "stb_image_write.h"
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <GLES/gl.h>
|
||||
|
@ -31,68 +32,11 @@ static void ensure_screenshots_folder(char *screenshots) {
|
|||
|
||||
// Take Screenshot
|
||||
static int save_png(const char *filename, unsigned char *pixels, int line_size, int width, int height) {
|
||||
// Return value
|
||||
int ret = 0;
|
||||
// Setup
|
||||
stbi_flip_vertically_on_write(1);
|
||||
|
||||
// Variables
|
||||
png_structp png = NULL;
|
||||
png_infop info = NULL;
|
||||
FILE *file = NULL;
|
||||
png_colorp palette = NULL;
|
||||
png_bytep rows[height];
|
||||
for (int i = 0; i < height; ++i) {
|
||||
rows[height - i - 1] = (png_bytep) (&pixels[i * line_size]);
|
||||
}
|
||||
|
||||
// Init
|
||||
png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if (!png) {
|
||||
ret = 1;
|
||||
goto ret;
|
||||
}
|
||||
info = png_create_info_struct(png);
|
||||
if (!info) {
|
||||
ret = 1;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
// Open File
|
||||
file = fopen(filename, "wb");
|
||||
if (!file) {
|
||||
ret = 1;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
// Prepare To Write
|
||||
png_init_io(png, file);
|
||||
png_set_IHDR(png, info, width, height, 8 /* Depth */, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
|
||||
palette = (png_colorp) png_malloc(png, PNG_MAX_PALETTE_LENGTH * sizeof(png_color));
|
||||
if (!palette) {
|
||||
ret = 1;
|
||||
goto ret;
|
||||
}
|
||||
png_set_PLTE(png, info, palette, PNG_MAX_PALETTE_LENGTH);
|
||||
png_write_info(png, info);
|
||||
png_set_packing(png);
|
||||
|
||||
// Write
|
||||
png_write_image(png, rows);
|
||||
png_write_end(png, info);
|
||||
|
||||
ret:
|
||||
// Free
|
||||
if (palette != NULL) {
|
||||
png_free(png, palette);
|
||||
}
|
||||
if (file != NULL) {
|
||||
fclose(file);
|
||||
}
|
||||
if (png != NULL) {
|
||||
png_destroy_write_struct(&png, &info);
|
||||
}
|
||||
|
||||
// Return
|
||||
return ret;
|
||||
// Write Image
|
||||
return !stbi_write_png(filename, width, height, 4, pixels, line_size);
|
||||
}
|
||||
void screenshot_take(char *home) {
|
||||
// Get Directory
|
||||
|
@ -144,7 +88,8 @@ void screenshot_take(char *home) {
|
|||
int size = height * line_size;
|
||||
|
||||
// Read Pixels
|
||||
unsigned char pixels[size];
|
||||
unsigned char *pixels = (unsigned char *) malloc(size);
|
||||
ALLOC_CHECK(pixels);
|
||||
glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
// Save Image
|
||||
|
@ -157,4 +102,5 @@ void screenshot_take(char *home) {
|
|||
// Free
|
||||
free(file);
|
||||
free(screenshots);
|
||||
free(pixels);
|
||||
}
|
||||
|
|
|
@ -60,7 +60,8 @@ static ServerProperties &get_server_properties() {
|
|||
#define DEFAULT_WORLD_NAME "world"
|
||||
#define DEFAULT_MAX_PLAYERS "4"
|
||||
#define DEFAULT_WHITELIST "false"
|
||||
#define DEFAULT_DEATH_MESSAGES "false"
|
||||
#define DEFAULT_DEATH_MESSAGES "true"
|
||||
#define DEFAULT_GENERATE_CAVES "true"
|
||||
|
||||
// Get World Name
|
||||
static std::string get_world_name() {
|
||||
|
@ -487,6 +488,9 @@ static const char *get_features() {
|
|||
if (get_server_properties().get_bool("death-messages", DEFAULT_DEATH_MESSAGES)) {
|
||||
features += "Implement Death Messages|";
|
||||
}
|
||||
if (get_server_properties().get_bool("generate-caves", DEFAULT_GENERATE_CAVES)) {
|
||||
features += "Generate Caves|";
|
||||
}
|
||||
}
|
||||
return features.c_str();
|
||||
}
|
||||
|
@ -536,6 +540,8 @@ static void server_init() {
|
|||
properties_file_output << "whitelist=" DEFAULT_WHITELIST "\n";
|
||||
properties_file_output << "# Enable Death Messages\n";
|
||||
properties_file_output << "death-messages=" DEFAULT_DEATH_MESSAGES "\n";
|
||||
properties_file_output << "# Generate Caves\n";
|
||||
properties_file_output << "generate-caves=" DEFAULT_GENERATE_CAVES "\n";
|
||||
properties_file_output.close();
|
||||
// Re-Open File
|
||||
properties_file = std::ifstream(file);
|
||||
|
|
2
mods/src/skin/README.md
Normal file
2
mods/src/skin/README.md
Normal file
|
@ -0,0 +1,2 @@
|
|||
# ``skin`` Mod
|
||||
This mod adds custom skin loading.
|
144
mods/src/skin/loader.cpp
Normal file
144
mods/src/skin/loader.cpp
Normal file
|
@ -0,0 +1,144 @@
|
|||
#include <pthread.h>
|
||||
#include <vector>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
#include <GLES/gl.h>
|
||||
|
||||
#include <mods/misc/misc.h>
|
||||
#include <mods/textures/textures.h>
|
||||
#include "skin-internal.h"
|
||||
|
||||
#include "stb_image.h"
|
||||
|
||||
// Constants
|
||||
#define SKIN_WIDTH 64
|
||||
#define SKIN_HEIGHT 32
|
||||
|
||||
// Loading Pending Skins
|
||||
struct pending_skin {
|
||||
int32_t texture_id;
|
||||
char *data;
|
||||
int size;
|
||||
};
|
||||
static std::vector<pending_skin> &get_pending_skins() {
|
||||
static std::vector<pending_skin> pending_skins;
|
||||
return pending_skins;
|
||||
}
|
||||
static pthread_mutex_t pending_skins_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static void load_pending_skins(__attribute__((unused)) unsigned char *minecraft) {
|
||||
// Lock
|
||||
pthread_mutex_lock(&pending_skins_lock);
|
||||
|
||||
// Loop
|
||||
for (pending_skin &skin : get_pending_skins()) {
|
||||
// Read PNG Info
|
||||
int width = 0, height = 0, channels = 0;
|
||||
stbi_uc *img = stbi_load_from_memory((unsigned char *) skin.data, skin.size, &width, &height, &channels, STBI_rgb_alpha);
|
||||
if (width != SKIN_WIDTH || height != SKIN_HEIGHT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Load Texture
|
||||
GLint last_texture;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||
glBindTexture(GL_TEXTURE_2D, skin.texture_id);
|
||||
glTexSubImage2D_with_scaling(GL_TEXTURE_2D, 0, 0, 0, width, height, SKIN_WIDTH, SKIN_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, img);
|
||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||
|
||||
// Free
|
||||
stbi_image_free(img);
|
||||
}
|
||||
|
||||
// Free
|
||||
for (pending_skin &skin : get_pending_skins()) {
|
||||
free(skin.data);
|
||||
}
|
||||
|
||||
// Clear
|
||||
get_pending_skins().clear();
|
||||
|
||||
// Unlock
|
||||
pthread_mutex_unlock(&pending_skins_lock);
|
||||
}
|
||||
|
||||
// Skin Server
|
||||
static std::string get_skin_server() {
|
||||
const char *custom_server = getenv("MCPI_SKIN_SERVER");
|
||||
if (custom_server != NULL) {
|
||||
return custom_server;
|
||||
} else {
|
||||
return MCPI_SKIN_SERVER;
|
||||
}
|
||||
}
|
||||
|
||||
// Skin Loader
|
||||
struct loader_data {
|
||||
int32_t texture_id;
|
||||
std::string name;
|
||||
};
|
||||
static void *loader_thread(void *user_data) {
|
||||
// Loader Data
|
||||
loader_data *data = (loader_data *) user_data;
|
||||
|
||||
// Download
|
||||
std::string url = get_skin_server() + '/' + data->name + ".png";
|
||||
int return_code;
|
||||
const char *command[] = {"wget", "-O", "-", url.c_str(), NULL};
|
||||
size_t output_size = 0;
|
||||
char *output = run_command(command, &return_code, &output_size);
|
||||
|
||||
// Check Success
|
||||
if (output != NULL && is_exit_status_success(return_code)) {
|
||||
// Success
|
||||
DEBUG("Downloaded Skin: %s", data->name.c_str());
|
||||
|
||||
// Add To Pending Skins
|
||||
pending_skin skin;
|
||||
skin.texture_id = data->texture_id;
|
||||
skin.data = output;
|
||||
skin.size = (int) output_size;
|
||||
pthread_mutex_lock(&pending_skins_lock);
|
||||
get_pending_skins().push_back(skin);
|
||||
pthread_mutex_unlock(&pending_skins_lock);
|
||||
} else {
|
||||
// Failure
|
||||
WARN("Failed To Download Skin: %s", data->name.c_str());
|
||||
free(output);
|
||||
}
|
||||
|
||||
// Free
|
||||
delete data;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Intercept Texture Creation
|
||||
static int32_t Textures_assignTexture_injection(unsigned char *textures, std::string const& name, unsigned char *data) {
|
||||
// Call Original Method
|
||||
int32_t id = (*Textures_assignTexture)(textures, name, data);
|
||||
|
||||
// Load Skin
|
||||
if (starts_with(name.c_str(), "$")) {
|
||||
loader_data *user_data = new loader_data;
|
||||
user_data->name = name.substr(1);
|
||||
DEBUG("Loading Skin: %s", user_data->name.c_str());
|
||||
user_data->texture_id = id;
|
||||
// Start Thread
|
||||
pthread_t thread;
|
||||
pthread_create(&thread, NULL, loader_thread, (void *) user_data);
|
||||
}
|
||||
|
||||
// Return
|
||||
return id;
|
||||
}
|
||||
|
||||
// Init
|
||||
void _init_skin_loader() {
|
||||
// Intercept Texture Creation
|
||||
overwrite_calls((void *) Textures_assignTexture, (void *) Textures_assignTexture_injection);
|
||||
// Pending Skins
|
||||
misc_run_on_tick(load_pending_skins);
|
||||
// Log
|
||||
DEBUG("Skin Server: %s", get_skin_server().c_str());
|
||||
}
|
3
mods/src/skin/skin-internal.h
Normal file
3
mods/src/skin/skin-internal.h
Normal file
|
@ -0,0 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
__attribute__((visibility("internal"))) void _init_skin_loader();
|
97
mods/src/skin/skin.cpp
Normal file
97
mods/src/skin/skin.cpp
Normal file
|
@ -0,0 +1,97 @@
|
|||
#include <libreborn/libreborn.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
#include <mods/init/init.h>
|
||||
#include <mods/feature/feature.h>
|
||||
#include "skin-internal.h"
|
||||
|
||||
// Base64 Encode (https://gist.github.com/tomykaira/f0fd86b6c73063283afe550bc5d77594)
|
||||
static std::string base64_encode(const std::string data) {
|
||||
static constexpr char encoding_table[] = {
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
|
||||
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
||||
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
||||
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
|
||||
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
|
||||
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
|
||||
'w', 'x', 'y', 'z', '0', '1', '2', '3',
|
||||
'4', '5', '6', '7', '8', '9', '+', '/'
|
||||
};
|
||||
|
||||
size_t in_len = data.size();
|
||||
size_t out_len = 4 * ((in_len + 2) / 3);
|
||||
std::string ret(out_len, '\0');
|
||||
size_t i;
|
||||
char *p = const_cast<char*>(ret.c_str());
|
||||
|
||||
for (i = 0; i < in_len - 2; i += 3) {
|
||||
*p++ = encoding_table[(data[i] >> 2) & 0x3f];
|
||||
*p++ = encoding_table[((data[i] & 0x3) << 4) | ((int) (data[i + 1] & 0xf0) >> 4)];
|
||||
*p++ = encoding_table[((data[i + 1] & 0xf) << 2) | ((int) (data[i + 2] & 0xc0) >> 6)];
|
||||
*p++ = encoding_table[data[i + 2] & 0x3f];
|
||||
}
|
||||
if (i < in_len) {
|
||||
*p++ = encoding_table[(data[i] >> 2) & 0x3f];
|
||||
if (i == (in_len - 1)) {
|
||||
*p++ = encoding_table[((data[i] & 0x3) << 4)];
|
||||
*p++ = '=';
|
||||
}
|
||||
else {
|
||||
*p++ = encoding_table[((data[i] & 0x3) << 4) | ((int) (data[i + 1] & 0xf0) >> 4)];
|
||||
*p++ = encoding_table[((data[i + 1] & 0xf) << 2)];
|
||||
}
|
||||
*p++ = '=';
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Change Texture For Player Entities
|
||||
static void Player_username_assign_injection(std::string *target, std::string *username) {
|
||||
// Call Original Method
|
||||
*target = *username;
|
||||
|
||||
// Get Player
|
||||
unsigned char *player = ((unsigned char *) target) - Player_username_property_offset;
|
||||
// Get Texture
|
||||
std::string *texture = (std::string *) (player + Mob_texture_property_offset);
|
||||
|
||||
// Set Texture
|
||||
*texture = '$' + base64_encode(*username);
|
||||
}
|
||||
static void Player_username_assign_injection_2(std::string *target, const char *username) {
|
||||
std::string username_str = username;
|
||||
Player_username_assign_injection(target, &username_str);
|
||||
}
|
||||
|
||||
// Change Texture For HUD
|
||||
static int32_t Textures_loadAndBindTexture_injection(unsigned char *textures, __attribute__((unused)) std::string const& name) {
|
||||
// Change Texture
|
||||
static std::string new_texture;
|
||||
if (new_texture.length() == 0) {
|
||||
std::string username = base64_encode(*default_username);
|
||||
new_texture = '$' + username;
|
||||
}
|
||||
|
||||
// Call Original Method
|
||||
return (*Textures_loadAndBindTexture)(textures, new_texture);
|
||||
}
|
||||
|
||||
// Init
|
||||
void init_skin() {
|
||||
// Check Feature Flag
|
||||
if (feature_has("Load Custom Skins", server_disabled)) {
|
||||
// LocalPlayer
|
||||
overwrite_call((void *) 0x44c28, (void *) Player_username_assign_injection);
|
||||
// RemotePlayer
|
||||
overwrite_call((void *) 0x6ce58, (void *) Player_username_assign_injection_2);
|
||||
// ServerPlayer
|
||||
overwrite_call((void *) 0x7639c, (void *) Player_username_assign_injection_2);
|
||||
|
||||
// HUD
|
||||
overwrite_call((void *) 0x4c6d0, (void *) Textures_loadAndBindTexture_injection);
|
||||
|
||||
// Loader
|
||||
_init_skin_loader();
|
||||
}
|
||||
}
|
|
@ -59,10 +59,8 @@ std::string _sound_get_source_file() {
|
|||
static void play(std::string name, float x, float y, float z, float volume, float pitch, bool is_ui) {
|
||||
std::string source = _sound_get_source_file();
|
||||
std::string resolved_name = _sound_pick(name);
|
||||
if (pitch < 0.5f) {
|
||||
pitch = 0.5f;
|
||||
} else if (pitch > 2.0f) {
|
||||
pitch = 2.0f;
|
||||
if (pitch < 0.01f) {
|
||||
pitch = 1;
|
||||
}
|
||||
if (source.size() > 0 && resolved_name.size() > 0) {
|
||||
media_audio_play(source.c_str(), resolved_name.c_str(), x, y, z, pitch, volume, is_ui);
|
||||
|
|
14
mods/src/textures/headless.cpp
Normal file
14
mods/src/textures/headless.cpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
#include <libreborn/libreborn.h>
|
||||
#include <symbols/minecraft.h>
|
||||
#include <mods/init/init.h>
|
||||
|
||||
// Disable Texture Loading
|
||||
static Texture AppPlatform_linux_loadTexture_injection(__attribute__((unused)) unsigned char *app_platform, __attribute__((unused)) std::string const& path, __attribute__((unused)) bool b) {
|
||||
return Texture();
|
||||
}
|
||||
|
||||
// Init
|
||||
void init_textures() {
|
||||
// Disable Texture Loading
|
||||
overwrite((void *) AppPlatform_linux_loadTexture, (void *) AppPlatform_linux_loadTexture_injection);
|
||||
}
|
|
@ -9,8 +9,11 @@
|
|||
|
||||
#include <mods/misc/misc.h>
|
||||
#include <mods/feature/feature.h>
|
||||
#include <mods/textures/textures.h>
|
||||
#include <mods/init/init.h>
|
||||
|
||||
#include "stb_image.h"
|
||||
|
||||
// Animated Water
|
||||
static void Minecraft_tick_injection(unsigned char *minecraft) {
|
||||
// Tick Dynamic Textures
|
||||
|
@ -124,7 +127,7 @@ static void *scale_texture(const unsigned char *src, GLsizei old_width, GLsizei
|
|||
}
|
||||
|
||||
// Scale Animated Textures
|
||||
static void Textures_tick_glTexSubImage2D_injection(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) {
|
||||
void glTexSubImage2D_with_scaling(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLsizei normal_texture_width, GLsizei normal_texture_height, GLenum format, GLenum type, const void *pixels) {
|
||||
// Get Current Texture Size
|
||||
GLint current_texture;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_texture);
|
||||
|
@ -133,8 +136,8 @@ static void Textures_tick_glTexSubImage2D_injection(GLenum target, GLint level,
|
|||
get_texture_size(current_texture, &texture_width, &texture_height);
|
||||
|
||||
// Calculate Factor
|
||||
float width_factor = ((float) texture_width) / 256.0f;
|
||||
float height_factor = ((float) texture_height) / 256.0f;
|
||||
float width_factor = ((float) texture_width) / ((float) normal_texture_width);
|
||||
float height_factor = ((float) texture_height) / ((float) normal_texture_height);
|
||||
|
||||
// Only Scale If Needed
|
||||
if (width_factor == 1.0f && height_factor == 1.0f) {
|
||||
|
@ -161,6 +164,41 @@ static void Textures_tick_glTexSubImage2D_injection(GLenum target, GLint level,
|
|||
free(new_pixels);
|
||||
}
|
||||
}
|
||||
static void Textures_tick_glTexSubImage2D_injection(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) {
|
||||
glTexSubImage2D_with_scaling(target, level, xoffset, yoffset, width, height, 256, 256, format, type, pixels);
|
||||
}
|
||||
|
||||
// Load Textures
|
||||
static Texture AppPlatform_linux_loadTexture_injection(__attribute__((unused)) unsigned char *app_platform, std::string const& path, bool b) {
|
||||
Texture out;
|
||||
std::string real_path = path;
|
||||
if (b) {
|
||||
real_path = "data/images/" + real_path;
|
||||
}
|
||||
|
||||
// Read Image
|
||||
int width = 0, height = 0, channels = 0;
|
||||
stbi_uc *img = stbi_load(real_path.c_str(), &width, &height, &channels, STBI_rgb_alpha);
|
||||
if (!img)
|
||||
{
|
||||
// Failed To Parse Image
|
||||
WARN("Unable To Load Texture: %s", real_path.c_str());
|
||||
return out;
|
||||
}
|
||||
|
||||
// Copy Image
|
||||
unsigned char *img2 = new unsigned char[width * height * channels];
|
||||
memcpy(img2, img, width * height * channels);
|
||||
stbi_image_free(img);
|
||||
|
||||
// Create Texture
|
||||
out.width = width;
|
||||
out.height = height;
|
||||
out.data = img2;
|
||||
|
||||
// Return
|
||||
return out;
|
||||
}
|
||||
|
||||
// Init
|
||||
void init_textures() {
|
||||
|
@ -171,4 +209,7 @@ void init_textures() {
|
|||
|
||||
// Scale Animated Textures
|
||||
overwrite_call((void *) 0x53274, (void *) Textures_tick_glTexSubImage2D_injection);
|
||||
|
||||
// Load Textures
|
||||
overwrite((void *) AppPlatform_linux_loadTexture, (void *) AppPlatform_linux_loadTexture_injection);
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user