Up Rough musicdisks

Started by Asle, March 01, 2015, 16:42:20

Previous topic - Next topic


 In the same spirit as the Confusion musicdisk discussion, I'm breaking my teeth on the various Up Rough musicdisks.
Several examples are on Up Rough homepage.

First, I can't even the damn things :) . Now, there's apparently an option, when running, to save the music being played. Even so, the musics are stored in sub-directories. However, they are encrypted. It's obviously a key, however, it's kind of a changing key.
Anyway, tried several times and went nowhere.
The one I've been looking after several time is this one : http://www.uprough.net/releases/UP-LP005.LHA

If anyone could help explain what I do wrong, that would be great.


Ah, more encrypted mods! This is excellent news, it has been a while...

What kind of problems exactly you had? I took a look at this and created a new UAE A4000 instance. First I did a fresh install of Workbench 3.1 on a harddisk image file. I then copied C= installer from Aminet into C: and ran the provided install script. (Man, the post-2000 musicdisk world is different from what it used to be - where is the track loader, for instance? What, no lack of memory allocation? No decompression to fixed memory address? Heck you can even exit these ones!)

The installer seems to be a bit broken, you need to manually fix some file protection settings once the install is complete:

protect EP:start +s
protect EP:prefs +s
protect EP:EP +e

After that you can run "start". I got a warning message Couldn't find the file "ENV:sys/ahi/prefs"! but this does not seem to matter. In the prefs you need to select a screenmode and EP dir (for this particular one it should be EP:EPs/blowme!morehitsforkids. Save the prefs and click Start, and the musicdisk runs just fine for me. And it can save the modules if you press "s".

I guess the authors realized the futility of encryption - after all there are people like us in the world.  :) We could of course crack it just for sport, but I am sure manually saving the modules is more efficient. Or maybe even asking the authors for originals. :)

I suggest you make sure you are using a harddisk image file (UAE can use the host OS disk but AmigaOS will likely get confused by the different file protection/permission bits, remember AmigaDOS is pretty unique with this). Then just use the provided install script with the manual fixes and save the modules manually. If you need my .uaerc I can send it to you but it will need to be adapted for you.

As for the actual encryption: I don't really know, but it seems to include some kind of compression as the encrypted mods are smaller than originals. Or perhaps it is just a different way of storing the pattern data.


hum. Right. So .. first, thanks for this feedback :)
About the setup thing, I had not figured it out, so, that's helpful.

However, I had in mind this encryption, of course.
The 'save' feature saves from memory or converts from disk ? I'd say from memory since it saves the "current" music.

The result files _are_ something for which we are, of course, very grateful :). It's my extremist side which takes over ;)

Thanks for your thorough reply ! Very appreciated.



Quote from: Asle on March 12, 2015, 18:45:39
The 'save' feature saves from memory or converts from disk ? I'd say from memory since it saves the "current" music.

Hmm. I wonder - if you can't tell the difference, does it really, really matter? I will show you that in this case they are the same, but as you probably won't believe me without seeing the disk rip decoder yourself, we will go the hard way. :) So, let us begin.

I was able to locate the decryption (or perhaps just descrambling or decoding) code with UAE by using breakpoints to intercept dos.library Read() calls and examining what happens next in the code. This turned out to be both easy and fruitful, as the program immediately decodes the file after loading. With disassembler I saw a call to subroutine that does some odd bit fiddling with the loaded data. It looked promising so I ran it to completion and the end result was decoded file in the same memory location. Yay! Below is the decoder for your viewing pleasure. It is called with the address of loaded data in registers a0 and a1, and the length of the loaded data in d0.

