@modplayjs/fmt-prowizard 0.0.0-stage → 0.2.1
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 +42 -2
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/prowiz.d.ts +44 -0
- package/dist/prowiz.d.ts.map +1 -0
- package/dist/prowiz.js +157 -0
- package/dist/prowiz.js.map +1 -0
- package/dist/ptktable.d.ts +5 -0
- package/dist/ptktable.d.ts.map +1 -0
- package/dist/ptktable.js +49 -0
- package/dist/ptktable.js.map +1 -0
- package/dist/pw-ac1d.d.ts +4 -0
- package/dist/pw-ac1d.d.ts.map +1 -0
- package/dist/pw-ac1d.js +133 -0
- package/dist/pw-ac1d.js.map +1 -0
- package/dist/pw-di.d.ts +4 -0
- package/dist/pw-di.d.ts.map +1 -0
- package/dist/pw-di.js +177 -0
- package/dist/pw-di.js.map +1 -0
- package/dist/pw-eureka.d.ts +4 -0
- package/dist/pw-eureka.d.ts.map +1 -0
- package/dist/pw-eureka.js +171 -0
- package/dist/pw-eureka.js.map +1 -0
- package/dist/pw-fcm.d.ts +4 -0
- package/dist/pw-fcm.d.ts.map +1 -0
- package/dist/pw-fcm.js +102 -0
- package/dist/pw-fcm.js.map +1 -0
- package/dist/pw-fuchs.d.ts +4 -0
- package/dist/pw-fuchs.d.ts.map +1 -0
- package/dist/pw-fuchs.js +139 -0
- package/dist/pw-fuchs.js.map +1 -0
- package/dist/pw-heatseek.d.ts +4 -0
- package/dist/pw-heatseek.d.ts.map +1 -0
- package/dist/pw-heatseek.js +197 -0
- package/dist/pw-heatseek.js.map +1 -0
- package/dist/pw-hrt.d.ts +4 -0
- package/dist/pw-hrt.d.ts.map +1 -0
- package/dist/pw-hrt.js +104 -0
- package/dist/pw-hrt.js.map +1 -0
- package/dist/pw-ksm.d.ts +4 -0
- package/dist/pw-ksm.d.ts.map +1 -0
- package/dist/pw-ksm.js +212 -0
- package/dist/pw-ksm.js.map +1 -0
- package/dist/pw-mp.d.ts +6 -0
- package/dist/pw-mp.d.ts.map +1 -0
- package/dist/pw-mp.js +171 -0
- package/dist/pw-mp.js.map +1 -0
- package/dist/pw-np12.d.ts +6 -0
- package/dist/pw-np12.d.ts.map +1 -0
- package/dist/pw-np12.js +234 -0
- package/dist/pw-np12.js.map +1 -0
- package/dist/pw-np3.d.ts +4 -0
- package/dist/pw-np3.d.ts.map +1 -0
- package/dist/pw-np3.js +218 -0
- package/dist/pw-np3.js.map +1 -0
- package/dist/pw-p40.d.ts +4 -0
- package/dist/pw-p40.d.ts.map +1 -0
- package/dist/pw-p40.js +221 -0
- package/dist/pw-p40.js.map +1 -0
- package/dist/pw-plugin.d.ts +8 -0
- package/dist/pw-plugin.d.ts.map +1 -0
- package/dist/pw-plugin.js +27 -0
- package/dist/pw-plugin.js.map +1 -0
- package/dist/pw-pp.d.ts +8 -0
- package/dist/pw-pp.d.ts.map +1 -0
- package/dist/pw-pp.js +341 -0
- package/dist/pw-pp.js.map +1 -0
- package/dist/pw-skyt.d.ts +4 -0
- package/dist/pw-skyt.d.ts.map +1 -0
- package/dist/pw-skyt.js +116 -0
- package/dist/pw-skyt.js.map +1 -0
- package/dist/pw-starpack.d.ts +4 -0
- package/dist/pw-starpack.d.ts.map +1 -0
- package/dist/pw-starpack.js +253 -0
- package/dist/pw-starpack.js.map +1 -0
- package/dist/pw-theplayer.d.ts +6 -0
- package/dist/pw-theplayer.d.ts.map +1 -0
- package/dist/pw-theplayer.js +367 -0
- package/dist/pw-theplayer.js.map +1 -0
- package/dist/pw-tp1.d.ts +4 -0
- package/dist/pw-tp1.d.ts.map +1 -0
- package/dist/pw-tp1.js +162 -0
- package/dist/pw-tp1.js.map +1 -0
- package/dist/pw-tp3.d.ts +6 -0
- package/dist/pw-tp3.d.ts.map +1 -0
- package/dist/pw-tp3.js +217 -0
- package/dist/pw-tp3.js.map +1 -0
- package/dist/pw-unic.d.ts +8 -0
- package/dist/pw-unic.d.ts.map +1 -0
- package/dist/pw-unic.js +285 -0
- package/dist/pw-unic.js.map +1 -0
- package/dist/pw-unic2.d.ts +4 -0
- package/dist/pw-unic2.d.ts.map +1 -0
- package/dist/pw-unic2.js +173 -0
- package/dist/pw-unic2.js.map +1 -0
- package/dist/pw-wn.d.ts +4 -0
- package/dist/pw-wn.d.ts.map +1 -0
- package/dist/pw-wn.js +82 -0
- package/dist/pw-wn.js.map +1 -0
- package/dist/pw-xann.d.ts +4 -0
- package/dist/pw-xann.d.ts.map +1 -0
- package/dist/pw-xann.js +220 -0
- package/dist/pw-xann.js.map +1 -0
- package/dist/pw-zen.d.ts +4 -0
- package/dist/pw-zen.d.ts.map +1 -0
- package/dist/pw-zen.js +162 -0
- package/dist/pw-zen.js.map +1 -0
- package/package.json +49 -4
package/dist/pw-mp.js
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
// SPDX-License-Identifier: BSD-3-Clause
|
|
2
|
+
// Copyright (c) 2026 Bitti09 — modplayjs contributors
|
|
3
|
+
// Ported from: libxmp src/loaders/prowizard/mp.c (Module Protector, id +
|
|
4
|
+
// noID variants share depack_mp :36-80; test_mp_id :177-212, test_mp_noid
|
|
5
|
+
// :82-173).
|
|
6
|
+
import { readmem16b, readmem32b, moveData, writeZero, pwReadTitle } from './prowiz.js';
|
|
7
|
+
const MAGIC_TRK1 = 0x54524b31; // 'TRK1'
|
|
8
|
+
const PW_MOD_MAGIC = 0x4d2e4b2e; // 'M.K.'
|
|
9
|
+
function put8(out, b) { out.push(b & 0xff); }
|
|
10
|
+
function put16b(out, v) { out.push((v >> 8) & 0xff, v & 0xff); }
|
|
11
|
+
function put32b(out, v) {
|
|
12
|
+
out.push((v >>> 24) & 0xff, (v >> 16) & 0xff, (v >> 8) & 0xff, v & 0xff);
|
|
13
|
+
}
|
|
14
|
+
/** depack_mp (mp.c:36-80). */
|
|
15
|
+
function depackMp(data, start) {
|
|
16
|
+
let pos = start;
|
|
17
|
+
const out = [];
|
|
18
|
+
const u8 = () => data[pos++] ?? 0;
|
|
19
|
+
const u16 = () => { const v = readmem16b(data, pos); pos += 2; return v; };
|
|
20
|
+
const u32 = () => { const v = readmem32b(data, pos); pos += 4; return v; };
|
|
21
|
+
writeZero(out, 20); // title
|
|
22
|
+
// TRK1 magic present → skip it; otherwise rewind (mp.c:48-49)
|
|
23
|
+
if (u32() !== MAGIC_TRK1)
|
|
24
|
+
pos -= 4;
|
|
25
|
+
// Sample headers (mp.c:51-59)
|
|
26
|
+
let ssize = 0;
|
|
27
|
+
for (let i = 0; i < 31; i++) {
|
|
28
|
+
writeZero(out, 22); // name
|
|
29
|
+
const size = u16();
|
|
30
|
+
ssize += size * 2;
|
|
31
|
+
put16b(out, size);
|
|
32
|
+
put8(out, u8()); // finetune
|
|
33
|
+
put8(out, u8()); // volume
|
|
34
|
+
put16b(out, u16()); // loop start
|
|
35
|
+
put16b(out, u16()); // loop size
|
|
36
|
+
}
|
|
37
|
+
put8(out, u8()); // pattern table length
|
|
38
|
+
put8(out, u8()); // NoiseTracker restart byte
|
|
39
|
+
// Pattern list (mp.c:64-69)
|
|
40
|
+
let max = 0;
|
|
41
|
+
for (let i = 0; i < 128; i++) {
|
|
42
|
+
const c1 = u8();
|
|
43
|
+
put8(out, c1);
|
|
44
|
+
if (c1 > max)
|
|
45
|
+
max = c1;
|
|
46
|
+
}
|
|
47
|
+
max++;
|
|
48
|
+
put32b(out, PW_MOD_MAGIC);
|
|
49
|
+
// Bypass unknown empty bytes (mp.c:73-74)
|
|
50
|
+
if (u32() !== 0)
|
|
51
|
+
pos -= 4;
|
|
52
|
+
// Pattern + sample data (mp.c:76-77)
|
|
53
|
+
moveData(data, pos, out, 1024 * max);
|
|
54
|
+
pos += 1024 * max;
|
|
55
|
+
moveData(data, pos, out, ssize);
|
|
56
|
+
return Uint8Array.from(out);
|
|
57
|
+
}
|
|
58
|
+
/** test_mp_noid (mp.c:82-173). */
|
|
59
|
+
function testMpNoid(data, start) {
|
|
60
|
+
const s = data.length - start;
|
|
61
|
+
if (s < 378)
|
|
62
|
+
return 378 - s;
|
|
63
|
+
// test #2 (mp.c:86-120): 31 × 8-byte sample headers
|
|
64
|
+
let hdrSsize = 0;
|
|
65
|
+
for (let i = 0; i < 31; i++) {
|
|
66
|
+
const d = start + i * 8;
|
|
67
|
+
const size = readmem16b(data, d) << 1;
|
|
68
|
+
const lstart = readmem16b(data, d + 4) << 1;
|
|
69
|
+
const lsize = readmem16b(data, d + 6) << 1;
|
|
70
|
+
hdrSsize += size;
|
|
71
|
+
if (data[d + 2] > 0x0f)
|
|
72
|
+
return -1;
|
|
73
|
+
if (lsize !== 2 && lstart + lsize > size)
|
|
74
|
+
return -1;
|
|
75
|
+
if (lsize > size + 2)
|
|
76
|
+
return -1;
|
|
77
|
+
if (lstart !== 0 && lsize <= 2)
|
|
78
|
+
return -1;
|
|
79
|
+
if (size !== 0 && lsize === 0)
|
|
80
|
+
return -1;
|
|
81
|
+
}
|
|
82
|
+
if (hdrSsize <= 2)
|
|
83
|
+
return -1;
|
|
84
|
+
// test #3 (mp.c:122-127)
|
|
85
|
+
const len = data[start + 248];
|
|
86
|
+
if (len === 0 || len > 0x7f)
|
|
87
|
+
return -1;
|
|
88
|
+
// test #4 (mp.c:129-142)
|
|
89
|
+
let psize = 0;
|
|
90
|
+
for (let i = 0; i < 128; i++) {
|
|
91
|
+
const pat = data[start + 250 + i];
|
|
92
|
+
if (pat > 0x7f)
|
|
93
|
+
return -1;
|
|
94
|
+
if (pat > psize)
|
|
95
|
+
psize = pat;
|
|
96
|
+
if (i > len + 3 && pat !== 0)
|
|
97
|
+
return -1;
|
|
98
|
+
}
|
|
99
|
+
psize++;
|
|
100
|
+
psize <<= 8;
|
|
101
|
+
if (s < 378 + psize * 4)
|
|
102
|
+
return 378 + psize * 4 - s;
|
|
103
|
+
// test #5 (mp.c:145-151): ptk note check on pattern data
|
|
104
|
+
// test #5 (mp.c:144-152): sample-header words must be >= 0x71 (d = i*8)
|
|
105
|
+
for (let i = 0; i < 31; i++) {
|
|
106
|
+
const d = start + i * 8;
|
|
107
|
+
const val = readmem16b(data, d) & 0x0fff;
|
|
108
|
+
if (val > 0 && val < 0x71)
|
|
109
|
+
return -1;
|
|
110
|
+
}
|
|
111
|
+
// test #6 (mp.c:156-164)
|
|
112
|
+
for (let i = 0; i < 31; i++) {
|
|
113
|
+
const d = start + i * 8;
|
|
114
|
+
const size = readmem16b(data, d) << 1;
|
|
115
|
+
const lend = (readmem16b(data, d + 4) + readmem16b(data, d + 6)) << 1;
|
|
116
|
+
if (lend > size + 2)
|
|
117
|
+
return -1;
|
|
118
|
+
}
|
|
119
|
+
pwReadTitle(null, 0);
|
|
120
|
+
return 0;
|
|
121
|
+
}
|
|
122
|
+
/** test_mp_id (mp.c:177-212) — "TRK1" signature. */
|
|
123
|
+
function testMpId(data, start) {
|
|
124
|
+
const s = data.length - start;
|
|
125
|
+
if (s < 382)
|
|
126
|
+
return 382 - s;
|
|
127
|
+
if (readmem32b(data, start) !== MAGIC_TRK1)
|
|
128
|
+
return -1;
|
|
129
|
+
// test #1 (mp.c:184-188)
|
|
130
|
+
for (let i = 0; i < 31; i++) {
|
|
131
|
+
if (data[start + 6 + 8 * i] > 0x0f)
|
|
132
|
+
return -1;
|
|
133
|
+
}
|
|
134
|
+
// test #2 (mp.c:190-194)
|
|
135
|
+
const len = data[start + 252];
|
|
136
|
+
if (len === 0 || len > 0x7f)
|
|
137
|
+
return -1;
|
|
138
|
+
// test #4 (mp.c:196-207)
|
|
139
|
+
let psize = 0;
|
|
140
|
+
for (let i = 0; i < 128; i++) {
|
|
141
|
+
const pat = data[start + 254 + i];
|
|
142
|
+
if (pat > 0x7f)
|
|
143
|
+
return -1;
|
|
144
|
+
if (pat > psize)
|
|
145
|
+
psize = pat;
|
|
146
|
+
}
|
|
147
|
+
psize++;
|
|
148
|
+
psize <<= 8;
|
|
149
|
+
if (s < 382 + psize * 4)
|
|
150
|
+
return 382 + psize * 4 - s;
|
|
151
|
+
// test #5 (mp.c:210-214)
|
|
152
|
+
for (let i = 0; i < psize; i++) {
|
|
153
|
+
if (data[start + 382 + i * 4] > 19)
|
|
154
|
+
return -1;
|
|
155
|
+
}
|
|
156
|
+
pwReadTitle(null, 0);
|
|
157
|
+
return 0;
|
|
158
|
+
}
|
|
159
|
+
/** pw_mp_id: "Module Protector" (TRK1). */
|
|
160
|
+
export const pwMpId = {
|
|
161
|
+
name: 'Module Protector',
|
|
162
|
+
test: testMpId,
|
|
163
|
+
depack: depackMp,
|
|
164
|
+
};
|
|
165
|
+
/** pw_mp_noid: "Module Protector noID". */
|
|
166
|
+
export const pwMpNoid = {
|
|
167
|
+
name: 'Module Protector noID',
|
|
168
|
+
test: testMpNoid,
|
|
169
|
+
depack: depackMp,
|
|
170
|
+
};
|
|
171
|
+
//# sourceMappingURL=pw-mp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pw-mp.js","sourceRoot":"","sources":["../src/pw-mp.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pw-np12.d.ts","sourceRoot":"","sources":["../src/pw-np12.ts"],"names":[],"mappings":"AAMA,OAAO,EAA4D,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAiOtG,gCAAgC;AAChC,eAAO,MAAM,KAAK,EAAE,QAInB,CAAC;AAEF,gCAAgC;AAChC,eAAO,MAAM,KAAK,EAAE,QAInB,CAAC"}
|
package/dist/pw-np12.js
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
// SPDX-License-Identifier: BSD-3-Clause
|
|
2
|
+
// Copyright (c) 2026 Bitti09 — modplayjs contributors
|
|
3
|
+
// Ported from: libxmp src/loaders/prowizard/np1.c (NoisePacker v1) and
|
|
4
|
+
// np2.c (NoisePacker v2) — np2 shares np1's layout with small deltas.
|
|
5
|
+
import { ptkTable, ptkIsValidNote } from './ptktable.js';
|
|
6
|
+
import { readmem16b, readmem32b, moveData, writeZero, pwReadTitle } from './prowiz.js';
|
|
7
|
+
const PW_MOD_MAGIC = 0x4d2e4b2e; // 'M.K.'
|
|
8
|
+
function put8(out, b) { out.push(b & 0xff); }
|
|
9
|
+
function put16b(out, v) { out.push((v >> 8) & 0xff, v & 0xff); }
|
|
10
|
+
function put32b(out, v) {
|
|
11
|
+
out.push((v >>> 24) & 0xff, (v >> 16) & 0xff, (v >> 8) & 0xff, v & 0xff);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Shared depack (np1.c:40-156, np2.c:34-155). ver1: loop start halved and
|
|
15
|
+
* effect table lacks the 0x0e case + npat sanity.
|
|
16
|
+
*/
|
|
17
|
+
function depackNp12(data, start, ver1) {
|
|
18
|
+
let pos = start;
|
|
19
|
+
const out = [];
|
|
20
|
+
const u8 = () => data[pos++] ?? 0;
|
|
21
|
+
const u16 = () => { const v = readmem16b(data, pos); pos += 2; return v; };
|
|
22
|
+
const u32 = () => { const v = readmem32b(data, pos); pos += 4; return v; };
|
|
23
|
+
const c1 = u8();
|
|
24
|
+
const c2 = u8();
|
|
25
|
+
const nins = ((c1 << 4) & 0xf0) | ((c2 >> 4) & 0x0f);
|
|
26
|
+
writeZero(out, 20); // title
|
|
27
|
+
const len = u16() >> 1; // size of pattern list
|
|
28
|
+
if (len > 128)
|
|
29
|
+
throw new Error('np: pattern list too long');
|
|
30
|
+
u16(); // 2 unknown bytes
|
|
31
|
+
u16(); // track data size
|
|
32
|
+
// Sample descriptions (np1.c:65-83 / np2.c:63-82)
|
|
33
|
+
let ssize = 0;
|
|
34
|
+
for (let i = 0; i < nins; i++) {
|
|
35
|
+
u32(); // bypass 4 unknown bytes
|
|
36
|
+
writeZero(out, 22); // sample name
|
|
37
|
+
const size = u16();
|
|
38
|
+
ssize += size * 2;
|
|
39
|
+
put16b(out, size);
|
|
40
|
+
put8(out, u8()); // finetune
|
|
41
|
+
put8(out, u8()); // volume
|
|
42
|
+
u32(); // bypass 4 unknown bytes
|
|
43
|
+
const loopSize = u16();
|
|
44
|
+
put16b(out, ver1 ? u16() / 2 : u16()); // loop start
|
|
45
|
+
put16b(out, loopSize); // loop size
|
|
46
|
+
}
|
|
47
|
+
// Fill to 31 samples (np1.c:86-92): zeros with 0x01 loop flag.
|
|
48
|
+
{
|
|
49
|
+
const pad = new Array(30).fill(0);
|
|
50
|
+
pad[29] = 0x01;
|
|
51
|
+
for (let i = nins; i < 31; i++)
|
|
52
|
+
out.push(...pad);
|
|
53
|
+
}
|
|
54
|
+
put8(out, len);
|
|
55
|
+
put8(out, 0x7f); // noisetracker byte
|
|
56
|
+
pos += 2; // always $02? (np1.c:98)
|
|
57
|
+
pos += 2; // unknown (np1.c:99)
|
|
58
|
+
// Pattern table (np1.c:102-111)
|
|
59
|
+
const ptable = [];
|
|
60
|
+
let npat = 0;
|
|
61
|
+
for (let i = 0; i < len; i++) {
|
|
62
|
+
const p = u16() >> 3;
|
|
63
|
+
ptable.push(p);
|
|
64
|
+
if (p > npat)
|
|
65
|
+
npat = p;
|
|
66
|
+
}
|
|
67
|
+
npat++;
|
|
68
|
+
if (!ver1 && npat > 128)
|
|
69
|
+
throw new Error('np2: too many patterns');
|
|
70
|
+
for (let i = 0; i < 128; i++)
|
|
71
|
+
put8(out, ptable[i]);
|
|
72
|
+
put32b(out, PW_MOD_MAGIC);
|
|
73
|
+
// Track addresses per pattern (np1.c:114-129)
|
|
74
|
+
const trkAddr = [];
|
|
75
|
+
let maxAddr = 0;
|
|
76
|
+
for (let i = 0; i < npat; i++) {
|
|
77
|
+
const row = [];
|
|
78
|
+
for (let j = 0; j < 4; j++) {
|
|
79
|
+
const a = u16();
|
|
80
|
+
row.push(a);
|
|
81
|
+
if (a > maxAddr)
|
|
82
|
+
maxAddr = a;
|
|
83
|
+
}
|
|
84
|
+
trkAddr.push(row);
|
|
85
|
+
}
|
|
86
|
+
const trkStart = pos;
|
|
87
|
+
// Track data (np1.c:132-152): channel j reads track [3-j] (reversed);
|
|
88
|
+
// cells are placed ROW-MAJOR into the pattern body (tmp[x], x = k*16 + j*4).
|
|
89
|
+
for (let i = 0; i < npat; i++) {
|
|
90
|
+
const tmp = new Uint8Array(1024);
|
|
91
|
+
for (let j = 0; j < 4; j++) {
|
|
92
|
+
pos = trkStart + trkAddr[i][3 - j];
|
|
93
|
+
for (let k = 0; k < 64; k++) {
|
|
94
|
+
const x = k * 16 + j * 4;
|
|
95
|
+
const c1 = u8();
|
|
96
|
+
const c2 = u8();
|
|
97
|
+
const c3 = u8();
|
|
98
|
+
const c4 = Math.trunc((c1 & 0xfe) / 2);
|
|
99
|
+
if (!ptkIsValidNote(c4))
|
|
100
|
+
throw new Error('np: invalid note');
|
|
101
|
+
let eff2 = c2;
|
|
102
|
+
let eff3 = c3;
|
|
103
|
+
switch (c2 & 0x0f) {
|
|
104
|
+
case 0x08:
|
|
105
|
+
eff2 &= 0xf0;
|
|
106
|
+
break;
|
|
107
|
+
case 0x07:
|
|
108
|
+
eff2 = (eff2 & 0xf0) + 0x0a;
|
|
109
|
+
// falls through to 06/05 handling
|
|
110
|
+
eff3 = eff3 > 0x80 ? 0x100 - eff3 : (eff3 << 4) & 0xf0;
|
|
111
|
+
break;
|
|
112
|
+
case 0x06:
|
|
113
|
+
case 0x05:
|
|
114
|
+
eff3 = eff3 > 0x80 ? 0x100 - eff3 : (eff3 << 4) & 0xf0;
|
|
115
|
+
break;
|
|
116
|
+
case 0x0b:
|
|
117
|
+
eff3 = Math.trunc((eff3 + 4) / 2);
|
|
118
|
+
break;
|
|
119
|
+
case 0x0e:
|
|
120
|
+
if (!ver1)
|
|
121
|
+
eff3--;
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
tmp[x] = ((c1 << 4) & 0x10) | ptkTable[c4][0];
|
|
125
|
+
tmp[x + 1] = ptkTable[c4][1];
|
|
126
|
+
tmp[x + 2] = eff2 & 0xff;
|
|
127
|
+
tmp[x + 3] = eff3 & 0xff;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
for (let k = 0; k < 1024; k++)
|
|
131
|
+
out.push(tmp[k]);
|
|
132
|
+
}
|
|
133
|
+
// Sample data (np1.c:155-158)
|
|
134
|
+
moveData(data, start + maxAddr + 192 + trkStart, out, ssize);
|
|
135
|
+
return Uint8Array.from(out);
|
|
136
|
+
}
|
|
137
|
+
/** Shared test (np1.c:161-251, np2.c:158-269). */
|
|
138
|
+
function testNp12(data, start, ver1) {
|
|
139
|
+
const s = data.length - start;
|
|
140
|
+
if (s < 10)
|
|
141
|
+
return 10 - s;
|
|
142
|
+
// Pattern table size (np1.c:169-173)
|
|
143
|
+
const ptabSize = readmem16b(data, start + 2);
|
|
144
|
+
if (ptabSize === 0 || (ptabSize & 1) !== 0 || ptabSize > 0xff)
|
|
145
|
+
return -1;
|
|
146
|
+
// Sample count nibble check (np1.c:176-178)
|
|
147
|
+
if ((data[start + 1] & 0x0f) !== 0x0c)
|
|
148
|
+
return -1;
|
|
149
|
+
const numIns = ((data[start] << 4) & 0xf0) | ((data[start + 1] >> 4) & 0x0f);
|
|
150
|
+
if (numIns === 0 || numIns > 0x1f)
|
|
151
|
+
return -1;
|
|
152
|
+
// PW_REQUEST_DATA(s, 15 + num_ins * 16)
|
|
153
|
+
if (s < 15 + numIns * 16)
|
|
154
|
+
return 15 + numIns * 16 - s;
|
|
155
|
+
for (let i = 0; i < numIns; i++) {
|
|
156
|
+
if (data[start + 15 + i * 16] > 0x40)
|
|
157
|
+
return -1; // volumes
|
|
158
|
+
}
|
|
159
|
+
// Sample sizes (np1.c:185-206)
|
|
160
|
+
let ssize = 0;
|
|
161
|
+
for (let i = 0; i < numIns; i++) {
|
|
162
|
+
const d = start + i * 16;
|
|
163
|
+
const len = readmem16b(data, d + 12) << 1;
|
|
164
|
+
const lstart = readmem16b(data, d + 20) << 1;
|
|
165
|
+
const lsize = ver1 ? readmem16b(data, d + 22) : readmem16b(data, d + 22) << 1;
|
|
166
|
+
if (len > 0xffff || lstart > 0xffff || lsize > 0xffff)
|
|
167
|
+
return -1;
|
|
168
|
+
if (lstart + lsize > len + 2)
|
|
169
|
+
return -1;
|
|
170
|
+
if (lstart === 0 && lsize !== 0)
|
|
171
|
+
return -1;
|
|
172
|
+
ssize += len;
|
|
173
|
+
}
|
|
174
|
+
if (ssize <= 4)
|
|
175
|
+
return -1;
|
|
176
|
+
// Header size (np1.c:209-211)
|
|
177
|
+
let hdrSize = numIns * 16 + 8 + 4;
|
|
178
|
+
// PW_REQUEST_DATA(s, hdr_size + ptab_size + 2)
|
|
179
|
+
if (s < hdrSize + ptabSize + 2)
|
|
180
|
+
return hdrSize + ptabSize + 2 - s;
|
|
181
|
+
// Pattern table (np1.c:213-224)
|
|
182
|
+
let maxPptr = 0;
|
|
183
|
+
for (let i = 0; i < ptabSize; i += 2) {
|
|
184
|
+
const pptr = readmem16b(data, start + hdrSize + i);
|
|
185
|
+
if (ver1) {
|
|
186
|
+
if ((pptr & 0x07) !== 0 || pptr >= 0x400)
|
|
187
|
+
return -1;
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
if ((pptr & 0x07) !== 0 || pptr > 0x400)
|
|
191
|
+
return -1;
|
|
192
|
+
}
|
|
193
|
+
if (pptr > maxPptr)
|
|
194
|
+
maxPptr = pptr;
|
|
195
|
+
}
|
|
196
|
+
// Header to end of track list (np1.c:227-231)
|
|
197
|
+
hdrSize += ptabSize + maxPptr + 8;
|
|
198
|
+
// Track data size (np1.c:234-237)
|
|
199
|
+
const trkSize = readmem16b(data, start + 6);
|
|
200
|
+
if (trkSize < 192 || (trkSize & 0x3f) !== 0)
|
|
201
|
+
return -1;
|
|
202
|
+
// PW_REQUEST_DATA(s, hdr_size + trk_size [+16 for np2])
|
|
203
|
+
const need = hdrSize + trkSize + (ver1 ? 0 : 16);
|
|
204
|
+
if (s < need)
|
|
205
|
+
return need - s;
|
|
206
|
+
// Notes (np1.c:239-247, np2.c:245-262)
|
|
207
|
+
for (let i = 0; i < trkSize; i += 3) {
|
|
208
|
+
const d = start + hdrSize + i;
|
|
209
|
+
if (data[d] > 0x49)
|
|
210
|
+
return -1;
|
|
211
|
+
if (!ver1) {
|
|
212
|
+
const ins = ((data[d] << 4) & 0x10) | ((data[d + 1] >> 4) & 0x0f);
|
|
213
|
+
if (ins > numIns)
|
|
214
|
+
return -1;
|
|
215
|
+
if ((data[d + 1] & 0x0f) === 0 && data[d + 2] !== 0)
|
|
216
|
+
return -1;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
pwReadTitle(null, 0);
|
|
220
|
+
return 0;
|
|
221
|
+
}
|
|
222
|
+
/** pw_np1: "NoisePacker v1". */
|
|
223
|
+
export const pwNp1 = {
|
|
224
|
+
name: 'NoisePacker v1',
|
|
225
|
+
test: (data, st) => testNp12(data, st, true),
|
|
226
|
+
depack: (data, st) => depackNp12(data, st, true),
|
|
227
|
+
};
|
|
228
|
+
/** pw_np2: "NoisePacker v2". */
|
|
229
|
+
export const pwNp2 = {
|
|
230
|
+
name: 'NoisePacker v2',
|
|
231
|
+
test: (data, st) => testNp12(data, st, false),
|
|
232
|
+
depack: (data, st) => depackNp12(data, st, false),
|
|
233
|
+
};
|
|
234
|
+
//# sourceMappingURL=pw-np12.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pw-np12.js","sourceRoot":"","sources":["../src/pw-np12.ts"],"names":[],"mappings":"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"}
|
package/dist/pw-np3.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pw-np3.d.ts","sourceRoot":"","sources":["../src/pw-np3.ts"],"names":[],"mappings":"AAMA,OAAO,EAAgD,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAuN1F,gCAAgC;AAChC,eAAO,MAAM,KAAK,EAAE,QAInB,CAAC"}
|
package/dist/pw-np3.js
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
// SPDX-License-Identifier: BSD-3-Clause
|
|
2
|
+
// Copyright (c) 2026 Bitti09 — modplayjs contributors
|
|
3
|
+
// Ported from: libxmp src/loaders/prowizard/np3.c (NoisePacker v3) —
|
|
4
|
+
// depack_np3 :34-217, test_np3 :220-304.
|
|
5
|
+
import { ptkTable, ptkIsValidNote } from './ptktable.js';
|
|
6
|
+
import { readmem16b, moveData, writeZero, pwReadTitle } from './prowiz.js';
|
|
7
|
+
const PW_MOD_MAGIC = 0x4d2e4b2e; // 'M.K.'
|
|
8
|
+
function put8(out, b) { out.push(b & 0xff); }
|
|
9
|
+
function put16b(out, v) { out.push((v >> 8) & 0xff, v & 0xff); }
|
|
10
|
+
function put32b(out, v) {
|
|
11
|
+
out.push((v >>> 24) & 0xff, (v >> 16) & 0xff, (v >> 8) & 0xff, v & 0xff);
|
|
12
|
+
}
|
|
13
|
+
/** depack_np3 (np3.c:34-217). */
|
|
14
|
+
function depackNp3(data, start) {
|
|
15
|
+
let pos = start;
|
|
16
|
+
const out = [];
|
|
17
|
+
const u8 = () => data[pos++] ?? 0;
|
|
18
|
+
const u16 = () => { const v = readmem16b(data, pos); pos += 2; return v; };
|
|
19
|
+
const c1 = u8();
|
|
20
|
+
const c2 = u8();
|
|
21
|
+
const nins = ((c1 << 4) & 0xf0) | ((c2 >> 4) & 0x0f);
|
|
22
|
+
writeZero(out, 20); // title
|
|
23
|
+
const len = u16() >> 1; // pattern list size
|
|
24
|
+
if (len > 128)
|
|
25
|
+
throw new Error('np3: pattern list too long');
|
|
26
|
+
u16(); // 2 unknown bytes
|
|
27
|
+
u16(); // track data size
|
|
28
|
+
// Sample descriptions (np3.c:64-74): 16-byte records, reordered fields.
|
|
29
|
+
let ssize = 0;
|
|
30
|
+
for (let i = 0; i < nins; i++) {
|
|
31
|
+
const rec = data.subarray(pos, pos + 16);
|
|
32
|
+
pos += 16;
|
|
33
|
+
writeZero(out, 22); // sample name
|
|
34
|
+
const size = readmem16b(rec, 6);
|
|
35
|
+
ssize += size * 2;
|
|
36
|
+
put16b(out, size);
|
|
37
|
+
put8(out, rec[0]); // finetune
|
|
38
|
+
put8(out, rec[1]); // volume
|
|
39
|
+
// write loop start (tmp+14) then loop size (tmp+12) — swapped in file
|
|
40
|
+
out.push(rec[14], rec[15]);
|
|
41
|
+
out.push(rec[12], rec[13]);
|
|
42
|
+
}
|
|
43
|
+
// Fill to 31 (np3.c:77-81)
|
|
44
|
+
{
|
|
45
|
+
const pad = new Array(30).fill(0);
|
|
46
|
+
pad[29] = 0x01;
|
|
47
|
+
for (let i = nins; i < 31; i++)
|
|
48
|
+
out.push(...pad);
|
|
49
|
+
}
|
|
50
|
+
put8(out, len);
|
|
51
|
+
put8(out, 0x7f);
|
|
52
|
+
pos += 2; // always $02?
|
|
53
|
+
pos += 2; // unknown
|
|
54
|
+
// Pattern table (np3.c:84-93): u16 / 8
|
|
55
|
+
const ptable = [];
|
|
56
|
+
let npat = 0;
|
|
57
|
+
for (let i = 0; i < len; i++) {
|
|
58
|
+
const p = Math.trunc(u16() / 8);
|
|
59
|
+
ptable.push(p);
|
|
60
|
+
if (p > npat)
|
|
61
|
+
npat = p;
|
|
62
|
+
}
|
|
63
|
+
npat++;
|
|
64
|
+
for (let i = 0; i < 128; i++)
|
|
65
|
+
put8(out, ptable[i]);
|
|
66
|
+
put32b(out, PW_MOD_MAGIC);
|
|
67
|
+
// Track addresses (np3.c:96-110)
|
|
68
|
+
const trkAddr = [];
|
|
69
|
+
for (let i = 0; i < npat; i++) {
|
|
70
|
+
const row = [];
|
|
71
|
+
for (let j = 0; j < 4; j++)
|
|
72
|
+
row.push(u16());
|
|
73
|
+
trkAddr.push(row);
|
|
74
|
+
}
|
|
75
|
+
const trkStart = pos;
|
|
76
|
+
// Track data (np3.c:113-196): 0x80-or-more = blank-run skip; smp_addr
|
|
77
|
+
// tracks the furthest read position across all tracks.
|
|
78
|
+
let smpAddr = 0;
|
|
79
|
+
for (let i = 0; i < npat; i++) {
|
|
80
|
+
const tmp = new Uint8Array(1024);
|
|
81
|
+
for (let j = 0; j < 4; j++) {
|
|
82
|
+
pos = trkStart + trkAddr[i][3 - j];
|
|
83
|
+
for (let k = 0; k < 64; k++) {
|
|
84
|
+
const x = k * 16 + j * 4;
|
|
85
|
+
const c1 = u8();
|
|
86
|
+
if (c1 >= 0x80) {
|
|
87
|
+
k += (0x100 - c1) - 1;
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
const c2 = u8();
|
|
91
|
+
const c3 = u8();
|
|
92
|
+
const c4 = Math.trunc((c1 & 0xfe) / 2);
|
|
93
|
+
if (!ptkIsValidNote(c4))
|
|
94
|
+
throw new Error('np3: invalid note');
|
|
95
|
+
let eff2 = c2;
|
|
96
|
+
let eff3 = c3;
|
|
97
|
+
switch (c2 & 0x0f) {
|
|
98
|
+
case 0x08:
|
|
99
|
+
eff2 &= 0xf0;
|
|
100
|
+
break;
|
|
101
|
+
case 0x07:
|
|
102
|
+
eff2 = (eff2 & 0xf0) + 0x0a;
|
|
103
|
+
eff3 = eff3 > 0x80 ? 0x100 - eff3 : (eff3 << 4) & 0xf0;
|
|
104
|
+
break;
|
|
105
|
+
case 0x06:
|
|
106
|
+
case 0x05:
|
|
107
|
+
eff3 = eff3 > 0x80 ? 0x100 - eff3 : (eff3 << 4) & 0xf0;
|
|
108
|
+
break;
|
|
109
|
+
case 0x0e:
|
|
110
|
+
eff3 = 1;
|
|
111
|
+
break;
|
|
112
|
+
case 0x0b:
|
|
113
|
+
eff3 = Math.trunc((eff3 + 4) / 2);
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
tmp[x] = ((c1 << 4) & 0x10) | ptkTable[c4][0];
|
|
117
|
+
tmp[x + 1] = ptkTable[c4][1];
|
|
118
|
+
tmp[x + 2] = eff2;
|
|
119
|
+
tmp[x + 3] = eff3;
|
|
120
|
+
if ((c2 & 0x0f) === 0x0d)
|
|
121
|
+
break; // pattern break ends the track
|
|
122
|
+
}
|
|
123
|
+
if (pos > smpAddr)
|
|
124
|
+
smpAddr = pos;
|
|
125
|
+
}
|
|
126
|
+
for (let k = 0; k < 1024; k++)
|
|
127
|
+
out.push(tmp[k]);
|
|
128
|
+
}
|
|
129
|
+
// Sample data (np3.c:200-206): smp_addr aligned to even.
|
|
130
|
+
if ((smpAddr & 1) !== 0)
|
|
131
|
+
smpAddr++;
|
|
132
|
+
moveData(data, smpAddr, out, ssize);
|
|
133
|
+
return Uint8Array.from(out);
|
|
134
|
+
}
|
|
135
|
+
/** test_np3 (np3.c:220-304). */
|
|
136
|
+
function testNp3(data, start) {
|
|
137
|
+
const s = data.length - start;
|
|
138
|
+
if (s < 10)
|
|
139
|
+
return 10 - s;
|
|
140
|
+
const ptabSize = readmem16b(data, start + 2);
|
|
141
|
+
if (ptabSize === 0 || (ptabSize & 0x01) !== 0 || ptabSize > 0xff)
|
|
142
|
+
return -1;
|
|
143
|
+
if ((data[start + 1] & 0x0f) !== 0x0c)
|
|
144
|
+
return -1;
|
|
145
|
+
const numIns = ((data[start] << 4) & 0xf0) | ((data[start + 1] >> 4) & 0x0f);
|
|
146
|
+
if (numIns === 0 || numIns > 0x1f)
|
|
147
|
+
return -1;
|
|
148
|
+
if (s < 15 + numIns * 16)
|
|
149
|
+
return 15 + numIns * 16 - s;
|
|
150
|
+
// Volumes (np3.c:241-245) — note offset 9, not 15.
|
|
151
|
+
for (let i = 0; i < numIns; i++) {
|
|
152
|
+
if (data[start + 9 + i * 16] > 0x40)
|
|
153
|
+
return -1;
|
|
154
|
+
}
|
|
155
|
+
// Sample sizes (np3.c:248-268): len at d+14 (not d+12).
|
|
156
|
+
let ssize = 0;
|
|
157
|
+
for (let i = 0; i < numIns; i++) {
|
|
158
|
+
const d = start + i * 16;
|
|
159
|
+
const len = readmem16b(data, d + 14) << 1;
|
|
160
|
+
const lstart = readmem16b(data, d + 20) << 1;
|
|
161
|
+
const lsize = readmem16b(data, d + 22) << 1;
|
|
162
|
+
if (len > 0xffff || lstart > 0xffff || lsize > 0xffff)
|
|
163
|
+
return -1;
|
|
164
|
+
if (lstart + lsize > len + 2)
|
|
165
|
+
return -1;
|
|
166
|
+
if (lstart === 0 && lsize !== 0)
|
|
167
|
+
return -1;
|
|
168
|
+
ssize += len;
|
|
169
|
+
}
|
|
170
|
+
if (ssize <= 4)
|
|
171
|
+
return -1;
|
|
172
|
+
let hdrSize = numIns * 16 + 8 + 4;
|
|
173
|
+
if (s < hdrSize + ptabSize + 2)
|
|
174
|
+
return hdrSize + ptabSize + 2 - s;
|
|
175
|
+
// Pattern table (np3.c:275-284)
|
|
176
|
+
let maxPptr = 0;
|
|
177
|
+
for (let i = 0; i < ptabSize; i += 2) {
|
|
178
|
+
const pptr = readmem16b(data, start + hdrSize + i);
|
|
179
|
+
if ((pptr & 0x07) !== 0 || pptr >= 0x400)
|
|
180
|
+
return -1;
|
|
181
|
+
if (pptr > maxPptr)
|
|
182
|
+
maxPptr = pptr;
|
|
183
|
+
}
|
|
184
|
+
hdrSize += ptabSize + maxPptr + 8;
|
|
185
|
+
// Track data size (np3.c:291-294): > 63, no alignment check.
|
|
186
|
+
const trkSize = readmem16b(data, start + 6);
|
|
187
|
+
if (trkSize <= 63)
|
|
188
|
+
return -1;
|
|
189
|
+
if (s < hdrSize + trkSize + 2)
|
|
190
|
+
return hdrSize + trkSize + 2 - s;
|
|
191
|
+
// Notes (np3.c:297-322): errcount tolerance of 1 (Shadow Fighter quirk).
|
|
192
|
+
let errcount = 0;
|
|
193
|
+
for (let i = 0; i < trkSize; i++) {
|
|
194
|
+
const d = start + hdrSize + i;
|
|
195
|
+
if ((data[d] & 0x80) !== 0)
|
|
196
|
+
continue;
|
|
197
|
+
if (data[d] > 0x49 || (data[d + 1] & 0x0f) === 0x0a)
|
|
198
|
+
errcount++;
|
|
199
|
+
if ((data[d + 1] & 0x0f) === 0x0d && data[d + 2] > 0x40)
|
|
200
|
+
errcount++;
|
|
201
|
+
if ((((data[d] << 4) & 0x10) | ((data[d + 1] >> 4) & 0x0f)) > numIns)
|
|
202
|
+
errcount++;
|
|
203
|
+
if (data[d] === 0 && data[d + 1] === 0 && data[d + 2] === 0 && i < trkSize - 3)
|
|
204
|
+
errcount++;
|
|
205
|
+
if (errcount > 1)
|
|
206
|
+
return -1;
|
|
207
|
+
i += 2;
|
|
208
|
+
}
|
|
209
|
+
pwReadTitle(null, 0);
|
|
210
|
+
return 0;
|
|
211
|
+
}
|
|
212
|
+
/** pw_np3: "NoisePacker v3". */
|
|
213
|
+
export const pwNp3 = {
|
|
214
|
+
name: 'NoisePacker v3',
|
|
215
|
+
test: testNp3,
|
|
216
|
+
depack: depackNp3,
|
|
217
|
+
};
|
|
218
|
+
//# sourceMappingURL=pw-np3.js.map
|