Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1.0.7 #5

Merged
merged 17 commits into from
Feb 18, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
0d958de
[Core] Add support for writing RIFF EBX assets (#199)
Brawltendo Dec 15, 2022
faf806c
Checks if property object is null before creating a property grid ite…
natv1337 Dec 15, 2022
d59c78c
[MeshSetPlugin] Fixes issue with importing over rigid meshes (#206)
wannkunstbeikor Dec 22, 2022
cc1b506
[Core] Fixes some small issues (1.0.7) (#204)
wannkunstbeikor Dec 22, 2022
baebd3a
[Core] Adds delegates to the sdk (#207)
wannkunstbeikor Dec 27, 2022
68d95eb
[Sdk] Improve RIFF EBX writer (#202)
Brawltendo Dec 29, 2022
4ea8ab2
Bw localization plugin v6 on frosty1.7 (#208)
KrrKsThunder Jan 2, 2023
3270509
changed ToLower to ToLowerInvariant (#209)
mlg556 Jan 6, 2023
4f51bed
Add limited support for Bioware Games to ExportStringUsage function (…
KrrKsThunder Jan 6, 2023
9738686
Add BC4_UNORM extended header (#213)
CosmicDreamsOfCode Jan 11, 2023
493add2
[Core] Makes multiple new games into full profiles (#215)
wannkunstbeikor Jan 12, 2023
cbc2525
[Core] Fixes issues with added chunks and meshset (#216)
wannkunstbeikor Jan 14, 2023
876737f
[Core] Fixes issue with legacy files not getting written correctly to…
wannkunstbeikor Jan 14, 2023
1f61aa5
Added quotations to xcopy command in plugins to support spaces in dir…
DAPOTTIS Feb 2, 2023
c0cdb39
WIP Dead Space Profile (#221)
CosmicDreamsOfCode Feb 3, 2023
e212946
Chunk and resource bundle display(1.0.7) and port of project load err…
CosmicDreamsOfCode Feb 9, 2023
92d8a3e
Fix for finding TypeRef types (#228)
Brawltendo Feb 10, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Bw localization plugin v6 on frosty1.7 (CadeEvs#208)
* Commit full version 1.1.0.5 of the BW Localization Plugin

* Add option to search with decimal text ids

* Prepare data structure for editing declinated adjectives

* Implement DragonAgeDeclinatedAdjectiveTuples- functions missing from last commit

* Prepare writing capability for DA:I declinated crafting name adjectives, bump plugin version to reflect major change in produced mod file

* Add setter and remove methods in resource, fix test method

* Fix incorrectly stated number of declinations

* Add adjective getters to text resources

* Refactor xml export, write declinated adjectives.

* Allow Importing of declinated adjectives from xml file

* Add Toggle and (currently non functional) resource selector in ui

* Fix switching to adjectives

* Enable display of declinated adjectives

* Add first sign of adjective edit window

* Working Edit dialog for adjectives

* Try formatting code in accordance with frosty codingstandards

* Small fixes to the adjective edit window

* Add ReplaceWindow

* Fix higlighting and display issues

* Make replacement window available form generic string editor

* Add settings for xml export

* Adapt to changed paths in Frosty 1.7
  • Loading branch information
KrrKsThunder authored Jan 2, 2023
commit 4ea8ab2a7d6bef9f9e97b59c43229f7a80da0f37
68 changes: 68 additions & 0 deletions Plugins/BiowareLocalizationPlugin/BW LocaliziationResourceBits.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
Part: Type and what Byte position after this

MetaData (16 bytes, located in Frosty at Resource.resMeta, not part of the byte count )
{
uint dataOffset
3x byte value 0x0
}
Header
{
uint magic = 0xd78b40eb (pos 4)
uint ??? (pos 8) // doesn't seem to affect anything
uint dataOffset (pos 12) // not actually used, instead the one from the metadata is the base for the game
3x uint ??? (pos 24) // doens't seem to affect anything

uint nodeCount (pos 28)
// nodeCount is an even integer! The rootNode as would-be last node in the node list is *not* actually part of the list!

uint nodeOffset (pos 32)

uint stringsCount (pos 36)
uint stringsOffset (pos 40)

// Until the nodeOffset is reached
// If there are three or more entries in here,
// then the corresponding 8ByteBlockData after the second one contain ids and bit offsets for the declinated adjectives for text parts used for crafted items in DA:I (Note that these ids are not the same accross languages!)
N times Unknown8ByteBlockCountAndOffset
{
uint unknownCounts
uint unknownOffset
}
}

// Position = nodeOffset -> pos most likely either 56 or 64
HuffmanCoding
{
nodeCount x uint value == bitFlip char
}
(size = 4 per node)

// Position = stringsOffset
StringData
{
stringsCount x
{
uint stringId
int stringIndex / positionOffset
}
(size = 8 per string)
}

// Position = Unknown8ByteBlockCountAndOffset[0].unknownOffset
// The next data blocks appears the same N times as their Unknown8ByteBlockCountAndOffset counterpart in the header
// Everything past the second of these blocks contains the bit offsets of the text pieces used for crafted item names in DA:I
N times 8ByteBlockData
{
// Position = Unknown8ByteBlockCountAndOffset[index].unknownOffset
byte[].Length = Unknown8ByteBlockCountAndOffset[index].unknownCounts * 8
}

// Position = dataOffset
Strings
{
stringsCount * HuffmanEncodedChars
}
// stringIndex / positionOffset = bit offset from dataOffset == textBefore bitOffset + textBefore bitlentgh
// last symbol (only symbol of empty string) is huffman node with letter 0x00! I.e., _value_ = 0xFF

Remaining positions to full byte filled with 0s
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using BiowareLocalizationPlugin.Controls;
using Frosty.Core;
using FrostySdk;

namespace BiowareLocalizationPlugin
{
public class BioWareLocalizedStringEditorMenuExtension : MenuExtension
{

private const string ITEM_NAME = "Bioware Localized String Editor";

public override string TopLevelMenuName => "View";

public override string SubLevelMenuName => null;
public override string MenuItemName => ITEM_NAME;

public override RelayCommand MenuItemClicked => new RelayCommand((o) =>
{
if (ProfilesLibrary.DataVersion == (int)ProfileVersion.Anthem)
{
App.Logger.Log("Not applicable for Anthem, sorry for the inconvenience!");
return;
}
var textDb = (BiowareLocalizedStringDatabase) LocalizedStringDatabase.Current;
App.EditorWindow.OpenEditor(ITEM_NAME, new BiowareLocalizedStringEditor(textDb));
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
using BiowareLocalizationPlugin.LocalizedResources;
using Frosty.Core;
using Frosty.Core.IO;
using Frosty.Core.Mod;
using Frosty.Hash;
using FrostySdk;
using FrostySdk.IO;
using FrostySdk.Managers;
using FrostySdk.Managers.Entries;
using FrostySdk.Resources;
using System;
using System.Collections.Generic;
using System.Text;

namespace BiowareLocalizationPlugin
{
public class BiowareLocalizationCustomActionHandler : ICustomActionHandler
{

public HandlerUsage Usage => HandlerUsage.Merge;

// A mod is comprised of a series of base resources, embedded, ebx, res, and chunks. Embedded are used internally
// for the icon and images of a mod. Ebx/Res/Chunks are the core resources used for applying data to the game.
// When you create a custom handler, you need to provide your own resources for your custom handled data. This
// resource is unique however it is based on one of the three core types.
private class BiowareLocalizationModResource : EditorModResource
{

// Defines which type of resource this resource is.
public override ModResourceType Type => ModResourceType.Res;


// The resType is vital to be kept (its always LocalizedStringResource, but whatever)
private readonly uint m_resType;

// these other two fields may have to be written to the mod as well
private readonly ulong m_resRid;
private readonly byte[] m_resMeta;


public BiowareLocalizationModResource(ResAssetEntry inEntry, FrostyModWriter.Manifest inManifest) : base(inEntry)
{

// This constructor does the exact same thing as the ones in the TestPlugin

// obtain the modified data
ModifiedLocalizationResource md = inEntry.ModifiedEntry.DataObject as ModifiedLocalizationResource;
byte[] data = md.Save();

// store data and details about resource
name = inEntry.Name.ToLower();
sha1 = Utils.GenerateSha1(data);
resourceIndex = inManifest.Add(sha1, data);
size = data.Length;

// set the handler hash to the hash of the res type name
handlerHash = Fnv1.HashString(inEntry.Type.ToLower());

m_resType = inEntry.ResType;
m_resRid = inEntry.ResRid;
m_resMeta = inEntry.ResMeta;
}

/// <summary>
/// This method is calles when writing the mod. For Res Types it is vital that some additional information is persisted that is not written by the base method.
/// Mainly that is the ResourceType as uint
/// Additional data that is read, but I'm not sure whether it is actually necessary:
/// <ul>
/// <li>ResRid as ulong (not sure if this is really necessary, i.e., actually read)
/// <li>resMeta length
/// <li>resMeta as byte array
/// </ul>
/// </summary>
/// <param name="writer"></param>
public override void Write(NativeWriter writer)
{
base.Write(writer);

// write the required res type:
writer.Write(m_resType);

writer.Write(m_resRid);
writer.Write((m_resMeta != null) ? m_resMeta.Length : 0);
if (m_resMeta != null)
{
writer.Write(m_resMeta);
}
}
}

#region -- Editor Specific --

// This function is for writing resources to the mod file, this is where you would add your custom
// resources to be written.
public void SaveToMod(FrostyModWriter writer, AssetEntry entry)
{
writer.AddResource(new BiowareLocalizationModResource(entry as ResAssetEntry, writer.ResourceManifest));
}
#endregion

#region -- Mod Specific --

// This function is for the mod managers action view, to allow a handler to describe detailed actions performed
// format of the action string is <ResourceName>;<ResourceType>;<Action> where action can be Modify or Merge (or Add!)
// and ResourceType can be Ebx,Res,Chunk
public IEnumerable<string> GetResourceActions(string name, byte[] data)
{

if( !Config.Get(BiowareLocalizationPluginOptions.SHOW_INDIVIDUAL_TEXTIDS_OPTION_NAME, false, ConfigScope.Global))
{
return new List<string>();
}

ModifiedLocalizationResource modified = ModifiedResource.Read(data) as ModifiedLocalizationResource;

List<uint> textIds = new List<uint>(modified.AlteredTexts.Keys);
textIds.Sort();

List<string> resourceActions = new List<string>(textIds.Count);
foreach (uint textId in textIds)
{
string resourceName = new StringBuilder(name).Append(" (0x").Append(textId.ToString("X8")).Append(')').ToString();
string resourceType = "res";
string action = "Modify";

resourceActions.Add(resourceName + ";" + resourceType + ";" + action);
}

return resourceActions;
}

// This function is invoked when a mod with such a handler is loaded, if a previous mod with a handler for this
// particular asset was loaded previously, then existing will be populated with that data, allowing this function
// the chance to merge the two datasets together
public object Load(object existing, byte[] newData)
{

ModifiedLocalizationResource edited = (ModifiedLocalizationResource)existing;
ModifiedLocalizationResource newTexts = (ModifiedLocalizationResource) ModifiedResource.Read(newData);

if(edited == null)
{
return newTexts;
}

edited.Merge(newTexts);

return edited;
}

// This function is invoked at the end of the mod loading, to actually modify the existing game data with the end
// result of the mod loaded data, it also allows for a handler to add new Resources to be replaced.
// ie. an Ebx handler might want to add a new Chunk resource that it is dependent on.
public void Modify(AssetEntry origEntry, AssetManager am, RuntimeResources runtimeResources, object data, out byte[] outData)
{

// no idea what frosty does if the resource does not exist in the local game, so first check for null:
if(origEntry == null)
{
outData = System.Array.Empty<byte>();
return;
}

// load the original resource
ResAssetEntry originalResAsset = am.GetResEntry(origEntry.Name);
ModifiedLocalizationResource modified = data as ModifiedLocalizationResource;
LocalizedStringResource resource = am.GetResAs<LocalizedStringResource>(originalResAsset, modified);

// read about some weird null reference exception in here, so _maybe_ it was the resource?
if(resource == null)
{
throw new ArgumentNullException("resource", string.Format("Resource in BwLocalizationHandler Modify(...) is null after GetResAs call for <{0}>!", origEntry.Name));
}

byte[] uncompressedData = resource.SaveBytes();
outData = Utils.CompressFile(uncompressedData);

// update the metadata
byte[] alteredMetaData = resource.ResourceMeta;
((ResAssetEntry)origEntry).ResMeta = alteredMetaData;

// update relevant asset entry values
origEntry.OriginalSize = uncompressedData.Length;
origEntry.Size = outData.Length;
origEntry.Sha1 = Utils.GenerateSha1(outData);
}
#endregion
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,9 @@
<ProjectReference Include="..\..\FrostySdk\FrostySdk.csproj">
<Private>false</Private>
</ProjectReference>
<ProjectReference Include="..\..\FrostyModSupport\FrostyModSupport.csproj">
<Private>false</Private>
</ProjectReference>
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@

using Frosty.Core;
using FrostySdk.Attributes;

namespace BiowareLocalizationPlugin
{
[DisplayName("Bioware Localization Options")]
public class BiowareLocalizationPluginOptions : OptionsExtension
{

// The name for the global mod manager variable.
public static readonly string SHOW_INDIVIDUAL_TEXTIDS_OPTION_NAME = "BwLoMoShowIndividualTextIds";

public static readonly string ASK_XML_EXPORT_OPTIONS = "BwLoEoAskXmlExportOptions";

[Category("Mod Manager Options")]
[Description("If enabled, all individual text ids in each resource (res) are shown in the mod manager's Actions tab. Otherwise only the resource iteself is shown as merged. This setting is only for the mod manager and has no effect in the editor.")]
[DisplayName("Show Individual Text Ids")]
[EbxFieldMeta(FrostySdk.IO.EbxFieldType.Boolean)]
public bool ShowIndividualTextIds { get; set; } = false;

[Category("Editor Options")]
[DisplayName("Ask for Xml Export Options")]
[Description("If enabled, a popup prompt allows selecting whether to export all texts or only modified ones. If this value is false, then the default from below is used. This setting is only for the editor and has no effect in the mod manager.")]
[EbxFieldMeta(FrostySdk.IO.EbxFieldType.Boolean)]
public bool AskForXmlExportOptions { get; set; } = false;

public override void Load()
{
// mod manager
ShowIndividualTextIds = Config.Get(SHOW_INDIVIDUAL_TEXTIDS_OPTION_NAME, false, ConfigScope.Global);

// editor
AskForXmlExportOptions = Config.Get(ASK_XML_EXPORT_OPTIONS, false, ConfigScope.Global);
}

public override void Save()
{
// mod manager
Config.Add(SHOW_INDIVIDUAL_TEXTIDS_OPTION_NAME, ShowIndividualTextIds, ConfigScope.Global);

// editor
Config.Add(ASK_XML_EXPORT_OPTIONS, AskForXmlExportOptions, ConfigScope.Global);
}
}
}
Loading