4005acb8: 48e7 7ff0 41f0 0800 43f1 MVMLE.L #$7ff0,-(A7)
4005acbc: 41f0 0800 43f1 0800 45f9 LEA.L (A0, D0.L*1, $00) == $400cc6e1,A0
4005acc0: 43f1 0800 45f9 4005 f350 LEA.L (A1, D0.L*1, $00) == $400cc6e1,A1
4005acc4: 45f9 4005 f350 47f9 4005 LEA.L $4005f350,A2
4005acca: 47f9 4005 f394 7227 740d LEA.L $4005f394,A3
4005acd0: 7227 740d 760d 2e00 1821 MOVE.L #$00000027,D1
4005acd2: 740d 760d 2e00 1821 1a32 MOVE.L #$0000000d,D2
4005acd4: 760d 2e00 1821 1a32 1800 MOVE.L #$0000000d,D3
4005acd6: 2e00 1821 1a32 1800 1433 MOVE.L D0,D7
4005acd8: 1821 1a32 1800 1433 2800 MOVE.B -(A1),D4
4005acda: 1a32 1800 1433 2800 bb04 MOVE.B (A2, D1.L*1, $00) == $400cc6e1,D5
4005acde: 1433 2800 bb04 1633 3800 MOVE.B (A3, D2.L*1, $00) == $5008cef1,D2
4005ace2: bb04 1633 3800 1104 b902 EOR.B D5,D4
4005ace4: 1633 3800 1104 b902 b903 MOVE.B (A3, D3.L*1, $00) == $40069001,D3
4005ace8: 1104 b902 b903 0202 003f MOVE.B D4,-(A0)
4005acea: b902 b903 0202 003f e40b EOR.B D4,D2
4005acec: b903 0202 003f e40b 1202 EOR.B D4,D3
4005acee: 0202 003f e40b 1202 b701 AND.B #$3f,D2
4005acf2: e40b 1202 b701 5387 66dc LSR.B #$00000002,D3
4005acf4: 1202 b701 5387 66dc 43f9 MOVE.B D2,D1
4005acf6: b701 5387 66dc 43f9 4005 EOR.B D3,D1
4005acf8: 5387 66dc 43f9 4005 f348 SUB.L #$00000001,D7
4005acfa: 66dc 43f9 4005 f348 7200 BNE.B #$ffffffffffffffdc == 4005acd8 (TRUE)
4005acfc: 43f9 4005 f348 7200 740d LEA.L $4005f348,A1
4005ad02: 7200 740d 760d 7800 7a00 MOVE.L #$00000000,D1
4005ad04: 740d 760d 7800 7a00 7c00 MOVE.L #$0000000d,D2
4005ad06: 760d 7800 7a00 7c00 5380 MOVE.L #$0000000d,D3
4005ad08: 7800 7a00 7c00 5380 1c10 MOVE.L #$00000000,D4
4005ad0a: 7a00 7c00 5380 1c10 1e06 MOVE.L #$00000000,D5
4005ad0c: 7c00 5380 1c10 1e06 ccf1 MOVE.L #$00000000,D6
4005ad0e: 5380 1c10 1e06 ccf1 4800 SUB.L #$00000001,D0
4005ad10: 1c10 1e06 ccf1 4800 da06 MOVE.B (A0),D6
4005ad12: 1e06 ccf1 4800 da06 1c32 MOVE.B D6,D7
4005ad14: ccf1 4800 da06 1c32 1800 MULU.W (A1, D4.L*1, $00) == $400d67f4,D6
4005ad18: da06 1c32 1800 5404 bd07 ADD.B D6,D5
4005ad1a: 1c32 1800 5404 bd07 10c7 MOVE.B (A2, D1.L*1, $00) == $400cc6e1,D6
4005ad1e: 5404 bd07 10c7 0204 0006 ADD.B #$00000002,D4
4005ad20: bd07 10c7 0204 0006 1433 EOR.B D6,D7
4005ad22: 10c7 0204 0006 1433 2800 MOVE.B D7,(A0)+
4005ad24: 0204 0006 1433 2800 7c00 AND.B #$06,D4
4005ad28: 1433 2800 7c00 1633 3800 MOVE.B (A3, D2.L*1, $00) == $5008cef1,D2
4005ad2c: 7c00 1633 3800 bf02 bf03 MOVE.L #$00000000,D6
4005ad2e: 1633 3800 bf02 bf03 0202 MOVE.B (A3, D3.L*1, $00) == $40069001,D3
4005ad32: bf02 bf03 0202 003f e40b EOR.B D7,D2
4005ad34: bf03 0202 003f e40b 1202 EOR.B D7,D3
4005ad36: 0202 003f e40b 1202 b701 AND.B #$3f,D2
4005ad3a: e40b 1202 b701 5380 66cc LSR.B #$00000002,D3
4005ad3c: 1202 b701 5380 66cc 7001 MOVE.B D2,D1
4005ad3e: b701 5380 66cc 7001 ba10 EOR.B D3,D1
4005ad40: 5380 66cc 7001 ba10 6702 SUB.L #$00000001,D0
4005ad42: 66cc 7001 ba10 6702 7000 BNE.B #$ffffffffffffffcc == 4005ad10 (TRUE)
4005ad44: 7001 ba10 6702 7000 4cdf MOVE.L #$00000001,D0
4005ad46: ba10 6702 7000 4cdf 0ffe CMP.B (A0),D5
4005ad48: 6702 7000 4cdf 0ffe 4e75 BEQ.B #$00000002 == 4005ad4c (FALSE)
4005ad4a: 7000 4cdf 0ffe 4e75 4e71 MOVE.L #$00000000,D0
4005ad4c: 4cdf 0ffe 4e75 4e71 4eb9 MVMEL.L #$0ffe,(A7)+
4005ad50: 4e75 4e71 4eb9 4005 f3e8 RTS.L

As you can see the code refers to a decoding key at address $4005f350 (attached as file 4005f350). In the same spirit as the venerable Confusion music disk, the key is just program code, not really a separate key at all. But this time the algorithm is much more complex than just basic XOR. I am not sure about the length of the key. Since it is indexed with a byte offset both from beginning and offset 0x44, the total offset should never be more than 0x143. I just dumped 512 bytes of memory and that seems to be enough. Since the key is part of EP code, it is the same for all disks.

