mirror of
https://github.com/touchHLE/touchHLE.git
synced 2026-01-31 01:25:24 +01:00
Move MP3 handling to Symphonia
This removes dr_mp3 (and the associated dr_libs) from vendor/. Change-Id: Ia29d3d07f586644f6c182de6ec8fddc10c085b3c
This commit is contained in:
committed by
hikari_no_yume
parent
72ceffc6b2
commit
8bdb241ef0
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -8,9 +8,6 @@
|
||||
[submodule "openal-soft"]
|
||||
path = vendor/openal-soft
|
||||
url = https://github.com/kcat/openal-soft
|
||||
[submodule "vendor/dr_libs"]
|
||||
path = vendor/dr_libs
|
||||
url = https://github.com/mackron/dr_libs.git
|
||||
[submodule "vendor/SDL"]
|
||||
path = vendor/SDL
|
||||
url = https://github.com/libsdl-org/SDL.git
|
||||
|
||||
22
Cargo.lock
generated
22
Cargo.lock
generated
@@ -602,12 +602,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62e48dba70095f265fdb269b99619b95d04c89e619538138383e63310b14d941"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"symphonia-bundle-mp3",
|
||||
"symphonia-codec-aac",
|
||||
"symphonia-core",
|
||||
"symphonia-format-isomp4",
|
||||
"symphonia-metadata",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "symphonia-bundle-mp3"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f31d7fece546f1e6973011a9eceae948133bbd18fd3d52f6073b1e38ae6368a"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"symphonia-core",
|
||||
"symphonia-metadata",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "symphonia-codec-aac"
|
||||
version = "0.5.3"
|
||||
@@ -767,7 +781,6 @@ dependencies = [
|
||||
"sdl2",
|
||||
"sdl2-sys",
|
||||
"symphonia",
|
||||
"touchHLE_dr_mp3_wrapper",
|
||||
"touchHLE_dynarmic_wrapper",
|
||||
"touchHLE_gl_bindings",
|
||||
"touchHLE_openal_soft_wrapper",
|
||||
@@ -776,13 +789,6 @@ dependencies = [
|
||||
"zip",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "touchHLE_dr_mp3_wrapper"
|
||||
version = "0.2.2"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "touchHLE_dynarmic_wrapper"
|
||||
version = "0.2.2"
|
||||
|
||||
12
Cargo.toml
12
Cargo.toml
@@ -44,11 +44,12 @@ mach_object = "0.1.17"
|
||||
plist = "1.3.1"
|
||||
zip = { version = "0.6.4", default-features = false, features = ["deflate"] }
|
||||
rusttype = "0.9.3"
|
||||
# Symphonia is only used by src/audio/aac.rs right now, so that determines the
|
||||
# supported features. Only the AAC-LC profile (the "aac" feature) should be
|
||||
# enabled, because it's old enough that it *probably* isn't patent-encumbered,
|
||||
# but IANAL. Newer AAC profiles on the other hand are nightmares.
|
||||
symphonia = { version = "0.5.3", default-features = false, features = ["aac", "isomp4"] }
|
||||
# While most Symphonia codecs are (likely) unpatented/have freely licenseable
|
||||
# patents as of 2024, all of the AAC profiles except AAC-LC (likely) have
|
||||
# active patent claims. The "aac" feature only enables AAC-LC, so it's should
|
||||
# be ok.
|
||||
# (The above statements should not understood as legal claims/advice.)
|
||||
symphonia = { version = "0.5.3", default-features = false, features = ["aac", "isomp4", "mp3"] }
|
||||
quick-xml = "0.36.2"
|
||||
md5 = "0.7.0"
|
||||
# We currently use a fork of rust-sdl2 because we need a fix for Android builds
|
||||
@@ -59,7 +60,6 @@ md5 = "0.7.0"
|
||||
# SDL2 that rust-sdl2 uses, so that the Android JNI interface matches.
|
||||
sdl2 = { git = "https://github.com/hikari-no-yume/rust-sdl2.git", tag = "touchHLE-2", features = ["hidapi"] }
|
||||
sdl2-sys = { git = "https://github.com/hikari-no-yume/rust-sdl2.git", tag = "touchHLE-2" }
|
||||
touchHLE_dr_mp3_wrapper = { path = "src/audio/dr_mp3_wrapper" }
|
||||
touchHLE_dynarmic_wrapper = { path = "src/cpu/dynarmic_wrapper" }
|
||||
touchHLE_gl_bindings = { path = "src/gles/gl_bindings" }
|
||||
touchHLE_openal_soft_wrapper = { path = "src/audio/openal_soft_wrapper" }
|
||||
|
||||
@@ -114,7 +114,7 @@ Please note that different licensing terms apply to the bundled dynamic librarie
|
||||
We stand on the shoulders of giants. Thank you to:
|
||||
|
||||
* Everyone who has contributed to the project or supported any of its contributors financially.
|
||||
* The authors of and contributors to the many libraries used by this project: [dynarmic](https://github.com/merryhime/dynarmic), [rust-macho](https://github.com/flier/rust-macho), [SDL](https://libsdl.org/), [rust-sdl2](https://github.com/Rust-SDL2/rust-sdl2), [stb\_image](https://github.com/nothings/stb), Imagination Technologies' [PVRTC decompressor](https://github.com/powervr-graphics/Native_SDK/blob/master/framework/PVRCore/texture/PVRTDecompress.cpp), [openal-soft](https://github.com/kcat/openal-soft), [hound](https://github.com/ruuda/hound), [caf](https://github.com/rustaudio/caf), [dr\_mp3](https://github.com/mackron/dr_libs), [Symphonia](https://github.com/pdeljanov/Symphonia), [RustType](https://gitlab.redox-os.org/redox-os/rusttype), [the Liberation fonts](https://github.com/liberationfonts/liberation-fonts), [the Noto CJK fonts](https://github.com/googlefonts/noto-cjk), [rust-plist](https://github.com/ebarnard/rust-plist), [quick-xml](https://github.com/tafia/quick-xml), [gl-rs](https://github.com/brendanzab/gl-rs), [cargo-license](https://github.com/onur/cargo-license), [cc-rs](https://github.com/rust-lang/cc-rs), [cmake-rs](https://github.com/rust-lang/cmake-rs), [cargo-ndk](https://github.com/bbqsrc/cargo-ndk), [cargo-ndk-android-gradle](https://github.com/willir/cargo-ndk-android-gradle), [md5](https://github.com/stainless-steel/md5), and the Rust standard library.
|
||||
* The authors of and contributors to the many libraries used by this project: [dynarmic](https://github.com/merryhime/dynarmic), [rust-macho](https://github.com/flier/rust-macho), [SDL](https://libsdl.org/), [rust-sdl2](https://github.com/Rust-SDL2/rust-sdl2), [stb\_image](https://github.com/nothings/stb), Imagination Technologies' [PVRTC decompressor](https://github.com/powervr-graphics/Native_SDK/blob/master/framework/PVRCore/texture/PVRTDecompress.cpp), [openal-soft](https://github.com/kcat/openal-soft), [hound](https://github.com/ruuda/hound), [caf](https://github.com/rustaudio/caf), [Symphonia](https://github.com/pdeljanov/Symphonia), [RustType](https://gitlab.redox-os.org/redox-os/rusttype), [the Liberation fonts](https://github.com/liberationfonts/liberation-fonts), [the Noto CJK fonts](https://github.com/googlefonts/noto-cjk), [rust-plist](https://github.com/ebarnard/rust-plist), [quick-xml](https://github.com/tafia/quick-xml), [gl-rs](https://github.com/brendanzab/gl-rs), [cargo-license](https://github.com/onur/cargo-license), [cc-rs](https://github.com/rust-lang/cc-rs), [cmake-rs](https://github.com/rust-lang/cmake-rs), [cargo-ndk](https://github.com/bbqsrc/cargo-ndk), [cargo-ndk-android-gradle](https://github.com/willir/cargo-ndk-android-gradle), [md5](https://github.com/stainless-steel/md5), and the Rust standard library.
|
||||
* The Skyline emulator project (RIP), for [writing the tedious boilerplate needed to replace file management on newer Android versions](https://github.com/skyline-emu/skyline/blob/dc20a615275f66bee20a4fd851ef0231daca4f14/app/src/main/java/emu/skyline/provider/DocumentsProvider.kt).
|
||||
* The [Rust project](https://www.rust-lang.org/) generally.
|
||||
* The various people out there who've documented the iPhone OS platform, officially or otherwise. Much of this documentation is linked to within this codebase!
|
||||
|
||||
53
src/audio.rs
53
src/audio.rs
@@ -6,17 +6,16 @@
|
||||
//! Audio file decoding and OpenAL bindings.
|
||||
//!
|
||||
//! The audio file decoding support is an abstraction over various libraries
|
||||
//! (currently [caf], [hound], and dr_mp3), usage of which should be confined to
|
||||
//! this module.
|
||||
//! (currently [caf], [hound], and [symphonia]), usage of which should be
|
||||
//! confined to this module.
|
||||
//!
|
||||
//! Resources:
|
||||
//! - [Apple Core Audio Format Specification 1.0](https://developer.apple.com/library/archive/documentation/MusicAudio/Reference/CAFSpec/CAF_intro/CAF_intro.html)
|
||||
|
||||
mod aac;
|
||||
mod ima4;
|
||||
mod symphonia_formats;
|
||||
|
||||
pub use ima4::decode_ima4;
|
||||
use touchHLE_dr_mp3_wrapper as dr_mp3;
|
||||
pub use touchHLE_openal_soft_wrapper as openal;
|
||||
|
||||
use crate::fs::{Fs, GuestPath};
|
||||
@@ -54,8 +53,7 @@ pub struct AudioFile(AudioFileInner);
|
||||
enum AudioFileInner {
|
||||
Wave(hound::WavReader<Cursor<Vec<u8>>>),
|
||||
Caf(caf::CafPacketReader<Cursor<Vec<u8>>>),
|
||||
Mp3(dr_mp3::Mp3DecodedToPcm),
|
||||
Aac(aac::AacDecodedToPcm),
|
||||
Symphonia(symphonia_formats::SymphoniaDecodedToPcm),
|
||||
}
|
||||
|
||||
impl AudioFile {
|
||||
@@ -75,28 +73,19 @@ impl AudioFile {
|
||||
// trying both. This is worked around here by using temporary readers
|
||||
// for checking if the file is the supported format, then recreating the
|
||||
// reader if that works.
|
||||
|
||||
if hound::WavReader::new(Cursor::new(&bytes)).is_ok() {
|
||||
let reader = hound::WavReader::new(Cursor::new(bytes)).unwrap();
|
||||
Ok(AudioFile(AudioFileInner::Wave(reader)))
|
||||
} else if caf::CafPacketReader::new(Cursor::new(&bytes), vec![]).is_ok() {
|
||||
let reader = caf::CafPacketReader::new(Cursor::new(bytes), vec![]).unwrap();
|
||||
Ok(AudioFile(AudioFileInner::Caf(reader)))
|
||||
// TODO: Real MP3 container handling. Currently we are immediately
|
||||
// decoding the entire file to PCM and acting as if it's a PCM file,
|
||||
// simply because because this is easier. Full MP3 support would require
|
||||
// a lot of changes in Audio Toolbox.
|
||||
} else if let Ok(pcm) = dr_mp3::decode_mp3_to_pcm(&bytes) {
|
||||
Ok(AudioFile(AudioFileInner::Mp3(pcm)))
|
||||
// TODO: Real MP4 container handling for AAC. The situation is the same
|
||||
// as for MP3.
|
||||
} else if let Ok(pcm) = aac::decode_aac_to_pcm(Cursor::new(bytes)) {
|
||||
Ok(AudioFile(AudioFileInner::Aac(pcm)))
|
||||
// TODO: Real MP3/MP4/Non-linear PCM container handling. Currently we
|
||||
// are immediately decoding the entire file to PCM and acting as if
|
||||
// it's a PCM file, simply because because this is easier. Full MP3
|
||||
// support would require a lot of changes in Audio Toolbox.
|
||||
} else if let Ok(pcm) = symphonia_formats::decode_symphonia_to_pcm(Cursor::new(bytes)) {
|
||||
Ok(AudioFile(AudioFileInner::Symphonia(pcm)))
|
||||
} else {
|
||||
log!(
|
||||
"Could not decode audio file at path {:?}, likely an unimplemented file format.",
|
||||
path.as_ref()
|
||||
);
|
||||
Err(AudioFileOpenError::FileDecodeError)
|
||||
}
|
||||
}
|
||||
@@ -167,12 +156,7 @@ impl AudioFile {
|
||||
bits_per_channel,
|
||||
}
|
||||
}
|
||||
AudioFileInner::Mp3(dr_mp3::Mp3DecodedToPcm {
|
||||
sample_rate,
|
||||
channels,
|
||||
..
|
||||
})
|
||||
| AudioFileInner::Aac(aac::AacDecodedToPcm {
|
||||
AudioFileInner::Symphonia(symphonia_formats::SymphoniaDecodedToPcm {
|
||||
sample_rate,
|
||||
channels,
|
||||
..
|
||||
@@ -214,16 +198,17 @@ impl AudioFile {
|
||||
// variable size not implemented
|
||||
u64::from(self.packet_size_fixed()) * self.packet_count()
|
||||
}
|
||||
AudioFileInner::Mp3(dr_mp3::Mp3DecodedToPcm { ref bytes, .. })
|
||||
| AudioFileInner::Aac(aac::AacDecodedToPcm { ref bytes, .. }) => bytes.len() as u64,
|
||||
AudioFileInner::Symphonia(symphonia_formats::SymphoniaDecodedToPcm {
|
||||
ref bytes,
|
||||
..
|
||||
}) => bytes.len() as u64,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn packet_count(&self) -> u64 {
|
||||
match self.0 {
|
||||
AudioFileInner::Wave(_)
|
||||
| AudioFileInner::Mp3(dr_mp3::Mp3DecodedToPcm { .. })
|
||||
| AudioFileInner::Aac(aac::AacDecodedToPcm { .. }) => {
|
||||
| AudioFileInner::Symphonia(symphonia_formats::SymphoniaDecodedToPcm { .. }) => {
|
||||
// never variable-size
|
||||
self.byte_count() / u64::from(self.packet_size_fixed())
|
||||
}
|
||||
@@ -316,8 +301,10 @@ impl AudioFile {
|
||||
}
|
||||
Ok(byte_offset)
|
||||
}
|
||||
AudioFileInner::Mp3(dr_mp3::Mp3DecodedToPcm { ref bytes, .. })
|
||||
| AudioFileInner::Aac(aac::AacDecodedToPcm { ref bytes, .. }) => {
|
||||
AudioFileInner::Symphonia(symphonia_formats::SymphoniaDecodedToPcm {
|
||||
ref bytes,
|
||||
..
|
||||
}) => {
|
||||
let bytes = bytes.get(offset as usize..).ok_or(())?;
|
||||
let bytes_to_read = buffer.len().min(bytes.len());
|
||||
let bytes = &bytes[..bytes_to_read];
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
[package]
|
||||
name = "touchHLE_dr_mp3_wrapper"
|
||||
version = { workspace = true }
|
||||
edition = { workspace = true }
|
||||
license = { workspace = true }
|
||||
authors = { workspace = true }
|
||||
homepage = { workspace = true }
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
||||
[build-dependencies]
|
||||
cc = { workspace = true }
|
||||
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
use std::path::Path;
|
||||
|
||||
fn rerun_if_changed(path: &Path) {
|
||||
println!("cargo:rerun-if-changed={}", path.to_str().unwrap());
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let package_root = Path::new(env!("CARGO_MANIFEST_DIR"));
|
||||
let workspace_root = package_root.join("../../..");
|
||||
|
||||
cc::Build::new()
|
||||
.file(package_root.join("lib.c"))
|
||||
.compile("dr_mp3_wrapper");
|
||||
rerun_if_changed(&package_root.join("lib.c"));
|
||||
rerun_if_changed(&workspace_root.join("vendor/dr_libs/dr_mp3.h"));
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
#define DR_MP3_IMPLEMENTATION
|
||||
#define DR_MP3_NO_STDIO
|
||||
#include "../../../vendor/dr_libs/dr_mp3.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int16_t *touchHLE_decode_mp3_to_pcm(const uint8_t *data, size_t data_size,
|
||||
uint32_t *channels, uint32_t *sample_rate,
|
||||
uint64_t *frame_count) {
|
||||
drmp3_config config;
|
||||
int16_t *samples = drmp3_open_memory_and_read_pcm_frames_s16(
|
||||
data, data_size, &config, (drmp3_uint64 *)frame_count,
|
||||
/* pAllocationCallbacks: */ NULL);
|
||||
if (samples) {
|
||||
*channels = config.channels;
|
||||
*sample_rate = config.sampleRate;
|
||||
}
|
||||
return samples;
|
||||
}
|
||||
|
||||
void touchHLE_free_decoded_mp3_pcm(int16_t *samples) {
|
||||
drmp3_free(samples, /* pAllocationCallbacks: */ NULL);
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
//! This is separated out into its own package so that we can avoid rebuilding
|
||||
//! dr_mp3 more often than necessary, and to improve build-time parallelism.
|
||||
|
||||
// Allow the crate to have a non-snake-case name (touchHLE).
|
||||
// This also allows items in the crate to have non-snake-case names.
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
// See build.rs and lib.c
|
||||
extern "C" {
|
||||
fn touchHLE_decode_mp3_to_pcm(
|
||||
data: *const u8,
|
||||
data_size: usize,
|
||||
channels: *mut u32,
|
||||
sample_rate: *mut u32,
|
||||
frame_count: *mut u64,
|
||||
) -> *mut i16;
|
||||
fn touchHLE_free_decoded_mp3_pcm(samples: *mut i16);
|
||||
}
|
||||
|
||||
/// PCM data decoded from an MP3 file.
|
||||
pub struct Mp3DecodedToPcm {
|
||||
/// 16-bit little-endian PCM samples, grouped in frames (one sample per
|
||||
/// channel in each frame).
|
||||
pub bytes: Vec<u8>,
|
||||
/// Sample rate in Hz.
|
||||
pub sample_rate: u32,
|
||||
/// Channel count.
|
||||
pub channels: u32,
|
||||
}
|
||||
|
||||
#[allow(clippy::result_unit_err)]
|
||||
pub fn decode_mp3_to_pcm(data: &[u8]) -> Result<Mp3DecodedToPcm, ()> {
|
||||
let mut channels = 0;
|
||||
let mut sample_rate = 0;
|
||||
let mut frame_count = 0;
|
||||
let samples_ptr = unsafe {
|
||||
touchHLE_decode_mp3_to_pcm(
|
||||
data.as_ptr(),
|
||||
data.len(),
|
||||
&mut channels,
|
||||
&mut sample_rate,
|
||||
&mut frame_count,
|
||||
)
|
||||
};
|
||||
if samples_ptr.is_null() {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
let bytes = unsafe {
|
||||
std::slice::from_raw_parts(
|
||||
samples_ptr as *const _,
|
||||
std::mem::size_of::<i16>() * (frame_count as usize) * (channels as usize),
|
||||
)
|
||||
}
|
||||
.to_vec();
|
||||
unsafe { touchHLE_free_decoded_mp3_pcm(samples_ptr) };
|
||||
|
||||
Ok(Mp3DecodedToPcm {
|
||||
bytes,
|
||||
sample_rate,
|
||||
channels,
|
||||
})
|
||||
}
|
||||
@@ -11,11 +11,11 @@
|
||||
|
||||
use std::io::Cursor;
|
||||
use symphonia::core::audio::{RawSampleBuffer, SignalSpec};
|
||||
use symphonia::core::codecs::CODEC_TYPE_AAC;
|
||||
use symphonia::core::codecs::{CODEC_TYPE_AAC, CODEC_TYPE_MP3};
|
||||
use symphonia::core::io::MediaSourceStream;
|
||||
|
||||
/// PCM data decoded from an AAC file.
|
||||
pub struct AacDecodedToPcm {
|
||||
pub struct SymphoniaDecodedToPcm {
|
||||
/// 16-bit little-endian PCM samples, grouped in frames (one sample per
|
||||
/// channel in each frame).
|
||||
pub bytes: Vec<u8>,
|
||||
@@ -25,7 +25,7 @@ pub struct AacDecodedToPcm {
|
||||
pub channels: u32,
|
||||
}
|
||||
|
||||
pub fn decode_aac_to_pcm(file: Cursor<Vec<u8>>) -> Result<AacDecodedToPcm, ()> {
|
||||
pub fn decode_symphonia_to_pcm(file: Cursor<Vec<u8>>) -> Result<SymphoniaDecodedToPcm, ()> {
|
||||
let mss = MediaSourceStream::new(Box::new(file), Default::default());
|
||||
|
||||
// If this failed, the container format is not supported.
|
||||
@@ -43,7 +43,7 @@ pub fn decode_aac_to_pcm(file: Cursor<Vec<u8>>) -> Result<AacDecodedToPcm, ()> {
|
||||
let track = format
|
||||
.tracks()
|
||||
.iter()
|
||||
.find(|t| t.codec_params.codec == CODEC_TYPE_AAC)
|
||||
.find(|t| t.codec_params.codec == CODEC_TYPE_AAC || t.codec_params.codec == CODEC_TYPE_MP3)
|
||||
.ok_or(())?;
|
||||
let track_id = track.id;
|
||||
|
||||
@@ -91,8 +91,7 @@ pub fn decode_aac_to_pcm(file: Cursor<Vec<u8>>) -> Result<AacDecodedToPcm, ()> {
|
||||
}
|
||||
}
|
||||
let signal_spec = signal_spec.ok_or(())?;
|
||||
|
||||
Ok(AacDecodedToPcm {
|
||||
Ok(SymphoniaDecodedToPcm {
|
||||
bytes: out_pcm,
|
||||
sample_rate: signal_spec.rate,
|
||||
channels: signal_spec.channels.count().try_into().unwrap(),
|
||||
@@ -127,13 +127,6 @@ const PVRTD_LICENSE: &str = include_str!(concat!(
|
||||
"/vendor/PVRTDecompress/LICENSE.md"
|
||||
));
|
||||
|
||||
const DR_MP3: &str = "
|
||||
touchHLE, and therefore this executable, incorporates the library dr_mp3,
|
||||
which is available either under The Unlicense (which is a public domain
|
||||
dedication) or under the terms of the MIT license. dr_mp3 is in turn derived
|
||||
from the library minimp3, which is licensed under the Creative Commons CC0 1.0
|
||||
Universal Public Domain Dedication.
|
||||
";
|
||||
|
||||
// When resource files are bundled with touchHLE in such a way that the user can
|
||||
// read their license files directly, use this caveat.
|
||||
@@ -215,8 +208,6 @@ fn print(out: &mut String, resources_are_external_files: bool) -> Result<(), std
|
||||
divider(out)?;
|
||||
writeln!(out, "{}", PVRTD_DESCRIPTION)?;
|
||||
writeln!(out, "{}", PVRTD_LICENSE.trim_end())?;
|
||||
divider(out)?;
|
||||
writeln!(out, "{}", DR_MP3)?;
|
||||
if !resources_are_external_files {
|
||||
divider(out)?;
|
||||
writeln!(out, "{}", INTERNAL_DYLIBS_DESCRIPTION)?;
|
||||
|
||||
1
vendor/dr_libs
vendored
1
vendor/dr_libs
vendored
Submodule vendor/dr_libs deleted from dd762b861e
Reference in New Issue
Block a user