mirror of
https://github.com/mitch030504/AstroQuest-Frame.git
synced 2026-10-20 22:01:13 +02:00
On top of the shadps4-arm64 core imported in the previous commit: - PlayStation VR emulation: headset, tracker, reprojection, camera and social screen; the player's seat and view reset; head velocity for head-butts; field of view settings - Sound: a native Ngs2 engine (samplers, submixers, effects), the Audio3d spatializer, virtual surround for headset speakers, microphone pass-through; libSceJson2; libSceFiber on FEX - Fixes for CUSA12392 under emulation: real-time step, pace and resolution governor, larger render sizes on the PC, save loading at start - Renderer: geometry shaders fed with fans/polygons/loops, cube-array layers of light probes, sample-count mismatches on Adreno, timeline semaphore hang, FXAA in place of the MSAA resolve, sharpening, VR frame export - quest-host: the Quest app (OpenXR host that runs the glibc core as a child process, frames through AHardwareBuffers, DualSense mapping, hand-tracked controller placement, KGSL shim) - PC: in-process OpenXR host (Virtual Desktop or any OpenXR runtime), Touch controllers as the gamepad, launcher with a settings window; vendored OpenXR SDK 1.1.63 - Builds keep the build machine's folders out of the binaries (-ffile-prefix-map); machine settings (Python, headset serial, signing key) live in git-ignored tools/*.local files - tools: build, packaging and test scripts for Windows and the headset - README with installation, license (GPL-2.0-or-later), third-party notices and thanks No game files are part of the repository; .gitignore only lets listed paths in. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
83 lines
3.1 KiB
Java
83 lines
3.1 KiB
Java
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
package com.astrobotquest.vrhost;
|
|
|
|
import android.content.Context;
|
|
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.File;
|
|
import java.io.FileOutputStream;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.nio.file.Files;
|
|
import java.util.zip.ZipEntry;
|
|
import java.util.zip.ZipInputStream;
|
|
|
|
/**
|
|
* Unpacks the Linux runtime the emulator runs in (its libraries, the GPU driver, the emulator
|
|
* core itself) from the app's assets into the app's files folder. The assets carry a stamp of
|
|
* what they hold; a folder with the same stamp is left alone.
|
|
*/
|
|
final class RuntimeInstaller {
|
|
private RuntimeInstaller() {}
|
|
|
|
/** Returns true when the runtime had to be unpacked, false when it was there already. */
|
|
static boolean install(Context context, File runtime) throws IOException {
|
|
String stamp;
|
|
try (InputStream in = context.getAssets().open("runtime.stamp")) {
|
|
stamp = new String(readAll(in), StandardCharsets.UTF_8).trim();
|
|
}
|
|
File stampFile = new File(runtime, ".stamp");
|
|
if (stampFile.isFile()
|
|
&& new String(Files.readAllBytes(stampFile.toPath()), StandardCharsets.UTF_8)
|
|
.trim().equals(stamp)) {
|
|
return false;
|
|
}
|
|
|
|
deleteRecursively(runtime);
|
|
runtime.mkdirs();
|
|
String root = runtime.getCanonicalPath() + File.separator;
|
|
byte[] buffer = new byte[1 << 16];
|
|
try (ZipInputStream zip = new ZipInputStream(context.getAssets().open("runtime.zip"))) {
|
|
for (ZipEntry entry = zip.getNextEntry(); entry != null; entry = zip.getNextEntry()) {
|
|
File target = new File(runtime, entry.getName());
|
|
if (!target.getCanonicalPath().startsWith(root)) {
|
|
throw new IOException("bad runtime entry " + entry.getName());
|
|
}
|
|
if (entry.isDirectory()) {
|
|
target.mkdirs();
|
|
continue;
|
|
}
|
|
target.getParentFile().mkdirs();
|
|
try (FileOutputStream out = new FileOutputStream(target)) {
|
|
for (int count = zip.read(buffer); count > 0; count = zip.read(buffer)) {
|
|
out.write(buffer, 0, count);
|
|
}
|
|
}
|
|
target.setExecutable(true, true);
|
|
}
|
|
}
|
|
Files.write(stampFile.toPath(), stamp.getBytes(StandardCharsets.UTF_8));
|
|
return true;
|
|
}
|
|
|
|
private static byte[] readAll(InputStream in) throws IOException {
|
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
byte[] buffer = new byte[4096];
|
|
for (int count = in.read(buffer); count > 0; count = in.read(buffer)) {
|
|
out.write(buffer, 0, count);
|
|
}
|
|
return out.toByteArray();
|
|
}
|
|
|
|
static void deleteRecursively(File file) {
|
|
File[] children = file.listFiles();
|
|
if (children != null) {
|
|
for (File child : children) {
|
|
deleteRecursively(child);
|
|
}
|
|
}
|
|
file.delete();
|
|
}
|
|
}
|