From eb758b7f3ae16c834f0cb5026047549a7f834dd9 Mon Sep 17 00:00:00 2001 From: Jeremy Penner Date: Sat, 23 Dec 2023 12:06:52 -0500 Subject: [PATCH] Improve animation decoding --- index.js | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/index.js b/index.js index 0629b26..0bf1c40 100644 --- a/index.js +++ b/index.js @@ -201,14 +201,6 @@ const decodeCel = (data, changesColorRam) => { return cel } -const decodeFrame = (byte, stateCount) => { - const frameIndex = byte & 0x7f - if (frameIndex > stateCount) { - return null - } - return { state: frameIndex, cycle: (byte & 0x80) != 0 } -} - const decodeSide = (byte) => { const side = byte & 0x03 if (side == 0x00) { @@ -242,7 +234,7 @@ const decodeProp = (data) => { colorBitmask: data.getUint8(1), containerXYOff: data.getUint8(3), // TODO: parse this when nonzero walkto: { left: decodeWalkto(data.getUint8(4)), right: decodeWalkto(data.getUint8(5)), yoff: data.getInt8(6) }, - frames: [], + animations: [], celmasks: [], cels: [] } @@ -272,12 +264,16 @@ const decodeProp = (data) => { // the props in the Habitat source tree. // It's possible for there to be no frames, which is represented by an offset of 0 (no_animation) if (graphicStateOff != 0) { - for (let frameOff = graphicStateOff; ; frameOff ++) { - const frame = decodeFrame(data.getUint8(frameOff), stateCount) - if (!frame) { + for (let frameOff = graphicStateOff; ; frameOff += 2) { + // each animation is two bytes: the starting state, and the ending state + // the first byte can have its high bit set to indicate that the animation should cycle + const cycle = (data.getUint8(frameOff) & 0x80) != 0 + const startState = data.getUint8(frameOff) & 0x7f + const endState = data.getUint8(frameOff + 1) + if (startState >= stateCount || endState >= stateCount) { break } - prop.frames.push(frame) + prop.animations.push({ cycle: cycle, startState: startState, endState: endState }) } } for (let celOffsetOff = celOffsetsOff; allCelsMask != 0; celOffsetOff += 2) {