Closed shooking closed 3 years ago
And now I realise, after writing my own ZD2 parser, you already did most of what I do with your construct and Python.
Just incase you are interested it is also possible to pull out the parameter names directly from the ZD2.
/*
** OK so we look for
** 54 58 45 31 == TXE1
** 4f 6e 4f 66 66 == OnOff (later we try to work out a vector to this offset)
** 50 52 4d 4a == PRMJ - like PRME but with binary data
** 50 52 4d 45 == PRME - more readable form
*/
I am pretty sure the PRMJ is Japanese and E is English. Why?
Infile: ZNR.ZD2
Filesize: 26307
INPUT
FX: ZNR
VERSION: 1.30
Mungewell's ID
01 00 00 40
FXID: 64(0040) FXGID: 8(0008)
...
PRMJstart = 61f3( 25075)
"Parameters":[
{
"name":"DETCT",
"explanation":"制御信号の検出位置を選択します。",
"blackback":false,
"pedal":false
},
{
"name":"Depth",
"explanation":"ノイズリダクションの深さを設定します。",
"blackback":false,
"pedal":false
},
{
"name":"THRSH",
"explanation":"効果が現れる閾値を調節します。",
"blackback":false,
"pedal":false
},
{
"name":"Decay",
"explanation":"減衰時間を調節します。",
"blackback":false,
"pedal":false
}
]
PRMEstart = 6470( 25712)
"Parameters":[
{
"name":"DETCT",
"explanation":"Sets control signal detection level.",
"blackback":false,
"pedal":false
},
{
"name":"Depth",
"explanation":"Sets the depth of noise reduction.",
"blackback":false,
"pedal":false
},
{
"name":"THRSH",
"explanation":"Adjusts the effect sensitivity.",
"blackback":false,
"pedal":false
},
{
"name":"Decay",
"explanation":"Adjust the envelope release.",
"blackback":false,
"pedal":false
}
]
Not sure if you already done this but I also managed to pull out the bitmaps. Write from hex 88 offset to bitmap file size [[there is a BM at 0x88, the header is standard bitmap]]. The size is int from bytes 0x8a - 0x8d (fileSize in struct below)
typedef struct t_bmHeader {
BYTE signature[2];
BYTE fileSize[4];
BYTE reserved[4];
BYTE dataOffset[4];
} bmHeader;
typedef struct t_bmInfoHeader {
BYTE size[4];
BYTE width[4];
BYTE height[4];
BYTE planes[2];
BYTE bitsPerPixel[2];
BYTE compression[4];
BYTE imageSize[4];
BYTE xPixelsPerM[4];
BYTE yPixelsPerM[4];
BYTE coloursUsed[4];
BYTE importantColours[4];
} bmInfoHeader;
typedef struct t_bmColourTable{
BYTE red;
BYTE green;
BYTE blue;
BYTE reserved;
} bmColourTable;
need 2 of the above colour .. one for white, one for black.
I am almost there with the decode now. Thanks for all your tips. Now to write it in Lua for Ctrlr.
OK and now I see the Max midi value, that I was getting from the CycleFXData, is also available in the ZD2 files ... nice!
pi@raspberrypi:~/Software/ZoomPedal/ZD2 $ ../ParseZD2_000 HALL.ZD2
Infile: HALL.ZD2
Filesize: 17933
INPUT
"FX": {
"name" : "Hall",
"filename": "HALL.ZD2"
"bmpname": "HALL.ZD2.BMP"
"version" : "1.50",
"FXID" : 48,
"FXGID": 9,
"groupName": "REVERB",
"description" : "This reverb effect simulates the acoustics of a concert hall.",
OnOffStart = 1502( 5378)
O (4f) n (6e) O (4f) f (66) f (66) (00) (00) (00)
(00) (00) (00) (00) (01) (00) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00)
(00) (00) (00) (00) \u00b4 (b4)
(0a) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00) Max midi: 1, default: 0
H (48) a (61) l (6c) l (6c) (00) (00) (00) (00)
(00) (00) (00) (00) \u00ff (ff) \u00ff (ff) \u00ff (ff) \u00ff (ff)
(00) (00) (00) (00) (01) (00) (00) (00)
(00) (00) (00) (00) (14)
(0c) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00) Max midi: -1, default: 0
P (50) r (72) e (65) D (44) (00) (00) (00) (00)
(00) (00) (00) (00) c (63) (00) (00) (00)
0 (30) (00) (00) (00) (00) (00) (00) (00)
(00) (00) (00) (00) 0 (30) (09) (00) (00)
(0d) (00) (00) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00) Max midi: 99, default: 48
D (44) e (65) c (63) a (61) y (79) (00) (00) (00)
(00) (00) (00) (00) (1d) (00) (00) (00)
(09) (00) (00) (00) (1d) (00) (00) (00)
(00) (00) (00) (00) \u00ec (ec)
(0c) (00) (00)
(0d) (00) (00) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00)
(10) (00) (00) (00) (00) (00) (00) (00) Max midi: 29, default: 9
M (4d) i (69) x (78) (00) (00) (00) (00) (00)
(00) (00) (00) (00) d (64) (00) (00) (00)
. (2e) (00) (00) (00) d (64) (00) (00) (00)
(00) (00) (00) (00) \u00c8 (c8)
(0b) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00)
(10) (00) (00) (00) (00) (00) (00) (00) Max midi: 100, default: 46
T (54) a (61) i (69) l (6c) (00) (00) (00) (00)
(00) (00) (00) (00) (01) (00) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00)
(00) (00) (00) (00) \u00b4 (b4)
(0a) (00) (00)
(0d) (00) (00) (00) (9a)
(00) (00) (00) (00) (00) (00) (00) (00)
(06) (00) (00) (00) (00) (00) (00) (00) Max midi: 1, default: 0
(17) (00) (00) (00) (1e) (00) (00) (00)
\u00d8 (d8) (06) (00) (80) (14) (00) (00) (00)
(0a) (00) (00) (00) \u00c0 (c0) (07) (00) (80)
(18) (00) (00) (00) (16) (00) (00) (00)
8 (38) (07) (00) (80) (00) (00) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00) Max midi: 20, default: 10
(00) (00) (00) (00) (00) (00) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00) Max midi: 0, default: 0
(00) (00) (00) (00) (00) (00) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00) Max midi: 0, default: 0
(00) (00) (00) (00) (00) (00) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00)
(00) (00) (00) (00) (00) (00) (00) (00) Max midi: 0, default: 0
"Parameters":[
{
"name":"PreD",
"explanation":"Adjusts the delay between input of the original sound and start of the reverb sound.",
"blackback":false,
"pedal":false
},
{
"name":"Decay",
"explanation":"Sets the duration of the reverberations.",
"blackback":false,
"pedal":false
},
{
"name":"Mix",
"explanation":"Adjusts the amount of effected sound that is mixed with the original sound.",
"blackback":false,
"pedal":false
},
{
"name":"Tail",
"explanation":"When ON, effect sound continues even after effect is turned off. When OFF, effect sound stops right when effect is turned off.",
"blackback":false,
"pedal":false
}
]
Basically I look for the OnOffstart, and values are relative to that
// 5 is longest hex string we look for
for (unsigned int i = 0; i < unpacked.size() - 5; i++)
{
..
else if
(
unpacked[i] == 0x4f && unpacked[i+1] == 0x6e &&
unpacked[i+2] == 0x4f && unpacked[i+3] == 0x66 &&
unpacked[i+4] == 0x66
)
{
OnOffstart = i + 5;
}
...
if (OnOffstart !=-1)
{
// we need to work out offset
printf("OnOffStart = %8x(%8d)\n", OnOffstart, OnOffstart);
// OnOff, Name, 1 - 8 parameters?
for (int j = 0; j < 10; j++)
{
for (size_t i = 0; i < 0x38; i++)
{
if (i % 8 == 0) printf("\n");
int v = unpacked[OnOffstart - 5 + j * 0x38 + i];
printf("%2c (%02x) ", v, v);
}
// so [12, 13] and [16, 17] for each param is interesting
short mmax =
unpacked[OnOffstart - 5 + j * 0x38 + 12] +
unpacked[OnOffstart - 5 + j * 0x38 + 13] * 256;
short mcurr =
unpacked[OnOffstart - 5 + j * 0x38 + 16] +
unpacked[OnOffstart - 5 + j * 0x38 + 17] * 256;
printf("Max midi: %d, default: %d\n", mmax, mcurr);
printf("\n");
}
}
This is almost everything I need!
Added some of this functionality to 'decode_effect.py' https://github.com/mungewell/zoom-zt2/commit/e38bf2dcf870b7127840fd7d611c9f505c68197f
forgot to close this - sorry. Great work as ever
Hi Mungewell
I managed to find some time to revisit the Zoom pedals recently - your decode preset was super useful. C, inspite of its lovely low level bit operators, caused me no end of grief with bit arrays, packing and struct alignment.
Anyhow in your excellent work you find IDs like:
It's taken me an age to realise this can be interpreted as two shorts that store hints on the FXID and GID. So your ID can also be viewed as GID x 32 (first short) and FXID (2nd short).
I am sure you already know this - just incase others are not aware. Likely it is some misaligned bit pattern.
What is not so clear. On some FX the slot is 2 wide (we know this but I not yet managed to find from the preset alone). I think the decode_screens knows this right?
But I was able to then set "7" FX on a single preset :-). Now it is only 5, but well a bit odd. And this is somewhat non-deterministic. So I can get the 7th slot to add an FX sometimes, not others.
I used this program to drive it.
I generated the decode of the patch. Then deleted - notice I then had to adjust the slot IDs for my code.
Original state:
So sometimes FXM_Delete.sh 7 actually deletes slot 1. Quite literally odd.