brs-js 2.0.0 → 2.0.3
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 +1 -1
- package/debug/Conf Spacestation.brs +0 -0
- package/debug/Electrks_Feminine_Challenge.brs +0 -0
- package/debug/a5bricks.brs +0 -0
- package/debug/a5p2.2.brs +0 -0
- package/debug/a5p2.brs +0 -0
- package/debug/audio.brs +0 -0
- package/debug/brick a5.brs +0 -0
- package/debug/brick qa.brs +0 -0
- package/debug/brsv10.brs +0 -0
- package/debug/brsv10brick.brs +0 -0
- package/debug/bruteforce.js +254 -0
- package/debug/clone.html +36 -0
- package/debug/ctf_tileset.brs +0 -0
- package/debug/ctf_tileset_5.brs +0 -0
- package/debug/evil.brs +0 -0
- package/debug/evilwrite.js +390 -0
- package/debug/foo.txt +3080 -0
- package/debug/kenko_big.brs +0 -0
- package/debug/light.brs +0 -0
- package/debug/out.json +105 -0
- package/debug/read.js +30 -0
- package/debug/readSpeed.js +32 -0
- package/debug/readTest.js +45 -0
- package/debug/temp.brs +0 -0
- package/debug/western.brs +0 -0
- package/dist/dist.js +1 -1
- package/dist/dist.node.js +1 -1
- package/dist/dist.web.js +1 -1
- package/dist/src/constants.d.ts +1 -0
- package/dist/src/constants.d.ts.map +1 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/read.d.ts +1 -0
- package/dist/src/read.d.ts.map +1 -0
- package/dist/src/read.v1.d.ts +1 -0
- package/dist/src/read.v1.d.ts.map +1 -0
- package/dist/src/read.v10.d.ts +1 -0
- package/dist/src/read.v10.d.ts.map +1 -0
- package/dist/src/read.v2.d.ts +1 -0
- package/dist/src/read.v2.d.ts.map +1 -0
- package/dist/src/read.v3.d.ts +1 -0
- package/dist/src/read.v3.d.ts.map +1 -0
- package/dist/src/read.v4.d.ts +1 -0
- package/dist/src/read.v4.d.ts.map +1 -0
- package/dist/src/read.v8.d.ts +1 -0
- package/dist/src/read.v8.d.ts.map +1 -0
- package/dist/src/read.v9.d.ts +1 -0
- package/dist/src/read.v9.d.ts.map +1 -0
- package/dist/src/types.d.ts +1 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/utils.d.ts +2 -1
- package/dist/src/utils.d.ts.map +1 -0
- package/dist/src/uuid.d.ts +1 -0
- package/dist/src/uuid.d.ts.map +1 -0
- package/dist/src/write.d.ts +1 -0
- package/dist/src/write.d.ts.map +1 -0
- package/examples/ATCFort.brs +0 -0
- package/examples/read_example.html +34 -0
- package/examples/read_example.js +21 -0
- package/examples/write_example.js +25 -0
- package/examples/write_planet.html +144 -0
- package/examples/write_simplex.html +82 -0
- package/examples/write_wedge_sphere.html +173 -0
- package/package.json +4 -3
- package/src/index.ts +1 -0
- package/src/utils.ts +2 -3
- package/test/lib.test.js +1 -1
- package/test/utils.test.js +37 -21
- package/tsconfig.json +6 -2
- package/webpack.config.js +42 -31
- package/.vscode/extensions.json +0 -5
package/README.md
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/debug/a5p2.2.brs
ADDED
|
Binary file
|
package/debug/a5p2.brs
ADDED
|
Binary file
|
package/debug/audio.brs
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/debug/brsv10.brs
ADDED
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
|
|
3
|
+
const {utils: {read, isEqual}, constants: {MAGIC}} = require('../dist/dist.node.js');
|
|
4
|
+
|
|
5
|
+
// arg parsing
|
|
6
|
+
const file = process.argv.find(f => f.endsWith('brs'));
|
|
7
|
+
if (!file) {
|
|
8
|
+
console.error('missing save argument');
|
|
9
|
+
process.exit(1);
|
|
10
|
+
}
|
|
11
|
+
if (!fs.existsSync(file)) {
|
|
12
|
+
console.error('file does not exist');
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// read the file
|
|
17
|
+
const data = Array.from(fs.readFileSync(file));
|
|
18
|
+
const copyData = () => data.slice();
|
|
19
|
+
|
|
20
|
+
const bgra = ([b, g, r, a]) => [r, g, b, a];
|
|
21
|
+
const PNG_MAGIC = [137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82];
|
|
22
|
+
let quiet = false;
|
|
23
|
+
|
|
24
|
+
function tryRead(data, type, fn, results) {
|
|
25
|
+
try {
|
|
26
|
+
if (typeof type === 'function')
|
|
27
|
+
return type(data, results);
|
|
28
|
+
|
|
29
|
+
switch(type) {
|
|
30
|
+
case 'magic': return isEqual(data.splice(0, MAGIC.length), MAGIC);
|
|
31
|
+
case 'pngmagic': return isEqual(data.splice(0, PNG_MAGIC.length), PNG_MAGIC);
|
|
32
|
+
case 'compressed': return read.compressed(data);
|
|
33
|
+
case 'compressed.array': return read.array(read.compressed(data), data => fn(data, results));
|
|
34
|
+
case 'string': return read.string(data);
|
|
35
|
+
case 'uuid': return read.uuid(data);
|
|
36
|
+
case 'byte': return data.splice(0, 1)[0];
|
|
37
|
+
case 'u16': return read.u16(data);
|
|
38
|
+
case 'i32': return read.i32(data);
|
|
39
|
+
case 'time': return data.splice(0, 8);
|
|
40
|
+
case 'word': return data.splice(0, 4);
|
|
41
|
+
case 'bits': return read.bits(data);
|
|
42
|
+
case 'array': return read.array(data, data => fn(data, results));
|
|
43
|
+
case 'rest': return data.splice(0, data.length);
|
|
44
|
+
case 'bricks':
|
|
45
|
+
const brickData = read.compressed(data);
|
|
46
|
+
// console.log(brickData.map(d => d.toString(2).padStart(8, '0')).join(''));
|
|
47
|
+
const brickBits = read.bits(brickData);
|
|
48
|
+
const bricks = [];
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
while(!brickBits.empty() && bricks.length < results.header1.brickCount) {
|
|
52
|
+
brickBits.align();
|
|
53
|
+
const start = brickBits.pos;
|
|
54
|
+
const brick = fn(brickBits, results);
|
|
55
|
+
brick.bitsize = (brickBits.pos - start);
|
|
56
|
+
bricks.push(brick);
|
|
57
|
+
}
|
|
58
|
+
} catch (e) {
|
|
59
|
+
console.error(e)
|
|
60
|
+
return bricks;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return bricks;
|
|
64
|
+
}
|
|
65
|
+
} catch (e) {
|
|
66
|
+
console.log(e);
|
|
67
|
+
return ';;badvalue;;';
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function bruteforce(data, steps, indent=0) {
|
|
72
|
+
let i = 0;
|
|
73
|
+
const results = {};
|
|
74
|
+
for (let step of steps) {
|
|
75
|
+
i ++;
|
|
76
|
+
|
|
77
|
+
// convert string and arrays into objects
|
|
78
|
+
if (typeof step === 'string')
|
|
79
|
+
step = {name: step, bin: false, type: step};
|
|
80
|
+
if (typeof step === 'object' && typeof step.length === 'number')
|
|
81
|
+
step = {name: 'scan', attempt: step};
|
|
82
|
+
|
|
83
|
+
// check if ther's any data left
|
|
84
|
+
if (data.length === 0) {
|
|
85
|
+
if(!quiet) console.log(''.padStart(indent * 2, ' '), i, ')', step.name || '?', '[no bytes left]');
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
let type = step.type;
|
|
90
|
+
|
|
91
|
+
// if this is a conditional step, assign the next steps based on this one
|
|
92
|
+
if (step.test) {
|
|
93
|
+
const test = step.test(tryRead(data, step.type));
|
|
94
|
+
if(!quiet) console.log(''.padStart(indent * 2, ' '), i, '-', step.name || '?', 'test', test);
|
|
95
|
+
step.contains = test ? step.yes : step.no;
|
|
96
|
+
step.type = 'rest';
|
|
97
|
+
} else if (!type) {
|
|
98
|
+
// scan for a matching type
|
|
99
|
+
type = step.attempt.find(t => tryRead(data.slice(), typeof t === 'object' ? t.name : t, t.fn) !== ';;badvalue;;');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
const val = step.test ? 'test' : tryRead(data, type, step.fn, results);
|
|
104
|
+
if(!quiet) console.log(''.padStart(indent * 2, '.'), i, ')', step.name || '?', '=', step.bin ? val.length + ' bytes' : val);
|
|
105
|
+
results[step.name] = step.contains
|
|
106
|
+
? bruteforce(step.test ? data : val, step.contains, indent+1, results)
|
|
107
|
+
: val;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return results;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const go = (before, after) => bruteforce(copyData(), [
|
|
114
|
+
{name: 'BRS', type: 'magic'},
|
|
115
|
+
{name: 'version', type: 'u16'},
|
|
116
|
+
{name: 'game version', type: 'i32'},
|
|
117
|
+
{
|
|
118
|
+
name: 'header1', type: 'compressed', bin: true,
|
|
119
|
+
contains: [
|
|
120
|
+
{name: 'map', type: 'string'},
|
|
121
|
+
{name: 'saverName', type: 'string'},
|
|
122
|
+
{name: 'description', type: 'string'},
|
|
123
|
+
{name: 'saverId', type: 'uuid'},
|
|
124
|
+
{name: 'hostName', type: 'string'},
|
|
125
|
+
{name: 'hostId', type: 'uuid'},
|
|
126
|
+
{name: 'saveDate', type: 'time'},
|
|
127
|
+
{name: 'brickCount', type: 'i32'},
|
|
128
|
+
],
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
name: 'header2', type: 'compressed', bin: true,
|
|
132
|
+
contains: [
|
|
133
|
+
{name: 'mods', type: 'array', fn: read.string},
|
|
134
|
+
{name: 'assets', type: 'array', fn: read.string},
|
|
135
|
+
{name: 'colors', type: 'array', fn: data => bgra(data.splice(0, 4))},
|
|
136
|
+
{name: 'materials', type: 'array', fn: read.string},
|
|
137
|
+
{name: 'owners', type: 'array', fn: data => ({
|
|
138
|
+
id: read.uuid(data),
|
|
139
|
+
name: read.string(data),
|
|
140
|
+
count: read.i32(data)
|
|
141
|
+
})},
|
|
142
|
+
],
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
name: 'preview',
|
|
146
|
+
test: v => v, type: 'byte',
|
|
147
|
+
yes: [
|
|
148
|
+
{name: 'data', type: data => {
|
|
149
|
+
const len = read.i32(data);
|
|
150
|
+
const png = data.splice(0, len);
|
|
151
|
+
return len + ' bytes';
|
|
152
|
+
}},
|
|
153
|
+
],
|
|
154
|
+
no: [],
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
name: 'bricks',
|
|
158
|
+
type: 'bricks',
|
|
159
|
+
fn: (bits, parent) => ({
|
|
160
|
+
asset_index: bits.int(Math.max(parent.header2.assets.length, 2)),
|
|
161
|
+
size: bits.bit() ? [bits.uint_packed(), bits.uint_packed(), bits.uint_packed()] : [0, 0, 0],
|
|
162
|
+
position: [bits.int_packed(), bits.int_packed(), bits.int_packed()],
|
|
163
|
+
...(orientation => ({
|
|
164
|
+
direction: (orientation >> 2) % 6,
|
|
165
|
+
rotation: orientation & 3,
|
|
166
|
+
}))(bits.int(24)),
|
|
167
|
+
collision: bits.bit(),
|
|
168
|
+
visibility: bits.bit(),
|
|
169
|
+
material_index: bits.bit() ? bits.uint_packed() : 1,
|
|
170
|
+
// material_index: bits.int(Math.max(parent.header2.materials.length, 2)),
|
|
171
|
+
color: bits.bit() ? bgra(bits.bytes(4)) : bits.int(parent.header2.colors.length),
|
|
172
|
+
owner_index: bits.uint_packed(true),
|
|
173
|
+
}),
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
name: 'components', type: 'compressed.array', fn: (data, parent) => {
|
|
177
|
+
const name = read.string(data);
|
|
178
|
+
const bits = read.bits(data.splice(0, read.i32(data)));
|
|
179
|
+
const version = read.i32(bits.bytes(4));
|
|
180
|
+
const brick_indices = bits.array(() => bits.int(Math.max(parent.header1.brickCount, 2)));
|
|
181
|
+
const properties = bits.array(() => [bits.string(), bits.string()]);
|
|
182
|
+
|
|
183
|
+
const bricks = brick_indices.map(i => ({
|
|
184
|
+
index: i,
|
|
185
|
+
props: Object.fromEntries(properties.map(([name, type]) => {
|
|
186
|
+
let val;
|
|
187
|
+
switch(type) {
|
|
188
|
+
case 'Class':
|
|
189
|
+
val = bits.string();
|
|
190
|
+
break;
|
|
191
|
+
case 'Boolean':
|
|
192
|
+
val = !!read.i32(bits.bytes(4));
|
|
193
|
+
break;
|
|
194
|
+
case 'Float':
|
|
195
|
+
val = bits.float();
|
|
196
|
+
break;
|
|
197
|
+
case 'Color':
|
|
198
|
+
val = bgra(bits.bytes(4));
|
|
199
|
+
break;
|
|
200
|
+
case 'Rotator':
|
|
201
|
+
val = [bits.float(), bits.float(), bits.float()];
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
204
|
+
return [name, val];
|
|
205
|
+
})),
|
|
206
|
+
}));
|
|
207
|
+
return {
|
|
208
|
+
name,
|
|
209
|
+
version,
|
|
210
|
+
brick_indices,
|
|
211
|
+
properties: Object.fromEntries(properties),
|
|
212
|
+
bricks,
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
]);
|
|
217
|
+
|
|
218
|
+
/*
|
|
219
|
+
for each component type used in the build, it will
|
|
220
|
+
write the component type name [done]
|
|
221
|
+
write the version [done]
|
|
222
|
+
write an array of brick indices to attach to [done]
|
|
223
|
+
write the data layout
|
|
224
|
+
write an array of property infos
|
|
225
|
+
write the name of the property
|
|
226
|
+
write the type of the property
|
|
227
|
+
write the size of the following data section
|
|
228
|
+
write the data
|
|
229
|
+
write each component instance
|
|
230
|
+
write each property
|
|
231
|
+
|
|
232
|
+
*/
|
|
233
|
+
|
|
234
|
+
// console.log(go(1).bricks.bricks.slice(0, 2))
|
|
235
|
+
|
|
236
|
+
quiet = true;
|
|
237
|
+
for (let before = 0; before < 1; before++) {
|
|
238
|
+
for (let after = 0; after < 1; after++) {
|
|
239
|
+
const res = go(before, after);
|
|
240
|
+
// return;
|
|
241
|
+
// const colorOk = res.bricks.every(b => b.color === 0);
|
|
242
|
+
const bricksOk = res.bricks.length === res.header1.brickCount && res.bricks.every(b => b.owner_index <= res.header2.owners.length );
|
|
243
|
+
// const ownerOk = res.bricks.some(b => b.owner_index !== 1) && res.bricks.some(b => b.owner_index === 0);
|
|
244
|
+
// const materialOk = res.bricks.every(b => b.color === 0);
|
|
245
|
+
if (true) {
|
|
246
|
+
const bin = arr => arr.map(a => a?'1':'0').join('');
|
|
247
|
+
res.components.map(c => console.log(c, ...c.bricks))
|
|
248
|
+
console.log(
|
|
249
|
+
res,
|
|
250
|
+
{bricks: res.bricks.length, before, after},
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
package/debug/clone.html
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<script src="../dist/dist.js"></script>
|
|
3
|
+
|
|
4
|
+
<!-- Files uploaded will be -->
|
|
5
|
+
<input id="fileInput" type="file">
|
|
6
|
+
|
|
7
|
+
<a id="anchor" download="cloned.brs">Download</a>
|
|
8
|
+
|
|
9
|
+
<!-- This will be filled with the save object as JSON or the error message -->
|
|
10
|
+
<pre id="jsonElem"></pre>
|
|
11
|
+
|
|
12
|
+
<script>
|
|
13
|
+
fileInput.addEventListener('change', e => {
|
|
14
|
+
const file = e.target.files[0];
|
|
15
|
+
if (file) {
|
|
16
|
+
// Read the file into a byte array
|
|
17
|
+
file.arrayBuffer()
|
|
18
|
+
.then(buff => {
|
|
19
|
+
const save = BRS.read(buff);
|
|
20
|
+
|
|
21
|
+
// Log the save object
|
|
22
|
+
console.log(save);
|
|
23
|
+
|
|
24
|
+
// Render the save object as formatted JSON
|
|
25
|
+
jsonElem.innerText = '';
|
|
26
|
+
|
|
27
|
+
const blob = new Blob([new Uint8Array(BRS.write(save))]);
|
|
28
|
+
anchor.href = URL.createObjectURL(blob);
|
|
29
|
+
})
|
|
30
|
+
.catch(err => {
|
|
31
|
+
// Display the error
|
|
32
|
+
jsonElem.innerText = 'Error: ' + err.message;
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
</script>
|
|
Binary file
|
|
Binary file
|
package/debug/evil.brs
ADDED
|
Binary file
|