Skip to content

Commit

Permalink
Add a way to preview files in-game, WIP!
Browse files Browse the repository at this point in the history
  • Loading branch information
TopazTK committed Sep 11, 2023
1 parent 04932ab commit ca10e0b
Show file tree
Hide file tree
Showing 5 changed files with 899 additions and 9 deletions.
81 changes: 74 additions & 7 deletions OpenKh.Tools.LayoutEditor/App.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Eventing.Reader;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Windows;
using Xe.Tools.Wpf.Dialogs;

using static OpenKh.Tools.Common.CustomImGui.ImGuiEx;

namespace OpenKh.Tools.LayoutEditor
Expand Down Expand Up @@ -56,9 +58,20 @@ public class App : IEditorSettings, IDisposable

private const string LinkToPcsx2ActionName = "Open file and link it to PCSX2";
private const string ResourceSelectionDialogTitle = "Resource selection";
private const string PreviewTitle = "In-Game Preview Target";
private const string TargetSelectTitle = "In-Game Target Selection";

private bool _isResourceSelectionDialogOpening;
private bool _isResourceSelectingLayout;

private bool _isPrevDialogOpening;
private bool _isTargetDialogOpening;

private PreviewTargetDialog _prevDialog;
private TargetSelectionDialog _targetDialog;
private ResourceSelectionDialog _resourceSelectionDialog;


private Dictionary<Keys, Action> _keyMapping = new Dictionary<Keys, Action>();

public event IEditorSettings.ChangeBackground OnChangeBackground;
Expand Down Expand Up @@ -178,6 +191,36 @@ public bool MainLoop()
}
}

if (ImGui.BeginPopupModal(PreviewTitle, ref dummy,
ImGuiWindowFlags.Popup | ImGuiWindowFlags.Modal | ImGuiWindowFlags.AlwaysAutoResize))
{
_prevDialog.Run();
ImGui.EndPopup();
}

if (ImGui.BeginPopupModal(TargetSelectTitle, ref dummy,
ImGuiWindowFlags.Popup | ImGuiWindowFlags.Modal | ImGuiWindowFlags.AlwaysAutoResize))
{
_targetDialog.Run();
ImGui.EndPopup();

if (_targetDialog.HasTargetBeenSelected)
{
var _fetchFile = CurrentEditor.SaveAnimation("comw");
var _memStream = new MemoryStream((int)_fetchFile.Stream.Length);

ulong _offset = _fetchFile.Type == Bar.EntryType.Seqd ? (ulong)0x00 : (ulong)0x20;

_fetchFile.Stream.Position = 0;
_fetchFile.Stream.CopyTo(_memStream);

Hypervisor.WriteArray(_prevDialog.FetchedPointer + (ulong)_targetDialog.SelectedAnimation.Offset + _offset, _memStream.ToArray(), true);

_prevDialog = null;
_targetDialog = null;
}
}

ImGuiEx.MainWindow(() =>
{
MainMenu();
Expand All @@ -190,6 +233,25 @@ public bool MainLoop()
_isResourceSelectionDialogOpening = false;
}

if (_isPrevDialogOpening)
{
ImGui.OpenPopup(PreviewTitle);
_isPrevDialogOpening = false;
}

if (_prevDialog != null && _prevDialog.FetchedFile != null && _targetDialog == null)
{
var _barFile = _prevDialog.FetchedFile;

var sequenceEntry = _barFile.FirstOrDefault(x => x.Type == Bar.EntryType.Seqd);
var layoutEntry = _barFile.FirstOrDefault(x => x.Type == Bar.EntryType.Layout);

_targetDialog = new TargetSelectionDialog(_barFile, sequenceEntry == null ? Bar.EntryType.Layout : Bar.EntryType.Seqd);

ImGui.OpenPopup(TargetSelectTitle);
_isTargetDialogOpening = true;
}

return _exitFlag;
}

Expand Down Expand Up @@ -220,16 +282,10 @@ void MainMenu()
ForMenuItem($"{LinkToPcsx2ActionName}...", "CTRL+L", MenuFileOpenPcsx2);
ForMenuItem("Save", "CTRL+S", MenuFileSave, CurrentEditor != null);
ForMenuItem("Save as...", MenuFileSaveAs, CurrentEditor != null);
ForMenuItem("Preview In-Game...", MenuFilePreview, CurrentEditor != null);
ImGui.Separator();
ForMenu("Preferences", () =>
{
//var checkerboardBackground = CheckerboardBackground;
//if (ImGui.Checkbox("Checkerboard background", ref checkerboardBackground))
//{
// CheckerboardBackground = false;
// OnChangeBackground?.Invoke(this, this);
//}
var editorBackground = new Vector3(EditorBackground.R,
EditorBackground.G, EditorBackground.B);
if (ImGui.ColorEdit3("Background color", ref editorBackground))
Expand Down Expand Up @@ -262,6 +318,11 @@ private void MenuFileOpen()
}, Filters);
}

private void MenuFilePreview()
{
OpenPreviewDialog();
}

