@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-di.js
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
// SPDX-License-Identifier: BSD-3-Clause
|
|
2
|
+
// Copyright (c) 2026 Bitti09 — modplayjs contributors
|
|
3
|
+
// Ported from: libxmp src/loaders/prowizard/di.c (Digital Illusions) —
|
|
4
|
+
// write_event :34-59, depack_di :61-159, test_di :165-268.
|
|
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
|
+
/** write_event (di.c:34-59): 3 input bytes → 4-byte PTK cell. */
|
|
14
|
+
function writeEvent(out, c1, c2, fxp) {
|
|
15
|
+
const note = ((c1 << 4) & 0x30) | ((c2 >> 4) & 0x0f);
|
|
16
|
+
if (!ptkIsValidNote(note)) {
|
|
17
|
+
// di.nightmare has note 49! (di.c:39-44)
|
|
18
|
+
out.push(0, 0, 0, 0);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const ins = (c1 >> 2) & 0x1f;
|
|
22
|
+
const fxt = c2 & 0x0f;
|
|
23
|
+
out.push((ptkTable[note][0] | (ins & 0xf0)) & 0xff);
|
|
24
|
+
out.push(ptkTable[note][1]);
|
|
25
|
+
out.push((((ins << 4) & 0xf0) | fxt) & 0xff);
|
|
26
|
+
out.push(fxp & 0xff);
|
|
27
|
+
}
|
|
28
|
+
/** depack_di (di.c:61-159). */
|
|
29
|
+
function depackDi(data, start) {
|
|
30
|
+
let pos = start;
|
|
31
|
+
const out = [];
|
|
32
|
+
const u8 = () => data[pos++] ?? 0;
|
|
33
|
+
const u16 = () => { const v = readmem16b(data, pos); pos += 2; return v; };
|
|
34
|
+
const u32 = () => { const v = readmem32b(data, pos); pos += 4; return v; };
|
|
35
|
+
writeZero(out, 20); // title
|
|
36
|
+
const nins = u16();
|
|
37
|
+
if (nins > 31)
|
|
38
|
+
throw new Error('di: too many samples');
|
|
39
|
+
const seqOfs = u32();
|
|
40
|
+
u32(); // pat_offs
|
|
41
|
+
const smpOfs = u32();
|
|
42
|
+
// Sample headers (di.c:81-89)
|
|
43
|
+
let ssize = 0;
|
|
44
|
+
for (let i = 0; i < nins; i++) {
|
|
45
|
+
writeZero(out, 22); // name
|
|
46
|
+
const size = u16();
|
|
47
|
+
ssize += size * 2;
|
|
48
|
+
put16b(out, size);
|
|
49
|
+
put8(out, u8()); // finetune
|
|
50
|
+
put8(out, u8()); // volume
|
|
51
|
+
put16b(out, u16()); // loop start
|
|
52
|
+
put16b(out, u16()); // loop size
|
|
53
|
+
}
|
|
54
|
+
// Pad to 31 (di.c:92-96)
|
|
55
|
+
{
|
|
56
|
+
const pad = new Array(30).fill(0);
|
|
57
|
+
for (let i = nins; i < 31; i++)
|
|
58
|
+
out.push(...pad);
|
|
59
|
+
}
|
|
60
|
+
const posAfterSamples = pos;
|
|
61
|
+
// Sequence table (di.c:98-104): 0xff-terminated
|
|
62
|
+
pos = start + seqOfs;
|
|
63
|
+
const ptable = new Array(128).fill(0);
|
|
64
|
+
let i = 0;
|
|
65
|
+
let c1 = 0;
|
|
66
|
+
do {
|
|
67
|
+
c1 = u8();
|
|
68
|
+
ptable[i++] = c1;
|
|
69
|
+
} while (c1 !== 0xff);
|
|
70
|
+
ptable[i - 1] = 0;
|
|
71
|
+
const npat = i - 1;
|
|
72
|
+
put8(out, npat);
|
|
73
|
+
put8(out, 0x7f);
|
|
74
|
+
// Highest pattern (di.c:109-115)
|
|
75
|
+
let max = 0;
|
|
76
|
+
for (i = 0; i < 128; i++) {
|
|
77
|
+
put8(out, ptable[i]);
|
|
78
|
+
if (ptable[i] > max)
|
|
79
|
+
max = ptable[i];
|
|
80
|
+
}
|
|
81
|
+
if (max >= 128)
|
|
82
|
+
throw new Error('di: pattern number too high');
|
|
83
|
+
put32b(out, PW_MOD_MAGIC);
|
|
84
|
+
// Pattern data (di.c:118-153): paddr per pattern; cells have 3 forms
|
|
85
|
+
// (bit7 clear = note+2bytes, 0xff = empty u32, else note+3bytes).
|
|
86
|
+
pos = posAfterSamples;
|
|
87
|
+
const paddr = [];
|
|
88
|
+
for (i = 0; i <= max; i++)
|
|
89
|
+
paddr.push(u16());
|
|
90
|
+
for (i = 0; i <= max; i++) {
|
|
91
|
+
pos = start + paddr[i];
|
|
92
|
+
for (let k = 0; k < 256; k++) {
|
|
93
|
+
const c1v = u8();
|
|
94
|
+
if ((c1v & 0x80) === 0) {
|
|
95
|
+
const c2v = u8();
|
|
96
|
+
writeEvent(out, c1v, c2v, 0);
|
|
97
|
+
}
|
|
98
|
+
else if (c1v === 0xff) {
|
|
99
|
+
out.push(0, 0, 0, 0);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
const c2v = u8();
|
|
103
|
+
const c3v = u8();
|
|
104
|
+
writeEvent(out, c1v, c2v, c3v);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Sample data (di.c:156-158)
|
|
109
|
+
moveData(data, start + smpOfs, out, ssize);
|
|
110
|
+
return Uint8Array.from(out);
|
|
111
|
+
}
|
|
112
|
+
/** test_di (di.c:165-268). */
|
|
113
|
+
function testDi(data, start) {
|
|
114
|
+
const s = data.length - start;
|
|
115
|
+
if (s < 14)
|
|
116
|
+
return 14 - s;
|
|
117
|
+
// Number of samples (di.c:174-177)
|
|
118
|
+
const numsmp = readmem16b(data, start);
|
|
119
|
+
if (numsmp > 31)
|
|
120
|
+
return -1;
|
|
121
|
+
if (s < 14 + numsmp * 8)
|
|
122
|
+
return 14 + numsmp * 8 - s;
|
|
123
|
+
// Finetunes and sample sizes (di.c:180-202)
|
|
124
|
+
let ssize = 0;
|
|
125
|
+
for (let i = 0; i < numsmp; i++) {
|
|
126
|
+
const d = start + i * 8 + 14; // note: fields at +14/+18/+20 within the
|
|
127
|
+
// 8-byte stride window per the C pointer arithmetic (d advances i*8 but
|
|
128
|
+
// field offsets +14/+18/+20 exceed 8 — this matches C exactly).
|
|
129
|
+
const len = readmem16b(data, d) << 1;
|
|
130
|
+
const lstart = readmem16b(data, d + 4) << 1;
|
|
131
|
+
const lsize = readmem16b(data, d + 6) << 1;
|
|
132
|
+
if (len > 0xffff || lstart > 0xffff || lsize > 0xffff)
|
|
133
|
+
return -1;
|
|
134
|
+
if (lstart + lsize > len)
|
|
135
|
+
return -1;
|
|
136
|
+
if (data[d + 2] > 0x0f)
|
|
137
|
+
return -1;
|
|
138
|
+
if (data[d + 3] > 0x40)
|
|
139
|
+
return -1;
|
|
140
|
+
ssize += len;
|
|
141
|
+
}
|
|
142
|
+
if (ssize <= 2)
|
|
143
|
+
return -1;
|
|
144
|
+
// Addresses (di.c:206-216)
|
|
145
|
+
const psize = numsmp * 8 + 2;
|
|
146
|
+
const ptabOfs = readmem32b(data, start + 2);
|
|
147
|
+
const patOfs = readmem32b(data, start + 6);
|
|
148
|
+
const smpOfs = readmem32b(data, start + 10);
|
|
149
|
+
if (ptabOfs < psize)
|
|
150
|
+
return -1;
|
|
151
|
+
if (patOfs <= ptabOfs || smpOfs <= ptabOfs || smpOfs <= patOfs)
|
|
152
|
+
return -1;
|
|
153
|
+
if (patOfs - ptabOfs > 128)
|
|
154
|
+
return -1;
|
|
155
|
+
// Pattern table reliability (di.c:250-254)
|
|
156
|
+
if (s < patOfs)
|
|
157
|
+
return patOfs - s;
|
|
158
|
+
for (let i = ptabOfs; i < patOfs - 1; i++) {
|
|
159
|
+
if (data[start + i] > 0x80)
|
|
160
|
+
return -1;
|
|
161
|
+
}
|
|
162
|
+
// 0xff at the end of the pattern list (di.c:257-260)
|
|
163
|
+
if (data[start + patOfs - 1] !== 0xff)
|
|
164
|
+
return -1;
|
|
165
|
+
// Sample data address > $ffff (di.c:263-266)
|
|
166
|
+
if (smpOfs > 65535)
|
|
167
|
+
return -1;
|
|
168
|
+
pwReadTitle(null, 0);
|
|
169
|
+
return 0;
|
|
170
|
+
}
|
|
171
|
+
/** pw_di: "Digital Illusions". */
|
|
172
|
+
export const pwDi = {
|
|
173
|
+
name: 'Digital Illusions',
|
|
174
|
+
test: testDi,
|
|
175
|
+
depack: depackDi,
|
|
176
|
+
};
|
|
177
|
+
//# sourceMappingURL=pw-di.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pw-di.js","sourceRoot":"","sources":["../src/pw-di.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pw-eureka.d.ts","sourceRoot":"","sources":["../src/pw-eureka.ts"],"names":[],"mappings":"AAKA,OAAO,EAAoC,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAiK9E,8BAA8B;AAC9B,eAAO,MAAM,IAAI,EAAE,QAIlB,CAAC"}
|
|
@@ -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/eureka.c (Eureka Packer) —
|
|
4
|
+
// depack_eu :35-122, test_eu :125-218.
|
|
5
|
+
import { readmem16b, readmem32b, moveData } from './prowiz.js';
|
|
6
|
+
const PW_MOD_MAGIC = 0x4d2e4b2e; // 'M.K.'
|
|
7
|
+
function put32b(out, v) {
|
|
8
|
+
out.push((v >>> 24) & 0xff, (v >> 16) & 0xff, (v >> 8) & 0xff, v & 0xff);
|
|
9
|
+
}
|
|
10
|
+
/** depack_eu (eureka.c:35-122). Header is PTK-compatible. */
|
|
11
|
+
function depackEu(data, start) {
|
|
12
|
+
let pos = start;
|
|
13
|
+
const out = [];
|
|
14
|
+
// header: 1080 bytes moved verbatim (eureka.c:38-40)
|
|
15
|
+
for (let i = 0; i < 1080; i++)
|
|
16
|
+
out.push(data[pos++] ?? 0);
|
|
17
|
+
// whole sample size (eureka.c:43-45): sizes at 42 + i*30
|
|
18
|
+
let ssize = 0;
|
|
19
|
+
for (let i = 0; i < 31; i++) {
|
|
20
|
+
ssize += 2 * ((data[start + i * 30 + 42] << 8) | data[start + i * 30 + 43]);
|
|
21
|
+
}
|
|
22
|
+
// pattern list max (eureka.c:47-53)
|
|
23
|
+
let npat = 0;
|
|
24
|
+
for (let i = 0; i < 128; i++) {
|
|
25
|
+
if (data[start + 952 + i] > npat)
|
|
26
|
+
npat = data[start + 952 + i];
|
|
27
|
+
}
|
|
28
|
+
npat++;
|
|
29
|
+
put32b(out, PW_MOD_MAGIC);
|
|
30
|
+
const smpAddr = readmem32b(data, pos);
|
|
31
|
+
pos += 4; // sample data address
|
|
32
|
+
// Track addresses (eureka.c:56-61)
|
|
33
|
+
const trkAddr = [];
|
|
34
|
+
for (let i = 0; i < npat; i++) {
|
|
35
|
+
const row = [];
|
|
36
|
+
for (let j = 0; j < 4; j++) {
|
|
37
|
+
row.push((data[pos] << 8) | data[pos + 1]);
|
|
38
|
+
pos += 2;
|
|
39
|
+
}
|
|
40
|
+
trkAddr.push(row);
|
|
41
|
+
}
|
|
42
|
+
// Track data (eureka.c:64-110): 4 cell forms per 2-bit prefix.
|
|
43
|
+
for (let i = 0; i < npat; i++) {
|
|
44
|
+
const tmp = new Uint8Array(1024);
|
|
45
|
+
for (let j = 0; j < 4; j++) {
|
|
46
|
+
pos = start + trkAddr[i][j];
|
|
47
|
+
for (let k = 0; k < 64; k++) {
|
|
48
|
+
const x = k * 16 + j * 4;
|
|
49
|
+
const c1 = data[pos++] ?? 0;
|
|
50
|
+
if ((c1 & 0xc0) === 0x00) {
|
|
51
|
+
// full 4-byte cell (eureka.c:67-72)
|
|
52
|
+
tmp[x] = c1;
|
|
53
|
+
tmp[x + 1] = data[pos++] ?? 0;
|
|
54
|
+
tmp[x + 2] = data[pos++] ?? 0;
|
|
55
|
+
tmp[x + 3] = data[pos++] ?? 0;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if ((c1 & 0xc0) === 0xc0) {
|
|
59
|
+
k += c1 & 0x3f; // blank rows (eureka.c:73-76)
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
if ((c1 & 0xc0) === 0x40) {
|
|
63
|
+
// effect-only (eureka.c:77-82)
|
|
64
|
+
tmp[x + 2] = c1 & 0x0f;
|
|
65
|
+
tmp[x + 3] = data[pos++] ?? 0;
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if ((c1 & 0xc0) === 0x80) {
|
|
69
|
+
// note+ins without effect (eureka.c:83-88)
|
|
70
|
+
tmp[x] = data[pos++] ?? 0;
|
|
71
|
+
tmp[x + 1] = data[pos++] ?? 0;
|
|
72
|
+
tmp[x + 2] = (c1 << 4) & 0xf0;
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
for (let k = 0; k < 1024; k++)
|
|
78
|
+
out.push(tmp[k]);
|
|
79
|
+
}
|
|
80
|
+
// Sample data (eureka.c:113-116)
|
|
81
|
+
moveData(data, start + smpAddr, out, ssize);
|
|
82
|
+
return Uint8Array.from(out);
|
|
83
|
+
}
|
|
84
|
+
/** test_eu (eureka.c:125-218). */
|
|
85
|
+
function testEu(data, start) {
|
|
86
|
+
const s = data.length - start;
|
|
87
|
+
if (s < 1084)
|
|
88
|
+
return 1084 - s;
|
|
89
|
+
// test 2 (eureka.c:131-135)
|
|
90
|
+
const len = data[start + 950];
|
|
91
|
+
if (len === 0 || len > 127)
|
|
92
|
+
return -1;
|
|
93
|
+
// test #3 (eureka.c:137-156)
|
|
94
|
+
for (let i = 0; i < 31; i++) {
|
|
95
|
+
const d = start + i * 30;
|
|
96
|
+
const size = readmem16b(data, d + 42) << 1;
|
|
97
|
+
const lstart = readmem16b(data, d + 46) << 1;
|
|
98
|
+
const lsize = readmem16b(data, d + 48) << 1;
|
|
99
|
+
if (size > 0xffff || lstart > 0xffff || lsize > 0xffff)
|
|
100
|
+
return -1;
|
|
101
|
+
if (lstart + lsize > size + 2)
|
|
102
|
+
return -1;
|
|
103
|
+
if (data[d + 44] > 0x0f || data[d + 45] > 0x40)
|
|
104
|
+
return -1;
|
|
105
|
+
}
|
|
106
|
+
// test 4 (eureka.c:159-167)
|
|
107
|
+
const smpOfs = readmem32b(data, start + 1080);
|
|
108
|
+
if (smpOfs < 1084)
|
|
109
|
+
return -1;
|
|
110
|
+
// Pattern list (eureka.c:169-183)
|
|
111
|
+
let maxPat = 0;
|
|
112
|
+
let i = 0;
|
|
113
|
+
for (; i < len; i++) {
|
|
114
|
+
const pat = data[start + 952 + i];
|
|
115
|
+
if (pat > 127)
|
|
116
|
+
return -1;
|
|
117
|
+
if (pat > maxPat)
|
|
118
|
+
maxPat = pat;
|
|
119
|
+
}
|
|
120
|
+
for (; i < 128; i++) {
|
|
121
|
+
if (data[start + 952 + i] !== 0)
|
|
122
|
+
return -1;
|
|
123
|
+
}
|
|
124
|
+
maxPat++;
|
|
125
|
+
// Track address bounds (eureka.c:186-199)
|
|
126
|
+
let maxTrk = 0;
|
|
127
|
+
let minTrk = 999999;
|
|
128
|
+
if (s < maxPat * 4 * 2 + 1085)
|
|
129
|
+
return maxPat * 4 * 2 + 1085 - s;
|
|
130
|
+
for (i = 0; i < maxPat * 4; i++) {
|
|
131
|
+
const trk = readmem16b(data, start + i * 2 + 1084);
|
|
132
|
+
if (trk > smpOfs || trk < 1084)
|
|
133
|
+
return -1;
|
|
134
|
+
if (trk > maxTrk)
|
|
135
|
+
maxTrk = trk;
|
|
136
|
+
if (trk < minTrk)
|
|
137
|
+
minTrk = trk;
|
|
138
|
+
}
|
|
139
|
+
if (s < maxTrk)
|
|
140
|
+
return maxTrk - s;
|
|
141
|
+
// Track data sanity (eureka.c:203-215)
|
|
142
|
+
for (i = minTrk; i < maxTrk; i++) {
|
|
143
|
+
const c = data[start + i];
|
|
144
|
+
if ((c & 0xc0) === 0xc0)
|
|
145
|
+
continue;
|
|
146
|
+
if ((c & 0xc0) === 0x80) {
|
|
147
|
+
i += 2;
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
if ((c & 0xc0) === 0x40) {
|
|
151
|
+
if ((c & 0x3f) === 0 && data[start + i + 1] === 0)
|
|
152
|
+
return -1;
|
|
153
|
+
i++;
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
if ((c & 0xc0) === 0) {
|
|
157
|
+
if (c > 0x13)
|
|
158
|
+
return -1;
|
|
159
|
+
i += 3;
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return 0;
|
|
164
|
+
}
|
|
165
|
+
/** pw_eu: "Eureka Packer". */
|
|
166
|
+
export const pwEu = {
|
|
167
|
+
name: 'Eureka Packer',
|
|
168
|
+
test: testEu,
|
|
169
|
+
depack: depackEu,
|
|
170
|
+
};
|
|
171
|
+
//# sourceMappingURL=pw-eureka.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pw-eureka.js","sourceRoot":"","sources":["../src/pw-eureka.ts"],"names":[],"mappings":"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"}
|
package/dist/pw-fcm.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pw-fcm.d.ts","sourceRoot":"","sources":["../src/pw-fcm.ts"],"names":[],"mappings":"AAKA,OAAO,EAAe,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAoGzD,6BAA6B;AAC7B,eAAO,MAAM,KAAK,EAAE,QAInB,CAAC"}
|
package/dist/pw-fcm.js
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// SPDX-License-Identifier: BSD-3-Clause
|
|
2
|
+
// Copyright (c) 2026 Bitti09 — modplayjs contributors
|
|
3
|
+
// Ported from: libxmp src/loaders/prowizard/fc-m.c (FC-M Packer 1.0) —
|
|
4
|
+
// depack_fcm :33-93, test_fcm :95-123.
|
|
5
|
+
import { pwReadTitle } from './prowiz.js';
|
|
6
|
+
const PW_MOD_MAGIC = 0x4d2e4b2e; // 'M.K.'
|
|
7
|
+
function put8(out, b) { out.push(b & 0xff); }
|
|
8
|
+
function put16b(out, v) { out.push((v >> 8) & 0xff, v & 0xff); }
|
|
9
|
+
function put32b(out, v) {
|
|
10
|
+
out.push((v >>> 24) & 0xff, (v >> 16) & 0xff, (v >> 8) & 0xff, v & 0xff);
|
|
11
|
+
}
|
|
12
|
+
/** depack_fcm (fc-m.c:33-93) — chunked container, mostly verbatim moves. */
|
|
13
|
+
function depackFcm(data, start) {
|
|
14
|
+
let pos = start;
|
|
15
|
+
const out = [];
|
|
16
|
+
const u8 = () => data[pos++] ?? 0;
|
|
17
|
+
const u16 = () => { const v = (data[pos] << 8) | data[pos + 1]; pos += 2; return v; };
|
|
18
|
+
const u32 = () => { const v = read32(data, pos); pos += 4; return v; };
|
|
19
|
+
const read32 = (d, o) => ((d[o] << 24) | (d[o + 1] << 16) | (d[o + 2] << 8) | d[o + 3]) >>> 0;
|
|
20
|
+
u32(); // bypass "FC-M" ID
|
|
21
|
+
u16(); // version number?
|
|
22
|
+
u32(); // bypass "NAME" chunk
|
|
23
|
+
// title: move 20 bytes (fc-m.c:42)
|
|
24
|
+
for (let i = 0; i < 20; i++)
|
|
25
|
+
out.push(data[pos++] ?? 0);
|
|
26
|
+
u32(); // bypass "INST" chunk
|
|
27
|
+
// Sample descriptions (fc-m.c:46-57)
|
|
28
|
+
let ssize = 0;
|
|
29
|
+
for (let i = 0; i < 31; i++) {
|
|
30
|
+
for (let k = 0; k < 22; k++)
|
|
31
|
+
out.push(0); // sample name
|
|
32
|
+
const size = u16();
|
|
33
|
+
put16b(out, size);
|
|
34
|
+
ssize += size * 2;
|
|
35
|
+
put8(out, u8()); // finetune
|
|
36
|
+
put8(out, u8()); // volume
|
|
37
|
+
put16b(out, u16()); // loop start
|
|
38
|
+
let loopSize = u16();
|
|
39
|
+
if (loopSize === 0)
|
|
40
|
+
loopSize = 1;
|
|
41
|
+
put16b(out, loopSize);
|
|
42
|
+
}
|
|
43
|
+
u32(); // bypass "LONG" chunk
|
|
44
|
+
const patPos = u8();
|
|
45
|
+
put8(out, patPos);
|
|
46
|
+
put8(out, u8()); // NoiseTracker byte
|
|
47
|
+
u32(); // bypass "PATT" chunk
|
|
48
|
+
// Pattern list (fc-m.c:63-68)
|
|
49
|
+
let patMax = 0;
|
|
50
|
+
let i = 0;
|
|
51
|
+
for (; i < patPos; i++) {
|
|
52
|
+
const c1 = u8();
|
|
53
|
+
put8(out, c1);
|
|
54
|
+
if (c1 > patMax)
|
|
55
|
+
patMax = c1;
|
|
56
|
+
}
|
|
57
|
+
for (; i < 128; i++)
|
|
58
|
+
put8(out, 0);
|
|
59
|
+
put32b(out, PW_MOD_MAGIC);
|
|
60
|
+
u32(); // bypass "SONG" chunk
|
|
61
|
+
// Pattern data (fc-m.c:72-74): verbatim 1024-byte blocks
|
|
62
|
+
for (i = 0; i <= patMax; i++) {
|
|
63
|
+
for (let k = 0; k < 1024; k++)
|
|
64
|
+
out.push(data[pos++] ?? 0);
|
|
65
|
+
}
|
|
66
|
+
u32(); // bypass "SAMP" chunk
|
|
67
|
+
// Sample data (fc-m.c:75-76)
|
|
68
|
+
for (let k = 0; k < ssize && pos < data.length; k++)
|
|
69
|
+
out.push(data[pos++] ?? 0);
|
|
70
|
+
return Uint8Array.from(out);
|
|
71
|
+
}
|
|
72
|
+
/** test_fcm (fc-m.c:95-123). */
|
|
73
|
+
function testFcm(data, start) {
|
|
74
|
+
const s = data.length - start;
|
|
75
|
+
if (s < 37 + 8 * 31)
|
|
76
|
+
return 37 + 8 * 31 - s;
|
|
77
|
+
// "FC-M" (fc-m.c:100-104)
|
|
78
|
+
if (data[start] !== 0x46 || data[start + 1] !== 0x43 ||
|
|
79
|
+
data[start + 2] !== 0x2d || data[start + 3] !== 0x4d) {
|
|
80
|
+
return -1;
|
|
81
|
+
}
|
|
82
|
+
// test 1 (fc-m.c:106-109)
|
|
83
|
+
if (data[start + 4] !== 0x01)
|
|
84
|
+
return -1;
|
|
85
|
+
// test 2 (fc-m.c:111-114)
|
|
86
|
+
if (data[start + 5] !== 0x00)
|
|
87
|
+
return -1;
|
|
88
|
+
// test 3 (fc-m.c:116-120)
|
|
89
|
+
for (let j = 0; j < 31; j++) {
|
|
90
|
+
if (data[start + 37 + 8 * j] > 0x40)
|
|
91
|
+
return -1;
|
|
92
|
+
}
|
|
93
|
+
pwReadTitle(data.subarray(start + 10), 20);
|
|
94
|
+
return 0;
|
|
95
|
+
}
|
|
96
|
+
/** pw_fcm: "FC-M Packer". */
|
|
97
|
+
export const pwFcm = {
|
|
98
|
+
name: 'FC-M Packer',
|
|
99
|
+
test: testFcm,
|
|
100
|
+
depack: depackFcm,
|
|
101
|
+
};
|
|
102
|
+
//# sourceMappingURL=pw-fcm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pw-fcm.js","sourceRoot":"","sources":["../src/pw-fcm.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pw-fuchs.d.ts","sourceRoot":"","sources":["../src/pw-fuchs.ts"],"names":[],"mappings":"AAKA,OAAO,EAAuC,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AA8IjF,gCAAgC;AAChC,eAAO,MAAM,MAAM,EAAE,QAIpB,CAAC"}
|
package/dist/pw-fuchs.js
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
// SPDX-License-Identifier: BSD-3-Clause
|
|
2
|
+
// Copyright (c) 2026 Bitti09 — modplayjs contributors
|
|
3
|
+
// Ported from: libxmp src/loaders/prowizard/fuchs.c (Fuchs Tracker) —
|
|
4
|
+
// depack_fuchs :35-143, test_fuchs :145-200.
|
|
5
|
+
import { readmem16b, readmem32b, pwReadTitle } from './prowiz.js';
|
|
6
|
+
const PW_MOD_MAGIC = 0x4d2e4b2e; // 'M.K.'
|
|
7
|
+
function put32b(out, v) {
|
|
8
|
+
out.push((v >>> 24) & 0xff, (v >> 16) & 0xff, (v >> 8) & 0xff, v & 0xff);
|
|
9
|
+
}
|
|
10
|
+
/** depack_fuchs (fuchs.c:35-143). */
|
|
11
|
+
function depackFuchs(data, start) {
|
|
12
|
+
let pos = start;
|
|
13
|
+
const out = [];
|
|
14
|
+
const u16 = () => { const v = readmem16b(data, pos); pos += 2; return v; };
|
|
15
|
+
const u32 = () => { const v = readmem32b(data, pos); pos += 4; return v; };
|
|
16
|
+
// Fuchs builds a full 1080-byte PTK header in `data`.
|
|
17
|
+
const hdr = new Uint8Array(1080);
|
|
18
|
+
// title: 10 bytes moved (fuchs.c:40)
|
|
19
|
+
for (let i = 0; i < 10; i++)
|
|
20
|
+
hdr[i] = data[pos++] ?? 0;
|
|
21
|
+
u32(); // all sample data size
|
|
22
|
+
// sample sizes (fuchs.c:44-49): smp_len → data[42+i*30], [43+i*30]
|
|
23
|
+
const smpLen = [];
|
|
24
|
+
for (let i = 0; i < 16; i++) {
|
|
25
|
+
const l = u16();
|
|
26
|
+
smpLen.push(l);
|
|
27
|
+
hdr[42 + i * 30] = (l >> 9) & 0xff;
|
|
28
|
+
hdr[43 + i * 30] = (l >> 1) & 0xff;
|
|
29
|
+
}
|
|
30
|
+
// volumes (fuchs.c:52-55): data[45+i*30]
|
|
31
|
+
for (let i = 0; i < 16; i++) {
|
|
32
|
+
hdr[45 + i * 30] = u16() & 0xff;
|
|
33
|
+
}
|
|
34
|
+
// loop start (fuchs.c:58-63)
|
|
35
|
+
const loopStart = [];
|
|
36
|
+
for (let i = 0; i < 16; i++) {
|
|
37
|
+
const l = u16();
|
|
38
|
+
loopStart.push(l);
|
|
39
|
+
hdr[46 + i * 30] = (l >> 1) & 0xff;
|
|
40
|
+
}
|
|
41
|
+
// replen (fuchs.c:66-79)
|
|
42
|
+
for (let i = 0; i < 16; i++) {
|
|
43
|
+
const loopSize = smpLen[i] - loopStart[i];
|
|
44
|
+
if (loopSize === 0 || loopStart[i] === 0) {
|
|
45
|
+
hdr[49 + i * 30] = 1;
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
hdr[48 + i * 30] = (loopSize >> 9) & 0xff;
|
|
49
|
+
hdr[49 + i * 30] = (loopSize >> 1) & 0xff;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// fill replens for samples 16..30 with $0001 (fuchs.c:82-85)
|
|
53
|
+
for (let i = 16; i < 31; i++) {
|
|
54
|
+
hdr[49 + i * 30] = 1;
|
|
55
|
+
}
|
|
56
|
+
// pattern list (fuchs.c:89-99): count @950, ntk @951, 40 u16 entries
|
|
57
|
+
hdr[950] = u16() & 0xff;
|
|
58
|
+
hdr[951] = 0x7f;
|
|
59
|
+
let maxPat = 0;
|
|
60
|
+
for (let i = 0; i < 40; i++) {
|
|
61
|
+
const pat = u16();
|
|
62
|
+
hdr[952 + i] = pat & 0xff;
|
|
63
|
+
if (pat > maxPat)
|
|
64
|
+
maxPat = pat;
|
|
65
|
+
}
|
|
66
|
+
// write the 1080-byte header (fuchs.c:102-106)
|
|
67
|
+
for (let i = 0; i < 1080; i++)
|
|
68
|
+
out.push(hdr[i]);
|
|
69
|
+
put32b(out, PW_MOD_MAGIC);
|
|
70
|
+
// pattern data (fuchs.c:109-127): bypass "SONG" ID, read size, convert
|
|
71
|
+
u32(); // "SONG" ID
|
|
72
|
+
const patSize = u32();
|
|
73
|
+
if (patSize === 0 || patSize > 0x20000 || (patSize & 0x3) !== 0) {
|
|
74
|
+
throw new Error('fuchs: bad pattern size');
|
|
75
|
+
}
|
|
76
|
+
const tmp = new Uint8Array(patSize);
|
|
77
|
+
for (let i = 0; i < patSize; i++)
|
|
78
|
+
tmp[i] = data[pos++] ?? 0;
|
|
79
|
+
// convert fx C arg back to hex value (fuchs.c:130-134)
|
|
80
|
+
for (let i = 0; i < patSize; i += 4) {
|
|
81
|
+
if ((tmp[i + 2] & 0x0f) === 0x0c) {
|
|
82
|
+
const x = tmp[i + 3];
|
|
83
|
+
tmp[i + 3] = 10 * (x >> 4) + (x & 0xf);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// write pattern data (fuchs.c:137-139)
|
|
87
|
+
for (let i = 0; i < patSize; i++)
|
|
88
|
+
out.push(tmp[i]);
|
|
89
|
+
// sample data (fuchs.c:142-149): bypass "INST" ID, sequential non-empty
|
|
90
|
+
pos += 4; // "INST" Id
|
|
91
|
+
for (let i = 0; i < 16; i++) {
|
|
92
|
+
if (smpLen[i] !== 0) {
|
|
93
|
+
for (let k = 0; k < smpLen[i] && pos < data.length; k++)
|
|
94
|
+
out.push(data[pos++] ?? 0);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return Uint8Array.from(out);
|
|
98
|
+
}
|
|
99
|
+
/** test_fuchs (fuchs.c:145-200). */
|
|
100
|
+
function testFuchs(data, start) {
|
|
101
|
+
const s = data.length - start;
|
|
102
|
+
if (s < 196)
|
|
103
|
+
return 196 - s;
|
|
104
|
+
// "SONG" at 192 (fuchs.c:149-150)
|
|
105
|
+
if (readmem32b(data, start + 192) !== 0x534f4e47)
|
|
106
|
+
return -1;
|
|
107
|
+
// all sample size (fuchs.c:153-156)
|
|
108
|
+
const hdrSsize = readmem32b(data, start + 10);
|
|
109
|
+
if (hdrSsize <= 2 || hdrSsize >= 65535 * 16)
|
|
110
|
+
return -1;
|
|
111
|
+
// sample descriptions (fuchs.c:159-177): fields at i*2 strides per C
|
|
112
|
+
let ssize = 0;
|
|
113
|
+
for (let i = 0; i < 16; i++) {
|
|
114
|
+
const d = start + i * 2;
|
|
115
|
+
const len = readmem16b(data, d + 14);
|
|
116
|
+
const lstart = readmem16b(data, d + 78);
|
|
117
|
+
if (data[d + 46] > 0x40)
|
|
118
|
+
return -1; // volumes
|
|
119
|
+
if (len < lstart)
|
|
120
|
+
return -1;
|
|
121
|
+
ssize += len;
|
|
122
|
+
}
|
|
123
|
+
if (ssize <= 2 || ssize > hdrSsize)
|
|
124
|
+
return -1;
|
|
125
|
+
// pattern list entries <= 40 (fuchs.c:182-190)
|
|
126
|
+
for (let i = 0; i < 40; i++) {
|
|
127
|
+
if (data[start + i * 2 + 113] > 40)
|
|
128
|
+
return -1;
|
|
129
|
+
}
|
|
130
|
+
pwReadTitle(null, 0);
|
|
131
|
+
return 0;
|
|
132
|
+
}
|
|
133
|
+
/** pw_fchs: "Fuchs Tracker". */
|
|
134
|
+
export const pwFchs = {
|
|
135
|
+
name: 'Fuchs Tracker',
|
|
136
|
+
test: testFuchs,
|
|
137
|
+
depack: depackFuchs,
|
|
138
|
+
};
|
|
139
|
+
//# sourceMappingURL=pw-fuchs.js.map
|