Also, there is a small table used for multiplications at $4005f348 (attached as file 4005f348). Based on this saved information, it is possible to write a decoder even without understanding the decoder function at all. Just extract the code and run it on input data using the key and table. I wrote a simple C language emulator for the disassembly above and a CLI frontend to load files, call the decoder and save decoder file. (Attached as unuprough.c, key.h and Makefile). Again, just build it and run it on the encoded module files like this:

./unuprough module01.up module02.up ...

The output file name is generated by concatenating strings "mod." and whatever is in the beginning of the decoded file. This works for Protracker mods, but some modules are in different format (AHX at least, perhaps others) and these files will get random file names. Perhaps it is better to decode them one at time and rename the random name manually.

Now that we can decode the disk rips, we can also verify that the files obtained by the "s" command are identical. :)

P.S. in my earlier message I made a mistake - the encoded file is not shorter than the original, instead it is always 1 byte longer.
P.P.S. I think I just learned something about myself... I'll throw myself at any crazy impulse challenge you post here... and really enjoy that. :)


man, this was crazy !
wow. very impressive.

OK, so, it compiles and works greatly :). I just changed one line in the source:

/*strncat(outname, modbuf, sizeof(outname));*/
strncat(outname, name, sizeof(outname));

The reason is because some of those files are actually AHX. Their title is actually at the end :) .

I haven't have time to try your trick to run this from wb yet, so I can't really test. However, in the LP004, there are musics by our own Curt Cool. I compared his original with the depacked version and they are identical.

When reading the decoding func, it looked really crazy. But then, you managed to pull it off. There's indeed no real need to understand this.

I'm out of words to actually say anything meaningful. A mere "thank you", at least, is the best I can utter for now ;)

Now, I'll dig into those disks and report if I stubble on anything suspicious.



and upon further tests, I confirm the 's' function does save from memory (i.e. all 4 first bytes of each sample is cleared).
So, double kuddos for this decrypting tool !

On my way throughout all the UP musicdisks now. yeah !


You're welcome, and I'm happy to hear the tool gets some serious action right away. :)

But I'm confused about the 's' function now. I ran my tool on one of the encrypted modules and got one file, then saved the same module with 's' command. I did bit-by-bit comparison and the files were identical. Or did I just manage to pick a module which is not affected by clearing the first 4 bytes (and shouldn't that be 2 bytes if we are talking about the repeat info)?


OK, I assumed the files we stored here were the result of 's'. Maybe not.
My example is UP-LP003. I had to update three musics by Skope from this musicdisk. The list is in today's additions.
Those three were memory rips. If you're still set up and can run this, are you willing to try the 's' there ? Still didn't get around installing wb 3.1 yet :(

Note that the decrypting tool works on everything (text, raw picture, etc.). This is _very_ useful to retrieve the production text for example. So, if only for that, it great :)


I saved all the modules of up-ep003 with 's' key and the compared to files decrypted with the tool. Each of the 5 modules was identical. Maybe the old AMP files were obtained from some other source, or maybe ripped with something like ProWizard from memory?


I wonder where I got my 3 by Skope from then?

Mine are datestamped 2005 for 2 of them and 2009 for the other. Filesizes are identical.


Now I'm confused. why would someone perform a memory rip if this 's' feature saves the file without the four first bytes of each sample cleared ?
Another thing that is unsettling. UP-EP001 has musics by Ronny. I retrieved these musics from Up-Rough website a while ago. All were memory rips.
All this is rather confusing.

Still, I'm glad for this remarkable tool. 14 musicdisks handled so far. I updated some musics on AMP. Got 3 more "chip music disks" to go. Audit traces of said updates are coming shortly.

@Axxy, identical size is not enough. you should perform a binary file comparison. As for your sources, I'm afraid I can't help ;)


Quote from: Asle on March 19, 2015, 19:18:36

@Axxy, identical size is not enough. you should perform a binary file comparison. As for your sources, I'm afraid I can't help ;)

Mine are identical except "def chaos filter" has slight variations in the file. Seems strange I had only those 3 as the others, "freshly 2000" is datestamped 2013 and I didn't have welcome003...  Must have found a download for them somewhere, as I obviously didn't rip them back then.


well, Up Rough _does_ provide the MODs for various musicdisks on their website. The link to those is generally close to the musicdisk link itself. Though, they more easily link to MP3 version. Maybe you got your version from their website ?


And I'm done with all Up Rough musicdisks.
That includes all LP and EP series.
Several additions/updates were made to AMP because of that. So, in case I didn't make it clear, thanks a lot for your tool ! it helped a lot !



Great! I am really happy to hear that.

I must say I do miss the good old days and hacking with UAE is like a time machine. And it also help make my tiny contribution to the awesome AMP. Now, I go back optimizing my 68000 mandelbrot code, see you again in next music disk!