private void MenuFileOpenWithoutPcsx2()
{
_linkToPcsx2 = false;
Expand Down Expand Up @@ -467,6 +528,12 @@ private void OpenResourceSelectionDialog(IEnumerable<Bar.Entry> entries,
_isResourceSelectingLayout = animationType == Bar.EntryType.Layout;
}

public void OpenPreviewDialog()
{
_prevDialog = new PreviewTargetDialog();
_isPrevDialogOpening = true;
}

private void OpenSequenceEditor(Bar.Entry sequenceEntry, Bar.Entry textureEntry)
{
AnimationName = sequenceEntry.Name;
Expand Down
99 changes: 99 additions & 0 deletions OpenKh.Tools.LayoutEditor/Dialogs/PreviewTargetDialog.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
using Binarysharp.MSharp;
using Binarysharp.MSharp.Native;
using ImGuiNET;
using OpenKh.Kh2;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Windows;
using OpenKh.Common;
using System.IO;

using OpenKh.Tools.LayoutEditor;

namespace OpenKh.Tools.LayoutEditor.Dialogs
{
public class PreviewTargetDialog : IDisposable
{
private byte[] _nameBuff;

public ulong FetchedPointer;
public Bar FetchedFile;

private Dictionary<string, ulong> _pointMap = new Dictionary<string, ulong>()
{
{ "field2d/us/zz0command.2dd", 0x9B8348 }
};

public PreviewTargetDialog()
{
FetchedFile = null;
_nameBuff = new byte[32];
}

public void Run()
{
ImGui.Text("Please enter the name of the file you want to target for preview.");
ImGui.InputText("", _nameBuff, 32);

if (ImGui.Button("Open"))
{
var _findProcess = Process.GetProcessesByName("KINGDOM HEARTS II FINAL MIX");

if (_findProcess == null || _findProcess.Length == 0x00)
MessageBox.Show("Kingdom Hearts II was not detected\nPlease ensure that it is running!", "Error 405: Process not found!", MessageBoxButton.OK, MessageBoxImage.Warning);

else
{
Hypervisor.AttachProcess(_findProcess[0], 0x0000000);
var _sharpHook = new MemorySharp(_findProcess[0]);

var _fileName = Encoding.ASCII.GetString(_nameBuff).Replace("\0", "");

var _findPoint = _pointMap.FirstOrDefault(x => x.Key == _fileName);
var _fileFind = _sharpHook[(IntPtr)0x39A820].Execute<int>(Binarysharp.MSharp.Assembly.CallingConvention.CallingConventions.MicrosoftX64, _fileName, -1);

if (_fileFind != 0x00 || _findPoint.Key != null)
{
FetchedPointer = _findPoint.Key == null ? Hypervisor.Read<ulong>(Hypervisor.MemoryOffset + (ulong)(_fileFind + 0x58), true) : Hypervisor.Read<ulong>(_findPoint.Value);
var _fileSize = _sharpHook[(IntPtr)0x39E2F0].Execute<int>(_fileName);

var _barRead = Hypervisor.ReadArray(FetchedPointer, _fileSize, true);

var _barCount = BitConverter.ToInt32(_barRead, 0x04);
var _barOffset = BitConverter.ToInt32(_barRead, 0x08);

using (var _stream = new MemoryStream(_barRead, true))
{
_stream.Position = 0x10;

for (int i = 0; i < _barCount; i++)
{
var _streamRead = BitConverter.ToUInt32(_barRead, 0x10 + (0x10 * i) + 0x08);
var _newValue = _streamRead - _barOffset;

_stream.Position = 0x10 + (0x10 * i) + 0x08;
_stream.Write(_newValue);
}

_stream.Position = 0x00;
FetchedFile = Bar.Read(_stream);
}

ImGui.CloseCurrentPopup();
}

else
MessageBox.Show("File is not present in the game cache!\nPlease enter the correct name!", "Error 404: File not found!", MessageBoxButton.OK, MessageBoxImage.Warning);
}
}
}

public void Dispose()
{

}
}
}
64 changes: 64 additions & 0 deletions OpenKh.Tools.LayoutEditor/Dialogs/TargetSelectionDialog.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using ImGuiNET;
using OpenKh.Kh2;
using System;
using System.Collections.Generic;
using System.Linq;

namespace OpenKh.Tools.LayoutEditor.Dialogs
{
public class TargetSelectionDialog : IDisposable
{
private readonly Bar.Entry[] _animations;
private int _selectedAnimIndex;

public bool HasTargetBeenSelected { get; private set; }
public Bar.Entry SelectedAnimation { get; private set; }

public TargetSelectionDialog(
IEnumerable<Bar.Entry> entries,
Bar.EntryType animationType)
{
_animations = entries
.Where(x => x.Type == animationType && x.Index == 0)
.ToArray();
}

public void Run()
{
if (_animations.Length == 1)
{
HasTargetBeenSelected = true;
SelectedAnimation = _animations[0];
ImGui.CloseCurrentPopup();
}

ImGui.Text("The selected file contains multiple elements.");
ImGui.Text("Please choose the appropiate sub-file you want to target.");

ImGui.Columns(1, "Select Sub-File:", true);
ImGui.Text("Animation");
for (var i = 0; i < _animations.Length; i++)
{
if (ImGui.Selectable($"{_animations[i].Name}##anm",
_selectedAnimIndex == i,
ImGuiSelectableFlags.DontClosePopups))
_selectedAnimIndex = i;
}

ImGui.Columns(1);
ImGui.Separator();

if (ImGui.Button("Open"))
{
HasTargetBeenSelected = true;
SelectedAnimation = _animations[_selectedAnimIndex];
ImGui.CloseCurrentPopup();
}
}

public void Dispose()
{

}
}
}
1 change: 1 addition & 0 deletions OpenKh.Tools.LayoutEditor/OpenKh.Tools.LayoutEditor.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Binarysharp.MSharp\Binarysharp.MSharp.csproj" />
<ProjectReference Include="..\OpenKh.Engine.MonoGame\OpenKh.Engine.MonoGame.csproj" />
<ProjectReference Include="..\OpenKh.Engine\OpenKh.Engine.csproj" />
<ProjectReference Include="..\OpenKh.Kh2\OpenKh.Kh2.csproj" />
Expand Down
Loading

0 comments on commit ca10e0b

Please sign in to comment.