rw-parser-ng 2.1.1 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +252 -52
- package/lib/codecs/bitmap.d.ts +6 -0
- package/lib/codecs/bitmap.js +77 -0
- package/lib/codecs/color.d.ts +6 -0
- package/lib/codecs/color.js +43 -0
- package/lib/codecs/dxt.d.ts +3 -0
- package/lib/codecs/dxt.js +212 -0
- package/lib/codecs/formats.d.ts +25 -0
- package/lib/codecs/formats.js +32 -0
- package/lib/codecs/index.d.ts +5 -0
- package/lib/codecs/index.js +21 -0
- package/lib/codecs/palette.d.ts +6 -0
- package/lib/codecs/palette.js +86 -0
- package/lib/common/types.d.ts +50 -0
- package/lib/common/types.js +2 -0
- package/lib/core/byte-stream.d.ts +20 -0
- package/lib/core/byte-stream.js +71 -0
- package/lib/core/errors.d.ts +5 -0
- package/lib/core/errors.js +34 -0
- package/lib/core/index.d.ts +5 -0
- package/lib/core/index.js +21 -0
- package/lib/core/rw-file.d.ts +9 -0
- package/lib/core/rw-file.js +36 -0
- package/lib/core/rw-sections.d.ts +24 -0
- package/lib/core/rw-sections.js +28 -0
- package/lib/core/rw-version.d.ts +3 -0
- package/lib/core/rw-version.js +27 -0
- package/lib/dff/dff-model-type.d.ts +5 -0
- package/lib/dff/dff-model-type.js +9 -0
- package/lib/dff/index.d.ts +4 -0
- package/lib/dff/index.js +20 -0
- package/lib/dff/parser.d.ts +5 -0
- package/lib/dff/parser.js +154 -0
- package/lib/dff/readers/2d-effect.d.ts +3 -0
- package/lib/dff/readers/2d-effect.js +211 -0
- package/lib/dff/readers/geometry.d.ts +4 -0
- package/lib/dff/readers/geometry.js +229 -0
- package/lib/dff/readers/index.d.ts +5 -0
- package/lib/dff/readers/index.js +21 -0
- package/lib/dff/readers/material.d.ts +5 -0
- package/lib/dff/readers/material.js +72 -0
- package/lib/dff/readers/mesh.d.ts +5 -0
- package/lib/dff/readers/mesh.js +84 -0
- package/lib/dff/readers/structure.d.ts +6 -0
- package/lib/dff/readers/structure.js +67 -0
- package/lib/dff/types.d.ts +237 -0
- package/lib/dff/types.js +44 -0
- package/lib/fxp/index.d.ts +2 -0
- package/lib/fxp/index.js +18 -0
- package/lib/fxp/info-parser.d.ts +2 -0
- package/lib/fxp/info-parser.js +169 -0
- package/lib/fxp/parser.d.ts +3 -0
- package/lib/fxp/parser.js +285 -0
- package/lib/fxp/types/common.d.ts +36 -0
- package/lib/fxp/types/common.js +2 -0
- package/lib/fxp/types/index.d.ts +3 -0
- package/lib/fxp/types/index.js +19 -0
- package/lib/fxp/types/info.d.ts +186 -0
- package/lib/fxp/types/info.js +2 -0
- package/lib/fxp/types/system.d.ts +27 -0
- package/lib/fxp/types/system.js +2 -0
- package/lib/ifp/index.d.ts +4 -0
- package/lib/ifp/index.js +20 -0
- package/lib/ifp/parser.d.ts +5 -0
- package/lib/ifp/parser.js +38 -0
- package/lib/ifp/readers/anp3.d.ts +3 -0
- package/lib/ifp/readers/anp3.js +56 -0
- package/lib/ifp/readers/anpk.d.ts +3 -0
- package/lib/ifp/readers/anpk.js +86 -0
- package/lib/ifp/types.d.ts +28 -0
- package/lib/ifp/types.js +9 -0
- package/lib/index.d.ts +6 -9
- package/lib/index.js +6 -13
- package/lib/renderware/fxp/FxpData.d.ts +246 -0
- package/lib/renderware/fxp/FxpData.js +2 -0
- package/lib/renderware/fxp/FxpParser.d.ts +3 -0
- package/lib/renderware/fxp/FxpParser.js +512 -0
- package/lib/renderware/fxp/index.d.ts +2 -0
- package/lib/renderware/fxp/index.js +18 -0
- package/lib/txd/bitmap-decoder.d.ts +3 -0
- package/lib/txd/bitmap-decoder.js +57 -0
- package/lib/txd/index.d.ts +3 -0
- package/lib/txd/index.js +19 -0
- package/lib/txd/parser.d.ts +8 -0
- package/lib/txd/parser.js +122 -0
- package/lib/txd/types.d.ts +27 -0
- package/lib/txd/types.js +2 -0
- package/package.json +16 -9
- package/src/codecs/bitmap.ts +75 -0
- package/src/codecs/color.ts +40 -0
- package/src/codecs/dxt.ts +243 -0
- package/src/codecs/formats.ts +28 -0
- package/src/codecs/index.ts +5 -0
- package/src/codecs/palette.ts +106 -0
- package/src/common/types.ts +59 -0
- package/src/core/byte-stream.ts +87 -0
- package/src/core/errors.ts +7 -0
- package/src/core/index.ts +5 -0
- package/src/core/rw-file.ts +23 -0
- package/src/core/rw-sections.ts +24 -0
- package/src/core/rw-version.ts +24 -0
- package/src/dff/dff-model-type.ts +5 -0
- package/src/dff/index.ts +4 -0
- package/src/dff/parser.ts +142 -0
- package/src/dff/readers/2d-effect.ts +265 -0
- package/src/dff/readers/geometry.ts +264 -0
- package/src/dff/readers/index.ts +5 -0
- package/src/dff/readers/material.ts +89 -0
- package/src/dff/readers/mesh.ts +93 -0
- package/src/dff/readers/structure.ts +79 -0
- package/src/dff/types.ts +278 -0
- package/src/fxp/index.ts +2 -0
- package/src/fxp/info-parser.ts +166 -0
- package/src/fxp/parser.ts +323 -0
- package/src/fxp/types/common.ts +23 -0
- package/src/fxp/types/index.ts +3 -0
- package/src/fxp/types/info.ts +251 -0
- package/src/fxp/types/system.ts +30 -0
- package/src/ifp/index.ts +4 -0
- package/src/ifp/parser.ts +16 -0
- package/src/ifp/readers/anp3.ts +75 -0
- package/src/ifp/readers/anpk.ts +110 -0
- package/src/ifp/types.ts +33 -0
- package/src/index.ts +6 -12
- package/src/txd/bitmap-decoder.ts +73 -0
- package/src/txd/index.ts +3 -0
- package/src/txd/parser.ts +148 -0
- package/src/txd/types.ts +29 -0
- package/src/renderware/RwFile.ts +0 -26
- package/src/renderware/RwSections.ts +0 -27
- package/src/renderware/common/types.ts +0 -59
- package/src/renderware/dff/DffModelType.ts +0 -5
- package/src/renderware/dff/DffParser.ts +0 -611
- package/src/renderware/errors/RwParseError.ts +0 -11
- package/src/renderware/ifp/IfpData.ts +0 -33
- package/src/renderware/ifp/IfpParser.ts +0 -203
- package/src/renderware/txd/TxdParser.ts +0 -235
- package/src/renderware/utils/ImageDecoder.ts +0 -571
- package/src/renderware/utils/ImageFormatEnums.ts +0 -28
- package/src/renderware/utils/RwVersion.ts +0 -28
- package/src/utils/ByteStream.ts +0 -80
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { RwFile } from "../../core/rw-file";
|
|
2
|
+
import {
|
|
3
|
+
IfpVersion,
|
|
4
|
+
type RwIfp,
|
|
5
|
+
type RwIfpAnimation,
|
|
6
|
+
type RwIfpBone,
|
|
7
|
+
type RwIfpKeyframe,
|
|
8
|
+
} from "../types";
|
|
9
|
+
|
|
10
|
+
const QUAT_SCALE = 4096.0;
|
|
11
|
+
const POS_SCALE = 1024.0;
|
|
12
|
+
|
|
13
|
+
export function readAnp3(file: RwFile): RwIfp {
|
|
14
|
+
file.skip(4); // ANP3 signature
|
|
15
|
+
file.readUint32(); // size
|
|
16
|
+
const name = file.readString(24);
|
|
17
|
+
const animationsCount = file.readUint32();
|
|
18
|
+
|
|
19
|
+
const animations: RwIfpAnimation[] = [];
|
|
20
|
+
for (let i = 0; i < animationsCount; i++) {
|
|
21
|
+
animations.push(readAnimation(file));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return { version: IfpVersion.ANP3, name, animations };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function readAnimation(file: RwFile): RwIfpAnimation {
|
|
28
|
+
const name = file.readString(24);
|
|
29
|
+
const bonesCount = file.readUint32();
|
|
30
|
+
file.skip(8); // keyframes_size + unk
|
|
31
|
+
|
|
32
|
+
const bones: RwIfpBone[] = [];
|
|
33
|
+
for (let i = 0; i < bonesCount; i++) {
|
|
34
|
+
bones.push(readBone(file));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return { name, bones };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function readBone(file: RwFile): RwIfpBone {
|
|
41
|
+
const name = file.readString(24);
|
|
42
|
+
const keyframeTypeNum = file.readUint32();
|
|
43
|
+
const keyframesCount = file.readUint32();
|
|
44
|
+
const keyframeType = keyframeTypeNum === 4 ? "KRT0" : "KR00";
|
|
45
|
+
const boneId = file.readInt32();
|
|
46
|
+
|
|
47
|
+
const keyframes: RwIfpKeyframe[] = [];
|
|
48
|
+
const hasTranslation = keyframeType[2] === "T";
|
|
49
|
+
|
|
50
|
+
for (let i = 0; i < keyframesCount; i++) {
|
|
51
|
+
const qx = file.readInt16() / QUAT_SCALE;
|
|
52
|
+
const qy = file.readInt16() / QUAT_SCALE;
|
|
53
|
+
const qz = file.readInt16() / QUAT_SCALE;
|
|
54
|
+
const qw = file.readInt16() / QUAT_SCALE;
|
|
55
|
+
const time = file.readInt16();
|
|
56
|
+
|
|
57
|
+
let px = 0,
|
|
58
|
+
py = 0,
|
|
59
|
+
pz = 0;
|
|
60
|
+
if (hasTranslation) {
|
|
61
|
+
px = file.readInt16() / POS_SCALE;
|
|
62
|
+
py = file.readInt16() / POS_SCALE;
|
|
63
|
+
pz = file.readInt16() / POS_SCALE;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
keyframes.push({
|
|
67
|
+
time,
|
|
68
|
+
position: { x: px, y: py, z: pz },
|
|
69
|
+
rotation: { w: qw, x: qx, y: qy, z: qz },
|
|
70
|
+
scale: { x: 1, y: 1, z: 1 },
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return { name, keyframeType, useBoneId: true, boneId, keyframes };
|
|
75
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import type { RwFile } from "../../core/rw-file";
|
|
2
|
+
import {
|
|
3
|
+
IfpVersion,
|
|
4
|
+
type RwIfp,
|
|
5
|
+
type RwIfpAnimation,
|
|
6
|
+
type RwIfpBone,
|
|
7
|
+
type RwIfpKeyframe,
|
|
8
|
+
} from "../types";
|
|
9
|
+
|
|
10
|
+
export function readAnpk(file: RwFile): RwIfp {
|
|
11
|
+
file.skip(4); // ANPK signature
|
|
12
|
+
file.readUint32(); // size
|
|
13
|
+
file.skip(4); // INFO
|
|
14
|
+
const infoLen = file.readUint32();
|
|
15
|
+
const animationsCount = file.readUint32();
|
|
16
|
+
const name = file.readString(infoLen - 4);
|
|
17
|
+
file.skip((4 - (infoLen % 4)) % 4); // align
|
|
18
|
+
|
|
19
|
+
const animations: RwIfpAnimation[] = [];
|
|
20
|
+
for (let i = 0; i < animationsCount; i++) {
|
|
21
|
+
animations.push(readAnimation(file));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return { version: IfpVersion.ANPK, name, animations };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function readAnimation(file: RwFile): RwIfpAnimation {
|
|
28
|
+
file.skip(4); // NAME
|
|
29
|
+
const nameLen = file.readUint32();
|
|
30
|
+
const name = file.readString(nameLen);
|
|
31
|
+
file.skip((4 - (nameLen % 4)) % 4); // align
|
|
32
|
+
file.skip(4); // DGAN
|
|
33
|
+
file.skip(4); // animation_size
|
|
34
|
+
file.skip(4); // INFO
|
|
35
|
+
file.skip(4); // unk_size
|
|
36
|
+
const bonesCount = file.readUint32();
|
|
37
|
+
file.skip(4); // unk
|
|
38
|
+
|
|
39
|
+
const bones: RwIfpBone[] = [];
|
|
40
|
+
for (let i = 0; i < bonesCount; i++) {
|
|
41
|
+
bones.push(readBone(file));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return { name, bones };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function readBone(file: RwFile): RwIfpBone {
|
|
48
|
+
file.skip(4); // CPAN
|
|
49
|
+
file.skip(4); // bone_len
|
|
50
|
+
file.skip(4); // ANIM
|
|
51
|
+
const animLen = file.readUint32();
|
|
52
|
+
const name = file.readString(28);
|
|
53
|
+
const keyframesCount = file.readUint32();
|
|
54
|
+
file.skip(8); // unk
|
|
55
|
+
|
|
56
|
+
const useBoneId = animLen === 44;
|
|
57
|
+
let boneId = 0;
|
|
58
|
+
if (useBoneId) {
|
|
59
|
+
boneId = file.readInt32();
|
|
60
|
+
} else {
|
|
61
|
+
file.skip(8); // sibling_x, sibling_y
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
let keyframeType = "K000";
|
|
65
|
+
const keyframes: RwIfpKeyframe[] = [];
|
|
66
|
+
|
|
67
|
+
if (keyframesCount > 0) {
|
|
68
|
+
keyframeType = file.readString(4);
|
|
69
|
+
file.skip(4); // keyframes_len
|
|
70
|
+
|
|
71
|
+
const hasTranslation = keyframeType[2] === "T";
|
|
72
|
+
const hasScale = keyframeType[3] === "S";
|
|
73
|
+
|
|
74
|
+
for (let i = 0; i < keyframesCount; i++) {
|
|
75
|
+
const qx = file.readFloat();
|
|
76
|
+
const qy = file.readFloat();
|
|
77
|
+
const qz = file.readFloat();
|
|
78
|
+
const qw = file.readFloat();
|
|
79
|
+
|
|
80
|
+
let px = 0,
|
|
81
|
+
py = 0,
|
|
82
|
+
pz = 0;
|
|
83
|
+
if (hasTranslation) {
|
|
84
|
+
px = file.readFloat();
|
|
85
|
+
py = file.readFloat();
|
|
86
|
+
pz = file.readFloat();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
let sx = 1,
|
|
90
|
+
sy = 1,
|
|
91
|
+
sz = 1;
|
|
92
|
+
if (hasScale) {
|
|
93
|
+
sx = file.readFloat();
|
|
94
|
+
sy = file.readFloat();
|
|
95
|
+
sz = file.readFloat();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const time = file.readFloat();
|
|
99
|
+
|
|
100
|
+
keyframes.push({
|
|
101
|
+
time,
|
|
102
|
+
position: { x: px, y: py, z: pz },
|
|
103
|
+
rotation: { w: qw, x: qx, y: qy, z: qz },
|
|
104
|
+
scale: { x: sx, y: sy, z: sz },
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return { name, keyframeType, useBoneId, boneId, keyframes };
|
|
110
|
+
}
|
package/src/ifp/types.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { RwQuaternion, RwVector3 } from "../common/types";
|
|
2
|
+
|
|
3
|
+
export enum IfpVersion {
|
|
4
|
+
ANP3,
|
|
5
|
+
ANPK,
|
|
6
|
+
UNSUPPORTED,
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface RwIfp {
|
|
10
|
+
version: IfpVersion;
|
|
11
|
+
name: string;
|
|
12
|
+
animations: RwIfpAnimation[];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface RwIfpAnimation {
|
|
16
|
+
name: string;
|
|
17
|
+
bones: RwIfpBone[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface RwIfpBone {
|
|
21
|
+
name: string;
|
|
22
|
+
keyframeType: string;
|
|
23
|
+
useBoneId: boolean;
|
|
24
|
+
boneId: number;
|
|
25
|
+
keyframes: RwIfpKeyframe[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface RwIfpKeyframe {
|
|
29
|
+
time: number;
|
|
30
|
+
position: RwVector3;
|
|
31
|
+
rotation: RwQuaternion;
|
|
32
|
+
scale: RwVector3;
|
|
33
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
export * from
|
|
6
|
-
export * from
|
|
7
|
-
export * from './renderware/ifp/IfpParser';
|
|
8
|
-
|
|
9
|
-
export * from './renderware/dff/DffModelType';
|
|
10
|
-
export * from './renderware/ifp/IfpData';
|
|
11
|
-
|
|
12
|
-
export * from './renderware/common/types';
|
|
1
|
+
export * from "./common/types";
|
|
2
|
+
export * from "./core";
|
|
3
|
+
export * from "./dff";
|
|
4
|
+
export * from "./fxp";
|
|
5
|
+
export * from "./ifp";
|
|
6
|
+
export * from "./txd";
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { bgra555, bgra565, bgra888, bgra1555, bgra4444, bgra8888 } from "../codecs/bitmap";
|
|
2
|
+
import { bc1, bc2, bc3 } from "../codecs/dxt";
|
|
3
|
+
import { D3DFormat, PaletteType, RasterFormat } from "../codecs/formats";
|
|
4
|
+
import { lum8, lum8a8, pal4, pal4NoAlpha, pal8, pal8NoAlpha } from "../codecs/palette";
|
|
5
|
+
|
|
6
|
+
export function decodePaletteBitmap(
|
|
7
|
+
paletteType: number,
|
|
8
|
+
depth: number,
|
|
9
|
+
hasAlpha: boolean,
|
|
10
|
+
raster: Uint8Array,
|
|
11
|
+
palette: Uint8Array,
|
|
12
|
+
width: number,
|
|
13
|
+
height: number,
|
|
14
|
+
): Uint8Array {
|
|
15
|
+
if (paletteType !== PaletteType.PALETTE_8 && depth === 4) {
|
|
16
|
+
return hasAlpha
|
|
17
|
+
? pal4(raster, palette, width, height)
|
|
18
|
+
: pal4NoAlpha(raster, palette, width, height);
|
|
19
|
+
}
|
|
20
|
+
return hasAlpha
|
|
21
|
+
? pal8(raster, palette, width, height)
|
|
22
|
+
: pal8NoAlpha(raster, palette, width, height);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function decodeDxtBitmap(
|
|
26
|
+
dxtType: string,
|
|
27
|
+
raster: Uint8Array,
|
|
28
|
+
width: number,
|
|
29
|
+
height: number,
|
|
30
|
+
): Uint8Array {
|
|
31
|
+
switch (dxtType) {
|
|
32
|
+
case D3DFormat.D3D_DXT1:
|
|
33
|
+
return bc1(raster, width, height);
|
|
34
|
+
case D3DFormat.D3D_DXT2:
|
|
35
|
+
return bc2(raster, width, height, true);
|
|
36
|
+
case D3DFormat.D3D_DXT3:
|
|
37
|
+
return bc2(raster, width, height, false);
|
|
38
|
+
case D3DFormat.D3D_DXT4:
|
|
39
|
+
return bc3(raster, width, height, true);
|
|
40
|
+
case D3DFormat.D3D_DXT5:
|
|
41
|
+
return bc3(raster, width, height, false);
|
|
42
|
+
case D3DFormat.D3DFMT_A8L8:
|
|
43
|
+
return lum8a8(raster, width, height);
|
|
44
|
+
default:
|
|
45
|
+
return new Uint8Array(0);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function decodeRasterBitmap(
|
|
50
|
+
rasterFormat: number,
|
|
51
|
+
raster: Uint8Array,
|
|
52
|
+
width: number,
|
|
53
|
+
height: number,
|
|
54
|
+
): Uint8Array {
|
|
55
|
+
switch (rasterFormat) {
|
|
56
|
+
case RasterFormat.RASTER_1555:
|
|
57
|
+
return bgra1555(raster, width, height);
|
|
58
|
+
case RasterFormat.RASTER_565:
|
|
59
|
+
return bgra565(raster, width, height);
|
|
60
|
+
case RasterFormat.RASTER_4444:
|
|
61
|
+
return bgra4444(raster, width, height);
|
|
62
|
+
case RasterFormat.RASTER_LUM:
|
|
63
|
+
return lum8(raster, width, height);
|
|
64
|
+
case RasterFormat.RASTER_8888:
|
|
65
|
+
return bgra8888(raster, width, height);
|
|
66
|
+
case RasterFormat.RASTER_888:
|
|
67
|
+
return bgra888(raster, width, height);
|
|
68
|
+
case RasterFormat.RASTER_555:
|
|
69
|
+
return bgra555(raster, width, height);
|
|
70
|
+
default:
|
|
71
|
+
return new Uint8Array(0);
|
|
72
|
+
}
|
|
73
|
+
}
|
package/src/txd/index.ts
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { PaletteType, PlatformType, RasterFormat } from "../codecs/formats";
|
|
2
|
+
import { RwFile } from "../core/rw-file";
|
|
3
|
+
import { decodeDxtBitmap, decodePaletteBitmap, decodeRasterBitmap } from "./bitmap-decoder";
|
|
4
|
+
import type { RwTextureDictionary, RwTextureNative, RwTxd } from "./types";
|
|
5
|
+
|
|
6
|
+
export class TxdParser extends RwFile {
|
|
7
|
+
parse(): RwTxd {
|
|
8
|
+
return { textureDictionary: this.readTextureDictionary() };
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
public readTextureDictionary(): RwTextureDictionary {
|
|
12
|
+
this.readSectionHeader();
|
|
13
|
+
this.readSectionHeader();
|
|
14
|
+
|
|
15
|
+
const textureCount = this.readUint16();
|
|
16
|
+
this.skip(2);
|
|
17
|
+
|
|
18
|
+
const textureNatives: RwTextureNative[] = [];
|
|
19
|
+
for (let i = 0; i < textureCount; i++) {
|
|
20
|
+
textureNatives.push(this.readTextureNative());
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
this.skip(this.readSectionHeader().sectionSize);
|
|
24
|
+
|
|
25
|
+
return { textureCount, textureNatives };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public readTextureNative(): RwTextureNative {
|
|
29
|
+
this.readSectionHeader();
|
|
30
|
+
this.readSectionHeader();
|
|
31
|
+
|
|
32
|
+
const platformId = this.readUint32();
|
|
33
|
+
const flags = this.readUint32();
|
|
34
|
+
const filterMode = flags & 0xff;
|
|
35
|
+
const uAddressing = (flags & 0xf00) >> 8;
|
|
36
|
+
const vAddressing = (flags & 0xf000) >> 12;
|
|
37
|
+
|
|
38
|
+
const textureName = this.readString(32);
|
|
39
|
+
const maskName = this.readString(32);
|
|
40
|
+
|
|
41
|
+
const rasterFormat = this.readUint32();
|
|
42
|
+
const d3dFormat = this.readString(4);
|
|
43
|
+
const width = this.readUint16();
|
|
44
|
+
const height = this.readUint16();
|
|
45
|
+
const depth = this.readUint8();
|
|
46
|
+
const mipmapCount = this.readUint8();
|
|
47
|
+
const rasterType = this.readUint8();
|
|
48
|
+
const compressionFlags = this.readUint8();
|
|
49
|
+
|
|
50
|
+
const alpha = (compressionFlags & (1 << 0)) !== 0;
|
|
51
|
+
const cubeTexture = (compressionFlags & (1 << 1)) !== 0;
|
|
52
|
+
const autoMipMaps = (compressionFlags & (1 << 2)) !== 0;
|
|
53
|
+
const compressed = (compressionFlags & (1 << 3)) !== 0;
|
|
54
|
+
|
|
55
|
+
const paletteType = (rasterFormat >> 13) & 0b11;
|
|
56
|
+
const pixelFormat = rasterFormat & 0x0f00;
|
|
57
|
+
const palette =
|
|
58
|
+
paletteType !== PaletteType.PALETTE_NONE
|
|
59
|
+
? this.read(paletteType === PaletteType.PALETTE_8 ? 1024 : depth === 4 ? 64 : 128)
|
|
60
|
+
: new Uint8Array(0);
|
|
61
|
+
|
|
62
|
+
const mipmaps: number[][] = [];
|
|
63
|
+
|
|
64
|
+
for (let i = 0; i < mipmapCount; i++) {
|
|
65
|
+
const rasterSize = this.readUint32();
|
|
66
|
+
const raster = this.read(rasterSize);
|
|
67
|
+
|
|
68
|
+
if (i === 0) {
|
|
69
|
+
const bitmap = this.decodeBitmap(
|
|
70
|
+
platformId,
|
|
71
|
+
compressionFlags,
|
|
72
|
+
compressed,
|
|
73
|
+
alpha,
|
|
74
|
+
paletteType,
|
|
75
|
+
depth,
|
|
76
|
+
pixelFormat,
|
|
77
|
+
d3dFormat,
|
|
78
|
+
raster,
|
|
79
|
+
palette,
|
|
80
|
+
width,
|
|
81
|
+
height,
|
|
82
|
+
);
|
|
83
|
+
mipmaps.push(Array.from(bitmap));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
this.skip(this.readSectionHeader().sectionSize);
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
platformId,
|
|
91
|
+
filterMode,
|
|
92
|
+
uAddressing,
|
|
93
|
+
vAddressing,
|
|
94
|
+
textureName,
|
|
95
|
+
maskName,
|
|
96
|
+
rasterFormat,
|
|
97
|
+
d3dFormat,
|
|
98
|
+
width,
|
|
99
|
+
height,
|
|
100
|
+
depth,
|
|
101
|
+
mipmapCount,
|
|
102
|
+
rasterType,
|
|
103
|
+
alpha,
|
|
104
|
+
cubeTexture,
|
|
105
|
+
autoMipMaps,
|
|
106
|
+
compressed,
|
|
107
|
+
mipmaps,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private decodeBitmap(
|
|
112
|
+
platformId: number,
|
|
113
|
+
compressionFlags: number,
|
|
114
|
+
compressed: boolean,
|
|
115
|
+
alpha: boolean,
|
|
116
|
+
paletteType: number,
|
|
117
|
+
depth: number,
|
|
118
|
+
pixelFormat: number,
|
|
119
|
+
d3dFormat: string,
|
|
120
|
+
raster: Uint8Array,
|
|
121
|
+
palette: Uint8Array,
|
|
122
|
+
width: number,
|
|
123
|
+
height: number,
|
|
124
|
+
): Uint8Array {
|
|
125
|
+
if (palette.length !== 0) {
|
|
126
|
+
const noAlphaFormats = [
|
|
127
|
+
RasterFormat.RASTER_565,
|
|
128
|
+
RasterFormat.RASTER_LUM,
|
|
129
|
+
RasterFormat.RASTER_888,
|
|
130
|
+
RasterFormat.RASTER_555,
|
|
131
|
+
];
|
|
132
|
+
const hasAlpha =
|
|
133
|
+
(platformId === PlatformType.D3D9 && alpha) ||
|
|
134
|
+
(platformId === PlatformType.D3D8 && !noAlphaFormats.includes(pixelFormat));
|
|
135
|
+
return decodePaletteBitmap(paletteType, depth, hasAlpha, raster, palette, width, height);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (platformId === PlatformType.D3D8 && compressionFlags !== 0) {
|
|
139
|
+
return decodeDxtBitmap(`DXT${compressionFlags}`, raster, width, height);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (platformId === PlatformType.D3D9 && compressed) {
|
|
143
|
+
return decodeDxtBitmap(d3dFormat, raster, width, height);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return decodeRasterBitmap(pixelFormat, raster, width, height);
|
|
147
|
+
}
|
|
148
|
+
}
|
package/src/txd/types.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface RwTxd {
|
|
2
|
+
textureDictionary: RwTextureDictionary;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export interface RwTextureDictionary {
|
|
6
|
+
textureCount: number;
|
|
7
|
+
textureNatives: RwTextureNative[];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface RwTextureNative {
|
|
11
|
+
platformId: number;
|
|
12
|
+
filterMode: number;
|
|
13
|
+
uAddressing: number;
|
|
14
|
+
vAddressing: number;
|
|
15
|
+
textureName: string;
|
|
16
|
+
maskName: string;
|
|
17
|
+
rasterFormat: number;
|
|
18
|
+
d3dFormat: string;
|
|
19
|
+
width: number;
|
|
20
|
+
height: number;
|
|
21
|
+
depth: number;
|
|
22
|
+
mipmapCount: number;
|
|
23
|
+
rasterType: number;
|
|
24
|
+
alpha: boolean;
|
|
25
|
+
cubeTexture: boolean;
|
|
26
|
+
autoMipMaps: boolean;
|
|
27
|
+
compressed: boolean;
|
|
28
|
+
mipmaps: number[][];
|
|
29
|
+
}
|
package/src/renderware/RwFile.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { ByteStream } from "../utils/ByteStream";
|
|
2
|
-
|
|
3
|
-
export interface RwSectionHeader {
|
|
4
|
-
sectionType: number,
|
|
5
|
-
sectionSize: number,
|
|
6
|
-
versionNumber: number
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export class RwFile extends ByteStream {
|
|
10
|
-
|
|
11
|
-
constructor(stream: Buffer) {
|
|
12
|
-
super(stream);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
public readSectionHeader(): RwSectionHeader {
|
|
16
|
-
if (this.getPosition() + 12 > this.getSize()) {
|
|
17
|
-
throw new Error(`Cannot read section header at offset ${this.getPosition().toString(16)}: need 12 bytes but only ${this.getSize() - this.getPosition()} bytes remaining`);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const sectionType = this.readUint32();
|
|
21
|
-
const sectionSize = this.readUint32();
|
|
22
|
-
const versionNumber = this.readUint32();
|
|
23
|
-
|
|
24
|
-
return { sectionType, sectionSize, versionNumber };
|
|
25
|
-
}
|
|
26
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
export enum RwSections {
|
|
2
|
-
// Core
|
|
3
|
-
RwStruct = 0x0001,
|
|
4
|
-
RwString = 0x0002,
|
|
5
|
-
RwExtension = 0x0003,
|
|
6
|
-
RwTexture = 0x0006,
|
|
7
|
-
RwMaterial = 0x0007,
|
|
8
|
-
RwMaterialList = 0x0008,
|
|
9
|
-
RwFrameList = 0x000E,
|
|
10
|
-
RwGeometry = 0x000F,
|
|
11
|
-
RwClump = 0x0010,
|
|
12
|
-
RwAtomic = 0x0014,
|
|
13
|
-
RwTextureNative = 0x0015,
|
|
14
|
-
RwTextureDictionary = 0x0016,
|
|
15
|
-
RwGeometryList = 0x001A,
|
|
16
|
-
RwSkin = 0x116,
|
|
17
|
-
RwAnim = 0x11E,
|
|
18
|
-
|
|
19
|
-
// Toolkit
|
|
20
|
-
RwMaterialEffectsPLG = 0x0120,
|
|
21
|
-
|
|
22
|
-
// R* specific RW plugins
|
|
23
|
-
RwReflectionMaterial = 0x0253F2FC,
|
|
24
|
-
// This was renamed to RwNodeName from RwFrame to prevent confusion.
|
|
25
|
-
// https://gtamods.com/wiki/Node_Name_(RW_Section)
|
|
26
|
-
RwNodeName = 0x0253F2FE,
|
|
27
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
export interface RwVector2 {
|
|
2
|
-
x: number,
|
|
3
|
-
y: number,
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
export interface RwVector3 {
|
|
7
|
-
x: number,
|
|
8
|
-
y: number,
|
|
9
|
-
z: number,
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface RwVector4 {
|
|
13
|
-
x: number,
|
|
14
|
-
y: number,
|
|
15
|
-
z: number,
|
|
16
|
-
t: number,
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface RwQuaternion {
|
|
20
|
-
x: number,
|
|
21
|
-
y: number,
|
|
22
|
-
z: number,
|
|
23
|
-
w: number,
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export interface RwMatrix3 {
|
|
27
|
-
right: RwVector3,
|
|
28
|
-
up: RwVector3,
|
|
29
|
-
at: RwVector3,
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export interface RwMatrix4 {
|
|
33
|
-
right: RwVector4,
|
|
34
|
-
up: RwVector4,
|
|
35
|
-
at: RwVector4,
|
|
36
|
-
transform: RwVector4,
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export interface RwColor {
|
|
40
|
-
r: number,
|
|
41
|
-
g: number,
|
|
42
|
-
b: number,
|
|
43
|
-
a: number,
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export interface RwTextureCoordinate {
|
|
47
|
-
u: number,
|
|
48
|
-
v: number,
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export interface RwTriangle {
|
|
52
|
-
vector: RwVector3,
|
|
53
|
-
materialId: number,
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export interface RwSphere {
|
|
57
|
-
vector: RwVector3,
|
|
58
|
-
radius: number,
|
|
59
|
-
}
|