Open mungewell opened 5 years ago
Zoom just announced the A1Four/A1FourX, which apart from different effects have a couple of other interesting things. 1). Drum patterns are different. 2). Looper can be placed either before or after effects chain.
Obviously no F/W available yet, but will good to look at these features when it is...
They don't appear to be in the standard SMF format I would half have have expected,given their history of manufacturing rhythm machines. I could be wrong on this though, still investigating. I would expect patterns still to have delta trigger timings for hits of each pattern but without knowing the format this will,obviously, be tricky.
This ties in with what I am trying to unravel. Knowing the actual structure of ZDL (in my case) or ZD2 files would open up a whole new world allowing new effects to be programmed. Much of them appear to be graphic data and crap spewed from the linker. Using simple effects, such as LineSel, would reveal much about the hardware froma coding point of view and I would love to be able to recreate the ZDL format.
Willkeep nibbling away at it as and when I have time here. Great work by the way, your guys information is a great help.
Oh, to answer your initial question... The drum patterns, samples, rhythm and looper(s) code are in the BIN folder of the firmware updaters self-contained resources. In the case of the G5n/G1Xon, at least, it is filename "129".
PS: Pondering on my wish to code for the devices, all I actualy need is to know where the code segment is in a ZDL as I should then be able to use existing effects as a template. I assume a checksumor three isinvolved but will deal with that later. I should be abletoworkout how the hardware is mapped with that information. No definitve joy, sofar...
Further information on drum patterns. In the resource mentioned, and others, areas appear to be dilineated by the ASCII string "YSX". Using SMF format, although logical and easier to mod, would have been inefficient as there is no need here for things such as individual note off, velocity, volume/etc information and complete overkill. All that is needed in a simple rhythm loop player like this are patterns of delta timings, which can be easily manipulated for tempo changes and a trigger number (1 of 24 in this case I believe). Each would only need to be 8 bits and I would expect at least an end marker for each pattern but that isn't a given as the player may be working from a list start addresses and lengths. There are a number of areas that look interesting. I'm only scanning in between other things here in case a penny drops.
Also, my wish to get some code into the puppies is looking suspect at this point as I'm beginning to believe that code is decrypted by the boot ROM(s) upon transfer. In which case ZOOM did their job properly. sigh
Okay, I have found what I believe to be indexes to the rhythm patterns. But at this point I don't understand what file they are indexing or what the baseline for the index is. But it's a start. Perhaps.
Wow you seem to be 'storming ahead'! I attempted to find the '129' file, but my Java-Fu is weak. How can I get a copy of the file? Either by using the f/w tool, or downloading from the device. For files like this it may be helpful to view as hex, as you say it only needs to contain 'events' for the drum hits... perhaps this are encoded into a binary blob.
The installer executables are zip archives, just extract them. I actually have no use for this rhythm stuff personally but am intrigued at the moment. Need another cuppa, this actuallymay be simpler than I thought...
Actually, being able to install a setup with less effects but more complex rhythms would be useful thinking about it....
If you look at the section where the sample filenames are there is a string of 7 bytes directly before each pattern name each terminated by C0. There are possibly 8 - 10 bytes in the string but the first three are zeroes, the first of which I suspect is a string terminator from the preceding filename. Some examples...
04 04 02 20 B7 0D C0 ; Guide 04 04 02 58 B2 0D C0 ; 8Beats1 04 04 02 88 87 0D C0 ; 8Beats2 04 04 02 18 87 0D C0 ; 8Beats3 04 04 02 58 85 0D C0 ; 16Beats1 04 04 02 E8 6A 0D C0 ; 16Beats2 04 04 02 48 6A 0D C0 ; 16Beats3 ... 05 04 02 58 94 0D C0 ; CtWaltz1 03 04 02 78 A9 0D C0 ; CtWaltz2 03 04 02 B8 A2 0D C0 ; JzWaltz1 03 04 02 F0 AE 0D C0 ; JzWaltz2 03 04 02 98 A0 0D C0 ; Metro3 03 04 02 C8 B4 0D C0 ; Metro4 04 04 02 A8 B3 0D C0 ; Metro5 05 04 02 70 B2 0D C0 ; Metro
Bytes 3-5 look like poiners to me as they are generally linear as you work through the list, C0 a terminator/identifier/padding with others control bytes of some kind. IF they are pointers.the only file big enough to contain data with a 24 bit offset is file "136" in the updater resources.
Or bytes 3-4 could be a 16 bit pointer...
I think that the size and the contents show that the '129' file is very much more than just the drum patterns. There is a section which looks like it is assigning which sounds are used for which pattern...
00064D20: 00 03 04 02 30 02 18 C0 4A 7A 57 61 6C 74 7A 31 ....0...JzWaltz1
00064D30: 00 00 00 00 00 00 00 00 00 00 00 00 00 53 6E 72 .............Snr
00064D40: 41 6D 62 2E 72 61 77 00 00 53 6E 72 32 2E 72 61 Amb.raw..Snr2.ra
00064D50: 77 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 w...............
00064D60: 00 00 00 00 00 00 00 00 00 00 00 00 00 52 69 64 .............Rid
00064D70: 65 2E 72 61 77 00 00 00 00 00 00 00 00 00 00 00 e.raw...........
00064D80: 00 00 00 00 00 4B 69 6B 41 6D 62 2E 72 61 77 00 .....KikAmb.raw.
00064D90: 00 43 6C 69 63 6B 2E 72 61 77 00 00 00 03 04 02 .Click.raw......
00064DA0: 10 0F 18 C0 4A 7A 57 61 6C 74 7A 32 00 4B 69 6B ....JzWaltz2.Kik
00064DB0: 32 2E 72 61 77 00 00 00 00 53 6E 72 41 6D 62 2E 2.raw....SnrAmb.
00064DC0: 72 61 77 00 00 53 6E 72 32 2E 72 61 77 00 00 00 raw..Snr2.raw...
00064DD0: 00 53 6E 72 34 2E 72 61 77 00 00 00 00 48 48 46 .Snr4.raw....HHF
00064DE0: 2E 72 61 77 00 00 00 00 00 52 69 64 65 2E 72 61 .raw.....Ride.ra
00064DF0: 77 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 w...............
00064E00: 00 4B 69 6B 41 6D 62 2E 72 61 77 00 00 43 6C 69 .KikAmb.raw..Cli
00064E10: 63 6B 2E 72 61 77 00 00 00 03 04 02 40 00 18 C0 ck.raw......@...
00064E20: 4D 65 74 72 6F 33 00 00 00 00 00 00 00 00 00 00 Metro3..........
00064E30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00064E40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00064E50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00064E60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00064E70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00064E80: 00 00 00 00 00 00 00 00 00 43 6C 69 63 6B 2E 72 .........Click.r
00064E90: 61 77 00 00 00 03 04 02 80 14 18 C0 4D 65 74 72 aw..........Metr
00064EA0: 6F 34 00 00 00 00 00 00 00 00 00 00 00 00 00 00 o4..............
I'd suspect that the numbers ahead of the name define the number of samples/etc, so these should be easily parsable.
So we are both typing at the same time... ;-) BTW ZT2 files were using fixed length strings for file names.
Oh it's a hell of a lot more than drum patterns , It contains the looper(s) and rhythm player code (possibly encrypted and as fixed modules) and tuner parts of the deal as well. There has to be a structure for each pattern for, at least, what samples are in each pattern (kit) and timings (deltas probably). I reckon these are pointers to those structures. It's playing one loop effectively and resetting according to tempo. Simple stuff. Just can't find the structures. Youd imagine there would be data with plenty of low numbers (0-23) dotted around with 68 patterns in there somewhere. Things like hihats repeat plenty within a bar on some patterns. Unless that's, as I suspect, it in which case they are likely pointers directly to the patterns. If 16 bit, subtracting 220h from each number seems logical but not hit on anything so far that makes sense as pattern data.
Yep, fixed length filenames. Hadn't noticed that. So, 7 byte strings at this point it is then.
Actually, there's a simple way to test if they are indeed pointers...
Ha, soz using it as instant messaging here. :)
Things I'd expect:
Rather than a table of sample numbers, it may be a bit field of the drum sounds used in each beat.
One thing to question is whether the pattern info is before or after the pattern name... the last item seems to suggest after
00064F90: 98 10 18 C0 4D 65 74 72 6F 00 00 00 00 00 00 00 ....Metro.......
00064FA0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00064FB0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00064FC0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00064FD0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00064FE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00064FF0: 00 00 00 00 00 00 00 00 00 00 00 00 00 43 6C 69 .............Cli
00065000: 63 6B 2E 72 61 77 00 00 00_04_04_01_D8_15_18_C0 ck.raw.......... <--- is this the data for Metro
00065010: 00 41 5F 69 6E 69 74 69 61 6C 69 7A 65 64 50 61 .A_initializedPa
00065020: 72 61 6D 73 3A 20 75 6E 69 6E 69 74 69 61 6C 69 rams: uninitiali
00065030: 7A 65 64 20 50 61 72 61 6D 73 20 73 74 72 75 63 zed Params struc
It doesn't even need no of beats per bar or number of bars. It's only playing one pass then retriggering. Delatas would do on their own. It could have that information but not really needed for such a simple player.
I can't add to the archive here. I've copied the 8Beats1 7 string over 8Beats2 and 8Beats3 and want to update firmware to see if 8Beats1, 8Beats2 and 8Beats3 will then all play the same. If so, they are pattern pointers.
Looking at your list of "data; name", the data matches previous name.... waltz are in 3/4 time, and metro3/4/5 are 3/4/5 beats. All with 2 bars.
It may need to know time signature, as the looper can be set to bar/note lengths. Drum and looper tempo interact.
It still only needs deltas. Not saying it doesn't have that info but that's how I'd do it in such a simple setup. Start... Deltas per hit... Reset/retrigger. Also, you'll notice that the looper/rhythm can't resync. ;)
Do all the definitions have the same length (124 bytes), and same number of (potential) samples?
If we work on the assumption that data contains time sig and number of bars... what do the other 3 bytes mean? 0xC0 is likely a teminator, do the others imply offset (ie have nominal distance between them for 4/4 2 bars)?
000636E0: 46 75 6E 6B 32 00 00 00 00 4B 69 6B 31 2E 72 61 Funk2....Kik1.ra
000636F0: 77 00 00 00 00 53 6E 72 41 6D 62 2E 72 61 77 00 w....SnrAmb.raw.
00063700: 00 53 6E 72 33 2E 72 61 77 00 00 00 00 53 6E 72 .Snr3.raw....Snr
00063710: 32 2E 72 61 77 00 00 00 00 48 48 43 2E 72 61 77 2.raw....HHC.raw
00063720: 00 00 00 00 00 48 48 4F 2E 72 61 77 00 00 00 00 .....HHO.raw....
00063730: 00 48 48 43 41 6D 62 2E 72 61 77 00 00 4B 69 6B .HHCAmb.raw..Kik
00063740: 41 6D 62 2E 72 61 77 00 00 43 6C 69 63 6B 2E 72 Amb.raw..Click.r
00063750: 61 77 00 00 00 04 04 02 B0 C7 17 C0 aw..........Funk
vs
00064F10: 4D 65 74 72 6F 35 00 00 ....`...Metro5..
00064F20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00064F30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00064F40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00064F50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00064F60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00064F70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00064F80: 00 43 6C 69 63 6B 2E 72 61 77 00 00 00 05 04 02 .Click.raw......
00064F90: 98 10 18 C0 ....Metro.......
00064F90: 4D 65 74 72 6F 00 00 00 00 00 00 00 ....Metro.......
00064FA0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00064FB0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00064FC0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00064FD0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00064FE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00064FF0: 00 00 00 00 00 00 00 00 00 00 00 00 00 43 6C 69 .............Cli
00065000: 63 6B 2E 72 61 77 00 00 00 04 04 01 D8 15 18 C0 ck.raw..........
Doesn't the pattern get displayed with dots, coloured in as pattern is played...?
Most are 4/4 time, what does "12/8 Grv" do (12/8 time)?
Okay, updated installer. I think...
Another thing I note about the 'offsets'; yours mostly have '0x0D' as last byte and mine have '0x17' (B1 Four f/w).
it's only bytes 3-4 possibly. May not be, but these are certainlynot the patterns... and they must be somewhere!
Okay, I replaced 8Beats2 string with the one from 8Beats1 updated the firmware and they now play exactly the same pattern. This will have odd effects if simply done across patterns randomly as different patterns have different kits.
I reckon indexes, either...
04 04 - 02 20 - B7 0D C0 ; Guide 04 04 - 02 58 - B2 0D C0 ; 8Beats1 04 04 - 02 88 - 87 0D C0 ; 8Beats2 04 04 - 02 18 - 87 0D C0 ; 8Beats3 04 04 - 02 58 - 85 0D C0 ; 16Beats1 04 04 - 02 E8 - 6A 0D C0 ; 16Beats2 04 04 - 02 48 - 6A 0D C0 ; 16Beats3
or less likely (Although code is running in a TMS320C6745 and dependant however the memory is mapped) ...
04 04 - 02 20 B7 - 0D C0 ; Guide 04 04 - 02 58 B2 - 0D C0 ; 8Beats1 04 04 - 02 88 87 - 0D C0 ; 8Beats2 04 04 - 02 18 87 - 0D C0 ; 8Beats3 04 04 - 02 58 85 - 0D C0 ; 16Beats1 04 04 - 02 E8 6A - 0D C0 ; 16Beats2 04 04 - 02 48 6A - 0D C0 ; 16Beats3
The numbers increase pretty linearly to my eyes.
Each "pattern header" is 124 bytes long containing the identified string of 7 bytes along with fixed file-length sample filenames. However, a sample named in a kit does not necessarily mean it is actually used as evidenced by the first pattern header in the GFX1on. Where it actually only uses Kik1.raw and HHC.raw other samples are declared.
GUIDE����Kik1.raw����SnrAmb.raw��Snr1.raw����������������HHC.raw�����������������HHCAmb.raw��KikAmb.raw��Click.raw���X² À
Up to 9 samples slots are available per pattern and any unused slot may, or may not, be padded with zeroes. Unused samples listed in a header look to be preloads for next or previous patterns which would suggest that samples are loaded dynamically into user memory.
I think your interpretation is correct (name, sample filenames), but I am not convinced about the other data. I think these bytes are (in order), time-sig1, time-sig2 and number of bars.... likely followed (as you suggested) by an offset in code/memory to the actual data defining the pattern.
Most have '0x02', except for the 'Metro' pattern which has '0x01' - this one displays on device as "O O O O".
00064F90: 4D 65 74 72 6F 00 00 00 00 00 00 00 ....Metro.......
00064FA0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00064FB0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00064FC0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00064FD0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00064FE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00064FF0: 00 00 00 00 00 00 00 00 00 00 00 00 00 43 6C 69 .............Cli
00065000: 63 6B 2E 72 61 77 00 00 00 04 04 01 D8 15 18 C0 ck.raw.......... = D8 15 18
The other oddity is '12/8 Grv' which displays as "O o o O o o O o o O o o"
00064940: 31 32 2F 38 20 47 72 76 ........12/8 Grv
00064950: 00 4B 69 6B 31 2E 72 61 77 00 00 00 00 53 6E 72 .Kik1.raw....Snr
00064960: 41 6D 62 2E 72 61 77 00 00 53 6E 72 31 2E 72 61 Amb.raw..Snr1.ra
00064970: 77 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 w...............
00064980: 00 48 48 43 2E 72 61 77 00 00 00 00 00 00 00 00 .HHC.raw........
00064990: 00 00 00 00 00 00 00 00 00 48 48 43 41 6D 62 2E .........HHCAmb.
000649A0: 72 61 77 00 00 4B 69 6B 41 6D 62 2E 72 61 77 00 raw..KikAmb.raw.
000649B0: 00 43 6C 69 63 6B 2E 72 61 77 00 00 00 0C 08 02 .Click.raw......
000649C0: E8 CA 17 C0 ....Waltz....Kik = E8 CA 17
The "offsets" are not in sequence, for the B1 Four F/W (apparently different to your dataset) they can be sorted as follows. The difference between them is not consistent, which might suggest a variable length data block.
simon@thevoid:~$ sort offset.txt
17 B8 D0 = 000645E0: D0 B8 17 C0 53 6B 61 00 00 00 00 00 00 4B 69 6B ....Ska......Kik
17 BE D0 = 00064100: 61 77 00 00 00 04 04 02 D0 BE 17 C0 52 26 42 32 aw..........R&B2
17 C0 40 = 00064460: 63 6B 2E 72 61 77 00 00 00 04 04 02 40 C0 17 C0 ck.raw......@...
17 C0 F8 = 00063F10: 61 77 00 00 00 04 04 02 F8 C0 17 C0 aw..........ROCK
17 C2 60 = 00064370: 00 04 04 02 60 C2 17 C0 50 6F 70 00 00 00 00 00 ....`...Pop.....
17 C3 10 = 000634E0: 63 6B 2E 72 61 77 00 00 00 04 04 02 10 C3 17 C0 ck.raw..........
17 C5 10 = 00063200: 00 04 04 02 10 C5 17 C0 ........Rock1...
17 C5 B8 = 000643F0: B8 C5 17 C0 50 6F 70 52 6F 63 6B 00 00 4B 69 6B ....PopRock..Kik
17 C6 60 = 00063E90: 63 6B 2E 72 61 77 00 00 00 04 04 02 60 C6 17 C0 ck.raw......`...
17 C7 08 = 000636D0: 63 6B 2E 72 61 77 00 00 00 04 04 02 08 C7 17 C0 ck.raw..........
17 C7 B0 = 00063750: 61 77 00 00 00 04 04 02 B0 C7 17 C0 aw..........Funk
17 C8 58 = 00064750: 00 04 04 02 58 C8 17 C0 46 75 73 69 6F 6E 00 00 ....X...Fusion..
17 C9 00 = 00063B30: 61 77 00 00 00 04 04 02 00 C9 17 C0 42 6C 75 65 aw..........Blue
17 C9 A8 = 00063180: 61 77 00 00 00 04 04 02 A8 C9 17 C0 aw..........16Be
17 CA 48 = 00063100: 63 6B 2E 72 61 77 00 00 00 04 04 02 48 CA 17 C0 ck.raw......H...
17 CA E8 = 000649C0: E8 CA 17 C0 57 61 6C 74 7A 00 00 00 00 4B 69 6B ....Waltz....Kik
17 CB 80 = 00064940: 00 04 04 02 80 CB 17 C0 31 32 2F 38 20 47 72 76 ........12/8 Grv
17 CC 18 = 000637D0: 00 04 04 02 18 CC 17 C0 ........JazzFunk
17 CC B0 = 000635E0: 00 04 04 02 B0 CC 17 C0 45 6D 6F 00 00 00 00 00 ........Emo.....
17 CD 48 = 00064200: 48 CD 17 C0 39 30 73 20 53 6F 75 6C 00 4B 69 6B H...90s Soul.Kik
17 CD E0 = 000642F0: 61 77 00 00 00 04 04 02 E0 CD 17 C0 44 69 73 63 aw..........Disc
17 CE 70 = 00063850: 70 CE 17 C0 4D 6F 74 6F 77 6E 00 00 00 4B 69 6B p...Motown...Kik
17 D0 20 = 000638C0: 63 6B 2E 72 61 77 00 00 00 04 04 02 20 D0 17 C0 ck.raw...... ...
17 D1 40 = 00063C30: 40 D1 17 C0 4A 61 7A 7A 31 00 00 00 00 00 00 00 @...Jazz1.......
17 D1 C8 = 000647D0: C8 D1 17 C0 53 77 69 6E 67 31 00 00 00 4B 69 6B ....Swing1...Kik
17 D2 50 = 00064080: 63 6B 2E 72 61 77 00 00 00 04 04 02 50 D2 17 C0 ck.raw......P...
17 D7 58 = 00064180: 00 04 04 02 58 D7 17 C0 37 30 73 20 53 6F 75 6C ....X...70s Soul
17 D7 D8 = 00063AB0: 63 6B 2E 72 61 77 00 00 00 04 04 02 D8 D7 17 C0 ck.raw..........
17 D8 30 = 00063470: 30 DB 17 C0 4D 74 6C 43 6F 72 65 00 00 4B 69 6B 0...MtlCore..Kik
17 D8 58 = 00064270: 63 6B 2E 72 61 77 00 00 00 04 04 02 58 D8 17 C0 ck.raw......X...
17 DA B8 = 00064B30: 00 04 04 02 B8 DA 17 C0 42 72 65 61 6B 73 33 00 ........Breaks3.
17 DB A8 = 000644E0: 61 77 00 00 00 04 04 02 A8 DB 17 C0 45 75 72 6F aw..........Euro
17 DC 20 = 00063370: 61 77 00 00 00 04 04 02 20 DC 17 C0 48 61 72 64 aw...... ...Hard
17 DC 98 = 00064010: 98 DC 17 C0 ....TomTomBt.Kik
17 DD F0 = 00063090: F0 DD 17 C0 ....16Beats1.Kik
17 DE 60 = 000633F0: 00 04 04 02 60 DE 17 C0 48 65 61 76 79 4D 74 6C ....`...HeavyMtl
17 DE D0 = 000632F0: 63 6B 2E 72 61 77 00 00 00 04 04 02 D0 DE 17 C0 ck.raw..........
17 DF 40 = 00063010: 00 04 04 02 40 DF 17 C0 ....@...8Beats3.
17 DF B0 = 00062F90: 61 77 00 00 00 04 04 02 B0 DF 17 C0 aw..........8Bea
17 E0 20 = 00064AB0: 61 77 00 00 00 04 04 02 20 E0 17 C0 42 72 65 61 aw...... ...Brea
17 E0 90 = 00063280: 90 E0 17 C0 52 6F 63 6B 32 00 00 00 00 4B 69 6B ....Rock2....Kik
17 E1 68 = 000639C0: 00 04 04 02 68 E1 17 C0 52 6F 63 6B 65 72 73 00 ....h...Rockers.
17 E1 D0 = 00064BB0: D0 E1 17 C0 35 2F 34 20 47 72 76 00 00 4B 69 6B ....5/4 Grv..Kik
17 E2 38 = 000646D0: 61 77 00 00 00 04 04 02 38 E2 17 C0 53 68 75 66 aw......8...Shuf
17 F0 80 = 00063DA0: 00 04 04 02 80 F0 17 C0 42 6F 73 73 61 32 00 00 ........Bossa2..
17 F0 E0 = 00063E20: E0 F0 17 C0 53 61 6D 62 61 31 00 00 00 4B 69 6B ....Samba1...Kik
17 F2 00 = 000648C0: 61 77 00 00 00 04 04 02 00 F2 17 C0 31 32 2F 38 aw..........12/8
17 F3 10 = 00063660: 10 F3 17 C0 46 75 6E 6B 31 00 00 00 00 4B 69 6B ....Funk1....Kik
17 F3 68 = 00063560: 61 77 00 00 00 04 04 02 68 F3 17 C0 46 61 73 74 aw......h...Fast
17 F5 78 = 00064560: 00 04 04 02 78 F5 17 C0 4E 65 77 57 61 76 65 00 ....x...NewWave.
17 F5 D0 = 00063A40: D0 F5 17 C0 32 6E 64 20 4C 69 6E 65 00 4B 69 6B ....2nd Line.Kik
17 F6 28 = 00064650: 63 6B 2E 72 61 77 00 00 00 04 04 02 28 F6 17 C0 ck.raw......(...
17 F6 80 = 00064840: 63 6B 2E 72 61 77 00 00 00 04 04 02 80 F6 17 C0 ck.raw..........
17 F6 D8 = 00064C20: 63 6B 2E 72 61 77 00 00 00 05 04 02 D8 F6 17 C0 ck.raw..........
17 F8 F8 = 00063BB0: 00 04 04 02 F8 F8 17 C0 42 6C 75 65 73 32 00 00 ........Blues2..
17 F9 40 = 00063940: 61 77 00 00 00 04 04 02 40 F9 17 C0 53 74 65 70 aw......@...Step
17 F9 D0 = 00063F90: 00 04 04 02 D0 F9 17 C0 ........R'n'R...
18 00 08 = 00063D20: 61 77 00 00 00 04 04 02 08 00 18 C0 42 6F 73 73 aw..........Boss
18 00 40 = 00064E10: 63 6B 2E 72 61 77 00 00 00 03 04 02 40 00 18 C0 ck.raw......@...
18 00 78 = 00064A30: 63 6B 2E 72 61 77 00 00 00 03 04 02 78 00 18 C0 ck.raw......x...
18 02 30 = 00064D20: 00 03 04 02 30 02 18 C0 4A 7A 57 61 6C 74 7A 31 ....0...JzWaltz1
18 07 C0 = 00064CA0: 61 77 00 00 00 03 04 02 C0 07 18 C0 43 74 57 61 aw..........CtWa
18 0A E8 = 00063CA0: 63 6B 2E 72 61 77 00 00 00 04 04 02 E8 0A 18 C0 ck.raw..........
18 0F 10 = 00064DA0: 10 0F 18 C0 4A 7A 57 61 6C 74 7A 32 00 4B 69 6B ....JzWaltz2.Kik
18 10 80 = 00062F10: 63 6B 2E 72 61 77 00 00 00 04 04 02 80 10 18 C0 ck.raw..........
18 10 98 = 00064F90: 98 10 18 C0 ....Metro.......
18 12 60 = 00064F10: 00 04 04 02 60 12 18 C0 ....`...Metro5..
18 14 80 = 00064E90: 61 77 00 00 00 03 04 02 80 14 18 C0 4D 65 74 72 aw..........Metr
18 15 D8 = 00065000: 63 6B 2E 72 61 77 00 00 00 04 04 01 D8 15 18 C0 ck.raw..........
18 15 E8 = 00062EA0: E8 15 18 C0 ....GUIDE....Kik
The only reason I doubt the first 3 bytes are not bars/beats is that here some funkier time sigs would be declared as...
0C 08 02 88 6B 0D C0 ; Waltz - Possibly 05 04 02 58 94 0D C0 ; CtWaltz1 - ?? 03 04 02 C8 B4 0D C0 ; Metro4 - ?? 04 04 02 A8 B3 0D C0 ; Metro5 - ??
Again, only basing on how I would implement on a device like this, the idea of beats and bars in these devices is notional. It's triggering samples equal distances apart in time and resetting the start point at a predetermined time. All that is needed is a timer, some deltas that can be scaled for tempo and it will aways be in time with itself. We hear beats/bars but the code doesn't need to know the first thing about it as it can all be translated into "beats/bars" in a numerical form basically using division. If the patterns were linkable then that would be a completely different kettle of doohdah.
But you could be right :)
Either way, that pattern data is somewhere.
Actually, that can possibly be tested as well by putting the string for what is known to be 3/4 pattern into a 4/4 pattern header thinking about it. I don't even use the !"£$% rhythm thing!
So, my Guide pattern now plays a heavy metal waltz. I can replace the first three bytes with the original guide first 3 bytes and see what happens for a laugh...
It looks like you are using the data BEFORE the name, I think you should be look after.... ie. at the end of the block.
000649C0: 57 61 6C 74 7A 00 00 00 00 4B 69 6B ....Waltz....Kik
000649D0: 31 2E 72 61 77 00 00 00 00 53 6E 72 41 6D 62 2E 1.raw....SnrAmb.
000649E0: 72 61 77 00 00 53 6E 72 32 2E 72 61 77 00 00 00 raw..Snr2.raw...
000649F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 48 48 43 .............HHC
00064A00: 2E 72 61 77 00 00 00 00 00 00 00 00 00 00 00 00 .raw............
00064A10: 00 00 00 00 00 48 48 43 41 6D 62 2E 72 61 77 00 .....HHCAmb.raw.
00064A20: 00 4B 69 6B 41 6D 62 2E 72 61 77 00 00 43 6C 69 .KikAmb.raw..Cli
00064A30: 63 6B 2E 72 61 77 00 00 00 03 04 02 78 00 18 C0 ck.raw......x... = 78 00 18
^^ ^^ 3/4 time!
Ah, the string is at the END of the header. There are strings before and after the headers here that have skewed things. Anyway, going to try changing the first 3 bytes to something from a known 4\4 string. You're right, yep. The surrounding strings must be fluff or test patterns. I copied it into the correct place by mistake and it confused the hell out of me why the pattern changed.
Right, bars/beats it is. That fluff skewed all of the pattern associations. What I'm not understanding, is why isn't a different pattern being played? The associations with the patterns, wherever they are, must be somewhere else. Ah well, it's a start. Logically, the pattern data should be in that same block. Although the next section looks interesting...
Okay, the next section is the pattern data unless there is some voodoo going on here. Breaking it down into 32 byte chunks yields 68 data strings (with some yet undetermined stuff at the end). An example of how I am currently interpreting the first few "patterns" after experiments would be...
Dummy (This is a fluff pattern in the G1Xon which also threw me earlier on) 2C D7 0D C0 00 09 00 00 B8 05 09 C0 B4 05 09 C0 B0 05 09 C0 C0 05 09 C0 C0 05 09 C0 A8 05 09 C0 Guide (Pattern 1) A2 05 09 C0 98 05 09 C0 90 05 09 C0 8A 05 09 C0 86 05 09 C0 C0 05 09 C0 C0 05 09 C0 C0 05 09 C0 8Beats1 (Pattern 2) C0 05 09 C0 C0 05 09 C0 82 05 09 C0 7A 05 09 C0 C0 05 09 C0 C0 05 09 C0 C0 05 09 C0 C0 05 09 C0 etc
They may not all be referenced in order by the software but if we replace the 7 byte pattern header and pattern string of "8Beats1" with those of "Guide" (first pattern on G1Xon) then when the firmware is updated we find that .... both patterns play the same!
Be aware that the device will probably crash while booting if a pattern string is injected that requires undefined samples.
Of course, this could all just be nonsense and I've been poring over graphic data for the past few hours. :)
Upon further experimentation something not right there. Am back to the indexing idea on those extraneous pattern header bytes. Will spend another evening on it, got a lot going on and always get drawn into distractions at these points for some weird psychological reason. :)
So...
8Beats1 38 42 65 61 74 73 31 00 00 ; Pattern Name - (8Beats1) 4B 69 6B 31 2E 72 61 77 00 00 00 00 ; Sample filename Slot 1 - (Kik1.raw) 53 6E 72 41 6D 62 2E 72 61 77 00 00 ; Sample filename Slot 2 - (SnrAmb.raw) 53 6E 72 31 2E 72 61 77 00 00 00 00 ; Sample filename Slot 3 - (Snr1.raw) 00 00 00 00 00 00 00 00 00 00 00 00 ; Sample filename Slot 4 - (Empty) 48 48 43 2E 72 61 77 00 00 00 00 00 ; Sample filename Slot 5 - (HHC.raw) 00 00 00 00 00 00 00 00 00 00 00 00 ; Sample filename Slot 6 - (Empty) 48 48 43 41 6D 62 2E 72 61 77 00 00 ; Sample filename Slot 7 - (HHCAmb.raw) 4B 69 6B 41 6D 62 2E 72 61 77 00 00 ; Sample filename Slot 8 - (KikAmb.raw) 43 6C 69 63 6B 2E 72 61 77 00 00 00 ; Sample filename Slot 9 - (Click.raw) 04 04 ; Time Signature 02 ; Bars 88 87 ; ?? 0D ; ?? Device dependant constant C0 ; Header terminator
Re
0D ; ?? Device dependant constant
I think that your earlier suggestion that this (and preceeding 2 bytes?) might be a pointer may be correct. The G1Four and B1Four both use 0x17 and 0x18 (ie different in the same file). The processor for these devices is know to be different and may have a different memory map.
Some of common deltas for these supposed pointers are: 56, 88, 112, 136, 152, 168
One thought on locating the pattern data, for simple patterns each bar is likely the same. So if it's not automatically repeated by the F/W then we should see some data repeated.
Oh, that procrastination monster ;-)
Aye, a 24 bit address in a TMS320 memory map is perfectly normal. You would think the patterns should be optically identifialble indeed. They are definitely pointers, just swap any set of those numbers over here and the patterns change to different instrumentation if they are defined.
A chunk of data that neatly breaks down into 70 patterns or yet another structure.
By the way, there are 70 pattern headers declared here but two are not used by the firmware. One of the extra patterns is a dummy, the other called 12\8 Tri which is another shuffle pattern. Oh, the pattern declaration order isn't the same as on the device either.
The thing that deters me from belieiving they are 24 bit pointers is the however you interpret them the data range is too large for a bunch of timing data. The data size in total shouldn't be very large with the two bytes prior to the terminator being enough I would have thought. I'll try a few experiments on a new updater.
A thought that I had earlier today, but forgot about as usual, was that they could be bit patterns for overlaying timing data. That would be more efficient on a simple player such as this. It would literally only need a dozen or so delta timing patterns to make enough variations for what are on offer here. The footprint would be very small. The trigger hits could be tied to the timing data and the sounds changed by changing the sample associated with a slot in the header and if a trigger in an overlay isn't required in a pattern then just leave the slot empty.
Yep. They appear to be, at least, 16 bit pattern bitmaps (indirect indexes). I just replaced...
with...
and I get a kind of hybrid of the two. Then if on top of that I replace...
with...
it is yet another pattern. And if just for the hell of it...
is now replaced with...
a dodgy dance version of Time by Pink Floyd can be recreated complete with 7 dot on-screen display.
Still not a clue what the last byte is.
Okay, that'senough for me for a bit as I have other things that need sorting out.
Keep up the good work guys. Laterz. :)
On a break here and wanted to leave some notes for posterity...
The rhythm player appears to be a basic 8\9 channel tracker style implementation. Once the format of the data is worked out, which will require quite a bit of experimentation and firmware reflashing, this alone is a very flexible arrangement for building rhythm loops in a small footprint given easy access to variable bar lengths. Replacing data with dummy values until pennies drop should give results. Eventually.
BUT, there's always one isn't there, for the idea of adding user rhythms to be of any real practical use in the G\B devices an external player editor/arranger would really need to be impemented. Even a basic arranger using stock data would be able to create complex loops and would need to be to inject new samples\data into a firmware updater. Even if it only used the built in timing\trigger data and rearranged them as a basis this, coupled with changing samples\bar lengths\time sigs\deltas, would add a lot of functionality to the units.
What flags are available for such things as one shot\repeat\delta repeat\delta offset\etc on trigger data is yet to be explored. There is , at least, a method for controlling volume of a trigger. I may have a trawl\experiment here when time allows.
The following data is from a G1Xon\v1.21:
Pattern Header format: 38 42 65 61 74 73 31 00 00 ; Pattern Name - (8Beats1) 4B 69 6B 31 2E 72 61 77 00 00 00 00 ; Sample filename Slot 1 - (Kik1.raw) 53 6E 72 41 6D 62 2E 72 61 77 00 00 ; Sample filename Slot 2 - (SnrAmb.raw) 53 6E 72 31 2E 72 61 77 00 00 00 00 ; Sample filename Slot 3 - (Snr1.raw) 00 00 00 00 00 00 00 00 00 00 00 00 ; Sample filename Slot 4 - (Empty) 48 48 43 2E 72 61 77 00 00 00 00 00 ; Sample filename Slot 5 - (HHC.raw) 00 00 00 00 00 00 00 00 00 00 00 00 ; Sample filename Slot 6 - (Empty) 48 48 43 41 6D 62 2E 72 61 77 00 00 ; Sample filename Slot 7 - (HHCAmb.raw) 4B 69 6B 41 6D 62 2E 72 61 77 00 00 ; Sample filename Slot 8 - (KikAmb.raw) 43 6C 69 63 6B 2E 72 61 77 00 00 00 ; Sample filename Slot 9 - (Click.raw) 04 04 ; Time Signature - (String 0-1) 02 ; Number of measures - (String 2) 88 87 ; Pattern Bitmap - (String 3-4) 0D ; ?? - (Flags?) C0 ; Header terminator - (String 6)
Note: It looks that Click.raw needs to always be defined in Slot 9
Pattern Strings - (70 declared):
04 04 02 20 B7 0D C0 ; Dummy - (Not used) 04 04 02 58 B2 0D C0 ; GUIDE 04 04 02 88 87 0D C0 ; 8Beats1 04 04 02 18 87 0D C0 ; 8Beats2 04 04 02 58 85 0D C0 ; 16Beats3 04 04 02 E8 6A 0D C0 ; 16Beats1 04 04 02 48 6A 0D C0 ; 16Beats2 04 04 02 70 64 0D C0 ; 16beats3 04 04 02 68 88 0D C0 ; Rock1 04 04 02 38 86 0D C0 ; Rock2 04 04 02 F8 83 0D C0 ; Rock3 04 04 02 C8 85 0D C0 ; HardRock 04 04 02 08 83 0D C0 ; HeavyMtl 04 04 02 18 63 0D C0 ; MtlCore 04 04 02 90 8F 0D C0 ; Punk 04 04 02 50 6D 0D C0 ; FastPunk 04 04 02 38 8F 0D C0 ; Emo 04 04 02 68 66 0D C0 ; Funk1 04 04 02 10 67 0D C0 ; Funk2 04 04 02 B8 6C 0D C0 ; FunkRock 04 04 02 F8 77 0D C0 ; JazzFunk 04 04 02 18 79 0D C0 ; Motown 04 04 02 B0 99 0D C0 ; OneDrop 04 04 02 D8 88 0D C0 ; Steppers 04 04 02 F0 90 0D C0 ; Rockers 04 04 02 C0 7E 0D C0 ; 2ndLine 04 04 02 60 68 0D C0 ; Country 04 04 02 68 99 0D C0 ; Blues1 04 04 02 A8 79 0D C0 ; Blues2 04 04 02 E8 AA 0D C0 ; Jazz1 04 04 02 60 A0 0D C0 ; Jazz2 04 04 02 38 8B 0D C0 ; Bossa1 04 04 02 98 8B 0D C0 ; Bossa2 04 04 02 C0 65 0D C0 ; Samba1 04 04 02 00 61 0D C0 ; Samba2 04 04 02 88 9A 0D C0 ; ROCKABLY 04 04 02 70 84 0D C0 ; R'n'R 04 04 02 B8 7A 0D C0 ; TomTomBt 04 04 02 68 5D 0D C0 ; R&B1 04 04 02 40 7E 0D C0 ; R&B2 04 04 02 E8 6D 0D C0 ; 70s Soul 04 04 02 40 7F 0D C0 ; 90s Soul 04 04 02 68 77 0D C0 ; HipHop 04 04 02 68 62 0D C0 ; Disco 04 04 02 18 65 0D C0 ; Pop 04 04 02 48 60 0D C0 ; PopRock 04 04 02 80 83 0D C0 ; IndiePop 04 04 02 98 90 0D C0 ; Europop 04 04 02 B0 59 0D C0 ; NewWave 04 04 02 48 91 0D C0 ; Ska 04 04 02 A8 89 0D C0 ; Shuffle1 04 04 02 B8 67 0D C0 ; Shuffle2 04 04 02 30 7A 0D C0 ; Fusion 04 04 02 A0 91 0D C0 ; Swing1 04 04 02 78 8D 0D C0 ; Swing2 04 04 02 20 6C 0D C0 ; 12/8 Tri - (Not used) 0C 08 02 88 6B 0D C0 ; 12/8 Grv 03 04 02 D0 A0 0D C0 ; Waltz 04 04 02 F8 87 0D C0 ; Breaks1 04 04 02 90 82 0D C0 ; Breaks2 04 04 02 40 89 0D C0 ; Breaks3 05 04 02 58 94 0D C0 ; 5\4 Grv 03 04 02 78 A9 0D C0 ; CtWaltz1 03 04 02 B8 A2 0D C0 ; CtWaltz2 03 04 02 F0 AE 0D C0 ; JzWaltz1 03 04 02 98 A0 0D C0 ; JzWaltz2 03 04 02 C8 B4 0D C0 ; Metro3 04 04 02 A8 B3 0D C0 ; Metro4 05 04 02 70 B2 0D C0 ; Metro5 04 04 01 00 B7 0D C0 ; Metro
There is also an 8 byte preamble at the start of the pattern headers section preceding the headers themselves. These are likely to be relevant if new timing\trigger information is required instead of the predefined patterns:
80 85 0C C0 04 35 01 00
@Tomlinsky Great work on the patterns! Will be fun to add pattern editing to the G1on!
re the zdl format, I've seen the same debugger strings in the firmware. Haven't dove in but I know the chip zoom uses is the TI tms320c6745ptp (tms320c6x family) at least on the ms50. And yeah it would be fun to pick apart a simple one. Best bet is to try and throw the zdl files at a disassembler that supports it!
Getting back to this whilst off work at the moment... wrote a little python script to decode that table of patterns/samples from the binary blobs of the F/W. decode_patterns.zip
It appears that the new v2.00 F/W contain exactly the same data (G1 vs B1 vs G1X vs B1X), but the table is in a different location ('-O' for offset) to the v1.10 F/W.
C:\Users\simon\Documents\ZoomFW>python decode_patterns.py -O 407304 -d "B1 FOUR_v2.00\unzipped\.rsrc\1041\BIN\129" > "B1 FOUR_v2.00"\patterns.txt
C:\Users\simon\Documents\ZoomFW>python decode_patterns.py -O 407304 -d "B1X FOUR_v2.00\unzipped\.rsrc\1041\BIN\129" > "B1X FOUR_v2.00"\patterns.txt
C:\Users\simon\Documents\ZoomFW>python decode_patterns.py -O 407304 -d "G1X FOUR_v2.00\unzipped\.rsrc\1041\BIN\129" > "G1X FOUR_v2.00"\patterns.txt
C:\Users\simon\Documents\ZoomFW>python decode_patterns.py -O 407304 -d "G1 FOUR_v2.00\unzipped\.rsrc\1041\BIN\129" > "G1 FOUR_v2.00"\patterns.txt
C:\Users\simon\Documents\ZoomFW>python decode_patterns.py -O 405032 -d B1_FOUR_v1.10_Win_E\unzipped\.rsrc\1041\BIN\129 > B1_FOUR_v1.10_Win_E\patterns.txt
C:\Users\simon\Documents\ZoomFW>python decode_patterns.py -O 405032 -d G1_FOUR_v1.10_Win_E\unzipped\.rsrc\1041\BIN\129 > G1_FOUR_v1.10_Win_E\patterns.txt
Also v2.00 vs v1.10 has different values for the 'bit map' for each pattern.... I still suspect that this is a pointer to a location in memory where the actual pattern data is stored.
I did some looking at the 'offset' for the tables. Manually, and way too late into the night ;-)
As noted already the v2.00 F/W has different values for the offset compared to v1.10, however if you sort these offsets and then compare to calculate the number of bytes between them there is a very strong correlation between the F/Ws.
Mostly the drum pattern's data is the same 'length' (delta in 'offset'), although there are some slight changes for some. More complex patterns have a larger 'length'.
The annotated files are here: b1f_v200_patterns.txt b1f_v110_patterns.txt
I had made some copy+paste errors on the v1.10 report... now it's almost 100% correlation b1f_v110_patterns.txt
Offset is annotated "from -> to, length", "length" is almost identical. Will need to figure out where in the binaries these chunks of data are....
ListContainer: ListContainer:
ListContainer: ListContainer:
Container: Container:
name = u'Dummy' (total 5) name = u'Dummy' (total 5)
offset = 1578848 (last in list) | offset = 1578472 (last in list)
Container: Container:
name = u'GUIDE' (total 5) name = u'GUIDE' (total 5)
offset = 1577392 -> 1577416 24 | offset = 1577088 -> 1577112 24
Container: Container:
name = u'8Beats1' (total 7) name = u'8Beats1' (total 7)
offset = 1564992 -> 1565104 112 | offset = 1564592 -> 1564704 112
Container: Container:
name = u'8Beats2' (total 7) name = u'8Beats2' (total 7)
offset = 1564880 -> 1564992 112 | offset = 1564480 -> 1564592 112
Container: Container:
name = u'8Beats3' (total 7) name = u'8Beats3' (total 7)
offset = 1564432 -> 1564544 112 | offset = 1564144 -> 1564256 112
Container: Container:
name = u'16Beats1' (total 8) name = u'16Beats1' (total 8)
offset = 1559400 -> 1559560 160 | offset = 1559112 -> 1559272 160
Container: Container:
name = u'16Beats2' (total 8) name = u'16Beats2' (total 8)
offset = 1559240 -> 1559400 160 | offset = 1558952 -> 1559112 160
Container: Container:
name = u'16Beats3' (total 8) name = u'16Beats3' (total 8)
offset = 1558064 -> 1558232 168 | offset = 1557776 -> 1557944 168
Container: Container:
name = u'Rock1' (total 5) name = u'Rock1' (total 5)
offset = 1565216 -> 1565328 112 | offset = 1564816 -> 1565032 216
Container: Container:
name = u'Rock2' (total 5) name = u'Rock2' (total 5)
offset = 1564656 -> 1564880 224 | offset = 1564368 -> 1564480 112
Container: Container:
name = u'Rock3' (total 5) name = u'Rock3' (total 5)
offset = 1563968 -> 1564088 120 | offset = 1563680 -> 1563800 120
Container: Container:
name = u'HardRock' (total 8) name = u'HardRock' (total 8)
offset = 1564544 -> 1564656 112 | offset = 1564256 -> 1564368 112
Container: Container:
name = u'HeavyMtl' (total 8) name = u'HeavyMtl' (total 8)
offset = 1563728 -> 1563848 120 | offset = 1563440 -> 1563560 120
Container: Container:
name = u'MtlCore' (total 7) name = u'MtlCore' (total 7)
offset = 1557552 -> 1558064 512 | offset = 1557264 -> 1557776 512
Container: Container:
name = u'Punk' (total 4) name = u'Punk' (total 4)
offset = 1569936 -> 1570464 528 | offset = 1569640 -> 1570168 528
Container: Container:
name = u'FastPunk' (total 8) name = u'FastPunk' (total 8)
offset = 1560016 -> 1560168 152 | offset = 1559728 -> 1559880 152
Container: Container:
name = u'Emo' (total 3) name = u'Emo' (total 3)
offset = 1569848 -> 1569936 88 | offset = 1569552 -> 1569640 88
Container: Container:
name = u'Funk1' (total 5) name = u'Funk1' (total 5)
offset = 1558568 -> 1558736 168 | offset = 1558280 -> 1558448 168
Container: Container:
name = u'Funk2' (total 5) name = u'Funk2' (total 5)
offset = 1558736 -> 1558904 168 | offset = 1558448 -> 1558616 168
Container: Container:
name = u'FunkRock' (total 8) name = u'FunkRock' (total 8)
offset = 1559864 -> 1560016 152 | offset = 1559576 -> 1559728 152
Container: Container:
name = u'JazzFunk' (total 8) name = u'JazzFunk' (total 8)
offset = 1560464 -> 1560896 432 | offset = 1560176 -> 1560608 432
Container: Container:
name = u'Motown' (total 6) name = u'Motown' (total 6)
offset = 1560896 -> 1561184 288 | offset = 1560608 -> 1560896 288
Container: Container:
name = u'OneDrop' (total 7) name = u'OneDrop' (total 7)
offset = 1571432 -> 1571576 144 | offset = 1571136 -> 1571280 144
Container: Container:
name = u'Steppers' (total 8) name = u'Steppers' (total 8)
offset = 1565328 -> 1565432 104 | offset = 1565032 -> 1565136 104
Container: Container:
name = u'Rockers' (total 7) name = u'Rockers' (total 7)
offset = 1570552 -> 1570640 88 | offset = 1570256 -> 1570344 88
Container: Container:
name = u'2nd Line' (total 8) name = u'2nd Line' (total 8)
offset = 1562872 -> 1563000 128 | offset = 1562584 -> 1562712 128
Container: Container:
name = u'Country' (total 7) name = u'Country' (total 7)
offset = 1559072 -> 1559240 168 | offset = 1558784 -> 1558952 168
Container: Container:
name = u'Blues1' (total 6) name = u'Blues1' (total 6)
offset = 1571360 -> 1571432 72 | offset = 1571064 -> 1571136 72
Container: Container:
name = u'Blues2' (total 6) name = u'Blues2' (total 6)
offset = 1561184 -> 1561320 136 | offset = 1560896 -> 1561032 136
Container: Container:
name = u'Jazz1' (total 5) name = u'Jazz1' (total 5)
offset = 1575952 -> 1577048 1096 | offset = 1575656 -> 1576720 1064
Container: Container:
name = u'Jazz2' (total 5) name = u'Jazz2' (total 5)
offset = 1573168 -> 1573224 56 | offset = 1572872 -> 1572928 56
Container: Container:
name = u'Bossa1' (total 6) name = u'Bossa1' (total 6)
offset = 1569192 -> 1569288 96 | offset = 1568896 -> 1568992 96
Container: Container:
name = u'Bossa2' (total 6) name = u'Bossa2' (total 6)
offset = 1569288 -> 1569576 288 | offset = 1568992 -> 1569280 288
Container: Container:
name = u'Samba1' (total 6) name = u'Samba1' (total 6)
offset = 1558400 -> 1558568 168 | offset = 1558112 -> 1558280 168
Container: Container:
name = u'Samba2' (total 6) name = u'Samba2' (total 6)
offset = 1557016 -> 1557376 360 | offset = 1556728 -> 1557088 360
Container: Container:
name = u'ROCKABLY' (total 8) name = u'ROCKABLY' (total 8)
offset = 1571576 -> 1573168 1592 | offset = 1571280 -> 1572872 1592
Container: Container:
name = u"R'n'R" (total 5) name = u"R'n'R" (total 5)
offset = 1564088 -> 1564432 344 | offset = 1563800 -> 1564144 344
Container: Container:
name = u'TomTomBt' (total 8) name = u'TomTomBt' (total 8)
offset = 1561456 -> 1562744 1288 | offset = 1561168 -> 1562456 1288
Container: Container:
name = u'R&B1' (total 4) name = u'R&B1' (total 4)
offset = 1556464 -> 1556832 368 | offset = 1556176 -> 1556544 368
Container: Container:
name = u'R&B2' (total 4) name = u'R&B2' (total 4)
offset = 1562744 -> 1562872 128 | offset = 1562456 -> 1562584 128
Container: Container:
name = u'70s Soul' (total 8) name = u'70s Soul' (total 8)
offset = 1560168 -> 1560320 152 | offset = 1559880 -> 1560032 152
Container: Container:
name = u'90s Soul' (total 8) name = u'90s Soul' (total 8)
offset = 1563000 -> 1563608 608 | offset = 1562712 -> 1563320 608
Container: Container:
name = u'HipHop' (total 6) name = u'HipHop' (total 6)
offset = 1560320 -> 1560464 144 | offset = 1560032 -> 1560176 144
Container: Container:
name = u'Disco' (total 5) name = u'Disco' (total 5)
offset = 1557376 -> 1557552 176 | offset = 1557088 -> 1557264 176
Container: Container:
name = u'Pop' (total 3) name = u'Pop' (total 3)
offset = 1558232 -> 1558400 168 | offset = 1557944 -> 1558280 168
Container: Container:
name = u'PopRock' (total 7) name = u'PopRock' (total 7)
offset = 1556832 -> 1557016 184 | offset = 1556544 -> 1556728 184
Container: Container:
name = u'IndiePop' (total 8) name = u'IndiePop' (total 8)
offset = 1563848 -> 1563968 120 | offset = 1563560 -> 1563680 120
Container: Container:
name = u'EuroPop' (total 7) name = u'EuroPop' (total 7)
offset = 1570464 -> 1570552 88 | offset = 1570168 -> 1570256 88
Container: Container:
name = u'NewWave' (total 7) name = u'NewWave' (total 7)
offset = 1554928 -> 1556464 1536 (first in list) | offset = 1554640 -> 1556176 1536 (first in list)
Container: Container:
name = u'Ska' (total 3) name = u'Ska' (total 3)
offset = 1570640 -> 1570640 88 | offset = 1570344 -> 1570432 88
Container: Container:
name = u'Shuffle1' (total 8) name = u'Shuffle1' (total 8)
offset = 1565536 -> 1569192 3656 | offset = 1565240 -> 1568896 3656
Container: Container:
name = u'Shuffle2' (total 8) name = u'Shuffle2' (total 8)
offset = 1558904 -> 1559072 168 | offset = 1558616 -> 1558784 168
Container: Container:
name = u'Fusion' (total 6) name = u'Fusion' (total 6)
offset = 1561320 -> 1561456 136 | offset = 1561032 -> 1561168 136
Container: Container:
name = u'Swing1' (total 6) name = u'Swing1' (total 6)
offset = 1570728 -> 1570816 88 | offset = 1570432 -> 1570520 88
Container: Container:
name = u'Swing2' (total 6) name = u'Swing2' (total 6)
offset = 1569576 -> 1569848 272 | offset = 1569280 -> 1569552 272
Container: Container:
name = u'12/8 Tri' (total 8) name = u'12/8 Tri' (total 8)
offset = 1559712 -> 1559864 152 | offset = 1559424 -> 1559576 152
Container: Container:
name = u'12/8 Grv' (total 8) name = u'12/8 Grv' (total 8)
offset = 1559560 -> 1559712 152 | offset = 1559272 -> 1559424 152
Container: Container:
name = u'Waltz' (total 5) name = u'Waltz' (total 5)
offset = 1573280 -> 1573720 440 | offset = 1572984 -> 1573424 440
Container: Container:
name = u'Breaks1' (total 7) name = u'Breaks1' (total 7)
offset = 1565104 -> 1565216 112 | offset = 1564704 -> 1564816 112
Container: Container:
name = u'Breaks2' (total 7) name = u'Breaks2' (total 7)
offset = 1563608 -> 1563728 120 | offset = 1563320 -> 1563440 120
Container: Container:
name = u'Breaks3' (total 7) name = u'Breaks3' (total 7)
offset = 1565432 -> 1565536 104 | offset = 1565136 -> 1565240 104
Container: Container:
name = u'5/4 Grv' (total 7) name = u'5/4 Grv' (total 7)
offset = 1570816 -> 1571360 544 | offset = 1570520 -> 1571064 544
Container: Container:
name = u'CtWaltz1' (total 8) name = u'CtWaltz1' (total 8)
offset = 1575144 -> 1575952 808 | offset = 1574848 -> 1575656 808
Container: Container:
name = u'CtWaltz2' (total 8) name = u'CtWaltz2' (total 8)
offset = 1573720 -> 1575144 1424 | offset = 1573424 -> 1574848 1424
Container: Container:
name = u'JzWaltz1' (total 8) name = u'JzWaltz1' (total 8)
offset = 1577048 -> 1577392 344 | offset = 1576720 -> 1577088 368
Container: Container:
name = u'JzWaltz2' (total 8) name = u'JzWaltz2' (total 8)
offset = 1573224 -> 1573280 56 | offset = 1572928 -> 1572984 56
Container: Container:
name = u'Metro3' (total 6) name = u'Metro3' (total 6)
offset = 1578488 -> 1578832 344 | offset = 1578112 -> 1578456 344
Container: Container:
name = u'Metro4' (total 6) name = u'Metro4' (total 6)
offset = 1577896 -> 1578488 592 | offset = 1577568 -> 1578112 544
Container: Container:
name = u'Metro5' (total 6) name = u'Metro5' (total 6)
offset = 1577416 -> 1577896 480 | offset = 1577112 -> 1577568 456
Container: Container:
name = u'Metro' (total 5) name = u'Metro' (total 5)
offset = 1578832 -> 1578848 16 | offset = 1578456 -> 1578472 16
So, re-arranging the pattern names/offsets into sequential order we can see that the first difference in the "pattern table" between v2.00 and v1.10 is at "Rock1" (seems that pattern data may have been tweaked/swapped).
This means that there is about 9Kbytes (out of ~490K) which in theory are duplicated between files, but maybe at different locations.... thinking this might be a good(?) way to figure out which data block is for the patterns, Not sure about the best way to do such a comparison....
Ugh, spent way too much time staring into the abyss (aka hexdump of F/W).
Still don't see where a table of notes/timing might be stored, but I am 100% convinced it must be there somewhere... 3 bytes (in the table we found) is not enough space to encode enough information.
But agree that my earlier comment about 8KBytes seems to be way too much space (considering FW is only 46KByte in total. Since the drum pattern table is in FW (129 file) it makes sense that the note/pattern data is also there somewhere.
I took samples of each of the drum patterns, to see what they do and maybe re-create them. 'Metro' proves that they have some adjustment of sample level, others show they have (at least) 16th note resolution, and lots of patterns are pretty complex.
Another hook which might help is that Metro3, Metro4 and Metro5 are very simple. Just 'click' repeated on the whole note at same/full volume.
Also '12/8 Tri' is in the FW table, but not listed in Manual or displayed by device... why?
Anyone found a FW file for the A1Four/A1FourX? This apparently has a different set of drum patterns.
Oh, so many questions. Looking at the 3rd data byte, what do these have in common?
$ python3 ../decode_patterns.py -d -O 407304 unzipped/.rsrc/1041/BIN/129 | grep -e name -e data3 | grep -B 1 '= 24' | grep name
name = u'Dummy' (total 5)
name = u'GUIDE' (total 5)
name = u'Jazz1' (total 5)
name = u'Jazz2' (total 5)
name = u'Waltz' (total 5)
name = u'CtWaltz1' (total 8)
name = u'CtWaltz2' (total 8)
name = u'JzWaltz1' (total 8)
name = u'JzWaltz2' (total 8)
name = u'Metro3' (total 6)
name = u'Metro4' (total 6)
name = u'Metro5' (total 6)
name = u'Metro' (total 5)
Are they perhaps in a different area of memory?
Eyup munge. Bit busy to dive back into this at the moment but my pitch is that the Zoom's have simple 1 'pattern' tracker type players in them each of which would only need to comprise of a pointer to a few bytes of trigger deltas/sample Nos/Sample Volumes followed by a terminator.. This would be a very compact solution especially as no handling of pitch information is required. Each pattern would effectively a 'bar' in tracker world with each consisting of only a few tens bytes even in a complex drum pattern.
The project mentions changing the drum patterns.... has any work been done on this?
Is there a 'file' within the F/W image (like a 'zdl' or something) which contains the patterns, and if so has any of it been decoded?