diff --git a/avatars.md b/avatars.md index de8be42..939d244 100644 --- a/avatars.md +++ b/avatars.md @@ -2,7 +2,7 @@ ; 0-1 - offset to choreography index ; 2-3 - offset to choreography tables ; 4-6 - unknown, seems to always be ED 14 00 -; 7-18 - offsets of limbs (two bytes each, 6 limbs) +; 7-18 - array of offsets of limbs (two bytes each, 6 limbs) ; 19-44 - as follows ; (display_avatar in animate.m:30 copies 26 bytes into these tables) @@ -32,11 +32,8 @@ cels_affected_by_height: ; can have many different cels. however, only one cel per limb is ; displayed at any given time. -; avatar_height is defined in orientation - either 0 or 8 depending on the high bit - -; limbs are _embedded_ props?? animate.m get_av_prop_address -(A * 2) + 8 - high byte of offset!! - +; avatar_height is defined in orientation - either 0 or 8 depending on +; the high bit ; limb "prop": ; 0 - count of cel index "frames", minus one @@ -48,13 +45,49 @@ cels_affected_by_height: ; 1-2 - unknown. first byte seems to always be zero. second byte seems ; to be correlated with the number of frames or cels, but isn't a direct ; count of either. -; 3 - list of "frames" (cel indexes), (count + 1) bytes long -; (count + 4) - list of cel offsets (two-byte values) +; 3 - array of "frames" (cel indexes), (count + 1) bytes long +; (count + 4) - array of cel offsets (two-byte values) ; cels are in exactly the same format as in props. ; choreography index: -; TBD +; array of bytes, which are indexes into choreography tables. +; this is indexed by the bottom 7 bits of `requested_chore`. + +Possible choreography values? some special cases are handled in chore.m:212 +which suggests these as valid values. +; define AV_ACT_init = 0x80 + 0 + define AV_ACT_stand = 0x80 + 1 + define AV_ACT_walk = 0x80 + 2 + define AV_ACT_hand_back = 0x80 + 3 + define AV_ACT_sit_floor = 0x80 + 4 + define AV_ACT_sit_chair = 0x80 + 5 + define AV_ACT_bend_over = 0x80 + 6 + define AV_ACT_bend_back = 0x80 + 7 + define AV_ACT_point = 0x80 + 8 + define AV_ACT_throw = 0x80 + 9 + define AV_ACT_get_shot = 0x80 + 10 + define AV_ACT_jump = 0x80 + 11 + define AV_ACT_punch = 0x80 + 12 + define AV_ACT_wave = 0x80 + 13 + define AV_ACT_frown = 0x80 + 14 + define AV_ACT_stand_back = 0x80 + 15 + define AV_ACT_walk_front = 0x80 + 16 + define AV_ACT_walk_back = 0x80 + 17 + define AV_ACT_stand_front = 0x80 + 18 + define AV_ACT_unpocket = 0x80 + 19 + define AV_ACT_gimme = 0x80 + 20 + define AV_ACT_knife = 0x80 + 21 + define AV_ACT_arm_get = 0x80 + 22 + define AV_ACT_hand_out = 0x80 + 23 + define AV_ACT_operate = 0x80 + 24 + define AV_ACT_arm_back = 0x80 + 25 + define AV_ACT_shoot1 = 0x80 + 26 + define AV_ACT_shoot2 = 0x80 + 27 + define AV_ACT_nop = 0x80 + 28 + define AV_ACT_sit_front = 0x80 + 29 ; choreography tables: -; TBD \ No newline at end of file +; an array of arrays of bytes, indicating "states". if the high bit is +; set, this signals the end of the inner array. +; unclear at this time how exactly these values are interpreted. diff --git a/index.js b/index.js index 5001b78..6c88abf 100644 --- a/index.js +++ b/index.js @@ -491,6 +491,13 @@ const decodeLimb = (data, limb) => { limb.cels.push(decodeCel(new DataView(data.buffer, data.byteOffset + celOff))) } } +const choreographyActions = [ + "init", "stand", "walk", "hand_back", "sit_floor", "bend_over", + "bend_back", "point", "throw", "get_shot", "jump", "punch", "wave", + "frown", "stand_back", "walk_front", "walk_back", "stand_front", + "unpocket", "gimme", "knife", "arm_get", "hand_out", "operate", + "arm_back", "shoot1", "shoot2", "nop", "sit_front" +] const decodeBody = (data) => { const body = { @@ -499,7 +506,9 @@ const decodeBody = (data) => { frozenWhenStands: data.getUint8(20), frontFacingLimbOrder: [], backFacingLimbOrder: [], - limbs: [] + limbs: [], + choreography: [], + actions: {} } for (let ilimb = 0; ilimb < 6; ilimb ++) { body.frontFacingLimbOrder.push(data.getUint8(27 + ilimb)) @@ -512,6 +521,27 @@ const decodeBody = (data) => { decodeLimb(new DataView(data.buffer, limbOff), limb) body.limbs.push(limb) } + const choreographyIndexOff = data.getUint16(0, LE) + const choreographyTableOff = data.getUint16(2, LE) + const indexToChoreography = new Map() + for (const [i, action] of choreographyActions.entries()) { + let tableIndex = data.getUint8(choreographyIndexOff + i) + let choreographyIndex = indexToChoreography.get(tableIndex) + if (choreographyIndex == undefined) { + choreographyIndex = body.choreography.length + indexToChoreography.set(tableIndex, choreographyIndex) + const choreography = [] + body.choreography.push(choreography) + for (;; tableIndex ++) { + const state = data.getUint8(choreographyTableOff + tableIndex) + choreography.push(state & 0x7f) + if ((state & 0x80) != 0) { + break + } + } + } + body.actions[action] = choreographyIndex + } return body }