2.2.0
This commit is contained in:
parent
a762654e35
commit
d851a8f3e1
@ -115,6 +115,11 @@ if(BUILD_NATIVE_COMPONENTS)
|
||||
add_subdirectory(launcher)
|
||||
endif()
|
||||
|
||||
# Include Symbols
|
||||
if(BUILD_ARM_COMPONENTS)
|
||||
add_subdirectory(symbols)
|
||||
endif()
|
||||
|
||||
# Build Mods
|
||||
if(BUILD_ARM_COMPONENTS)
|
||||
add_subdirectory(mods)
|
||||
|
@ -1,7 +1,7 @@
|
||||
FROM debian:bullseye
|
||||
FROM debian:bullseye-slim
|
||||
|
||||
# Copy DEB
|
||||
ADD ./out/minecraft-pi-reborn-server_*~bullseye_amd64.deb /root
|
||||
ADD ./out/minecraft-pi-reborn-server_*_amd64.deb /root
|
||||
|
||||
# Install
|
||||
RUN \
|
||||
|
2
debian/client-arm
vendored
2
debian/client-arm
vendored
@ -4,4 +4,4 @@ Maintainer: TheBrokenRail <connor24nolan@live.com>
|
||||
Description: Fun with Blocks
|
||||
Homepage: https://www.minecraft.net/en-us/edition/pi
|
||||
Architecture: armhf
|
||||
Depends: libc6, libstdc++6, zenity, libgles1, libegl1, libglfw3 | libglfw3-wayland, libfreeimage3
|
||||
Depends: libc6, libstdc++6, zenity, libgles1, libegl1, libglfw3 | libglfw3-wayland, libfreeimage3, libopenal1
|
||||
|
2
debian/client-arm64
vendored
2
debian/client-arm64
vendored
@ -4,4 +4,4 @@ Maintainer: TheBrokenRail <connor24nolan@live.com>
|
||||
Description: Fun with Blocks
|
||||
Homepage: https://www.minecraft.net/en-us/edition/pi
|
||||
Architecture: arm64
|
||||
Depends: libc6, libstdc++6, libc6:armhf, libstdc++6:armhf, zenity, libgles1, libegl1, libglfw3 | libglfw3-wayland, libfreeimage3
|
||||
Depends: libc6, libstdc++6, libc6:armhf, libstdc++6:armhf, zenity, libgles1, libegl1, libglfw3 | libglfw3-wayland, libfreeimage3, libopenal1
|
||||
|
2
debian/client-x86_64
vendored
2
debian/client-x86_64
vendored
@ -4,4 +4,4 @@ Maintainer: TheBrokenRail <connor24nolan@live.com>
|
||||
Description: Fun with Blocks
|
||||
Homepage: https://www.minecraft.net/en-us/edition/pi
|
||||
Architecture: amd64
|
||||
Depends: libc6, libstdc++6, libc6-armhf-cross, libstdc++6-armhf-cross, zenity, libgles1, libegl1, libglfw3 | libglfw3-wayland, libfreeimage3, qemu-user-static
|
||||
Depends: libc6, libstdc++6, libc6-armhf-cross, libstdc++6-armhf-cross, zenity, libgles1, libegl1, libglfw3 | libglfw3-wayland, libfreeimage3, libopenal1, qemu-user-static
|
||||
|
@ -36,6 +36,7 @@ This sub-component re-implements a subset of SDL 1.2 calls with GLFW. It also pr
|
||||
The utility functions include:
|
||||
* Taking Screenshots
|
||||
* Fullscreen
|
||||
* Audio
|
||||
* Etc
|
||||
|
||||
This is always compiled for the host system's architecture.
|
||||
@ -87,17 +88,20 @@ This component contains various utility functions including:
|
||||
|
||||
* Code Patching (ARM Only)
|
||||
* Logging
|
||||
* MCPI Symbols
|
||||
* Etc
|
||||
|
||||
The code patching is ARM only because it relies on hard-coded ARM instructions. However, this is irrelevant since code patching is only needed in ARM code (to patch MCPI).
|
||||
|
||||
### ``symbols``
|
||||
This component contains all MCPI symbols.
|
||||
|
||||
## Dependencies
|
||||
MCPI-Reborn has several dependencies:
|
||||
* MCPI (Bundled)
|
||||
* GLFW (Only In Client Mode)
|
||||
* Open GL ES 1.1
|
||||
* EGL
|
||||
* OpenAL (Only In Client Mode)
|
||||
* ZLib (Required By LibPNG; Bundled)
|
||||
* LibPNG (Bundled)
|
||||
* FreeImage (Only In Client Mode)
|
||||
|
@ -24,6 +24,7 @@
|
||||
* Client Mode Only
|
||||
* GLFW
|
||||
* FreeImage
|
||||
* OpenAL
|
||||
|
||||
## Runtime Dependencies
|
||||
* Non-ARM Host Architectures
|
||||
@ -33,6 +34,7 @@
|
||||
* OpenGL ES 1.1
|
||||
* GLFW
|
||||
* FreeImage
|
||||
* OpenAL
|
||||
* Zenity
|
||||
|
||||
## Two-Step Build
|
||||
|
@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
**2.2.0**
|
||||
* Sound Support
|
||||
* Split Off "Allow Joining Survival Servers" From Game-Mode Mod
|
||||
* Separate Headless Code From Server Code
|
||||
* Fix Bug Where `RakNetInstance` Starts Pinging Potential Servers Before The "Join Game" Screen Is Opened
|
||||
* Clean-Up Code
|
||||
* Remove Support For Debian Buster
|
||||
|
||||
**2.1.8**
|
||||
* Fix Crash On ARM Systems
|
||||
|
||||
|
@ -1,25 +1,21 @@
|
||||
# Manual Installation
|
||||
[Download Packages Here](https://jenkins.thebrokenrail.com/job/minecraft-pi-reborn/job/master/lastSuccessfulBuild/artifact/out/)
|
||||
|
||||
## Supported Distributions
|
||||
* Ubuntu 20.04+
|
||||
* Debian Bullseye+
|
||||
|
||||
## Picking A Package
|
||||
|
||||
### Name Format
|
||||
```
|
||||
minecraft-pi-reborn-<Variant>_X.Y.Z~<Distribution>_<Architecture>
|
||||
minecraft-pi-reborn-<Variant>_X.Y.Z_<Architecture>
|
||||
```
|
||||
|
||||
### Picking A Variant
|
||||
* ``client``: Client mode, use this if you want to play MCPI
|
||||
* ``server``: Server mode, use this if you want to host a dedicated MCPI server
|
||||
|
||||
### Picking A Distribution
|
||||
This specifies which version of Debian MCPI-Reborn was built against. Which one you should use depends on your current distribution. If your distribution supports it, you should use ``bullseye`` for better mouse sensitivity.
|
||||
|
||||
* Ubuntu 20.04+: ``bullseye``
|
||||
* Raspberry Pi OS Buster: ``buster``
|
||||
* Debian Bullseye+: ``bullseye``
|
||||
* Debian Buster: ``buster``
|
||||
|
||||
### Picking An Architecture
|
||||
* ``amd64``: x86_64, use this if you are using a device with an AMD or Intel processor
|
||||
* ``armhf``: ARM 32-Bit, use this if you are using an ARM device (like a Raspberry Pi)
|
||||
|
@ -8,4 +8,5 @@
|
||||
* [View Architecture](ARCHITECTURE.md)
|
||||
* [View Command Line Arguments](COMMAND_LINE.md)
|
||||
* [View Multiplayer](MULTIPLAYER.md)
|
||||
* [View Sound](SOUND.md)
|
||||
* [View Changelog](CHANGELOG.md)
|
||||
|
7
docs/SOUND.md
Normal file
7
docs/SOUND.md
Normal file
@ -0,0 +1,7 @@
|
||||
# Sound
|
||||
One of MCPI-Reborn's main modifications is a sound-engine since MCPI doesn't include one by default[^1]. However, it can't be used out-of-box because MCPI doesn't contain any sound data and MCPI-Reborn can't include it because of copyright.
|
||||
|
||||
MCPE's sound data can be extracted from any MCPE v0.6.1[^2] APK file, just place its `libminecraftpe.so` into `~/.minecraft-pi/overrides` and you should have sound!
|
||||
|
||||
[^1]: The mute button is just leftover code from MCPE, it doesn't actually do anything in un-modded MCPI, however it is connected to MCPI-Reborn's sound-engine.
|
||||
[^2]: This isn't a hard limit, an MCPE v0.8.1 APK would probably work, but don't rely on it.
|
@ -2,6 +2,7 @@
|
||||
| Name | Description |
|
||||
| --- | --- |
|
||||
| MCPI | Shorthand for Minecraft: Pi Edition |
|
||||
| MCPE | Shorthand for Minecraft: Pocket Edition |
|
||||
| Host Architecture | The native architecture of the CPU that MCPi-Reborn will be running on |
|
||||
| Native Component | A component that *can* be compiled for the host architecture |
|
||||
| ARM Component | A component that *must* be compiled for ARM |
|
||||
|
BIN
images/start.png
BIN
images/start.png
Binary file not shown.
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
@ -25,3 +25,4 @@ TRUE Bind Common Toggleable Options To Function Keys
|
||||
TRUE Render Selected Item Text
|
||||
TRUE External Server Support
|
||||
TRUE Load Language Files
|
||||
TRUE Implement Sound Engine
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#define FORCE_PROC_FOR_ROOT_PATH
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
#include "bootstrap.h"
|
||||
@ -190,14 +189,6 @@ void bootstrap(int argc, char *argv[]) {
|
||||
setenv("QEMU_LD_PREFIX", "/usr/arm-linux-gnueabihf", 1);
|
||||
#endif
|
||||
|
||||
// Select Executable Interpreter
|
||||
#ifdef __ARM_ARCH
|
||||
#define EXE_INTERPRETER "/lib/ld-linux-armhf.so.3"
|
||||
#else
|
||||
// Use Static QEMU So It Isn't Affected By LD_* Variables
|
||||
#define EXE_INTERPRETER "qemu-arm-static"
|
||||
#endif
|
||||
|
||||
// Create Full Path
|
||||
char *full_path = NULL;
|
||||
safe_asprintf(&full_path, "%s/" MCPI_NAME, binary_directory);
|
||||
@ -205,6 +196,14 @@ void bootstrap(int argc, char *argv[]) {
|
||||
// Free Binary Directory
|
||||
free(binary_directory);
|
||||
|
||||
#ifdef __ARM_ARCH
|
||||
// Mark argc As Used
|
||||
(void) argc;
|
||||
// Run
|
||||
safe_execvpe(full_path, argv, environ);
|
||||
#else
|
||||
// Use Static QEMU So It Isn't Affected By LD_* Variables
|
||||
#define EXE_INTERPRETER "qemu-arm-static"
|
||||
// Create Arguments List
|
||||
char *new_argv[argc + 2];
|
||||
for (int i = 1; i <= argc; i++) {
|
||||
@ -214,4 +213,5 @@ void bootstrap(int argc, char *argv[]) {
|
||||
new_argv[1] = full_path; // Path To MCPI
|
||||
// Run
|
||||
safe_execvpe(EXE_INTERPRETER, new_argv, environ);
|
||||
#endif
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ target_include_directories(reborn-headers INTERFACE include)
|
||||
if(BUILD_ARM_COMPONENTS)
|
||||
add_library(reborn SHARED src/reborn.c)
|
||||
target_link_libraries(reborn dl reborn-headers)
|
||||
target_compile_definitions(reborn PUBLIC -DREBORN_HAS_COMPILED_CODE)
|
||||
# Install
|
||||
install(TARGETS reborn DESTINATION "${MCPI_LIB_DIR}")
|
||||
endif()
|
||||
|
@ -4,53 +4,46 @@
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <elf.h>
|
||||
#include <link.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "exec.h"
|
||||
|
||||
// Find And Iterate Over All .text Sections In Current Binary
|
||||
typedef void (*text_section_callback_t)(Elf32_Addr section, Elf32_Word size, void *data);
|
||||
typedef void (*text_section_callback_t)(ElfW(Addr) section, ElfW(Word) size, void *data);
|
||||
static inline void iterate_text_sections(text_section_callback_t callback, void *data) {
|
||||
// Find Main Binary
|
||||
char *real_path = NULL;
|
||||
{
|
||||
char *binary_directory = get_binary_directory();
|
||||
safe_asprintf(&real_path, "%s/minecraft-pi", binary_directory);
|
||||
free(binary_directory);
|
||||
}
|
||||
|
||||
// Load Main Binary
|
||||
FILE *file_obj = fopen(real_path, "rb");
|
||||
FILE *file_obj = fopen("/proc/self/exe", "rb");
|
||||
|
||||
// Verify Binary
|
||||
if (!file_obj) {
|
||||
ERR("Unable To Open Binary: %s", real_path);
|
||||
ERR("%s", "Unable To Open Current Binary");
|
||||
}
|
||||
|
||||
// Get File Size
|
||||
fseek(file_obj, 0L, SEEK_END);
|
||||
long int size = ftell(file_obj);
|
||||
long int file_size = ftell(file_obj);
|
||||
fseek(file_obj, 0L, SEEK_SET);
|
||||
|
||||
// Map File To Pointer
|
||||
unsigned char *file_map = (unsigned char *) mmap(0, size, PROT_READ, MAP_PRIVATE, fileno(file_obj), 0);
|
||||
unsigned char *file_map = (unsigned char *) mmap(0, file_size, PROT_READ, MAP_PRIVATE, fileno(file_obj), 0);
|
||||
|
||||
// Parse ELF
|
||||
Elf32_Ehdr *elf_header = (Elf32_Ehdr *) file_map;
|
||||
Elf32_Shdr *elf_section_headers = (Elf32_Shdr *) (file_map + elf_header->e_shoff);
|
||||
ElfW(Ehdr) *elf_header = (ElfW(Ehdr) *) file_map;
|
||||
ElfW(Shdr) *elf_section_headers = (ElfW(Shdr) *) (file_map + elf_header->e_shoff);
|
||||
int elf_section_header_count = elf_header->e_shnum;
|
||||
|
||||
// Locate Section Names
|
||||
Elf32_Shdr elf_strtab = elf_section_headers[elf_header->e_shstrndx];
|
||||
unsigned char *elf_strtab_p = file_map + elf_strtab.sh_offset;
|
||||
ElfW(Shdr) elf_shstrtab = elf_section_headers[elf_header->e_shstrndx];
|
||||
unsigned char *elf_shstrtab_p = file_map + elf_shstrtab.sh_offset;
|
||||
|
||||
// Track .text Sections
|
||||
int text_sections = 0;
|
||||
|
||||
// Iterate Sections
|
||||
for (int i = 0; i < elf_section_header_count; ++i) {
|
||||
Elf32_Shdr header = elf_section_headers[i];
|
||||
char *name = (char *) (elf_strtab_p + header.sh_name);
|
||||
ElfW(Shdr) header = elf_section_headers[i];
|
||||
char *name = (char *) (elf_shstrtab_p + header.sh_name);
|
||||
// Check Section Type
|
||||
if (strcmp(name, ".text") == 0) {
|
||||
// .text Section
|
||||
@ -61,13 +54,10 @@ static inline void iterate_text_sections(text_section_callback_t callback, void
|
||||
|
||||
// Ensure At Least .text Section Was Scanned
|
||||
if (text_sections < 1) {
|
||||
ERR("Unable To Find .text Sectons On: %s", real_path);
|
||||
ERR("%s", "Unable To Find .text Sectons");
|
||||
}
|
||||
|
||||
// Free Binary Path
|
||||
free(real_path);
|
||||
|
||||
// Unmap And Close File
|
||||
munmap(file_map, size);
|
||||
munmap(file_map, file_size);
|
||||
fclose(file_obj);
|
||||
}
|
||||
|
@ -21,15 +21,6 @@ __attribute__((noreturn)) static inline void safe_execvpe(const char *pathname,
|
||||
}
|
||||
// Get Binary Directory (Remember To Free)
|
||||
static inline char *get_binary_directory() {
|
||||
#ifndef FORCE_PROC_FOR_ROOT_PATH
|
||||
{
|
||||
// Check Environment
|
||||
char *specified_root = getenv("MCPI_ROOT_PATH");
|
||||
if (specified_root != NULL) {
|
||||
return strdup(specified_root);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// Get Path To Current Executable
|
||||
char *exe = realpath("/proc/self/exe", NULL);
|
||||
ALLOC_CHECK(exe);
|
||||
@ -43,9 +34,6 @@ static inline char *get_binary_directory() {
|
||||
}
|
||||
}
|
||||
|
||||
// Set Environment
|
||||
setenv("MCPI_ROOT_PATH", exe, 1);
|
||||
|
||||
// Return
|
||||
return exe;
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ extern "C" {
|
||||
#include "exec.h"
|
||||
#include "elf.h"
|
||||
|
||||
#ifdef __arm__
|
||||
#ifdef REBORN_HAS_COMPILED_CODE
|
||||
|
||||
// Patching Functions
|
||||
|
||||
|
@ -6,5 +6,5 @@
|
||||
// Logging
|
||||
#define INFO(format, ...) { fprintf(stderr, "[INFO]: " format "\n", __VA_ARGS__); }
|
||||
#define WARN(format, ...) { fprintf(stderr, "[WARN]: " format "\n", __VA_ARGS__); }
|
||||
#define ERR(format, ...) { fprintf(stderr, "[ERR]: " format "\n", __VA_ARGS__); exit(EXIT_FAILURE); }
|
||||
#define IMPOSSIBLE() ERR("(%s:%i) This Should Never Be Called", __FILE__, __LINE__)
|
||||
#define ERR(format, ...) { fprintf(stderr, "[ERR]: (%s:%i): " format "\n", __FILE__, __LINE__, __VA_ARGS__); exit(EXIT_FAILURE); }
|
||||
#define IMPOSSIBLE() ERR("%s", "This Should Never Be Called")
|
||||
|
@ -44,7 +44,7 @@ struct overwrite_data {
|
||||
void *replacement;
|
||||
int found;
|
||||
};
|
||||
static void overwrite_calls_callback(Elf32_Addr section_addr, Elf32_Word size, void *data) {
|
||||
static void overwrite_calls_callback(ElfW(Addr) section_addr, ElfW(Word) size, void *data) {
|
||||
struct overwrite_data *args = (struct overwrite_data *) data;
|
||||
void *section = (void *) section_addr;
|
||||
|
||||
@ -122,12 +122,14 @@ void _overwrite_calls(const char *file, int line, void *start, void *target) {
|
||||
// Increment Code Block Position
|
||||
increment_code_block();
|
||||
|
||||
// Check
|
||||
if (data.found < 1) {
|
||||
ERR("(%s:%i) Unable To Find Callsites For 0x%08x", file, line, (uint32_t) start);
|
||||
}
|
||||
}
|
||||
|
||||
// Overwrite Function
|
||||
// NOTE: "start" Must Be At Least 8 Bytes Long
|
||||
void _overwrite(const char *file, int line, void *start, void *target) {
|
||||
unsigned char patch_data[4] = {0x04, 0xf0, 0x1f, 0xe5}; // "ldr pc, [pc, #-0x4]"
|
||||
|
||||
|
@ -2,6 +2,9 @@ project(media-layer-core)
|
||||
|
||||
# Configuration
|
||||
set(CORE_SRC src/base.cpp src/media.c src/screenshot.c) # SDL Re-Implementation Using GLFW
|
||||
if(NOT MCPI_HEADLESS_MODE)
|
||||
list(APPEND CORE_SRC src/audio/api.cpp src/audio/engine.c src/audio/file.cpp)
|
||||
endif()
|
||||
|
||||
# Build
|
||||
if(MCPI_USE_MEDIA_LAYER_PROXY AND BUILD_NATIVE_COMPONENTS)
|
||||
@ -23,8 +26,10 @@ if(TARGET media-layer-core)
|
||||
find_package(glfw3 3.3 REQUIRED)
|
||||
# Find FreeImage
|
||||
find_library(FREEIMAGE_LIBRARY NAMES freeimage libfreeimage.so.3 REQUIRED)
|
||||
# Not Needed In Server Mode
|
||||
target_link_libraries(media-layer-core "${FREEIMAGE_LIBRARY}" GLESv1_CM glfw)
|
||||
# OpenAL
|
||||
find_library(OPENAL_LIBRARY NAMES openal REQUIRED)
|
||||
# Link
|
||||
target_link_libraries(media-layer-core "${FREEIMAGE_LIBRARY}" "${OPENAL_LIBRARY}" m GLESv1_CM glfw)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
104
media-layer/core/src/audio/api.cpp
Normal file
104
media-layer/core/src/audio/api.cpp
Normal file
@ -0,0 +1,104 @@
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
|
||||
#include <AL/al.h>
|
||||
|
||||
#include <media-layer/audio.h>
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
#include "file.h"
|
||||
#include "engine.h"
|
||||
|
||||
// Store Audio Sources
|
||||
static std::vector<ALuint> &get_sources() {
|
||||
static std::vector<ALuint> sources;
|
||||
return sources;
|
||||
}
|
||||
|
||||
#define AL_ERROR_CHECK() \
|
||||
{ \
|
||||
ALenum err = alGetError(); \
|
||||
if (err != AL_NO_ERROR) { \
|
||||
ERR("OpenAL Error: %s", alGetString(err)); \
|
||||
} \
|
||||
}
|
||||
|
||||
// Update Listener
|
||||
void media_audio_update(float volume, float x, float y, float z, float yaw) {
|
||||
// Update Listener Volume
|
||||
alListenerf(AL_GAIN, volume);
|
||||
AL_ERROR_CHECK();
|
||||
|
||||
// Update Listener Position
|
||||
alListener3f(AL_POSITION, x, y, z);
|
||||
AL_ERROR_CHECK();
|
||||
|
||||
// Update Listener Orientation
|
||||
float radian_yaw = yaw * (M_PI / 180);
|
||||
ALfloat orientation[] = {-sinf(radian_yaw), 0.0f, cosf(radian_yaw), 0.0f, 1.0f, 0.0f};
|
||||
alListenerfv(AL_ORIENTATION, orientation);
|
||||
AL_ERROR_CHECK();
|
||||
|
||||
// Clear Finished Sources
|
||||
std::vector<ALuint>::iterator it = get_sources().begin();
|
||||
while (it != get_sources().end()) {
|
||||
ALuint source = *it;
|
||||
// Check
|
||||
ALint source_state;
|
||||
alGetSourcei(source, AL_SOURCE_STATE, &source_state);
|
||||
AL_ERROR_CHECK();
|
||||
if (source_state != AL_PLAYING) {
|
||||
// Finished
|
||||
it = get_sources().erase(it);
|
||||
alDeleteSources(1, &source);
|
||||
AL_ERROR_CHECK();
|
||||
} else {
|
||||
// Still Playing
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void media_audio_play(const char *source, const char *name, float x, float y, float z, float pitch, float volume, int is_ui) {
|
||||
// Load Sound
|
||||
ALuint buffer = _media_audio_get_buffer(source, name);
|
||||
if (buffer) {
|
||||
// Create Source
|
||||
ALuint al_source;
|
||||
alGenSources(1, &al_source);
|
||||
AL_ERROR_CHECK();
|
||||
|
||||
// Set Properties
|
||||
alSourcef(al_source, AL_PITCH, pitch);
|
||||
AL_ERROR_CHECK();
|
||||
alSourcef(al_source, AL_GAIN, volume);
|
||||
AL_ERROR_CHECK();
|
||||
alSource3f(al_source, AL_POSITION, x, y, z);
|
||||
AL_ERROR_CHECK();
|
||||
alSource3f(al_source, AL_VELOCITY, 0, 0, 0);
|
||||
AL_ERROR_CHECK();
|
||||
alSourcei(al_source, AL_LOOPING, AL_FALSE);
|
||||
AL_ERROR_CHECK();
|
||||
alSourcei(al_source, AL_SOURCE_RELATIVE, is_ui ? AL_TRUE : AL_FALSE);
|
||||
AL_ERROR_CHECK();
|
||||
|
||||
// Set Attenuation
|
||||
alSourcei(al_source, AL_DISTANCE_MODEL, AL_LINEAR_DISTANCE);
|
||||
AL_ERROR_CHECK();
|
||||
alSourcef(al_source, AL_MAX_DISTANCE, 16.0f);
|
||||
AL_ERROR_CHECK();
|
||||
alSourcef(al_source, AL_ROLLOFF_FACTOR, 1.0f);
|
||||
AL_ERROR_CHECK();
|
||||
alSourcef(al_source, AL_REFERENCE_DISTANCE, 0.0f);
|
||||
AL_ERROR_CHECK();
|
||||
|
||||
// Set Buffer
|
||||
alSourcei(al_source, AL_BUFFER, buffer);
|
||||
AL_ERROR_CHECK();
|
||||
|
||||
// Play
|
||||
alSourcePlay(al_source);
|
||||
AL_ERROR_CHECK();
|
||||
get_sources().push_back(al_source);
|
||||
}
|
||||
}
|
85
media-layer/core/src/audio/engine.c
Normal file
85
media-layer/core/src/audio/engine.c
Normal file
@ -0,0 +1,85 @@
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
#include <AL/alext.h>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
#include "engine.h"
|
||||
#include "file.h"
|
||||
|
||||
// Store Device
|
||||
static ALCdevice *device = NULL;
|
||||
static ALCcontext *context = NULL;
|
||||
|
||||
// Store State
|
||||
static int is_loaded = 0;
|
||||
int _media_audio_is_loaded() {
|
||||
return is_loaded;
|
||||
}
|
||||
|
||||
// Init
|
||||
void _media_audio_init() {
|
||||
// Open Device
|
||||
device = alcOpenDevice(NULL);
|
||||
if (!device) {
|
||||
WARN("%s", "Unable To Load Audio Engine");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create Context
|
||||
context = alcCreateContext(device, NULL);
|
||||
ALCenum err = alcGetError(device);
|
||||
if (err != ALC_NO_ERROR) {
|
||||
ERR("Unable To Open Audio Context: %s", alcGetString(device, err));
|
||||
}
|
||||
|
||||
// Select Context
|
||||
alcMakeContextCurrent(context);
|
||||
err = alcGetError(device);
|
||||
if (err != ALC_NO_ERROR) {
|
||||
ERR("Unable To Select Audio Context: %s", alcGetString(device, err));
|
||||
}
|
||||
|
||||
// Enable AL_SOURCE_DISTANCE_MODEL
|
||||
alEnable(AL_SOURCE_DISTANCE_MODEL);
|
||||
ALenum al_err = alGetError();
|
||||
if (al_err != AL_NO_ERROR) {
|
||||
ERR("Unable To Enable AL_SOURCE_DISTANCE_MODEL: %s", alGetString(al_err));
|
||||
}
|
||||
|
||||
// Log
|
||||
INFO("%s", "Loaded Audio Engine");
|
||||
is_loaded = 1;
|
||||
}
|
||||
|
||||
// De-Init
|
||||
void _media_audio_cleanup() {
|
||||
if (_media_audio_is_loaded()) {
|
||||
// Delete Audio Buffers
|
||||
_media_audio_delete_buffers();
|
||||
|
||||
// Deselect Context
|
||||
alcMakeContextCurrent(NULL);
|
||||
ALCenum err = alcGetError(device);
|
||||
if (err != ALC_NO_ERROR) {
|
||||
ERR("Unable To Deselect Audio Context: %s", alcGetString(device, err));
|
||||
}
|
||||
|
||||
// Destroy Context
|
||||
alcDestroyContext(context);
|
||||
err = alcGetError(device);
|
||||
if (err != ALC_NO_ERROR) {
|
||||
ERR("Unable To Destroy Audio Context: %s", alcGetString(device, err));
|
||||
}
|
||||
|
||||
// Close Device
|
||||
alcCloseDevice(device);
|
||||
err = alcGetError(device);
|
||||
if (err != ALC_NO_ERROR) {
|
||||
ERR("Unable To Close Audio Device: %s", alcGetString(device, err));
|
||||
}
|
||||
|
||||
// Log
|
||||
INFO("%s", "Unloaded Audio Engine");
|
||||
}
|
||||
}
|
15
media-layer/core/src/audio/engine.h
Normal file
15
media-layer/core/src/audio/engine.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <AL/al.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
__attribute__((visibility("internal"))) void _media_audio_init();
|
||||
__attribute__((visibility("internal"))) void _media_audio_cleanup();
|
||||
__attribute__((visibility("internal"))) int _media_audio_is_loaded();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
241
media-layer/core/src/audio/file.cpp
Normal file
241
media-layer/core/src/audio/file.cpp
Normal file
@ -0,0 +1,241 @@
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <cstdint>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <elf.h>
|
||||
|
||||
#include <AL/al.h>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
#include "file.h"
|
||||
#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) {
|
||||
// File Data
|
||||
FILE *file_obj = NULL;
|
||||
unsigned char *file_map = NULL;
|
||||
long int file_size = 0;
|
||||
|
||||
// Code
|
||||
{
|
||||
// Load Main Binary
|
||||
file_obj = fopen(source, "rb");
|
||||
|
||||
// Verify Binary
|
||||
if (!file_obj) {
|
||||
WARN("Unable To Open: %s", source);
|
||||
goto end;
|
||||
}
|
||||
|
||||
// Get File Size
|
||||
fseek(file_obj, 0L, SEEK_END);
|
||||
file_size = ftell(file_obj);
|
||||
fseek(file_obj, 0L, SEEK_SET);
|
||||
|
||||
// Map File To Pointer
|
||||
file_map = (unsigned char *) mmap(0, file_size, PROT_READ, MAP_PRIVATE, fileno(file_obj), 0);
|
||||
|
||||
// Check ELF Magic
|
||||
if (file_map[EI_MAG0] != ELFMAG0 || file_map[EI_MAG1] != ELFMAG1 || file_map[EI_MAG2] != ELFMAG2 || file_map[EI_MAG3] != ELFMAG3) {
|
||||
WARN("Not An ELF File: %s", source);
|
||||
goto end;
|
||||
}
|
||||
if (file_map[EI_CLASS] != ELFCLASS32) {
|
||||
WARN("ELF File Isn't 32-Bit: %s", source);
|
||||
goto end;
|
||||
}
|
||||
if (file_map[EI_DATA] != ELFDATA2LSB) {
|
||||
WARN("ELF File Isn't Little-Endian: %s", source);
|
||||
goto end;
|
||||
}
|
||||
|
||||
// Parse ELF
|
||||
Elf32_Ehdr *elf_header = (Elf32_Ehdr *) file_map;
|
||||
Elf32_Shdr *elf_section_headers = (Elf32_Shdr *) (file_map + elf_header->e_shoff);
|
||||
int elf_section_header_count = elf_header->e_shnum;
|
||||
|
||||
// Locate Section Names
|
||||
Elf32_Shdr elf_shstrtab = elf_section_headers[elf_header->e_shstrndx];
|
||||
unsigned char *elf_shstrtab_p = file_map + elf_shstrtab.sh_offset;
|
||||
|
||||
// Locate String Table
|
||||
unsigned char *elf_strtab_p = NULL;
|
||||
for (int i = 0; i < elf_section_header_count; ++i) {
|
||||
Elf32_Shdr header = elf_section_headers[i];
|
||||
// Check Section Type
|
||||
if (header.sh_type == SHT_STRTAB) {
|
||||
// Check Section Name
|
||||
char *section_name = (char *) (elf_shstrtab_p + header.sh_name);
|
||||
if (strcmp(section_name, ".dynstr") == 0) {
|
||||
// Found
|
||||
elf_strtab_p = file_map + header.sh_offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (elf_strtab_p == NULL) {
|
||||
WARN("Unable To Find String Table In: %s", source);
|
||||
goto end;
|
||||
}
|
||||
|
||||
// Locate Symbol Tables
|
||||
Elf32_Sym *symbol = NULL;
|
||||
for (int i = 0; i < elf_section_header_count; ++i) {
|
||||
// Exit Loop If Finished
|
||||
if (symbol != NULL) {
|
||||
break;
|
||||
}
|
||||
// Get Section Header
|
||||
Elf32_Shdr header = elf_section_headers[i];
|
||||
// Check Section Type
|
||||
if (header.sh_type == SHT_DYNSYM) {
|
||||
// Symbol Table
|
||||
Elf32_Sym *table = (Elf32_Sym *) (file_map + header.sh_offset);
|
||||
for (int j = 0; (j * sizeof (Elf32_Sym)) < header.sh_size; j++) {
|
||||
// Check Symbol Name
|
||||
char *symbol_name = (char *) (elf_strtab_p + table[j].st_name);
|
||||
if (strcmp(symbol_name, name) == 0) {
|
||||
// Found
|
||||
symbol = &table[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check Symbol
|
||||
if (symbol != NULL) {
|
||||
// Convert Virtual Address To File Offset
|
||||
Elf32_Shdr symbol_section_header = elf_section_headers[symbol->st_shndx];
|
||||
int vaddr_to_offset = -symbol_section_header.sh_addr + symbol_section_header.sh_offset;
|
||||
Elf32_Off symbol_offset = symbol->st_value + vaddr_to_offset;
|
||||
// Access Symbol
|
||||
unsigned char *value = file_map + symbol_offset;
|
||||
uint32_t size = symbol->st_size;
|
||||
callback(value, size);
|
||||
} else {
|
||||
// Unable To Find Symbol
|
||||
WARN("Unable To Find Symbol: %s", name);
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
// Unmap And Close File
|
||||
if (file_map != NULL) {
|
||||
munmap(file_map, file_size);
|
||||
}
|
||||
if (file_obj != NULL) {
|
||||
fclose(file_obj);
|
||||
}
|
||||
}
|
||||
|
||||
// Audio Metadata
|
||||
struct audio_metadata {
|
||||
int32_t channels;
|
||||
int32_t frame_size;
|
||||
int32_t sample_rate;
|
||||
int32_t frames;
|
||||
};
|
||||
|
||||
// Load Sound Symbol Into ALunit
|
||||
static ALuint load_sound(const char *source, const char *name) {
|
||||
// Check OpenAL
|
||||
if (!_media_audio_is_loaded()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Store Result
|
||||
ALuint buffer = 0;
|
||||
|
||||
// Load Symbol
|
||||
load_symbol(source, name, [name, &buffer](unsigned char *symbol, uint32_t size) {
|
||||
// Load Metadata
|
||||
if (size < sizeof (audio_metadata)) {
|
||||
WARN("Symbol Too Small To Contain Audio Metadata: %s", name);
|
||||
return;
|
||||
}
|
||||
audio_metadata *meta = (audio_metadata *) symbol;
|
||||
|
||||
// Check Frame Size
|
||||
if (meta->frame_size != 1 && meta->frame_size != 2) {
|
||||
WARN("Unsupported Frame Size: %s: %i", name, meta->frame_size);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get Audio Format
|
||||
ALenum format = AL_NONE;
|
||||
if (meta->channels == 1) {
|
||||
format = meta->frame_size == 2 ? AL_FORMAT_MONO16 : AL_FORMAT_MONO8;
|
||||
} else if (meta->channels == 2) {
|
||||
format = meta->frame_size == 2 ? AL_FORMAT_STEREO16 : AL_FORMAT_STEREO8;
|
||||
} else {
|
||||
WARN("Unsupported Channel Count: %s: %i", name, meta->channels);
|
||||
return;
|
||||
}
|
||||
|
||||
// Load Data
|
||||
int remaining_size = size - sizeof (audio_metadata);
|
||||
int data_size = meta->channels * meta->frames * meta->frame_size;
|
||||
if (remaining_size < data_size) {
|
||||
WARN("Symbol Too Small To Contain Specified Audio Data: %s", name);
|
||||
return;
|
||||
}
|
||||
unsigned char *data = symbol + sizeof (audio_metadata);
|
||||
|
||||
// Create Buffer
|
||||
alGenBuffers(1, &buffer);
|
||||
alBufferData(buffer, format, data, data_size, meta->sample_rate);
|
||||
|
||||
// Check OpenAL Error
|
||||
ALenum err = alGetError();
|
||||
if (err != AL_NO_ERROR) {
|
||||
WARN("Unable To Store Audio Buffer: %s", alGetString(err));
|
||||
if (buffer && alIsBuffer(buffer)) {
|
||||
alDeleteBuffers(1, &buffer);
|
||||
}
|
||||
buffer = 0;
|
||||
}
|
||||
});
|
||||
|
||||
// Return
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// Store Buffers
|
||||
static std::unordered_map<std::string, ALuint> &get_buffers() {
|
||||
static std::unordered_map<std::string, ALuint> buffers;
|
||||
return buffers;
|
||||
}
|
||||
|
||||
// Get Buffer For Sound
|
||||
ALuint _media_audio_get_buffer(const char *source, const char *name) {
|
||||
// Check
|
||||
if (_media_audio_is_loaded()) {
|
||||
if (get_buffers().count(name) > 0) {
|
||||
// Return
|
||||
return get_buffers()[name];
|
||||
} else {
|
||||
// Load And Return
|
||||
get_buffers()[name] = load_sound(source, name);
|
||||
return _media_audio_get_buffer(source, name);
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Delete Buffers
|
||||
void _media_audio_delete_buffers() {
|
||||
if (_media_audio_is_loaded()) {
|
||||
for (auto it : get_buffers()) {
|
||||
if (it.second && alIsBuffer(it.second)) {
|
||||
alDeleteBuffers(1, &it.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
get_buffers().clear();
|
||||
}
|
14
media-layer/core/src/audio/file.h
Normal file
14
media-layer/core/src/audio/file.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <AL/al.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
__attribute__((visibility("internal"))) ALuint _media_audio_get_buffer(const char *source, const char *name);
|
||||
__attribute__((visibility("internal"))) void _media_audio_delete_buffers();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -4,7 +4,7 @@
|
||||
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
#include <libreborn/media-layer/internal.h>
|
||||
#include <media-layer/internal.h>
|
||||
|
||||
// SDL Is Replaced With GLFW
|
||||
|
||||
|
@ -9,10 +9,12 @@
|
||||
#endif // #ifndef MCPI_HEADLESS_MODE
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <libreborn/media-layer/core.h>
|
||||
#include <libreborn/media-layer/internal.h>
|
||||
#include <media-layer/core.h>
|
||||
#include <media-layer/internal.h>
|
||||
|
||||
// GLFW Code Not Needed In Server Mode
|
||||
#include "audio/engine.h"
|
||||
|
||||
// GLFW Code Not Needed In Headless Mode
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
|
||||
static GLFWwindow *glfw_window;
|
||||
@ -196,10 +198,14 @@ static void glfw_scroll(__attribute__((unused)) GLFWwindow *window, __attribute_
|
||||
|
||||
#endif // #ifndef MCPI_HEADLESS_MODE
|
||||
|
||||
// Init GLFW
|
||||
// Track Media Layer State
|
||||
static int is_running = 0;
|
||||
|
||||
// Init Media Layer
|
||||
void SDL_WM_SetCaption(const char *title, __attribute__((unused)) const char *icon) {
|
||||
// Don't Enable GLFW In Server Mode
|
||||
// Don't Enable GLFW In Headless Mode
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
// Init GLFW
|
||||
glfwSetErrorCallback(glfw_error);
|
||||
|
||||
if (!glfwInit()) {
|
||||
@ -221,7 +227,7 @@ void SDL_WM_SetCaption(const char *title, __attribute__((unused)) const char *ic
|
||||
ERR("%s", "Unable To Create GLFW Window");
|
||||
}
|
||||
|
||||
// Don't Process Events In Server Mode
|
||||
// Don't Process Events In Headless Mode
|
||||
glfwSetKeyCallback(glfw_window, glfw_key);
|
||||
glfwSetCharCallback(glfw_window, glfw_char);
|
||||
glfwSetCursorPosCallback(glfw_window, glfw_motion);
|
||||
@ -229,9 +235,15 @@ void SDL_WM_SetCaption(const char *title, __attribute__((unused)) const char *ic
|
||||
glfwSetScrollCallback(glfw_window, glfw_scroll);
|
||||
|
||||
glfwMakeContextCurrent(glfw_window);
|
||||
|
||||
// Init OpenAL
|
||||
_media_audio_init();
|
||||
#else // #ifndef MCPI_HEADLESS_MODE
|
||||
(void) title; // Mark As Used
|
||||
#endif // #ifndef MCPI_HEADLESS_MODE
|
||||
|
||||
// Set State
|
||||
is_running = 1;
|
||||
}
|
||||
|
||||
void media_swap_buffers() {
|
||||
@ -241,7 +253,7 @@ void media_swap_buffers() {
|
||||
#endif // #ifndef MCPI_HEADLESS_MODE
|
||||
}
|
||||
|
||||
// Fullscreen Not Needed In Server Mode
|
||||
// Fullscreen Not Needed In Headless Mode
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
static int is_fullscreen = 0;
|
||||
|
||||
@ -278,7 +290,7 @@ void media_toggle_fullscreen() {
|
||||
|
||||
// Intercept SDL Events
|
||||
void _media_handle_SDL_PollEvent() {
|
||||
// GLFW Is Disabled In Server Mode
|
||||
// GLFW And Audio Are Disabled Disabled In Headless Mode
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
// Process GLFW Events
|
||||
glfwPollEvents();
|
||||
@ -293,13 +305,22 @@ void _media_handle_SDL_PollEvent() {
|
||||
#endif // #ifndef MCPI_HEADLESS_MODE
|
||||
}
|
||||
|
||||
// Terminate GLFW
|
||||
// Cleanup Media Layer
|
||||
void media_cleanup() {
|
||||
// GLFW Is Disabled In Server Mode
|
||||
if (is_running) {
|
||||
// GLFW And Audio Are Disabled In Headless Mode
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
glfwDestroyWindow(glfw_window);
|
||||
glfwTerminate();
|
||||
// Terminate GLFW
|
||||
glfwDestroyWindow(glfw_window);
|
||||
glfwTerminate();
|
||||
|
||||
// Cleanup OpenAL
|
||||
_media_audio_cleanup();
|
||||
#endif // #ifndef MCPI_HEADLESS_MODE
|
||||
|
||||
// Update State
|
||||
is_running = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Store Cursor State
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Screenshot Code Is Useless In Server Mode
|
||||
// Screenshot Code Is Useless In Headless Mode
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
|
||||
#include <stdlib.h>
|
||||
@ -14,7 +14,7 @@
|
||||
#include <GLES/gl.h>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <libreborn/media-layer/core.h>
|
||||
#include <media-layer/core.h>
|
||||
|
||||
// Ensure Screenshots Folder Exists
|
||||
static void ensure_screenshots_folder(char *screenshots) {
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <libreborn/media-layer/core.h>
|
||||
#include <media-layer/core.h>
|
||||
|
||||
// SDL Stub
|
||||
void *SDL_SetVideoMode(__attribute__((unused)) int width, __attribute__((unused)) int height, __attribute__((unused)) int bpp, __attribute__((unused)) uint32_t flags) {
|
||||
|
12
media-layer/include/media-layer/audio.h
Normal file
12
media-layer/include/media-layer/audio.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void media_audio_update(float volume, float x, float y, float z, float yaw);
|
||||
void media_audio_play(const char *source, const char *name, float x, float y, float z, float pitch, float volume, int is_ui);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -135,7 +135,7 @@ char *read_string() {
|
||||
return strdup(str);
|
||||
}
|
||||
#define MAX_STRING_SIZE 256
|
||||
void write_string(char *str) {
|
||||
void write_string(const char *str) {
|
||||
unsigned char is_null = str == NULL;
|
||||
write_byte(is_null);
|
||||
if (!is_null) {
|
||||
|
@ -44,7 +44,7 @@ __attribute__((visibility("internal"))) void write_float(float x);
|
||||
|
||||
// Read/Write Strings
|
||||
__attribute__((visibility("internal"))) char *read_string(); // Remember To free()
|
||||
__attribute__((visibility("internal"))) void write_string(char *str);
|
||||
__attribute__((visibility("internal"))) void write_string(const char *str);
|
||||
|
||||
// Manipulate Connection
|
||||
__attribute__((visibility("internal"))) void set_connection(int read, int write);
|
||||
|
@ -3,8 +3,9 @@
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
#include <libreborn/media-layer/core.h>
|
||||
#include <libreborn/media-layer/internal.h>
|
||||
#include <media-layer/core.h>
|
||||
#include <media-layer/audio.h>
|
||||
#include <media-layer/internal.h>
|
||||
|
||||
#include "common/common.h"
|
||||
|
||||
@ -356,3 +357,62 @@ CALL(10, media_get_framebuffer_size, void, (int *width, int *height)) {
|
||||
write_int((uint32_t) height);
|
||||
#endif
|
||||
}
|
||||
|
||||
CALL(59, media_audio_update, void, (float volume, float x, float y, float z, float yaw)) {
|
||||
#if defined(MEDIA_LAYER_PROXY_SERVER)
|
||||
// Lock Proxy
|
||||
start_proxy_call();
|
||||
|
||||
// Arguments
|
||||
write_float(volume);
|
||||
write_float(x);
|
||||
write_float(y);
|
||||
write_float(z);
|
||||
write_float(yaw);
|
||||
|
||||
// Release Proxy
|
||||
end_proxy_call();
|
||||
#else
|
||||
float volume = read_float();
|
||||
float x = read_float();
|
||||
float y = read_float();
|
||||
float z = read_float();
|
||||
float yaw = read_float();
|
||||
// Run
|
||||
media_audio_update(volume, x, y, z, yaw);
|
||||
#endif
|
||||
}
|
||||
|
||||
CALL(60, media_audio_play, void, (const char *source, const char *name, float x, float y, float z, float pitch, float volume, int is_ui)) {
|
||||
#if defined(MEDIA_LAYER_PROXY_SERVER)
|
||||
// Lock Proxy
|
||||
start_proxy_call();
|
||||
|
||||
// Arguments
|
||||
write_string(source);
|
||||
write_string(name);
|
||||
write_float(x);
|
||||
write_float(y);
|
||||
write_float(z);
|
||||
write_float(pitch);
|
||||
write_float(volume);
|
||||
write_int(is_ui);
|
||||
|
||||
// Release Proxy
|
||||
end_proxy_call();
|
||||
#else
|
||||
char *source = read_string();
|
||||
char *name = read_string();
|
||||
float x = read_float();
|
||||
float y = read_float();
|
||||
float z = read_float();
|
||||
float pitch = read_float();
|
||||
float volume = read_float();
|
||||
int is_ui = read_int();
|
||||
// Run
|
||||
media_audio_play(source, name, x, y, z, pitch, volume, is_ui);
|
||||
// Free
|
||||
free(source);
|
||||
free(name);
|
||||
#endif
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
|
||||
## Mods
|
||||
|
||||
add_library(compat SHARED src/compat/compat.c src/compat/egl.c src/compat/x11.c)
|
||||
target_link_libraries(compat feature input chat sign media-layer-core home dl)
|
||||
target_link_libraries(compat reborn media-layer-core)
|
||||
|
||||
add_library(readdir SHARED src/readdir/readdir.c)
|
||||
|
||||
@ -16,73 +16,80 @@ add_library(feature SHARED src/feature/feature.c)
|
||||
target_link_libraries(feature reborn)
|
||||
|
||||
add_library(version SHARED src/version/version.cpp)
|
||||
target_link_libraries(version reborn)
|
||||
target_link_libraries(version reborn symbols)
|
||||
|
||||
add_library(chat SHARED src/chat/chat.cpp src/chat/ui.c)
|
||||
target_link_libraries(chat reborn symbols feature pthread)
|
||||
|
||||
if(MCPI_SERVER_MODE)
|
||||
add_library(server SHARED src/server/server.cpp src/server/server_properties.cpp)
|
||||
target_link_libraries(server reborn feature home compat version dl media-layer-core pthread)
|
||||
target_link_libraries(server reborn symbols feature home compat version dl media-layer-core pthread)
|
||||
else()
|
||||
target_link_libraries(compat input sign chat home dl)
|
||||
|
||||
target_link_libraries(chat input)
|
||||
|
||||
add_library(multiplayer SHARED src/multiplayer/multiplayer.cpp)
|
||||
target_link_libraries(multiplayer reborn home feature)
|
||||
target_link_libraries(multiplayer reborn symbols home feature)
|
||||
|
||||
add_library(sound SHARED src/sound/sound.cpp src/sound/repository.cpp)
|
||||
target_link_libraries(sound reborn symbols feature override media-layer-core)
|
||||
|
||||
add_library(camera SHARED src/camera/camera.cpp)
|
||||
target_link_libraries(camera reborn symbols media-layer-core feature home)
|
||||
|
||||
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)
|
||||
target_link_libraries(input reborn symbols feature media-layer-core)
|
||||
|
||||
add_library(sign SHARED src/sign/sign.cpp)
|
||||
target_link_libraries(sign reborn symbols feature input)
|
||||
|
||||
add_library(creative SHARED src/creative/creative.cpp)
|
||||
target_link_libraries(creative reborn symbols feature)
|
||||
|
||||
add_library(touch SHARED src/touch/touch.c)
|
||||
target_link_libraries(touch reborn symbols feature)
|
||||
|
||||
add_library(override SHARED src/override/override.c)
|
||||
target_link_libraries(override reborn symbols dl home)
|
||||
|
||||
add_library(textures SHARED src/textures/textures.cpp)
|
||||
target_link_libraries(textures reborn symbols feature)
|
||||
|
||||
add_library(atlas SHARED src/atlas/atlas.cpp)
|
||||
target_link_libraries(atlas reborn symbols feature GLESv1_CM)
|
||||
endif()
|
||||
|
||||
add_library(camera SHARED src/camera/camera.cpp)
|
||||
target_link_libraries(camera reborn media-layer-core feature home)
|
||||
|
||||
add_library(game-mode SHARED src/game-mode/game-mode.c src/game-mode/game-mode.cpp)
|
||||
target_link_libraries(game-mode reborn feature)
|
||||
|
||||
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)
|
||||
target_link_libraries(input reborn feature media-layer-core)
|
||||
|
||||
add_library(sign SHARED src/sign/sign.cpp)
|
||||
target_link_libraries(sign reborn feature input)
|
||||
target_link_libraries(game-mode reborn symbols feature)
|
||||
|
||||
add_library(death SHARED src/death/death.cpp)
|
||||
target_link_libraries(death reborn feature)
|
||||
target_link_libraries(death reborn symbols feature)
|
||||
|
||||
add_library(misc SHARED src/misc/misc.c src/misc/misc.cpp)
|
||||
target_link_libraries(misc reborn feature)
|
||||
|
||||
add_library(creative SHARED src/creative/creative.cpp)
|
||||
target_link_libraries(creative reborn feature)
|
||||
target_link_libraries(misc reborn symbols feature)
|
||||
|
||||
add_library(options SHARED src/options/options.c)
|
||||
target_link_libraries(options reborn feature)
|
||||
|
||||
add_library(touch SHARED src/touch/touch.c)
|
||||
target_link_libraries(touch reborn feature)
|
||||
|
||||
add_library(override SHARED src/override/override.c)
|
||||
target_link_libraries(override reborn dl home)
|
||||
|
||||
add_library(textures SHARED src/textures/textures.cpp)
|
||||
target_link_libraries(textures reborn feature)
|
||||
|
||||
add_library(atlas SHARED src/atlas/atlas.cpp)
|
||||
target_link_libraries(atlas reborn feature GLESv1_CM)
|
||||
|
||||
add_library(chat SHARED src/chat/chat.cpp src/chat/ui.c)
|
||||
target_link_libraries(chat reborn feature input pthread)
|
||||
target_link_libraries(options reborn symbols feature)
|
||||
|
||||
add_library(home SHARED src/home/home.c)
|
||||
target_link_libraries(home reborn)
|
||||
target_link_libraries(home reborn symbols)
|
||||
|
||||
add_library(test SHARED src/test/test.c)
|
||||
target_link_libraries(test reborn home)
|
||||
|
||||
add_library(init SHARED src/init/init.c)
|
||||
target_link_libraries(init compat game-mode camera input sign misc creative death options touch textures atlas chat home version test)
|
||||
target_link_libraries(init compat game-mode misc death options chat home version test)
|
||||