mirror of
https://github.com/ficed/Braver.git
synced 2024-11-23 13:19:43 +00:00
Add initial camdat decoders
This commit is contained in:
parent
efc8eb0ac3
commit
b5a2055da9
245
Ficedula.FF7/Battle/Camera.cs
Normal file
245
Ficedula.FF7/Battle/Camera.cs
Normal file
@ -0,0 +1,245 @@
|
||||
// This program and the accompanying materials are made available under the terms of the
|
||||
// Eclipse Public License v2.0 which accompanies this distribution, and is available at
|
||||
// https://www.eclipse.org/legal/epl-v20.html
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ficedula.FF7.Battle {
|
||||
public class CameraData : IDisposable {
|
||||
|
||||
private Stream _source;
|
||||
|
||||
private List<int[]> _offsets;
|
||||
public int CameraCount { get; private set; }
|
||||
|
||||
public CameraData(Stream source) {
|
||||
_source = source;
|
||||
|
||||
var offsets = Enumerable.Range(0, 4)
|
||||
.Select(_ => (int)(source.ReadU32() - 0x801A0000))
|
||||
.ToArray();
|
||||
CameraCount = (offsets[1] - offsets[0]) / 12; //4 byte pointer, 3 cameras per entry
|
||||
|
||||
_offsets = Enumerable.Range(0, 4)
|
||||
.Select(i => {
|
||||
int count = i < 2 ? CameraCount : 1;
|
||||
source.Position = offsets[i];
|
||||
int[] pointers = Enumerable.Range(0, count)
|
||||
.Select(_ => (int)(source.ReadU32() - 0x801A0000))
|
||||
.ToArray();
|
||||
return pointers;
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private byte[] Read(int camera, int index, bool focus, bool victoryCamera) {
|
||||
int[] offsets = _offsets[(focus ? 1 : 0) + (victoryCamera ? 2 : 0)];
|
||||
int offset = offsets[camera * 3 + index],
|
||||
next = offsets[camera * 3 + index + 1];
|
||||
byte[] data = new byte[next - offset];
|
||||
_source.Position = offset;
|
||||
_source.Read(data, 0, data.Length);
|
||||
return data;
|
||||
}
|
||||
|
||||
public CameraPositionScript ReadPosition(int camera, int index, bool isVictory) {
|
||||
return new CameraPositionScript(Read(camera, index, false, isVictory));
|
||||
}
|
||||
public CameraFocusScript ReadFocus(int camera, int index, bool isVictory) {
|
||||
return new CameraFocusScript(Read(camera, index, true, isVictory));
|
||||
}
|
||||
|
||||
|
||||
public void Dispose() {
|
||||
_source.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class CameraScript<T> where T : struct {
|
||||
|
||||
protected static Dictionary<T, int[]> _opParams;
|
||||
protected static T _conditionalRestartOp;
|
||||
|
||||
private byte[] _bytecode;
|
||||
private int _ip;
|
||||
|
||||
protected CameraScript(byte[] bytecode) {
|
||||
_bytecode = bytecode;
|
||||
}
|
||||
|
||||
protected abstract T FromByte(byte b);
|
||||
|
||||
public DecodedCameraOp<T> NextOp() {
|
||||
var op = new DecodedCameraOp<T> {
|
||||
Opcode = FromByte(_bytecode[_ip++]),
|
||||
};
|
||||
if (_opParams.TryGetValue(op.Opcode, out int[] parms)) {
|
||||
op.Operands = parms
|
||||
.Select(i => {
|
||||
switch (i) {
|
||||
case 1:
|
||||
return (int)_bytecode[_ip++];
|
||||
case 2:
|
||||
short s = BitConverter.ToInt16(_bytecode, _ip);
|
||||
_ip += 2;
|
||||
return s;
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
})
|
||||
.ToArray();
|
||||
}
|
||||
return op;
|
||||
}
|
||||
}
|
||||
|
||||
public class CameraPositionScript : CameraScript<CameraPositionOpcode> {
|
||||
|
||||
static CameraPositionScript() {
|
||||
_opParams = new() {
|
||||
[CameraPositionOpcode.UnknownD5] = new[] { 2 },
|
||||
[CameraPositionOpcode.UnknownD7] = new[] { 1, 1 },
|
||||
[CameraPositionOpcode.UnknownD8] = new[] { 1, 1, 2, 2, 2, 1 },
|
||||
[CameraPositionOpcode.SetActiveIdleCamera] = new[] { 1 },
|
||||
[CameraPositionOpcode.UnknownDE] = new[] { 1 },
|
||||
[CameraPositionOpcode.UnknownE0] = new[] { 1, 1 },
|
||||
[CameraPositionOpcode.UnknownE2] = new[] { 1 },
|
||||
[CameraPositionOpcode.UnknownE3] = new[] { 1, 1, 2, 2, 2, 1 },
|
||||
[CameraPositionOpcode.TransitionToAttackerJoint] = new[] { 1, 2, 2, 2, 1 },
|
||||
[CameraPositionOpcode.TransitionToTargetJoint] = new[] { 1, 2, 2, 2, 1 },
|
||||
[CameraPositionOpcode.UnknownE6] = new[] { 2, 2, 2, 1 },
|
||||
[CameraPositionOpcode.UnknownE7] = new[] { 1, 2, 2, 2, 1 },
|
||||
[CameraPositionOpcode.UnknownE9] = new[] { 1, 2, 2, 2, 1 },
|
||||
[CameraPositionOpcode.UnknownEB] = new[] { 1, 1, 2, 2, 2, 1 },
|
||||
[CameraPositionOpcode.UnknownEF] = new[] { 1, 1, 2, 2, 2 },
|
||||
[CameraPositionOpcode.UnknownF0] = new[] { 1, 2, 2, 2 },
|
||||
[CameraPositionOpcode.UnknownF2] = new[] { 1, 2, 2 },
|
||||
[CameraPositionOpcode.UnknownF3] = new[] { 1, 2, 2 },
|
||||
[CameraPositionOpcode.SetWait] = new[] { 1 },
|
||||
[CameraPositionOpcode.UnknownF7] = new[] { 1, 2, 2, 2 },
|
||||
[CameraPositionOpcode.UnknownF8] = new[] { 2, 2, 2, 2, 2, 2 },
|
||||
[CameraPositionOpcode.UnknownF9] = new[] { 2, 2, 2 },
|
||||
//ConditionalRestart is special
|
||||
};
|
||||
_conditionalRestartOp = CameraPositionOpcode.ConditionalRestart;
|
||||
}
|
||||
|
||||
public CameraPositionScript(byte[] bytecode) : base(bytecode) {
|
||||
}
|
||||
|
||||
protected override CameraPositionOpcode FromByte(byte b) {
|
||||
return (CameraPositionOpcode)b;
|
||||
}
|
||||
}
|
||||
|
||||
public class CameraFocusScript : CameraScript<CameraFocusOpcode> {
|
||||
|
||||
static CameraFocusScript() {
|
||||
_opParams = new() {
|
||||
[CameraFocusOpcode.UnknownD8] = new[] { 1, 1, 2, 2, 2, 1 },
|
||||
[CameraFocusOpcode.SetActiveIdleCamera] = new[] { 1 },
|
||||
[CameraFocusOpcode.UnknownDE] = new[] { 1 },
|
||||
[CameraFocusOpcode.UnknownE0] = new[] { 1, 1 },
|
||||
[CameraFocusOpcode.TransitionToIdle] = new[] { 1 },
|
||||
[CameraFocusOpcode.UnknownE3] = new[] { 1, 1, 2, 2, 2, 1 },
|
||||
[CameraFocusOpcode.TransitionToAttackerJoint] = new[] { 1, 1, 2, 2, 2, 1 },
|
||||
[CameraFocusOpcode.TransitionToTargetJoint] = new[] { 1, 2, 2, 2, 1 },
|
||||
[CameraFocusOpcode.UnknownE6] = new[] { 2, 2, 2, 1 },
|
||||
[CameraFocusOpcode.TransitionToAttackerView] = new[] { 1, 2, 2, 2, 1 },
|
||||
[CameraFocusOpcode.UnknownEA] = new[] { 1, 2, 2, 2, 1 },
|
||||
[CameraFocusOpcode.UnknownEC] = new[] { 1, 1, 2, 2, 2, 1 },
|
||||
[CameraFocusOpcode.UnknownF0] = new[] { 1, 1, 2, 2, 2 },
|
||||
[CameraFocusOpcode.SetWait] = new[] { 1 },
|
||||
[CameraFocusOpcode.UnknownF8] = new[] { 1, 2, 2, 2 },
|
||||
[CameraFocusOpcode.UnknownF9] = new[] { 1, 2, 2, 2 },
|
||||
[CameraFocusOpcode.LoadPoint] = new[] { 2, 2, 2 },
|
||||
//ConditionalRestart is special
|
||||
};
|
||||
_conditionalRestartOp = CameraFocusOpcode.ConditionalRestart;
|
||||
}
|
||||
|
||||
public CameraFocusScript(byte[] bytecode) : base(bytecode) {
|
||||
}
|
||||
|
||||
protected override CameraFocusOpcode FromByte(byte b) {
|
||||
return (CameraFocusOpcode)b;
|
||||
}
|
||||
}
|
||||
|
||||
public struct DecodedCameraOp<T> where T : struct {
|
||||
public T Opcode { get; set; }
|
||||
public int[] Operands { get; set; }
|
||||
}
|
||||
|
||||
public enum CameraPositionOpcode {
|
||||
UnknownD5 = 0xD5,
|
||||
UnknownD6 = 0xD6,
|
||||
UnknownD7 = 0xD7,
|
||||
UnknownD8 = 0xD8,
|
||||
UnknownD9 = 0xD9,
|
||||
UnknownDA = 0xDA,
|
||||
UnknownDB = 0xDB,
|
||||
UnknownDC = 0xDC,
|
||||
SetActiveIdleCamera = 0xDD,
|
||||
UnknownDE = 0xDE,
|
||||
UnknownDF = 0xDF,
|
||||
UnknownE0 = 0xE0,
|
||||
LoadIdleCameraPos = 0xE1,
|
||||
UnknownE2 = 0xE2,
|
||||
UnknownE3 = 0xE3,
|
||||
TransitionToAttackerJoint = 0xE4,
|
||||
TransitionToTargetJoint = 0xE5,
|
||||
UnknownE6 = 0xE6,
|
||||
UnknownE7 = 0xE7,
|
||||
UnknownE9 = 0xE9,
|
||||
UnknownEB = 0xEB,
|
||||
UnknownEF = 0xEF,
|
||||
UnknownF0 = 0xF0,
|
||||
UnknownF1 = 0xF1,
|
||||
UnknownF2 = 0xF2,
|
||||
UnknownF3 = 0xF3,
|
||||
Wait = 0xF4,
|
||||
SetWait = 0xF5,
|
||||
UnknownF7 = 0xF7,
|
||||
UnknownF8 = 0xF8,
|
||||
UnknownF9 = 0xF9,
|
||||
ConditionalRestart = 0xFE,
|
||||
ScriptEnd = 0xFF,
|
||||
}
|
||||
|
||||
public enum CameraFocusOpcode {
|
||||
UnknownD8 = 0xD8,
|
||||
UnknownD9 = 0xD9,
|
||||
UnknownDB = 0xDB,
|
||||
UnknownDC = 0xDC,
|
||||
SetActiveIdleCamera = 0xDD,
|
||||
UnknownDE = 0xDE,
|
||||
UnknownDF = 0xDF,
|
||||
UnknownE0 = 0xE0,
|
||||
LoadIdleCameraPos = 0xE1,
|
||||
TransitionToIdle = 0xE2,
|
||||
UnknownE3 = 0xE3,
|
||||
TransitionToAttackerJoint = 0xE4,
|
||||
TransitionToTargetJoint = 0xE5,
|
||||
UnknownE6 = 0xE6,
|
||||
TransitionToAttackerView = 0xE8,
|
||||
UnknownEA = 0xEA,
|
||||
UnknownEC = 0xEC,
|
||||
UnknownF0 = 0xF0,
|
||||
Wait = 0xF4,
|
||||
SetWait = 0xF5,
|
||||
UnknownF8 = 0xF8,
|
||||
UnknownF9 = 0xF9,
|
||||
LoadPoint = 0xFA,
|
||||
ConditionalRestart = 0xFE,
|
||||
ScriptEnd = 0xFF,
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user