NearInfinityBrowser / NearInfinity

An Infinity Engine Browser and Editor
GNU Lesser General Public License v2.1
85 stars 37 forks source link

ARE uneditable after adding a song header (via DLTCEP) #136

Closed lynxlynxlynx closed 1 year ago

lynxlynxlynx commented 3 years ago

I didn't find a way to do it in NI, so I used DLTCEP to add the header and set the day and night song entries. The rest of it is unset. At the same time I added songlist.2da and the matching playlist, so I don't quite get why NI complains.

Afterwards NI can't read it any more, hitting this exception:

Error reading ar0100.ARE
java.lang.reflect.InvocationTargetException
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
        at org.infinity.resource.ResourceFactory.getResource(Unknown Source)
        at org.infinity.resource.ResourceFactory.getResource(Unknown Source)
        at org.infinity.gui.ResourceTree.valueChanged(Unknown Source)
        at java.desktop/javax.swing.JTree.fireValueChanged(JTree.java:2967)
        at java.desktop/javax.swing.JTree$TreeSelectionRedirector.valueChanged(JTree.java:3456)
        at java.desktop/javax.swing.tree.DefaultTreeSelectionModel.fireValueChanged(DefaultTreeSelectionModel.java:641)
        at java.desktop/javax.swing.tree.DefaultTreeSelectionModel.notifyPathChange(DefaultTreeSelectionModel.java:1111)
        at java.desktop/javax.swing.tree.DefaultTreeSelectionModel.setSelectionPaths(DefaultTreeSelectionModel.java:297)
        at java.desktop/javax.swing.tree.DefaultTreeSelectionModel.setSelectionPath(DefaultTreeSelectionModel.java:191)
        at java.desktop/javax.swing.JTree.setSelectionPath(JTree.java:1656)
        at java.desktop/javax.swing.plaf.basic.BasicTreeUI.selectPathForEvent(BasicTreeUI.java:2736)
        at java.desktop/javax.swing.plaf.basic.BasicTreeUI$Handler.handleSelection(BasicTreeUI.java:4016)
        at java.desktop/javax.swing.plaf.basic.BasicTreeUI$Handler.mousePressed(BasicTreeUI.java:3955)
        at java.desktop/java.awt.AWTEventMulticaster.mousePressed(AWTEventMulticaster.java:287)
        at java.desktop/java.awt.Component.processMouseEvent(Component.java:6632)
        at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3342)
        at java.desktop/java.awt.Component.processEvent(Component.java:6400)
        at java.desktop/java.awt.Container.processEvent(Container.java:2263)
        at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:5011)
        at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2321)
        at java.desktop/java.awt.Component.dispatchEvent(Component.java:4843)
        at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4918)
        at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4544)
        at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4488)
        at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2307)
        at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2772)
        at java.desktop/java.awt.Component.dispatchEvent(Component.java:4843)
        at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:772)
        at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
        at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
        at java.base/java.security.AccessController.doPrivileged(Native Method)
        at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
        at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:95)
        at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:745)
        at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:743)
        at java.base/java.security.AccessController.doPrivileged(Native Method)
        at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
        at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:742)
        at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
        at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
        at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
        at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
        at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
        at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

Caused by: java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0
        at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
        at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
        at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
        at java.base/java.util.Objects.checkIndex(Objects.java:372)
        at java.base/java.util.ArrayList.get(ArrayList.java:459)
        at org.infinity.resource.key.Keyfile.getBIFFEntry(Unknown Source)
        at org.infinity.resource.key.BIFFResourceEntry.getBIFFEntry(Unknown Source)
        at org.infinity.datatype.AreResourceRef.<init>(Unknown Source)
        at org.infinity.resource.are.Song.read(Unknown Source)
        at org.infinity.resource.AbstractStruct.<init>(Unknown Source)
        at org.infinity.resource.AbstractStruct.<init>(Unknown Source)
        at org.infinity.resource.are.Song.<init>(Unknown Source)
        at org.infinity.resource.are.AreResource.read(Unknown Source)
        at org.infinity.resource.AbstractStruct.<init>(Unknown Source)
        at org.infinity.resource.are.AreResource.<init>(Unknown Source)
        ... 48 more

Checking the code, I thought perhaps it's a problem that they're OGGs or that there are no BIFFs, but the trace is hard to follow, since it doesn't have line number info.

Any pointers would be helpful, but you can also consider this a wishlist item: being able to add a song header to an area that doesn't have one (like with everything else in the Add menu).

Argent77 commented 3 years ago

From what I can reconstruct from the stack trace it looks like NI attempts to determine the BIFF file containing the WED resource associated with the ARE resource. (This is done when creating ambient sound entries in non-EE games.)

But then the IndexOutOfBoundsException is triggered when NI attempts to access the list of biff entries with the calculated source index portion from the resource locator in the chitin.key. I haven't touched the whole key/biff file relationship for quite some time, so I can't really say what could be the exact source of the problem.

lynxlynxlynx commented 3 years ago

Hmm, we do have a mostly empty chitin.key, since it's been optional so far (and a pain to append to). But the exception are the area WED, ARE and TIS files, since I think NI didn't want to display the graphic/tileset subwindow otherwise.

I tried chucking everything into a bif and that made it work. It was data.bif, so the list in AreResourceRef doesn't matter. I also tried nulling the resource locator field (had only the lowest bit set), but it didn't change anything.