home *** CD-ROM | disk | FTP | other *** search
Wrap
Text File | 1997-12-19 | 26.5 KB | 450 lines | [ TEXT/R*ch]
/* Analyzing CDFinder 2.0's SN# algorithm was _highly entertaining_, the author has obviously seen C&N or some such lists entry for CDFinder and has added distributed checks (except for a minor mistake -- documented with correction below) for the pirate user names "NASA" and "MoonDark". What was especially entertaining is how predictable this guy thinks, appart from the naming conventions I bet the following source code is 99.8% _exactly the same_ as the authors. The birthdate, authors initials and "PV" = "Pirated Version" insights were bonuses, but the icing on the cake was the logic error in the "MoonDark" test. I don't even use the program in question, but as soon as soon as I saw the check code I could see it was interesting so I just had to reverse engineer it. I hope everyone gets a kick out of this -- MoonDark, especially, should find this funny. Enclosed at the end is the 68K assembly source dump so you can see what I'm describing first hand. */ //A5 Globals - these are checked and/or used after by the main registration logic. UInt16 globA5Minus0x0DD6 = 0; //global that is set to its correct value of 0x07AE iff chars 2,5,9, and 10 of snStr[] are the correct digits UInt32 globA5Minus0x0DD4; //holds final nameStr hash value UInt16 globA5Minus0x0DD0 = 0; //global that is set to its correct value of 0x0007 iff chars 1 and 7 of snStr[] are correct [note this is the authors (Norbert Doerner) initials] UInt16 globA5Minus0x0DCE = 0; //global that is set to its correct value of 0x000D iff chars 3,4,6, and 8 of snStr[] are the correct digits //notice the magic correct numbers uniquely define the date 1966/07/13, which is almost undoubtedly the author's (or his girlfriend's) birthdate. //this is a more or less direct translation of the assembly code. //when combined with the assembly source below is a very good tutorial/example to learn from, especially for those that have difficulty following //intricate sequences of integer math operations. //the following returns 1 iff a pirate user name was used, otherwise it returns 0 - it also does almost all the work of validating a serial number UInt16 Check1CDFinder2SN(Str255 nameStr, Str15 snStr); UInt16 Check1CDFinder2SN(Str255 nameStr, Str15 snStr) { UInt32 d3 = 1; //flag indicating pirate user name "\pMoonDark" (actually the author made an error in the source code that checks for "oo" in "MoonDark", see below for explanation) UInt32 d4 = 1; //flag indicating pirate user name "\pNASA" SInt32 d5; UInt32 d7 = 0; UInt32 d6 = (UInt8) nameStr[0]; SInt32 u, v, w, d7; Str255 xStr; globA5Minus0x0DCE = 0; if (nameStr[0] == 0) return 0; if (nameStr[0] != 4) d4 = 0; if (nameStr[0] != 8) d3 = 0; for (d5 = d6; d5 > 0 ; d5--) //this loop calculates a partial hash of the nameStr { u = 7UL * (UInt32) (d5 * 17L); //note the UInt32 multiply v = (SInt16) ((u / 13L) * 831L); //note the SInt16 sign extend w = ((v * (v + 4097L)) / 83L) * 137L; d7 += (((SInt16) v / (SInt16) w) + u) * (UInt8) nameStr[d5]; //note the SInt16 divide then extend } if ((nameStr[8] != 'k') && (d3 != 0)) d3 = 0; //note: the last part of the conditional expression is unecessary if ((nameStr[2] != nameStr[4]) && (d4 != 0)) d4 = 0; //note: the last part of the conditional expression is unecessary d5 = d7 * 53L; //the following code should be present here, but due to a parenthesization/logic error in the authors code it is always false and thus never executed //if (((nameStr[2] != nameStr[3]) || (nameStr[2] != 'o')) && (d3 != 0)) d3 = 0; //note: the last part of the conditional expression is unecessary //in actuality the author wrote something like this: //if (((nameStr[2] != nameStr[3]) == 'o') && (d3 != 0)) d3 = 0; //of course the == 'o' condition is always false, thus any user name of the form "M**nDark", where '*' is any character, is in fact also illegal. if ((nameStr[4] != 'A') && (d4 != 0)) d4 = 0; //note: the last part of the conditional expression is unecessary NumToString(d5 * 7L, xStr); globA5Minus0x0DD4 = d5 * 7L; if ((nameStr[3] != 'S') && (d4 != 0)) d4 = 0; //note: the last part of the conditional expression is unecessary d6 = xStr[0]; if ((nameStr[1] != 'M') && (d3 != 0)) d3 = 0; //note: the last part of the conditional expression is unecessary if (snStr[0] != 10) return 1; if ((nameStr[1] != 'N') && (d4 != 0)) d4 = 0; //note: the last part of the conditional expression is unecessary if (xStr[0] < 8) //extend the hashed string to at least 8 chars in a nonstandard way { for (d5 = xStr[0] + 1; d5 <= 8; d5++) xStr[d5] = xStr[1]; xStr[0] = 8; } if ((nameStr[4] != 'n') && (d3 != 0)) d3 = 0; //note: the last part of the conditional expression is unecessary if (d4 != 0) //note that at this point (d4 != 0) implies that nameStr[] = "\pNASA" { xStr[5] = 'P'; //no doubt this stands for "Pirated Version" snStr[7] = 'V'; return 1; //pirate name was used } if ((nameStr[5] != 'D') && (d3 != 0)) d3 = 0; //note: the last part of the conditional expression is unecessary if (snStr[ 2] != xStr[5]) goto LB1; if (snStr[ 9] != xStr[2]) goto LB1; if (snStr[ 5] != xStr[7]) goto LB1; if (snStr[10] != xStr[6]) goto LB1; globA5Minus0x0DD6 = 0x07AE; //chars 2,5,9, and 10 of snStr[] are the correct digits LB1: if ((nameStr[7] != 'r') && (d3 != 0)) d3 = 0; //note: the last part of the conditional expression is unecessary if (snStr[7] != 'D') goto LB2; //Doerner if (snStr[1] != 'N') goto LB2; //Norbert globA5Minus0x0DD0 = 0x0007; //chars 1 and 7 of snStr[] are correct [note this is the authors (Norbert Doerner) initials] LB2: if ((nameStr[6] != 'a') && (d3 != 0)) d3 = 0; //note: the last part of the conditional expression is unecessary if (snStr[ 4] != xStr[4]) goto LB3; if (snStr[ 6] != xStr[3]) goto LB3; if (snStr[ 8] != xStr[1]) goto LB3; if (snStr[ 3] != xStr[8]) goto LB3; globA5Minus0x0DCE = 0x000D; //chars 3,4,6, and 8 of snStr[] are the correct digits LB3: if (d3 != 0) //note that at this point (d3 != 0) implies that nameStr[] = "\pM**nDark" { xStr[5] = 'P'; //no doubt this stands for "Pirated Version" snStr[7] = 'V'; return 1; //pirate name was used } if (d4 != 0) return d4; //the author was unsure of himself and added this extraneous check (d4 is always zero here) return 0; //pirate name was not used } //The following is a 68K assembly dump of the authors code corresponding to the above /* +08C1A 0527837A LINK A6,#$FFC0 +08C1E 0527837E MOVEM.L D3-D7/A2/A3,-(A7) +08C22 05278382 MOVEA.L $0008(A6),A2 +08C26 05278386 MOVEA.L $000C(A6),A3 +08C2A 0527838A MOVEQ #$01,D4 +08C2C 0527838C MOVEQ #$00,D6 +08C2E 0527838E MOVE.B (A2),D6 +08C30 05278390 CLR.W -$0DCE(A5) +08C34 05278394 TST.B (A2) +08C36 05278396 BNE.S 'CODE 0001 25…urces'+08C3E ; 0527839E +08C38 05278398 MOVEQ #$00,D0 +08C3A 0527839A BRA 'CODE 0001 25…urces'+08E1E ; 0527857E +08C3E 0527839E MOVEQ #$01,D3 +08C40 052783A0 MOVEQ #$00,D7 +08C42 052783A2 MOVEQ #$04,D0 +08C44 052783A4 CMP.L D0,D6 +08C46 052783A6 BEQ.S 'CODE 0001 25…urces'+08C4A ; 052783AA +08C48 052783A8 MOVEQ #$00,D4 +08C4A 052783AA MOVEQ #$08,D0 +08C4C 052783AC CMP.L D0,D6 +08C4E 052783AE BEQ.S 'CODE 0001 25…urces'+08C52 ; 052783B2 +08C50 052783B0 MOVEQ #$00,D3 +08C52 052783B2 MOVE.L D6,D5 +08C54 052783B4 BRA.S 'CODE 0001 25…urces'+08C76 ; 052783D6 +08C56 052783B6 //contents of this math loop are given below - it is quit interesting actually +08C72 052783D2 SUBQ.L #$1,D5 +08C74 052783D4 ADDQ.W #$4,A7 +08C76 052783D6 TST.L D5 +08C78 052783D8 BGT.S 'CODE 0001 25…urces'+08C56 ; 052783B6 +08C7A 052783DA CMPI.B #$6B,$0008(A2) ; 'k' +08C80 052783E0 BEQ.S 'CODE 0001 25…urces'+08C88 ; 052783E8 +08C82 052783E2 TST.L D3 +08C84 052783E4 BEQ.S 'CODE 0001 25…urces'+08C88 ; 052783E8 +08C86 052783E6 MOVEQ #$00,D3 +08C88 052783E8 MOVE.B $0002(A2),D0 +08C8C 052783EC CMP.B $0004(A2),D0 +08C90 052783F0 BEQ.S 'CODE 0001 25…urces'+08C98 ; 052783F8 +08C92 052783F2 TST.L D4 +08C94 052783F4 BEQ.S 'CODE 0001 25…urces'+08C98 ; 052783F8 +08C96 052783F6 MOVEQ #$00,D4 +08C98 052783F8 MOVEQ #$35,D5 ; '5' +08C9A 052783FA MULS.L D7,D5 +08C9E 052783FE MOVE.B $0002(A2),D0 +08CA2 05278402 CMP.B $0003(A2),D0 +08CA6 05278406 SEQ D0 //• this is where the "MoonDark" logic error is +08CA8 05278408 NEG.B D0 //• this is where the "MoonDark" logic error is +08CAA 0527840A CMPI.B #$6F,D0 ; 'o' +08CAE 0527840E BNE.S 'CODE 0001 25…urces'+08CB6 ; 05278416 +08CB0 05278410 TST.L D3 +08CB2 05278412 BEQ.S 'CODE 0001 25…urces'+08CB6 ; 05278416 +08CB4 05278414 MOVEQ #$00,D3 +08CB6 05278416 CMPI.B #$41,$0004(A2) ; 'A' +08CBC 0527841C BEQ.S 'CODE 0001 25…urces'+08CC4 ; 05278424 +08CBE 0527841E TST.L D4 +08CC0 05278420 BEQ.S 'CODE 0001 25…urces'+08CC4 ; 05278424 +08CC2 05278422 MOVEQ #$00,D4 +08CC4 05278424 MOVEQ #$07,D0 +08CC6 05278426 MULS.L D5,D0 +08CCA 0527842A MOVE.L D0,-(A7) +08CCC 0527842C PEA -$0040(A6) +08CD0 05278430 JSR 'CODE 0003 25…aries'+023D6 //this is just a NumToString call +08CD6 05278436 MOVEQ #$07,D0 +08CD8 05278438 MULS.L D5,D0 +08CDC 0527843C MOVE.L D0,-$0DD4(A5) +08CE0 05278440 CMPI.B #$53,$0003(A2) ; 'S' +08CE6 05278446 BEQ.S 'CODE 0001 25…urces'+08CEE ; 0527844E +08CE8 05278448 TST.L D4 +08CEA 0527844A BEQ.S 'CODE 0001 25…urces'+08CEE ; 0527844E +08CEC 0527844C MOVEQ #$00,D4 +08CEE 0527844E MOVEQ #$00,D6 +08CF0 05278450 MOVE.B -$0040(A6),D6 +08CF4 05278454 CMPI.B #$4D,$0001(A2) ; 'M' +08CFA 0527845A BEQ.S 'CODE 0001 25…urces'+08D02 ; 05278462 +08CFC 0527845C TST.L D3 +08CFE 0527845E BEQ.S 'CODE 0001 25…urces'+08D02 ; 05278462 +08D00 05278460 MOVEQ #$00,D3 +08D02 05278462 CMPI.B #$0A,(A3) +08D06 05278466 BEQ.S 'CODE 0001 25…urces'+08D0E ; 0527846E +08D08 05278468 MOVEQ #$01,D0 +08D0A 0527846A BRA 'CODE 0001 25…urces'+08E1E ; 0527857E +08D0E 0527846E CMPI.B #$4E,$0001(A2) ; 'N' +08D14 05278474 BEQ.S 'CODE 0001 25…urces'+08D1C ; 0527847C +08D16 05278476 TST.L D4 +08D18 05278478 BEQ.S 'CODE 0001 25…urces'+08D1C ; 0527847C +08D1A 0527847A MOVEQ #$00,D4 +08D1C 0527847C MOVEQ #$08,D0 +08D1E 0527847E CMP.L D0,D6 +08D20 05278480 BGE.S 'CODE 0001 25…urces'+08D40 ; 052784A0 +08D22 05278482 MOVE.B #$08,-$0040(A6) +08D28 05278488 MOVE.L D6,D5 +08D2A 0527848A ADDQ.L #$1,D5 +08D2C 0527848C BRA.S 'CODE 0001 25…urces'+08D3A ; 0527849A +08D2E 0527848E LEA -$0040(A6),A0 +08D32 05278492 MOVE.B -$003F(A6),$00(A0,D5.L) +08D38 05278498 ADDQ.L #$1,D5 +08D3A 0527849A MOVEQ #$08,D0 +08D3C 0527849C CMP.L D0,D5 +08D3E 0527849E BLE.S 'CODE 0001 25…urces'+08D2E ; 0527848E +08D40 052784A0 CMPI.B #$6E,$0004(A2) ; 'n' +08D46 052784A6 BEQ.S 'CODE 0001 25…urces'+08D4E ; 052784AE +08D48 052784A8 TST.L D3 +08D4A 052784AA BEQ.S 'CODE 0001 25…urces'+08D4E ; 052784AE +08D4C 052784AC MOVEQ #$00,D3 +08D4E 052784AE TST.L D4 +08D50 052784B0 BEQ.S 'CODE 0001 25…urces'+08D64 ; 052784C4 +08D52 052784B2 MOVE.B #$50,-$003B(A6) ; 'P' +08D58 052784B8 MOVE.B #$56,$0007(A3) ; 'V' +08D5E 052784BE MOVEQ #$01,D0 +08D60 052784C0 BRA 'CODE 0001 25…urces'+08E1E ; 0527857E +08D64 052784C4 CMPI.B #$44,$0005(A2) ; 'D' +08D6A 052784CA BEQ.S 'CODE 0001 25…urces'+08D72 ; 052784D2 +08D6C 052784CC TST.L D3 +08D6E 052784CE BEQ.S 'CODE 0001 25…urces'+08D72 ; 052784D2 +08D70 052784D0 MOVEQ #$00,D3 +08D72 052784D2 MOVE.B -$003B(A6),D0 +08D76 052784D6 CMP.B $0002(A3),D0 +08D7A 052784DA BNE.S 'CODE 0001 25…urces'+08DA0 ; 05278500 +08D7C 052784DC MOVE.B -$003E(A6),D0 +08D80 052784E0 CMP.B $0009(A3),D0 +08D84 052784E4 BNE.S 'CODE 0001 25…urces'+08DA0 ; 05278500 +08D86 052784E6 MOVE.B -$0039(A6),D0 +08D8A 052784EA CMP.B $0005(A3),D0 +08D8E 052784EE BNE.S 'CODE 0001 25…urces'+08DA0 ; 05278500 +08D90 052784F0 MOVE.B -$003A(A6),D0 +08D94 052784F4 CMP.B $000A(A3),D0 +08D98 052784F8 BNE.S 'CODE 0001 25…urces'+08DA0 ; 05278500 +08D9A 052784FA MOVE.W #$07AE,-$0DD6(A5) +08DA0 05278500 CMPI.B #$72,$0007(A2) ; 'r' +08DA6 05278506 BEQ.S 'CODE 0001 25…urces'+08DAE ; 0527850E +08DA8 05278508 TST.L D3 +08DAA 0527850A BEQ.S 'CODE 0001 25…urces'+08DAE ; 0527850E +08DAC 0527850C MOVEQ #$00,D3 +08DAE 0527850E CMPI.B #$44,$0007(A3) ; 'D' +08DB4 05278514 BNE.S 'CODE 0001 25…urces'+08DC4 ; 05278524 +08DB6 05278516 CMPI.B #$4E,$0001(A3) ; 'N' +08DBC 0527851C BNE.S 'CODE 0001 25…urces'+08DC4 ; 05278524 +08DBE 0527851E MOVE.W #$0007,-$0DD0(A5) +08DC4 05278524 CMPI.B #$61,$0006(A2) ; 'a' +08DCA 0527852A BEQ.S 'CODE 0001 25…urces'+08DD2 ; 05278532 +08DCC 0527852C TST.L D3 +08DCE 0527852E BEQ.S 'CODE 0001 25…urces'+08DD2 ; 05278532 +08DD0 05278530 MOVEQ #$00,D3 +08DD2 05278532 MOVE.B -$003C(A6),D0 +08DD6 05278536 CMP.B $0004(A3),D0 +08DDA 0527853A BNE.S 'CODE 0001 25…urces'+08E00 ; 05278560 +08DDC 0527853C MOVE.B -$003D(A6),D0 +08DE0 05278540 CMP.B $0006(A3),D0 +08DE4 05278544 BNE.S 'CODE 0001 25…urces'+08E00 ; 05278560 +08DE6 05278546 MOVE.B -$003F(A6),D0 +08DEA 0527854A CMP.B $0008(A3),D0 +08DEE 0527854E BNE.S 'CODE 0001 25…urces'+08E00 ; 05278560 +08DF0 05278550 MOVE.B -$0038(A6),D0 +08DF4 05278554 CMP.B $0003(A3),D0 +08DF8 05278558 BNE.S 'CODE 0001 25…urces'+08E00 ; 05278560 +08DFA 0527855A MOVE.W #$000D,-$0DCE(A5) +08E00 05278560 TST.L D3 +08E02 05278562 BEQ.S 'CODE 0001 25…urces'+08E14 ; 05278574 +08E04 05278564 MOVE.B #$50,-$003B(A6) ; 'P' +08E0A 0527856A MOVE.B #$56,$0007(A3) ; 'V' +08E10 05278570 MOVEQ #$01,D0 +08E12 05278572 BRA.S 'CODE 0001 25…urces'+08E1E ; 0527857E +08E14 05278574 TST.L D4 +08E16 05278576 BEQ.S 'CODE 0001 25…urces'+08E1C ; 0527857C +08E18 05278578 MOVE.B D4,D0 +08E1A 0527857A BRA.S 'CODE 0001 25…urces'+08E1E ; 0527857E +08E1C 0527857C MOVEQ #$00,D0 +08E1E 0527857E MOVEM.L (A7)+,D3-D7/A2/A3 +08E22 05278582 UNLK A6 +08E24 05278584 RTS //Math contained inside the 'Math loop', note code is linear with no branching //thus you may read top to bottom as if the jsr/bsr are not there //ie. I have traced thru and listed the code in the order it executes. //notice that there is some very subtle type changing going on… //specifically almost all the math is signed long, but watch out for the //exceptions -- they are critical +08C56 053405D6 MOVEQ #$11,D0 +08C58 053405D8 MULS.L D5,D0 +08C5C 053405DC MOVE.L D0,-(A7) +08C5E 053405DE BSR.L 'CODE 0001 25…urces'+08E26 ; 053407A6 +08E26 053407A6 LINK A6,#$FFFC +08E2A 053407AA MOVE.L D3,-(A7) +08E2C 053407AC MOVEQ #$07,D3 +08E2E 053407AE MULU.L $0008(A6),D3 //••• exception +08E34 053407B4 MOVE.L D3,D0 +08E36 053407B6 DIVS.L #$0000000D,D0 +08E3E 053407BE MULS.L #$0000033F,D0 +08E46 053407C6 MOVE.L D0,-$0004(A6) +08E4A 053407CA MOVE.W -$0002(A6),-(A7) +08E4E 053407CE MOVE.L D3,-(A7) +08E50 053407D0 JSR 'CODE 0001 25…urces'+08BBC ; 0534053C +08BBC 0534053C LINK A6,#$0000 +08BC0 05340540 MOVE.W $000C(A6),-(A7) +08BC4 05340544 BSR.L 'CODE 0001 25…urces'+08BDE ; 0534055E +08BDE 0534055E LINK A6,#$FFFC +08BE2 05340562 MOVE.L D5,-(A7) +08BE4 05340564 MOVE.W $0008(A6),D5 +08BE8 05340568 MOVEQ #$53,D2 ; 'S' +08BEA 0534056A MOVEA.W D5,A0 //••• exception, sign extension is implicit here +08BEC 0534056C MOVE.L A0,D1 +08BEE 0534056E ADDI.L #$00001001,D1 +08BF4 05340574 MOVE.L D1,D0 +08BF6 05340576 ADD.L A0,D0 +08BF8 05340578 MOVE.L D0,-$0004(A6) +08BFC 0534057C MOVE.L A0,D0 +08BFE 0534057E MULS.L D1,D0 +08C02 05340582 DIVS.L D2,D0 +08C06 05340586 MOVE.L D0,D2 +08C08 05340588 MOVE.L #$00000089,D1 +08C0E 0534058E MOVE.L D1,D0 +08C10 05340590 MULS.L D2,D0 +08C14 05340594 MOVE.L (A7)+,D5 +08C16 05340596 UNLK A6 +08C18 05340598 RTS +08BCA 0534054A MOVEA.W $000C(A6),A0 +08BCE 0534054E MOVE.L A0,D1 +08BD0 05340550 DIVS.W D0,D1 //••• exception +08BD2 05340552 EXT.L D1 +08BD4 05340554 ADD.L $0008(A6),D1 +08BD8 05340558 MOVE.W D1,D0 +08BDA 0534055A UNLK A6 +08BDC 0534055C RTS +08E54 053407D4 EXT.L D0 +08E56 053407D6 ADDQ.W #$6,A7 +08E58 053407D8 MOVE.L (A7)+,D3 +08E5A 053407DA UNLK A6 +08E5C 053407DC RTS +08C64 053405E4 MOVEQ #$00,D1 +08C66 053405E6 MOVE.B $00(A2,D5.L),D1 +08C6A 053405EA EXT.L D1 +08C6C 053405EC MULS.L D0,D1 +08C70 053405F0 ADD.L D1,D7 //this is the main registration logic that calls the above 'CODE 0001 25D4 Sources' +089F2 05278152 PEA -$0084(A6) +089F6 05278156 PEA -$0044(A6) +089FA 0527815A BSR.L 'CODE 0001 25…urces'+08C1A ; 0527837A //call the checking routine +08A00 05278160 SUBQ.B #$1,D0 +08A02 05278162 ADDQ.W #$8,A7 +08A04 05278164 BNE.S 'CODE 0001 25…urces'+08A1E ; 0527817E //will branch if user name was ok +08A06 05278166 CLR.W -$0DD0(A5) +08A0A 0527816A MOVE.W #$FFFF,-$0DCE(A5) +08A10 05278170 BSR.L 'CODE 0001 25…urces'+08A76 ; 052781D6 +08A16 05278176 MOVE.W #$000B,-$0DD6(A5) +08A1C 0527817C MOVEQ #$01,D5 +08A1E 0527817E CMPI.W #$0007,-$0DD0(A5) //check for correct magic globals combination starts here +08A24 05278184 BEQ.S 'CODE 0001 25…urces'+08A2E ; 0527818E +08A26 05278186 CMPI.W #$000D,-$0DCE(A5) +08A2C 0527818C BNE.S 'CODE 0001 25…urces'+08A38 ; 05278198 +08A2E 0527818E CMPI.W #$07AE,-$0DD6(A5) +08A34 05278194 BNE.S 'CODE 0001 25…urces'+08A38 ; 05278198 +08A36 05278196 MOVEQ #$01,D4 +08A38 05278198 TST.B D4 +08A3A 0527819A BNE.S 'CODE 0001 25…urces'+08A4C ; 052781AC +08A3C 0527819C TST.B D5 +08A3E 0527819E BNE.S 'CODE 0001 25…urces'+08A4C ; 052781AC +08A40 052781A0 MOVE.W #$0002,-(A7) +08A44 052781A4 BSR.L 'CODE 0001 25…urces'+00CC0 ; 05270420 +08A4A 052781AA ADDQ.W #$2,A7 +08A4C 052781AC TST.B D4 +08A4E 052781AE BEQ 'CODE 0001 25…urces'+0892C ; 0527808C +08A52 052781B2 PEA -$0084(A6) +08A56 052781B6 PEA -$0044(A6) +08A5A 052781BA BSR.L 'CODE 0001 25…urces'+06560 ; 05275CC0 +08A60 052781C0 MOVE.W #$0001,-(A7) +08A64 052781C4 BSR.L 'CODE 0001 25…urces'+00CC0 ; 05270420 +08A6A 052781CA LEA $000A(A7),A7 +08A6E 052781CE MOVEM.L (A7)+,D3-D5 +08A72 052781D2 UNLK A6 +08A74 052781D4 RTS */ //this is needed for the generator, which is below static Boolean myEqualPStrWithWildcardPStr(const Str255 s, const Str255 t); static Boolean myEqualPStrWithWildcardPStr(const Str255 s, const Str255 t) { UInt8 *p = (UInt8 *) s; UInt8 *q = (UInt8 *) t; UInt8 *r = &p[p[0] + 1]; if (*(p++) != *(q++)) return FALSE; if (p != r) while (((*p == *q) || (*q == '*')) && (++p != r)) ++q; return (Boolean) (p == r); } static void Generate1CDFinder2SN(const Str255 nameStr, Str15 snStr); static void Generate1CDFinder2SN(const Str255 nameStr, Str15 snStr) { SInt32 len = (UInt8) nameStr[0]; SInt32 i, u, v, w, x = 0; Str15 xStr; if ((len == 0) || myEqualPStr(nameStr, "\pNASA") || myEqualPStrWithWildcardPStr(nameStr, "\pM**nDark")) { snStr[0] = 0; return; } for (i = len; i > 0 ; i--) { u = 7UL * (UInt32) (i * 17L); //note the UInt32 multiply v = (SInt16) ((u / 13L) * 831L); //note the SInt16 sign extend w = ((v * (v + 4097L)) / 83L) * 137L; x+= (((SInt16) v / (SInt16) w) + u) * (UInt8) nameStr[i]; //note the SInt16 divide then extend } x*= 53L; x*= 7L; NumToString(x, xStr); if (xStr[0] < 8) //extend xStr to 8 chars in a nonstandard way { for (i = xStr[0] + 1; i <= 8; i++) xStr[i] = xStr[1]; xStr[0] = 8; } snStr[ 0] = 10; snStr[ 1] = 'N'; //Norbert snStr[ 2] = xStr[5]; snStr[ 3] = xStr[8]; snStr[ 4] = xStr[4]; snStr[ 5] = xStr[7]; snStr[ 6] = xStr[3]; snStr[ 7] = 'D'; //Doerner snStr[ 8] = xStr[1]; snStr[ 9] = xStr[2]; snStr[10] = xStr[6]; }