Add portable Windows build and update GC runtime
This commit is contained in:
+69
-8
@@ -288,9 +288,11 @@ mixed as ordinary scalars.
|
||||
### Up vector and roll
|
||||
|
||||
`FUN_005e0ad0` rebuilds `up` by projecting world-up `(0,1,0)` onto the plane
|
||||
normal to `target-eye`. If the two directions are collinear it falls back to
|
||||
`(0,0,1)`. `rotationB` then rotates that up vector around the normalized view
|
||||
axis.
|
||||
normal to `target-eye`. The Android `camera3D::BuildUpVector` uses `(0,0,1)`
|
||||
when the normalized view direction's L1 distance from either Y pole is below
|
||||
`0.001`; otherwise it uses `(0,1,0)`. `rotationB` then rotates that up vector
|
||||
around the normalized view axis. This is not equivalent to a generic
|
||||
dot-product parallelism threshold on near-vertical authored cameras.
|
||||
|
||||
### Gameplay projection
|
||||
|
||||
@@ -314,9 +316,13 @@ orthographic sections.
|
||||
The distance is not clamped to the near plane. A zero-length camera therefore
|
||||
also produces zero orthographic extents in the original. Likewise, its vector
|
||||
normalizer returns `(0,0,0)` for a zero-length input instead of propagating a
|
||||
NaN as `glm::normalize` does. The Linux port mirrors both edge cases and uses
|
||||
explicit left-handed view/projection builders; the `NO` depth variant is the
|
||||
OpenGL backend adaptation of the original D3D left-handed matrices.
|
||||
NaN as `glm::normalize` does. The Linux port mirrors both edge cases.
|
||||
|
||||
The matrix convention is backend-specific. Arcade emits D3D matrices, while
|
||||
Android's `matrix44::LookAt` uses `eye-target` and its perspective matrix has
|
||||
`-1` at `m[2][3]`, the OpenGL right-handed/no-depth-remap convention. Because
|
||||
Vectorail also renders through OpenGL, its GC path follows the Android RH/NO
|
||||
builders rather than feeding D3D handedness directly to GLM.
|
||||
|
||||
The evaluator sets `projBlend` to `0` for `projType=0` and `1` for
|
||||
`projType=1`. An `fMode=1` transition linearly interpolates the endpoint
|
||||
@@ -349,11 +355,66 @@ The player now imports the raw camera keys (including non-finite sentinel
|
||||
values) and ports the confirmed `aMode`,
|
||||
`fMode`, orbit, up/roll, projection type/blend, FOV and clipping-plane
|
||||
behavior. GC cameras are evaluated directly without the legacy follow-camera
|
||||
smoothing. Remaining camera work is validation against captured original
|
||||
frames.
|
||||
smoothing. The runtime uses Android's `a + (b-a)*u` float operation order and
|
||||
builds the GC view matrix without an extra host-side up-vector fallback.
|
||||
|
||||
An independent verifier reimplements the Android evaluator from decoded wire
|
||||
records instead of calling the player's camera helpers. Across the current
|
||||
2970-chart corpus it checked 171333 keys and 9113837 sampled times, including
|
||||
every track vertex and the interior of every camera-key interval. All seven
|
||||
`aMode` branches and `fMode` 0/1/2 were present:
|
||||
|
||||
```text
|
||||
eye/target max error: 0
|
||||
up max error: 0
|
||||
view max error: 0
|
||||
projection max error: 4.76837e-7
|
||||
```
|
||||
|
||||
This pass found and corrected a sign error in the expanded quaternion's `qz`
|
||||
term and replaced the previous approximate vertical-up threshold with the
|
||||
exact Android `0.001` L1 test.
|
||||
|
||||
## Switch and Android cross-version validation
|
||||
|
||||
The Android reference used here comes from
|
||||
`/home/au/Downloads/gc2offlinev4.xapk`. The outer package is an offline
|
||||
installer; the original game is its nested `assets/groovecoaster.apk`:
|
||||
|
||||
```text
|
||||
package: jp.co.taito.groovecoasterzero
|
||||
version: 1.0.18 (versionCode 76)
|
||||
native ABI: arm64-v8a
|
||||
native code: lib/arm64-v8a/libtune.so
|
||||
|
||||
XAPK SHA-256: c6c394f7a1cc65331edc98aac94014668f9d5277ce17262fecf9aeeb1a2a3003
|
||||
nested APK SHA-256: 62c9e739dc9b8c1bcbcb4b5234d78f154b20d1a930329b9c21a3c9236b92a0dc
|
||||
libtune.so SHA-256: 689b2e4c0bc4479a3f309944b5070796878c66c0dfdbd283c11ec0bbeeea9efa
|
||||
```
|
||||
|
||||
Unlike the arcade executable, this `libtune.so` retains C++ symbols. Relevant
|
||||
ELF virtual addresses (before Ghidra's `+0x100000` image base) are:
|
||||
|
||||
```text
|
||||
0x0933a0 TuneGameData::LoadGameData(bytearray*, bool)
|
||||
0x0953bc TuneGameData::GetWayPosition(int)
|
||||
0x095588 TuneGameData::GetCameraData(int, bool)
|
||||
0x0ad1a4 GameScene::SetCommonParam()
|
||||
0x0ad524 GameScene::CalcGameProjectionMatrix(camera3D&)
|
||||
0x0b8410 GameScene::CalcGamePerspectiveMatrix(camera3D&)
|
||||
0x0b847c GameScene::CalcGameOrthoMatrix(camera3D&)
|
||||
0x102c78 matrix44::Perspective(float, float, float, float)
|
||||
0x102d34 matrix44::LookAt(vector3 const&, vector3 const&, vector3 const&)
|
||||
0x1031f0 camera3D::BuildUpVector(float)
|
||||
0x103e48 RotateHPB::ToVector_Deg(float)
|
||||
```
|
||||
|
||||
`TuneGameData::LoadGameData` independently confirms every wire read and the
|
||||
59-byte camera record order. It expands each record to an aligned 0x48-byte
|
||||
runtime entry. `GameScene::SetCommonParam` then calls `GetCameraData` for the
|
||||
current chart time, builds the projection, and passes `eye`, `target`, and
|
||||
`up` to `matrix44::LookAt`.
|
||||
|
||||
The base Switch executable retains `CTuneGameData` RTTI and the original GC
|
||||
source filenames. Its stripped `CTuneGameData::GetWayPosition` and
|
||||
`CTuneGameData::GetCameraData` implementations were matched to the named
|
||||
|
||||
Reference in New Issue
Block a user