From b4bb07ecc462ecc1b85d45e1a2dccae3301b7d29 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Fri, 17 Oct 2025 08:46:53 +0200 Subject: [PATCH] refactor(common): consolidate header struct to kmx-plus-file.ts Consolidate the header structure in KMX+ to make it easier to add a version value to the header for v19+ KMX+ files; also DRYs out the header definitions a little. --- .../types/src/kmx/kmx-plus/kmx-plus-file.ts | 46 +++++++++---------- .../types/kmx/kmx-plus-builder/build-disp.ts | 6 ++- .../types/kmx/kmx-plus-builder/build-elem.ts | 8 ++-- .../types/kmx/kmx-plus-builder/build-keys.ts | 8 ++-- .../types/kmx/kmx-plus-builder/build-layr.ts | 8 ++-- .../types/kmx/kmx-plus-builder/build-list.ts | 8 ++-- .../types/kmx/kmx-plus-builder/build-loca.ts | 6 ++- .../types/kmx/kmx-plus-builder/build-meta.ts | 6 ++- .../types/kmx/kmx-plus-builder/build-sect.ts | 6 ++- .../types/kmx/kmx-plus-builder/build-strs.ts | 8 ++-- .../types/kmx/kmx-plus-builder/build-tran.ts | 8 ++-- .../types/kmx/kmx-plus-builder/build-uset.ts | 10 ++-- .../types/kmx/kmx-plus-builder/build-vars.ts | 8 ++-- .../kmx/kmx-plus-builder/builder-section.ts | 6 ++- .../kmx/kmx-plus-builder/kmx-plus-builder.ts | 12 ++--- 15 files changed, 89 insertions(+), 65 deletions(-) diff --git a/common/web/types/src/kmx/kmx-plus/kmx-plus-file.ts b/common/web/types/src/kmx/kmx-plus/kmx-plus-file.ts index 2644247323..97e764f755 100644 --- a/common/web/types/src/kmx/kmx-plus/kmx-plus-file.ts +++ b/common/web/types/src/kmx/kmx-plus/kmx-plus-file.ts @@ -61,6 +61,8 @@ export class KMXPlusFileFormat extends KMXFile { public readonly COMP_PLUS_VARS: any; public readonly COMP_PLUS_VARS_ITEM: any; + private readonly COMP_PLUS_SectionHeader: any; + constructor() { super(); // Binary-correct structures matching kmx_plus.h @@ -73,6 +75,14 @@ export class KMXPlusFileFormat extends KMXFile { const CHAR32 = r.uint32le; const STR_OR_CHAR32_OR_USET = r.uint32le; const IDENT = r.uint32le; + + // Section header - version dependent + + this.COMP_PLUS_SectionHeader = new r.Struct({ + ident: IDENT, + size: r.uint32le, + }); + // 'sect' this.COMP_PLUS_SECT_ITEM = new r.Struct({ @@ -81,8 +91,7 @@ export class KMXPlusFileFormat extends KMXFile { }); this.COMP_PLUS_SECT = new r.Struct({ - ident: IDENT, - size: r.uint32le, + header: this.COMP_PLUS_SectionHeader, total: r.uint32le, count: r.uint32le, items: new r.Array(this.COMP_PLUS_SECT_ITEM, 'count') @@ -98,8 +107,7 @@ export class KMXPlusFileFormat extends KMXFile { }); this.COMP_PLUS_DISP = new r.Struct({ - ident: IDENT, - size: r.uint32le, + header: this.COMP_PLUS_SectionHeader, count: r.uint32le, baseCharacter: CHAR32, items: new r.Array(this.COMP_PLUS_DISP_ITEM, 'count'), @@ -118,8 +126,7 @@ export class KMXPlusFileFormat extends KMXFile { }); this.COMP_PLUS_ELEM = new r.Struct({ - ident: IDENT, - size: r.uint32le, + header: this.COMP_PLUS_SectionHeader, count: r.uint32le, strings: new r.Array(this.COMP_PLUS_ELEM_STRING, 'count') // + variable subtable: Element data (see KMXPlusBuilder.emitElements()) @@ -155,8 +162,7 @@ export class KMXPlusFileFormat extends KMXFile { }); this.COMP_PLUS_LAYR = new r.Struct({ - ident: IDENT, - size: r.uint32le, + header: this.COMP_PLUS_SectionHeader, listCount: r.uint32le, layerCount: r.uint32le, rowCount: r.uint32le, @@ -199,8 +205,7 @@ export class KMXPlusFileFormat extends KMXFile { }); this.COMP_PLUS_KEYS = new r.Struct({ - ident: IDENT, - size: r.uint32le, + header: this.COMP_PLUS_SectionHeader, keyCount: r.uint32le, flicksCount: r.uint32le, flickCount: r.uint32le, @@ -223,8 +228,7 @@ export class KMXPlusFileFormat extends KMXFile { }); this.COMP_PLUS_LIST = new r.Struct({ - ident: IDENT, - size: r.uint32le, + header: this.COMP_PLUS_SectionHeader, listCount: r.uint32le, indexCount: r.uint32le, lists: new r.Array(this.COMP_PLUS_LIST_LIST, 'listCount'), @@ -236,8 +240,7 @@ export class KMXPlusFileFormat extends KMXFile { this.COMP_PLUS_LOCA_ITEM = r.uint32le; //str this.COMP_PLUS_LOCA = new r.Struct({ - ident: IDENT, - size: r.uint32le, + header: this.COMP_PLUS_SectionHeader, count: r.uint32le, items: new r.Array(this.COMP_PLUS_LOCA_ITEM, 'count') }); @@ -245,8 +248,7 @@ export class KMXPlusFileFormat extends KMXFile { // 'meta' this.COMP_PLUS_META = new r.Struct({ - ident: IDENT, - size: r.uint32le, + header: this.COMP_PLUS_SectionHeader, author: STR_REF, //str conform: STR_REF, //str layout: STR_REF, //str @@ -270,8 +272,7 @@ export class KMXPlusFileFormat extends KMXFile { }); this.COMP_PLUS_STRS = new r.Struct({ - ident: IDENT, - size: r.uint32le, + header: this.COMP_PLUS_SectionHeader, count: r.uint32le, items: new r.Array(this.COMP_PLUS_STRS_ITEM, 'count') // + variable subtable: String data (see KMXPlusBuilder.emitStrings()) @@ -298,8 +299,7 @@ export class KMXPlusFileFormat extends KMXFile { }); this.COMP_PLUS_TRAN = new r.Struct({ - ident: IDENT, - size: r.uint32le, + header: this.COMP_PLUS_SectionHeader, groupCount: r.uint32le, transformCount: r.uint32le, reorderCount: r.uint32le, @@ -322,8 +322,7 @@ export class KMXPlusFileFormat extends KMXFile { }); this.COMP_PLUS_USET = new r.Struct({ - ident: IDENT, - size: r.uint32le, + header: this.COMP_PLUS_SectionHeader, usetCount: r.uint32le, rangeCount: r.uint32le, usets: new r.Array(this.COMP_PLUS_USET_USET, 'usetCount'), @@ -340,8 +339,7 @@ export class KMXPlusFileFormat extends KMXFile { }); this.COMP_PLUS_VARS = new r.Struct({ - ident: IDENT, - size: r.uint32le, + header: this.COMP_PLUS_SectionHeader, markers: LIST_REF, varCount: r.uint32le, varEntries: new r.Array(this.COMP_PLUS_VARS_ITEM, 'varCount'), diff --git a/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-disp.ts b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-disp.ts index 6984aa2cfa..86e4b33367 100644 --- a/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-disp.ts +++ b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-disp.ts @@ -30,8 +30,10 @@ export function build_disp(kmxplus: KMXPlusData, sect_strs: BUILDER_STRS): BUILD } const disp: BUILDER_DISP = { - ident: constants.hex_section_id(constants.section.disp), - size: constants.length_disp + constants.length_disp_item * kmxplus.disp.disps.length, + header: { + ident: constants.hex_section_id(constants.section.disp), + size: constants.length_disp + constants.length_disp_item * kmxplus.disp.disps.length, + }, _offset: 0, count: kmxplus.disp.disps.length, baseCharacter: build_strs_index(sect_strs, kmxplus.disp.baseCharacter), diff --git a/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-elem.ts b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-elem.ts index 8e352d191f..b556cfcbbd 100644 --- a/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-elem.ts +++ b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-elem.ts @@ -48,8 +48,10 @@ function binaryElemCompare(a: BUILDER_ELEM_STRING, b: BUILDER_ELEM_STRING): numb export function build_elem(source_elem: Elem, sect_strs: BUILDER_STRS, sect_uset: BUILDER_USET): BUILDER_ELEM { const result: BUILDER_ELEM = { - ident: constants.hex_section_id(constants.section.elem), - size: 0, // finalized below + header: { + ident: constants.hex_section_id(constants.section.elem), + size: 0, // finalized below + }, _offset: 0, count: source_elem.strings.length, strings: [], // finalized below @@ -98,7 +100,7 @@ export function build_elem(source_elem: Elem, sect_strs: BUILDER_STRS, sect_uset } } - result.size = offset; + result.header.size = offset; return result; } diff --git a/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-keys.ts b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-keys.ts index fd48ec49ec..620a1397ec 100644 --- a/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-keys.ts +++ b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-keys.ts @@ -76,8 +76,10 @@ export function build_keys(kmxplus: KMXPlusData, sect_strs: BUILDER_STRS, sect_l } const keys: BUILDER_KEYS = { - ident: constants.hex_section_id(constants.section.keys), - size: 0, + header: { + ident: constants.hex_section_id(constants.section.keys), + size: 0, + }, keyCount: kmxplus.keys.keys.length, flicksCount: kmxplus.keys.flicks.length, flickCount: 0, @@ -169,7 +171,7 @@ export function build_keys(kmxplus: KMXPlusData, sect_strs: BUILDER_STRS, sect_l (constants.length_keys_flick_element * keys.flickCount) + (constants.length_keys_flick_list * keys.flicksCount) + (constants.length_keys_kmap * keys.kmapCount); - keys.size = offset; + keys.header.size = offset; return keys; } diff --git a/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-layr.ts b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-layr.ts index 07249368f4..1efe320768 100644 --- a/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-layr.ts +++ b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-layr.ts @@ -72,8 +72,10 @@ export function build_layr(kmxplus: KMXPlusData, sect_strs: BUILDER_STRS, sect_l } const layr: BUILDER_LAYR = { - ident: constants.hex_section_id(constants.section.layr), - size: constants.length_layr, + header: { + ident: constants.hex_section_id(constants.section.layr), + size: constants.length_layr, + }, _offset: 0, listCount: kmxplus.layr.lists.length, layerCount: 0, // calculated below @@ -155,6 +157,6 @@ export function build_layr(kmxplus: KMXPlusData, sect_strs: BUILDER_STRS, sect_l (constants.length_layr_entry * layr.layerCount) + (constants.length_layr_row * layr.rowCount) + (constants.length_layr_key * layr.keyCount); - layr.size = offset; + layr.header.size = offset; return layr; } diff --git a/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-list.ts b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-list.ts index 759f6498f4..787b246b71 100644 --- a/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-list.ts +++ b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-list.ts @@ -44,8 +44,10 @@ export function build_list(source_list: List, sect_strs: BUILDER_STRS): BUILDER_ } const result: BUILDER_LIST = { - ident: constants.hex_section_id(constants.section.list), - size: 0, + header: { + ident: constants.hex_section_id(constants.section.list), + size: 0, + }, _offset: 0, listCount: source_list.lists.length, indexCount: 0, @@ -77,7 +79,7 @@ export function build_list(source_list: List, sect_strs: BUILDER_STRS): BUILDER_ const offset = constants.length_list + (constants.length_list_item * result.listCount) + (constants.length_list_index * result.indexCount); - result.size = offset; + result.header.size = offset; return result; } diff --git a/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-loca.ts b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-loca.ts index 4a81fcd9ab..7ddd944590 100644 --- a/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-loca.ts +++ b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-loca.ts @@ -20,8 +20,10 @@ export interface BUILDER_LOCA extends BUILDER_SECTION { export function build_loca(kmxplus: KMXPlusData, sect_strs: BUILDER_STRS): BUILDER_LOCA { const loca: BUILDER_LOCA = { - ident: constants.hex_section_id(constants.section.loca), - size: constants.length_loca + constants.length_loca_item * kmxplus.loca.locales.length, + header: { + ident: constants.hex_section_id(constants.section.loca), + size: constants.length_loca + constants.length_loca_item * kmxplus.loca.locales.length, + }, _offset: 0, count: kmxplus.loca.locales.length, items: [] diff --git a/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-meta.ts b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-meta.ts index 208051356e..3f232fc23c 100644 --- a/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-meta.ts +++ b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-meta.ts @@ -25,8 +25,10 @@ export interface BUILDER_META extends BUILDER_SECTION { export function build_meta(kmxplus: KMXPlusData, sect_strs: BUILDER_STRS): BUILDER_META { return { - ident: constants.hex_section_id(constants.section.meta), - size: constants.length_meta, + header: { + ident: constants.hex_section_id(constants.section.meta), + size: constants.length_meta, + }, _offset: 0, author: build_strs_index(sect_strs, kmxplus.meta.author), conform: build_strs_index(sect_strs, kmxplus.meta.conform), diff --git a/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-sect.ts b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-sect.ts index b97555d6de..df20071e7e 100644 --- a/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-sect.ts +++ b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-sect.ts @@ -21,8 +21,10 @@ export interface BUILDER_SECT extends BUILDER_SECTION { export function build_sect(): BUILDER_SECT { return { - ident: constants.hex_section_id(constants.section.sect), - size: 0, // finalized later + header: { + ident: constants.hex_section_id(constants.section.sect), + size: 0, // finalized later + }, _offset: 0, total: 0, // finalized later count: 0, // finalized later diff --git a/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-strs.ts b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-strs.ts index 89d733f22d..0ad5b6b2ed 100644 --- a/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-strs.ts +++ b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-strs.ts @@ -30,8 +30,10 @@ export interface BUILDER_STRS extends BUILDER_SECTION { export function build_strs(source_strs: Strs): BUILDER_STRS { const result: BUILDER_STRS = { - ident: constants.hex_section_id(constants.section.strs), - size: 0, // finalized later + header: { + ident: constants.hex_section_id(constants.section.strs), + size: 0, // finalized later + }, _offset: 0, count: source_strs.strings.length, items: [], // filled below @@ -46,7 +48,7 @@ export function build_strs(source_strs: Strs): BUILDER_STRS { item.offset = offset; offset += item.length * 2 + 2; /* UTF-16 code units + sizeof null terminator */ } - result.size = offset; + result.header.size = offset; return result; } diff --git a/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-tran.ts b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-tran.ts index 2473651b88..aa8bea55ae 100644 --- a/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-tran.ts +++ b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-tran.ts @@ -48,8 +48,10 @@ export function build_tran(source_tran: Tran | Bksp, sect_strs: BUILDER_STRS, se } const tran: BUILDER_TRAN = { - ident: constants.hex_section_id(source_tran.id), - size: 0, // need to compute total transforms + reorders + header: { + ident: constants.hex_section_id(source_tran.id), + size: 0, // need to compute total transforms + reorders + }, _offset: 0, groupCount: source_tran.groups.length, transformCount: 0, @@ -94,7 +96,7 @@ export function build_tran(source_tran: Tran | Bksp, sect_strs: BUILDER_STRS, se tran.transformCount = tran.transforms.length; tran.reorderCount = tran.reorders.length; - tran.size = constants.length_tran + + tran.header.size = constants.length_tran + (constants.length_tran_group * source_tran.groups.length) + (constants.length_tran_transform * tran.transforms.length) + (constants.length_tran_reorder * tran.reorders.length); diff --git a/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-uset.ts b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-uset.ts index 1edd4d339f..2b2d17a904 100644 --- a/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-uset.ts +++ b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-uset.ts @@ -57,10 +57,12 @@ export function build_uset(kmxplus: KMXPlusData, sect_strs: BUILDER_STRS ) : BUI }); const uset: BUILDER_USET = { - ident: constants.hex_section_id(constants.section.uset), - size: constants.length_uset + - (constants.length_uset_uset * usets.length) + - (constants.length_uset_range * ranges.length), + header: { + ident: constants.hex_section_id(constants.section.uset), + size: constants.length_uset + + (constants.length_uset_uset * usets.length) + + (constants.length_uset_range * ranges.length), + }, usetCount: usets.length, rangeCount: ranges.length, usets, diff --git a/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-vars.ts b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-vars.ts index 92acbba9be..8ccc38694d 100644 --- a/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-vars.ts +++ b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/build-vars.ts @@ -46,9 +46,11 @@ export function build_vars(kmxplus: KMXPlusData, sect_strs: BUILDER_STRS, sect_e }); const vars: BUILDER_VARS = { - ident: constants.hex_section_id(constants.section.vars), - size: constants.length_vars + - (constants.length_vars_item * kmxplus.vars.totalCount()), + header: { + ident: constants.hex_section_id(constants.section.vars), + size: constants.length_vars + + (constants.length_vars_item * kmxplus.vars.totalCount()), + }, _offset: 0, markers: build_list_index(sect_list, kmxplus.vars.markers), varCount: kmxplus.vars.totalCount(), diff --git a/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/builder-section.ts b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/builder-section.ts index a6d81fd25e..c4d8a76193 100644 --- a/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/builder-section.ts +++ b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/builder-section.ts @@ -4,8 +4,10 @@ export type BUILDER_IDENT = number; export type BUILDER_U32CHAR = number; export interface BUILDER_SECTION { - ident: BUILDER_IDENT; - size: number; + header: { + ident: BUILDER_IDENT; + size: number; + }; _offset: number; // used only for building the output } ; diff --git a/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/kmx-plus-builder.ts b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/kmx-plus-builder.ts index acc732c932..49889025b6 100644 --- a/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/kmx-plus-builder.ts +++ b/developer/src/common/web/utils/src/types/kmx/kmx-plus-builder/kmx-plus-builder.ts @@ -115,9 +115,9 @@ export default class KMXPlusBuilder { } }); - this.sect.sect.size = constants.length_sect + constants.length_sect_item * this.sect.sect.count; + this.sect.sect.header.size = constants.length_sect + constants.length_sect_item * this.sect.sect.count; - let offset = this.sect.sect.size; + let offset = this.sect.sect.header.size; // Note: in order! Everyone's here except 'sect' which is at offset 0 offset = this.finalize_sect_item(this.sect.bksp, offset); offset = this.finalize_sect_item(this.sect.disp, offset); @@ -141,16 +141,16 @@ export default class KMXPlusBuilder { return offset; } sect._offset = offset; - this.sect.sect.items.push({sect: sect.ident, offset: offset}); - return offset + sect.size; + this.sect.sect.items.push({sect: sect.header.ident, offset: offset}); + return offset + sect.header.size; } private emitSection(file: Uint8Array, comp: any, sect: BUILDER_SECTION) { if(sect) { const buf = comp.toBuffer(sect); - if (buf.length > sect.size) { + if (buf.length > sect.header.size) { // buf.length may be < sect.size if there is a variable part (i.e. elem) - throw new RangeError(`Internal Error: Section ${constants.str_section_id(sect.ident)} claimed size ${sect.size} but produced buffer of size ${buf.length}.`); + throw new RangeError(`Internal Error: Section ${constants.str_section_id(sect.header.ident)} claimed size ${sect.header.size} but produced buffer of size ${buf.length}.`); } file.set(buf, sect._offset); }