networkwm-js 0.1.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/LICENSE +339 -0
- package/README.MD +110 -0
- package/dist/bytemanip.d.ts +12 -0
- package/dist/bytemanip.d.ts.map +1 -0
- package/dist/bytemanip.js +71 -0
- package/dist/database-abstraction.d.ts +39 -0
- package/dist/database-abstraction.d.ts.map +1 -0
- package/dist/database-abstraction.js +288 -0
- package/dist/databases.d.ts +85 -0
- package/dist/databases.d.ts.map +1 -0
- package/dist/databases.js +303 -0
- package/dist/devices.d.ts +6 -0
- package/dist/devices.d.ts.map +1 -0
- package/dist/devices.js +9 -0
- package/dist/encryption.d.ts +16 -0
- package/dist/encryption.d.ts.map +1 -0
- package/dist/encryption.js +123 -0
- package/dist/errors.d.ts +4 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +10 -0
- package/dist/filesystem/index.d.ts +2 -0
- package/dist/filesystem/index.d.ts.map +1 -0
- package/dist/filesystem/index.js +17 -0
- package/dist/filesystem/usb-mass-storage-webusb-filesystem.d.ts +44 -0
- package/dist/filesystem/usb-mass-storage-webusb-filesystem.d.ts.map +1 -0
- package/dist/filesystem/usb-mass-storage-webusb-filesystem.js +187 -0
- package/dist/functions.d.ts +12 -0
- package/dist/functions.d.ts.map +1 -0
- package/dist/functions.js +73 -0
- package/dist/helpers.d.ts +9 -0
- package/dist/helpers.d.ts.map +1 -0
- package/dist/helpers.js +47 -0
- package/dist/id3.d.ts +18 -0
- package/dist/id3.d.ts.map +1 -0
- package/dist/id3.js +137 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/init-data.d.ts +16 -0
- package/dist/init-data.d.ts.map +1 -0
- package/dist/init-data.js +18 -0
- package/dist/initialization.d.ts +4 -0
- package/dist/initialization.d.ts.map +1 -0
- package/dist/initialization.js +32 -0
- package/dist/sort.d.ts +13 -0
- package/dist/sort.d.ts.map +1 -0
- package/dist/sort.js +62 -0
- package/dist/tables.d.ts +19 -0
- package/dist/tables.d.ts.map +1 -0
- package/dist/tables.js +101 -0
- package/dist/tagged-oma.d.ts +12 -0
- package/dist/tagged-oma.d.ts.map +1 -0
- package/dist/tagged-oma.js +175 -0
- package/dist/utils.d.ts +9 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +90 -0
- package/package.json +43 -0
package/dist/id3.js
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.encodeUTF16BEStringEA3 = exports.serialize = exports.parse = exports.readSynchsafeInt32 = void 0;
|
|
4
|
+
const bytemanip_1 = require("./bytemanip");
|
|
5
|
+
function readSynchsafeInt32(data, offset) {
|
|
6
|
+
let value = 0;
|
|
7
|
+
let byte;
|
|
8
|
+
[byte, offset] = (0, bytemanip_1.readUint8)(data, offset);
|
|
9
|
+
value |= (byte & 0x7F) << 21;
|
|
10
|
+
[byte, offset] = (0, bytemanip_1.readUint8)(data, offset);
|
|
11
|
+
value |= (byte & 0x7F) << 14;
|
|
12
|
+
[byte, offset] = (0, bytemanip_1.readUint8)(data, offset);
|
|
13
|
+
value |= (byte & 0x7F) << 7;
|
|
14
|
+
[byte, offset] = (0, bytemanip_1.readUint8)(data, offset);
|
|
15
|
+
value |= byte & 0x7F;
|
|
16
|
+
return [value, offset];
|
|
17
|
+
}
|
|
18
|
+
exports.readSynchsafeInt32 = readSynchsafeInt32;
|
|
19
|
+
;
|
|
20
|
+
const textDecoder = new TextDecoder();
|
|
21
|
+
const textEncoder = new TextEncoder();
|
|
22
|
+
function parse(buffer) {
|
|
23
|
+
const data = new DataView(buffer.buffer);
|
|
24
|
+
let offset = 0;
|
|
25
|
+
// Read header
|
|
26
|
+
let bytes;
|
|
27
|
+
[bytes, offset] = (0, bytemanip_1.readBytes)(data, offset, 3);
|
|
28
|
+
if (String.fromCharCode(...bytes) !== 'ea3') {
|
|
29
|
+
throw new Error("Not an ID3v2 tag");
|
|
30
|
+
}
|
|
31
|
+
let major, minor, flags, size;
|
|
32
|
+
[major, offset] = (0, bytemanip_1.readUint8)(data, offset);
|
|
33
|
+
[minor, offset] = (0, bytemanip_1.readUint8)(data, offset);
|
|
34
|
+
[flags, offset] = (0, bytemanip_1.readUint8)(data, offset);
|
|
35
|
+
[size, offset] = readSynchsafeInt32(data, offset);
|
|
36
|
+
const tags = [];
|
|
37
|
+
// Parse frames
|
|
38
|
+
while ((offset + 10) < size + 10) {
|
|
39
|
+
let frameId, frameSize, frameFlags, frameContents;
|
|
40
|
+
[frameId, offset] = (0, bytemanip_1.readBytes)(data, offset, 4);
|
|
41
|
+
[frameSize, offset] = (0, bytemanip_1.readUint32)(data, offset);
|
|
42
|
+
[frameFlags, offset] = (0, bytemanip_1.readUint16)(data, offset);
|
|
43
|
+
[frameContents, offset] = (0, bytemanip_1.readBytes)(data, offset, frameSize);
|
|
44
|
+
// Stop if we encounter padding
|
|
45
|
+
if (frameId[0] === 0) {
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
tags.push({
|
|
49
|
+
id: textDecoder.decode(frameId),
|
|
50
|
+
flags: frameFlags,
|
|
51
|
+
contents: frameContents,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
version: {
|
|
56
|
+
major,
|
|
57
|
+
minor,
|
|
58
|
+
},
|
|
59
|
+
tags,
|
|
60
|
+
flags,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
exports.parse = parse;
|
|
64
|
+
;
|
|
65
|
+
function writeSynchsafeInt32(value) {
|
|
66
|
+
const array = new Uint8Array(4);
|
|
67
|
+
array[0] = (value >> 21) & 0x7f;
|
|
68
|
+
array[1] = (value >> 14) & 0x7f;
|
|
69
|
+
array[2] = (value >> 7) & 0x7f;
|
|
70
|
+
array[3] = value & 0x7f;
|
|
71
|
+
return array;
|
|
72
|
+
}
|
|
73
|
+
;
|
|
74
|
+
function serialize(tags) {
|
|
75
|
+
const header = new Uint8Array(10);
|
|
76
|
+
header.set(textEncoder.encode('ea3'));
|
|
77
|
+
header.set((0, bytemanip_1.writeUint8)(tags.version.major), 3);
|
|
78
|
+
header.set((0, bytemanip_1.writeUint8)(tags.version.minor), 4);
|
|
79
|
+
header.set((0, bytemanip_1.writeUint8)(tags.flags), 5);
|
|
80
|
+
let size = 0;
|
|
81
|
+
const frames = [];
|
|
82
|
+
for (const tag of tags.tags) {
|
|
83
|
+
const frame = new Uint8Array(10 + tag.contents.length);
|
|
84
|
+
if (tag.id.length !== 4)
|
|
85
|
+
throw new Error("Invalid TAG ID length!");
|
|
86
|
+
frame.set(textEncoder.encode(tag.id), 0);
|
|
87
|
+
frame.set((0, bytemanip_1.writeUint32)(tag.contents.length), 4);
|
|
88
|
+
frame.set((0, bytemanip_1.writeUint16)(tag.flags), 8);
|
|
89
|
+
frame.set(tag.contents, 10);
|
|
90
|
+
frames.push(frame);
|
|
91
|
+
size += frame.length;
|
|
92
|
+
}
|
|
93
|
+
if ((size + 10) % 16 !== 0) {
|
|
94
|
+
const diff = 16 - ((size + 10) % 16);
|
|
95
|
+
size += diff;
|
|
96
|
+
}
|
|
97
|
+
header.set(writeSynchsafeInt32(size), 6);
|
|
98
|
+
const result = new Uint8Array(10 + size);
|
|
99
|
+
result.set(header, 0);
|
|
100
|
+
let offset = 10;
|
|
101
|
+
for (const frame of frames) {
|
|
102
|
+
result.set(frame, offset);
|
|
103
|
+
offset += frame.length;
|
|
104
|
+
}
|
|
105
|
+
return result;
|
|
106
|
+
}
|
|
107
|
+
exports.serialize = serialize;
|
|
108
|
+
;
|
|
109
|
+
function encodeUTF16BEStringEA3(source, includeType = true) {
|
|
110
|
+
const rawArr = includeType ? [2] : []; // 2 - marker - UTF16BE
|
|
111
|
+
for (let i = 0; i < source.length; i++) {
|
|
112
|
+
let codePoint = source.charCodeAt(i);
|
|
113
|
+
if (codePoint >= 0xD800 && codePoint <= 0xDBFF) {
|
|
114
|
+
// This is a high surrogate, so we need to get the next character and form the full code point.
|
|
115
|
+
const highSurrogate = codePoint;
|
|
116
|
+
const lowSurrogate = source.charCodeAt(++i);
|
|
117
|
+
if (lowSurrogate < 0xDC00 || lowSurrogate > 0xDFFF) {
|
|
118
|
+
throw new Error("Invalid surrogate pair");
|
|
119
|
+
}
|
|
120
|
+
codePoint = 0x10000 + ((highSurrogate - 0xD800) << 10) + (lowSurrogate - 0xDC00);
|
|
121
|
+
}
|
|
122
|
+
if (codePoint <= 0xFFFF) {
|
|
123
|
+
// Encode as two-byte UTF-16BE
|
|
124
|
+
rawArr.push((codePoint >> 8) & 0xFF, codePoint & 0xFF);
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
// Encode as surrogate pair
|
|
128
|
+
codePoint -= 0x10000;
|
|
129
|
+
const highSurrogate = 0xD800 | (codePoint >> 10);
|
|
130
|
+
const lowSurrogate = 0xDC00 | (codePoint & 0x3FF);
|
|
131
|
+
rawArr.push((highSurrogate >> 8) & 0xFF, highSurrogate & 0xFF);
|
|
132
|
+
rawArr.push((lowSurrogate >> 8) & 0xFF, lowSurrogate & 0xFF);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return new Uint8Array(rawArr);
|
|
136
|
+
}
|
|
137
|
+
exports.encodeUTF16BEStringEA3 = encodeUTF16BEStringEA3;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './filesystem';
|
|
2
|
+
export * from './helpers';
|
|
3
|
+
export * from './bytemanip';
|
|
4
|
+
export * from './databases';
|
|
5
|
+
export * from './database-abstraction';
|
|
6
|
+
export * from './sort';
|
|
7
|
+
export * from './tagged-oma';
|
|
8
|
+
export * from './devices';
|
|
9
|
+
export { importKeys, initCrypto } from './encryption';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,wBAAwB,CAAC;AACvC,cAAc,QAAQ,CAAC;AACvB,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.initCrypto = exports.importKeys = void 0;
|
|
18
|
+
__exportStar(require("./filesystem"), exports);
|
|
19
|
+
__exportStar(require("./helpers"), exports);
|
|
20
|
+
__exportStar(require("./bytemanip"), exports);
|
|
21
|
+
__exportStar(require("./databases"), exports);
|
|
22
|
+
__exportStar(require("./database-abstraction"), exports);
|
|
23
|
+
__exportStar(require("./sort"), exports);
|
|
24
|
+
__exportStar(require("./tagged-oma"), exports);
|
|
25
|
+
__exportStar(require("./devices"), exports);
|
|
26
|
+
var encryption_1 = require("./encryption");
|
|
27
|
+
Object.defineProperty(exports, "importKeys", { enumerable: true, get: function () { return encryption_1.importKeys; } });
|
|
28
|
+
Object.defineProperty(exports, "initCrypto", { enumerable: true, get: function () { return encryption_1.initCrypto; } });
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const INIT_FILE_CONTENTS: {
|
|
2
|
+
"00010021.DAT": Uint8Array;
|
|
3
|
+
"00GTRLST.DAT": Uint8Array;
|
|
4
|
+
"01TREE01.DAT": Uint8Array;
|
|
5
|
+
"01TREE02.DAT": Uint8Array;
|
|
6
|
+
"01TREE03.DAT": Uint8Array;
|
|
7
|
+
"01TREE04.DAT": Uint8Array;
|
|
8
|
+
"02TREINF.DAT": Uint8Array;
|
|
9
|
+
"03GINF01.DAT": Uint8Array;
|
|
10
|
+
"03GINF02.DAT": Uint8Array;
|
|
11
|
+
"03GINF03.DAT": Uint8Array;
|
|
12
|
+
"03GINF04.DAT": Uint8Array;
|
|
13
|
+
"04CNTINF.DAT": Uint8Array;
|
|
14
|
+
"05CHINDC.DAT": Uint8Array;
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=init-data.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init-data.d.ts","sourceRoot":"","sources":["../src/init-data.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;CAc9B,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.INIT_FILE_CONTENTS = void 0;
|
|
4
|
+
exports.INIT_FILE_CONTENTS = {
|
|
5
|
+
"00010021.DAT": new Uint8Array([69, 75, 66, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 33, 0, 0, 0, 0, 117, 235, 254, 220, 201, 194, 217, 63, 114, 198, 213, 235, 134, 217, 169, 116, 248, 95, 111, 33, 222, 191, 41, 17, 0, 0, 0, 12, 0, 0, 0, 32, 0, 0, 0, 52, 164, 146, 65, 95, 128, 0, 0, 0, 0, 0, 0, 0, 18, 163, 225, 187, 118, 162, 176, 132, 191, 20, 46, 122, 172, 121, 207, 233, 240, 92, 183, 254, 222, 60, 148, 1, 120, 74, 113, 141, 159, 247, 244, 177, 0, 0, 0, 5, 1, 0, 0, 0, 1, 0, 0, 40, 49, 194, 220, 160, 49, 239, 65, 172, 233, 23, 239, 231, 77, 180, 222, 111, 60, 32, 165, 189, 50, 161, 207, 18, 140, 212, 9, 192, 107, 206, 87, 138, 206, 145, 95, 175, 136, 43, 92, 84]),
|
|
6
|
+
"00GTRLST.DAT": new Uint8Array([71, 84, 76, 84, 1, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 83, 89, 83, 66, 0, 0, 0, 48, 0, 0, 0, 112, 0, 0, 0, 0, 71, 84, 76, 66, 0, 0, 0, 160, 0, 0, 1, 80, 0, 0, 0, 0, 83, 89, 83, 66, 0, 1, 0, 80, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 84, 76, 66, 0, 4, 0, 80, 0, 0, 0, 4, 3, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 80, 69, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 65, 76, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 67, 79, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]),
|
|
7
|
+
"01TREE01.DAT": new Uint8Array([84, 82, 69, 69, 1, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 71, 80, 76, 66, 0, 0, 0, 48, 0, 0, 0, 16, 0, 0, 0, 0, 84, 80, 76, 66, 0, 0, 0, 64, 0, 0, 0, 16, 0, 0, 0, 0, 71, 80, 76, 66, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 84, 80, 76, 66, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0]),
|
|
8
|
+
"01TREE02.DAT": new Uint8Array([84, 82, 69, 69, 1, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 71, 80, 76, 66, 0, 0, 0, 48, 0, 0, 0, 16, 0, 0, 0, 0, 84, 80, 76, 66, 0, 0, 0, 64, 0, 0, 0, 16, 0, 0, 0, 0, 71, 80, 76, 66, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 84, 80, 76, 66, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0]),
|
|
9
|
+
"01TREE03.DAT": new Uint8Array([84, 82, 69, 69, 1, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 71, 80, 76, 66, 0, 0, 0, 48, 0, 0, 0, 16, 0, 0, 0, 0, 84, 80, 76, 66, 0, 0, 0, 64, 0, 0, 0, 16, 0, 0, 0, 0, 71, 80, 76, 66, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 84, 80, 76, 66, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0]),
|
|
10
|
+
"01TREE04.DAT": new Uint8Array([84, 82, 69, 69, 1, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 71, 80, 76, 66, 0, 0, 0, 48, 0, 0, 0, 16, 0, 0, 0, 0, 84, 80, 76, 66, 0, 0, 0, 64, 0, 0, 0, 16, 0, 0, 0, 0, 71, 80, 76, 66, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 84, 80, 76, 66, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0]),
|
|
11
|
+
"02TREINF.DAT": new Uint8Array([71, 84, 73, 70, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 71, 84, 70, 66, 0, 0, 0, 32, 0, 0, 31, 0, 0, 0, 0, 0, 71, 84, 70, 66, 0, 4, 0, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 128, 84, 73, 84, 50, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 128, 84, 73, 84, 50, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 128, 84, 73, 84, 50, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 128, 84, 73, 84, 50, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]),
|
|
12
|
+
"03GINF01.DAT": new Uint8Array([71, 80, 73, 70, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 71, 80, 70, 66, 0, 0, 0, 32, 0, 0, 0, 16, 0, 0, 0, 0, 71, 80, 70, 66, 0, 0, 3, 16, 0, 0, 0, 0, 0, 0, 0, 0]),
|
|
13
|
+
"03GINF02.DAT": new Uint8Array([71, 80, 73, 70, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 71, 80, 70, 66, 0, 0, 0, 32, 0, 0, 0, 16, 0, 0, 0, 0, 71, 80, 70, 66, 0, 0, 0, 144, 0, 0, 0, 0, 0, 0, 0, 0]),
|
|
14
|
+
"03GINF03.DAT": new Uint8Array([71, 80, 73, 70, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 71, 80, 70, 66, 0, 0, 0, 32, 0, 0, 0, 16, 0, 0, 0, 0, 71, 80, 70, 66, 0, 0, 0, 144, 0, 0, 0, 0, 0, 0, 0, 0]),
|
|
15
|
+
"03GINF04.DAT": new Uint8Array([71, 80, 73, 70, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 71, 80, 70, 66, 0, 0, 0, 32, 0, 0, 0, 16, 0, 0, 0, 0, 71, 80, 70, 66, 0, 0, 0, 144, 0, 0, 0, 0, 0, 0, 0, 0]),
|
|
16
|
+
"04CNTINF.DAT": new Uint8Array([67, 78, 73, 70, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 67, 78, 70, 66, 0, 0, 0, 32, 0, 0, 0, 16, 0, 0, 0, 0, 67, 78, 70, 66, 0, 0, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0]),
|
|
17
|
+
"05CHINDC.DAT": new Uint8Array([67, 72, 73, 68, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 67, 73, 68, 66, 0, 0, 0, 32, 0, 0, 0, 16, 0, 0, 0, 0, 67, 73, 68, 66, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0]),
|
|
18
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"initialization.d.ts","sourceRoot":"","sources":["../src/initialization.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAIzC,wBAAsB,YAAY,CAAC,UAAU,EAAE,cAAc,iBAgB5D;AAED,wBAAsB,kBAAkB,CAAC,UAAU,EAAE,cAAc,iBAMlE"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// This file's job is to create the initial structures required to get a brand new (or formatted)
|
|
3
|
+
// Sony NW to work.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.initializeIfNeeded = exports.initializeNW = void 0;
|
|
6
|
+
const init_data_1 = require("./init-data");
|
|
7
|
+
async function initializeNW(filesystem) {
|
|
8
|
+
// mkdir the root dir
|
|
9
|
+
await filesystem.mkdir("/OMGAUDIO");
|
|
10
|
+
console.log("Initializing the walkman...");
|
|
11
|
+
for (let [name, contents] of Object.entries(init_data_1.INIT_FILE_CONTENTS)) {
|
|
12
|
+
console.log(`Initializing ${name}...`);
|
|
13
|
+
const file = await filesystem.open(`/OMGAUDIO/${name}`, 'rw');
|
|
14
|
+
await file.write(contents);
|
|
15
|
+
await file.close();
|
|
16
|
+
}
|
|
17
|
+
console.log(`Initializing audio store...`);
|
|
18
|
+
await filesystem.mkdir("/OMGAUDIO/10F00");
|
|
19
|
+
const maclist = await filesystem.open("/OMGAUDIO/MACLIST0.DAT", 'rw');
|
|
20
|
+
await maclist.write(new Uint8Array(32768).fill(0));
|
|
21
|
+
await maclist.close();
|
|
22
|
+
console.log(`Initializing complete!`);
|
|
23
|
+
}
|
|
24
|
+
exports.initializeNW = initializeNW;
|
|
25
|
+
async function initializeIfNeeded(filesystem) {
|
|
26
|
+
const rootContents = await filesystem.list("/");
|
|
27
|
+
if (!rootContents.find(e => e.type === 'directory' && e.name === '/OMGAUDIO')) {
|
|
28
|
+
// This is an uninitialized NW.
|
|
29
|
+
await initializeNW(filesystem);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.initializeIfNeeded = initializeIfNeeded;
|
package/dist/sort.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare type ComplexSortGroupedResult<T> = T[] | {
|
|
2
|
+
name: string;
|
|
3
|
+
contents: ComplexSortGroupedResult<T>;
|
|
4
|
+
__complexSortGroupedResult: 1;
|
|
5
|
+
}[];
|
|
6
|
+
export declare type ComplexSortFormatPart = {
|
|
7
|
+
var: string;
|
|
8
|
+
} | {
|
|
9
|
+
literal: string;
|
|
10
|
+
};
|
|
11
|
+
export declare function complexSort<T>(format: ComplexSortFormatPart[][], data: T[]): ComplexSortGroupedResult<T>;
|
|
12
|
+
export declare function flatten<T>(data: ComplexSortGroupedResult<T>): T[];
|
|
13
|
+
//# sourceMappingURL=sort.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sort.d.ts","sourceRoot":"","sources":["../src/sort.ts"],"names":[],"mappings":"AAAA,oBAAY,wBAAwB,CAAC,CAAC,IAClC,CAAC,EAAE,GACH;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,wBAAwB,CAAC,CAAC,CAAC,CAAC;IAAC,0BAA0B,EAAE,CAAC,CAAA;CAAE,EAAE,CAAC;AAE7F,oBAAY,qBAAqB,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1E,wBAAgB,WAAW,CAAC,CAAC,EACzB,MAAM,EAAE,qBAAqB,EAAE,EAAE,EACjC,IAAI,EAAE,CAAC,EAAE,GACV,wBAAwB,CAAC,CAAC,CAAC,CAwC7B;AAED,wBAAgB,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,wBAAwB,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAcjE"}
|
package/dist/sort.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.flatten = exports.complexSort = void 0;
|
|
4
|
+
function complexSort(format, data) {
|
|
5
|
+
function createFieldForFormat(format, entry) {
|
|
6
|
+
let str = "";
|
|
7
|
+
let vars = [];
|
|
8
|
+
for (let e of format) {
|
|
9
|
+
if (e.var) {
|
|
10
|
+
let v = entry[e.var];
|
|
11
|
+
if (typeof v === 'number') {
|
|
12
|
+
v = v.toString().padStart(5, '0');
|
|
13
|
+
}
|
|
14
|
+
str += v;
|
|
15
|
+
vars.push(v);
|
|
16
|
+
}
|
|
17
|
+
else if (e.literal) {
|
|
18
|
+
str += e.literal;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return [str, vars];
|
|
22
|
+
}
|
|
23
|
+
const formatEntry = format[0];
|
|
24
|
+
if (format.length === 1) {
|
|
25
|
+
// This is the last fragment. Simply compute it
|
|
26
|
+
return [...data].sort((a, b) => createFieldForFormat(formatEntry, a)[0].localeCompare(createFieldForFormat(formatEntry, b)[0]));
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
// Take the first format, create groups, then recurse
|
|
30
|
+
const nextFormat = format.slice(1);
|
|
31
|
+
const formatCompliance = formatEntry.filter((e) => e.var).map((e) => e.var);
|
|
32
|
+
return data
|
|
33
|
+
.map(e => createFieldForFormat(formatEntry, e))
|
|
34
|
+
.sort((a, b) => a[0].localeCompare(b[0]))
|
|
35
|
+
.reduce((p, c) => (!p.some(e => e[1].every((z, i) => c[1][i] === z)) ? [...p, c] : p), [])
|
|
36
|
+
.map(e => ({
|
|
37
|
+
__complexSortGroupedResult: 1,
|
|
38
|
+
name: e[0],
|
|
39
|
+
contents: complexSort(nextFormat, data.filter((z) => formatCompliance
|
|
40
|
+
.map(q => z[q])
|
|
41
|
+
.every((f, i) => f === e[1][i])))
|
|
42
|
+
}));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.complexSort = complexSort;
|
|
46
|
+
function flatten(data) {
|
|
47
|
+
let finalArray = [];
|
|
48
|
+
if (!data.length)
|
|
49
|
+
return finalArray;
|
|
50
|
+
if (data[0].__complexSortGroupedResult == 1) {
|
|
51
|
+
// This is a nested result
|
|
52
|
+
for (let subContent of data) {
|
|
53
|
+
finalArray.push(...flatten(subContent.contents));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
// Normal
|
|
58
|
+
finalArray.push(...data);
|
|
59
|
+
}
|
|
60
|
+
return finalArray;
|
|
61
|
+
}
|
|
62
|
+
exports.flatten = flatten;
|
package/dist/tables.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface TableClassDefinition {
|
|
2
|
+
className: string;
|
|
3
|
+
startAddress: number;
|
|
4
|
+
classLength: number;
|
|
5
|
+
}
|
|
6
|
+
export interface TableClassContents {
|
|
7
|
+
className: string;
|
|
8
|
+
oneElementLength: number;
|
|
9
|
+
elements: Uint8Array[];
|
|
10
|
+
startAddress: number;
|
|
11
|
+
}
|
|
12
|
+
export interface TableFile {
|
|
13
|
+
name: string;
|
|
14
|
+
classes: TableClassDefinition[];
|
|
15
|
+
contents: TableClassContents[];
|
|
16
|
+
}
|
|
17
|
+
export declare function parseTable(tableFileContents: Uint8Array): TableFile;
|
|
18
|
+
export declare function serializeTable(tableFile: TableFile, writeSecondLength?: boolean): Uint8Array;
|
|
19
|
+
//# sourceMappingURL=tables.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tables.d.ts","sourceRoot":"","sources":["../src/tables.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,oBAAoB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,SAAS;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,oBAAoB,EAAE,CAAC;IAChC,QAAQ,EAAE,kBAAkB,EAAE,CAAA;CACjC;AAED,wBAAgB,UAAU,CAAC,iBAAiB,EAAE,UAAU,GAAG,SAAS,CA0CnE;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,SAAS,EAAE,iBAAiB,UAAO,GAAG,UAAU,CAoDzF"}
|
package/dist/tables.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.serializeTable = exports.parseTable = void 0;
|
|
4
|
+
const bytemanip_1 = require("./bytemanip");
|
|
5
|
+
const utils_1 = require("./utils");
|
|
6
|
+
function parseTable(tableFileContents) {
|
|
7
|
+
const dataView = new DataView(tableFileContents.buffer);
|
|
8
|
+
let offset = 0;
|
|
9
|
+
// Now in root:
|
|
10
|
+
let tableName, constant01010000, classDefinitionCount;
|
|
11
|
+
[tableName, offset] = (0, bytemanip_1.readString)(dataView, offset, 4);
|
|
12
|
+
[constant01010000, offset] = (0, bytemanip_1.readBytes)(dataView, offset, 4);
|
|
13
|
+
(0, utils_1.assert)((0, utils_1.arrayEq)(new Uint8Array([0x01, 0x01, 0x00, 0x00]), constant01010000));
|
|
14
|
+
[classDefinitionCount, offset] = (0, bytemanip_1.readUint8)(dataView, offset);
|
|
15
|
+
offset = (0, bytemanip_1.align)(offset, 0x10);
|
|
16
|
+
// Now in class definitions:
|
|
17
|
+
const classDefinitions = [];
|
|
18
|
+
const classContents = [];
|
|
19
|
+
for (let i = 0; i < classDefinitionCount; i++) {
|
|
20
|
+
let className, startAddress, classLength;
|
|
21
|
+
[className, offset] = (0, bytemanip_1.readString)(dataView, offset, 4);
|
|
22
|
+
[startAddress, offset] = (0, bytemanip_1.readUint32)(dataView, offset);
|
|
23
|
+
[classLength, offset] = (0, bytemanip_1.readUint32)(dataView, offset);
|
|
24
|
+
offset = (0, bytemanip_1.align)(offset, 0x10);
|
|
25
|
+
classDefinitions.push({ classLength, className, startAddress });
|
|
26
|
+
}
|
|
27
|
+
// Now read every definition. Seek to start address.
|
|
28
|
+
for (let definition of classDefinitions) {
|
|
29
|
+
offset = definition.startAddress;
|
|
30
|
+
let className, elementsCount, elementLength, elementsCount2;
|
|
31
|
+
const elements = [];
|
|
32
|
+
[className, offset] = (0, bytemanip_1.readString)(dataView, offset, 4);
|
|
33
|
+
[elementsCount, offset] = (0, bytemanip_1.readUint16)(dataView, offset);
|
|
34
|
+
[elementLength, offset] = (0, bytemanip_1.readUint16)(dataView, offset);
|
|
35
|
+
offset += 2;
|
|
36
|
+
[elementsCount2, offset] = (0, bytemanip_1.readUint16)(dataView, offset);
|
|
37
|
+
offset = (0, bytemanip_1.align)(offset, 0x10);
|
|
38
|
+
// assert(elementsCount2 == elementsCount);
|
|
39
|
+
for (let i = 0; i < elementsCount; i++) {
|
|
40
|
+
let element;
|
|
41
|
+
[element, offset] = (0, bytemanip_1.readBytes)(dataView, offset, elementLength);
|
|
42
|
+
elements.push(element);
|
|
43
|
+
}
|
|
44
|
+
classContents.push({ startAddress: definition.startAddress, className, oneElementLength: elementLength, elements });
|
|
45
|
+
}
|
|
46
|
+
return { classes: classDefinitions, contents: classContents, name: tableName };
|
|
47
|
+
}
|
|
48
|
+
exports.parseTable = parseTable;
|
|
49
|
+
function serializeTable(tableFile, writeSecondLength = true) {
|
|
50
|
+
const textEncoder = new TextEncoder();
|
|
51
|
+
// Recalculate lengths and starting addresses.
|
|
52
|
+
for (let i = 0; i < tableFile.classes.length; i++) {
|
|
53
|
+
// Calculate real length
|
|
54
|
+
let contentLength = tableFile.contents[i].elements.length * tableFile.contents[i].oneElementLength + 0x10; // 0x10 for the content header.
|
|
55
|
+
if (contentLength % 16 !== 0) {
|
|
56
|
+
contentLength += 16 - (contentLength % 16);
|
|
57
|
+
}
|
|
58
|
+
if (tableFile.classes[i].classLength < contentLength) {
|
|
59
|
+
let difference = contentLength - tableFile.classes[i].classLength;
|
|
60
|
+
tableFile.classes[i].classLength = contentLength;
|
|
61
|
+
for (let j = i + 1; j < tableFile.classes.length; j++) {
|
|
62
|
+
tableFile.classes[j].startAddress += difference;
|
|
63
|
+
tableFile.contents[j].startAddress += difference;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const size = Math.max.apply(null, tableFile.classes.map(e => e.startAddress + e.classLength));
|
|
68
|
+
const data = new Uint8Array(size).fill(0);
|
|
69
|
+
// Serialize the main header.
|
|
70
|
+
data.set(textEncoder.encode(tableFile.name), 0);
|
|
71
|
+
data.set(new Uint8Array([0x01, 0x01, 0x00, 0x00]), 4);
|
|
72
|
+
data[8] = tableFile.classes.length;
|
|
73
|
+
let offset = 0x10;
|
|
74
|
+
// Write all class definitions.
|
|
75
|
+
for (let classDef of tableFile.classes) {
|
|
76
|
+
data.set(textEncoder.encode(classDef.className), offset);
|
|
77
|
+
offset += 4;
|
|
78
|
+
data.set((0, bytemanip_1.writeUint32)(classDef.startAddress), offset);
|
|
79
|
+
offset += 4;
|
|
80
|
+
data.set((0, bytemanip_1.writeUint32)(classDef.classLength), offset);
|
|
81
|
+
offset += 8;
|
|
82
|
+
}
|
|
83
|
+
for (let classContent of tableFile.contents) {
|
|
84
|
+
offset = classContent.startAddress;
|
|
85
|
+
data.set(textEncoder.encode(classContent.className), offset);
|
|
86
|
+
offset += 4;
|
|
87
|
+
data.set((0, bytemanip_1.writeUint16)(classContent.elements.length), offset);
|
|
88
|
+
offset += 2;
|
|
89
|
+
data.set((0, bytemanip_1.writeUint16)(classContent.oneElementLength), offset);
|
|
90
|
+
offset += 4;
|
|
91
|
+
if (writeSecondLength)
|
|
92
|
+
data.set((0, bytemanip_1.writeUint16)(classContent.elements.length), offset);
|
|
93
|
+
offset += 6;
|
|
94
|
+
for (let e of classContent.elements) {
|
|
95
|
+
data.set(e, offset);
|
|
96
|
+
offset += e.length;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return data;
|
|
100
|
+
}
|
|
101
|
+
exports.serializeTable = serializeTable;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { HiMDCodec, HiMDFile } from "himd-js";
|
|
2
|
+
import { TrackMetadata } from './databases';
|
|
3
|
+
export declare function createTaggedEncryptedOMA(rawData: Uint8Array, titleInfo: TrackMetadata, codec: {
|
|
4
|
+
codecId: HiMDCodec;
|
|
5
|
+
codecInfo: Uint8Array;
|
|
6
|
+
}): {
|
|
7
|
+
data: Uint8Array;
|
|
8
|
+
maclistValue: Uint8Array;
|
|
9
|
+
duration: number;
|
|
10
|
+
};
|
|
11
|
+
export declare function updateMetadata(file: HiMDFile, titleInfo: TrackMetadata): Promise<void>;
|
|
12
|
+
//# sourceMappingURL=tagged-oma.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tagged-oma.d.ts","sourceRoot":"","sources":["../src/tagged-oma.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgC,SAAS,EAAE,QAAQ,EAAuB,MAAM,SAAS,CAAC;AAIjG,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAmH5C,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,KAAK,EAAE;IAAC,OAAO,EAAE,SAAS,CAAC;IAAC,SAAS,EAAE,UAAU,CAAA;CAAC;;;;EAczI;AAeD,wBAAsB,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,aAAa,iBAuC5E"}
|