The whole core of the MD5 code is very small: // Include C64 data. myMD5.append(cache.get()+fileOffset,info.c64dataLen); unsigned char tmp[2]; // Include INIT and PLAY address. writeLEword(tmp,info.initAddr); myMD5.append(tmp,sizeof(tmp)); writeLEword(tmp,info.playAddr); myMD5.append(tmp,sizeof(tmp)); // Include number of songs. writeLEword(tmp,info.songs); myMD5.append(tmp,sizeof(tmp)); // Include song speed for each song. for (unsigned int s = 1; s <= info.songs; s++) { selectSong(s); myMD5.append(&info.songSpeed,sizeof(info.songSpeed)); } // Deal with PSID v2NG clock speed flags: Let only NTSC // clock speed change the MD5 fingerprint. That way the // fingerprint of a PAL-speed sidtune in PSID v1, v2, and // PSID v2NG format is the same. if ( info.clockSpeed == SIDTUNE_CLOCK_NTSC ) myMD5.append(&info.clockSpeed,sizeof(info.clockSpeed)); // NB! If the fingerprint is used as an index into a // song-lengths database or cache, modify above code to // allow for PSID v2NG files which have clock speed set to // SIDTUNE_CLOCK_ANY. If the SID player program fully // supports the SIDTUNE_CLOCK_ANY setting, a sidtune could // either create two different fingerprints depending on // the clock speed chosen by the player, or there could be // two different values stored in the database/cache.
But the "selectSong(s)" is the not trivial part of the whole calculation which sets the songSpeed for every song. If you convert the selectSong method in the loop, for the things needed for the MD5 calculation, you will get: uint8 u8CiaSpeed = 60; uint8 u8VblSpeed = 0; for (i = 0; I < u16NumSongs; i++) { if (!boPSIDSpecific) { if (i < 31) // check tune 0-30 (bit 0 - 30) boVbiSpeed = !(u32Speed & (1 << i)); else boVbiSpeed = !(u32Speed & (1 << 31));// last bit sets speed for tunes >31 } else { // old PlaySID implementation boVbiSpeed = !(u32Speed & (1 << (i % 32))); } // speed setting if (boVbiSpeed) md5_append(&u8VblSpeed, 1); else md5_append(&u8CiaSpeed, 1); }
m = hashlib.md5() m.update(sid_data) m.update(struct.pack("<H", sid_header[HDR_INITADDRESS])) m.update(struct.pack("<H", sid_header[HDR_PLAYADDRESS])) m.update(struct.pack("<H", sid_header[HDR_SONGS])) for i in range(sid_header[HDR_SONGS]): if sid_header[HDR_SPEED] & (1<<i): m.update(chr(60)) else: m.update(chr(0))
m = hashlib.md5() m.update(sid_data[2:]) m.update(struct.pack("<H", sid_header[HDR_INITADDRESS])) m.update(struct.pack("<H", sid_header[HDR_PLAYADDRESS])) m.update(struct.pack("<H", sid_header[HDR_SONGS])) for i in range(sid_header[HDR_SONGS]): if sid_header[HDR_SPEED] & (1<<i): m.update(chr(60)) else: m.update(chr(0))
sid_header = unpack_header(data) sid_version = sid_header[HDR_VERSION] sid_data = data[sid_header[HDR_DATAOFFSET]:] m = hashlib.md5() m.update(sid_data[2:]) m.update(struct.pack("<H", sid_header[HDR_INITADDRESS])) m.update(struct.pack("<H", sid_header[HDR_PLAYADDRESS])) m.update(struct.pack("<H", sid_header[HDR_SONGS])) for i in range(sid_header[HDR_SONGS]): if sid_header[HDR_MAGIC] == "RSID": m.update(chr(60)) else: if sid_header[HDR_SPEED] & (1<<min(i, 31)): m.update(chr(60)) else: m.update(chr(0)) if sid_version == 2: if (sid_header[HDR_FLAGS] & 0x0c) == 0x08: m.update(chr(2))
/MUSICIANS/J/JCH/Tecnetium.sid {'COMM': 'I always get mixed feelings when I play this music. The title- tune is\nlong and I put a lot of work into it in april 1989, but today I can\nhear loads of harmonic errors here and there. The game was done for a\nsideways shoot\'em up which a couple of totally unknown danish guys was\nmaking. They soon lost all interest in their game, however. The\nhiscore theme was a conversion of the old Cliff Richard hit\n"Congratulations" done right out my head. I always wanted to make such\na hiscore tune, because I always thought Rob Hubbard did it all wrong\nwhen he made "sad" hiscore tunes. It is a sad thing when the game\nends, but getting a high score is supposed to be a GOOD thing! :)', 'TUNS': [{'LENG': 23330816, 'NAME': 'Title Screen'}, {'ARTI': 'Cliff Richard', 'LENG': 5963776, 'TITL': 'Congratulations'}, {'LENG': 262144}, {'LENG': 196608}, {'LENG': 2883584}, {'LENG': 65536, 'LOOP': 'G'}, {'LENG': 196608, 'LOOP': 'G'}, {'LENG': 65536, 'LOOP': 'G'}, {'LENG': 65536, 'LOOP': 'G'}, {'LENG': 65536, 'LOOP': 'G'}, {'LENG': 65536, 'LOOP': 'G'}, {'LENG': 65536, 'LOOP': 'G'}, {'LENG': 65536, 'LOOP': 'G'}, {'LENG': 65536, 'LOOP': 'G'}, {'LENG': 196608, 'LOOP': 'G'}, {'LENG': 131072, 'LOOP': 'G'}, {'LENG': 65536, 'LOOP': 'G'}, {'LENG': 65536, 'LOOP': 'G'}]}