-
-
Save BenjaminUrquhart/9ea8371746ca7f282f819100d68db523 to your computer and use it in GitHub Desktop.
Why
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* |----------------------CHUNK FORMAT----------------------| | |
* | Offset | Size | Type | Description | | |
* |--------------------------------------------------------| | |
* | 0 | 4 | uint32 | Number of entries | | |
* | 4 | 4*N | uint32[N]| Offsets to entries| | |
* |----------------------ENTRY FORMAT----------------------| | |
* | 0 | 4 | uint32 | Name (ptr to STRG)| | |
* | 4 | 4 | uint32 | Flags (See Notes) | | |
* | 8 | 4 | uint32 |FileEx(ptr to STRG)| | |
* | 12 | 4 | uint32 | Path (ptr to STRG)| | |
* | 16 | 4 | uint32 | ??? | | |
* | 20 | 4 | uint32 | Offset to ??? | | |
* | 24 | 4 | uint32 | ??? | | |
* | 28 | 4 | uint32 | ??? | | |
* | 30 | 4 | uint32 | ??? | | |
* | 32 | 4 | uint32 | AUDO index | | |
* |--------------------------------------------------------| | |
* | Notes: This was by FAR the most infuriating chunk to | | |
* | parse. My reference document made no mention of it. | | |
* | | | |
* | I went in with nothing but a hex editor and optimism. | | |
* | | | |
* | I left with crippling depression and an unhealthy | | |
* | desire to assassinate whoever thought THIS was a good | | |
* | way to store audio metadata. Really? You couldn't just,| | |
* | you know, store all of this WITH THE AUDIO??? | | |
* | | | |
* | I did this so you wouldn't have to. It's too late for | | |
* | me, save yourself. | | |
* | | | |
* | FLAGS: | | |
* | 0x01 -> EMBEDDED (contained within the data file) | | |
* | 0x02 -> COMPRESSED (READ: embedded OGG instead of WAV) | | |
* | 0x64 -> REGULAR (all the entries are "regular") | | |
* | | | |
* | Fun fact: any COMPRESSED files will have their FileEx | | |
* | as ".mp3" despite them being OGG Vorbis. Go figure. | | |
* |--------------------------------------------------------| | |
*/ | |
private static void initSoundMetadata() { | |
StringResource name, path; | |
boolean embedded; | |
int num = audioMetaChunk.readInt(0), offset, relativeOffset, index, flags, indexOffset = 0; | |
Set<AudioResource> processed = new HashSet<>(); | |
AudioResource audio; | |
Set<AudioResource.Flag> flagSet; | |
for(int i = 0; i < num; i++) { | |
offset = audioMetaChunk.readInt(4*(i+1)); | |
relativeOffset = (int)(offset-absoluteAudioMetaOffset); | |
name = getStringFromAbsoluteOffset(audioMetaChunk.readInt(relativeOffset)); | |
flags = audioMetaChunk.readInt(relativeOffset+4); | |
flagSet = AudioResource.Flag.parse(flags); | |
embedded = flagSet.contains(AudioResource.Flag.EMBEDDED) || flagSet.contains(AudioResource.Flag.COMPRESSED); | |
path = getStringFromAbsoluteOffset(audioMetaChunk.readInt(relativeOffset+12)); | |
index = audioMetaChunk.readInt(relativeOffset+32); | |
// Look, why even give us information for a track that isn't supposed to exist? | |
if(index < 0) { | |
System.out.printf("Invalid track %s (%s - %s) with index %d\n", name.getString(), path.getString(), flagSet, index); | |
continue; | |
} | |
//System.out.printf("Processing audio track %s (%s) at 0x%08x (Index: %d, Embedded: %s)\n", name.getString(), path.getString(), offset, index, embedded); | |
// The fact that we even NEED an index offset is absurd | |
if(embedded) { | |
audio = ResourceManager.audio.get(index+indexOffset); | |
//System.out.printf("0x%08x -> %s -> %s\n", offset, audio, audio.getSource()); | |
} | |
else { | |
audio = new AudioResource(null, 0, 0); | |
ResourceManager.audio.add(index+indexOffset, audio); | |
//System.out.printf("0x%08x -> <new instance> -> <no chunk>\n", offset); | |
indexOffset++; | |
} | |
/* Yes, this actually happened. This is why the stupid index offset is necessary. | |
* It turns out if an external audio resource is referenced, the index isn't | |
* updated until the next embedded resource. | |
* | |
* The result: we might accidentally set the metadata of an audio resource twice, making | |
* it inaccurate. | |
* | |
* Brilliant design, I applaud whoever made this. | |
* | |
* End me. | |
*/ | |
if(!processed.add(audio)) { | |
throw new IllegalStateException(String.format("encountered the same audio resource twice??? (Index: %d, Resource: %s)", index, audio)); | |
} | |
audio.setFilename(path.getString()); | |
audio.setName(name.getString()); | |
audio.setFlags(flagSet); | |
// AAAAAAAAAAAAAAAAAAAAAAAAAAAAA more sanity checks | |
audio.verify(); | |
audioTable.put(path.getString(), audio); | |
audioTable.put(name.getString(), audio); | |
} | |
} | |
/* |----------------------CHUNK FORMAT----------------------| | |
* | Offset | Size | Type | Description | | |
* |--------------------------------------------------------| | |
* | 0 | 4 | uint32 | Number of entries | | |
* | 4 | 4*N | uint32[N]| Offsets to entries| | |
* | 8 | ? | File[N] | Audio Files | | |
* |----------------------ENTRY FORMAT----------------------| | |
* | 0 | 4 | uint32 | File size | | |
* | 4 | N | uint8[N] | File data | | |
* |--------------------------------------------------------| | |
* | Notes: Why even HAVE the SOND chunk when you can just | | |
* | put the metadata here??? Just WHY??? | | |
* |--------------------------------------------------------| | |
*/ | |
private static void initAudio() { | |
audioTable = new HashMap<>(); | |
audio = new ArrayList<>(); | |
int num = audioChunk.readInt(0), offset, relativeOffset, length; | |
AudioResource resource; | |
for(int i = 0; i < num; i++) { | |
offset = audioChunk.readInt(4*(i+1)); | |
relativeOffset = (int)(offset-absoluteAudioOffset); | |
length = audioChunk.readInt(relativeOffset); | |
resource = new AudioResource(audioChunk, relativeOffset+4, length); | |
audio.add(resource); | |
if(resource.getSource() == null) { | |
throw new IllegalStateException("null source for newly-created audio object (" + resource + ")"); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment