Crack for Ancient Land of Y's (GS) - Broderbund/Kyodai by Jim Maricondo (The Mouse2 - AppleLink PE) - January 1990. After playing (cheating) with the game for awhile, the need for a crack became evident, so I set out to find one. The type of protection used is the now almost 'standard' nibble count on tracks $20/21 of side one. The actual nibble count code is on the Y's Data disk, but the nibble count is done on the Y's Program disk. I began by searching for the equivalent hexidecimal code, A2 20 A0 01 on the Y's Data disk. I found it on block $4A6. It looks like this: 06: 6B RTL end of routine before disk check 07: A9 00 LDA #$0000 start of this routine 0A: 8D CA 65 STA $65CA 0D: 8D C6 65 STA $65C6 10: 8D C8 65 STA $65C8 13: E2 30 SEP #$30 make accumulator/index regs 8-bit 15: A2 20 LDX #$20 track 20 17: A0 01 LDY #$01 of side 1 19: 20 4E 65 JSR $654E go do disk check 1C: B0 13 BCS $31 1E: 8E C6 65 STX $65C6 store half of returned value 21: 8C C7 65 STY $65C7 store other half of returned value 24: A2 21 LDX $21 track 21 26: A0 01 LDY $1 of side 1 28: 20 4E 65 JSR $654E go do disk check 2B: 8E C8 65 STX $65C8 store half of returned value 2E: 8C C9 65 STY $65C9 store other half 31: C2 30 REP #$30 make accumulator/index regs 16-bit 33: 90 0C BCC $41 35: AD CA 65 LDA $65CA load A and X regs depending on check 38: 49 FF FF EOR #$FFFF 3B: 1A INC 3C: A2 FF FF LDX #$FFFF 3F: 80 0C BRA $47 41: A9 C6 65 LDA #$65C6 44: A2 00 00 LDX #$0000 47: 60 RTS return to sender At first I tried just placing a RTS at $07, but that didn't work so I decided to find the routine that called this one by using the PLA PLX BRK technique. I found out that the disk check routine was called by the routine right before it! Here's the routine right before it (of which you see the end at $06 of the above example). The line numbers here have no relation to the ones in the above example. bank 01- 6D77: 6B RTL end of routine before this one 6D78: 8B PHB 6D79: 5A PHY 6D7A: 4B PHK 6D7B: AB PLB data bank = program bank 6D7C: AF E1 1E 05 LDA 051EE1 6D80: 48 PHA 6D81: 22 53 6E 01 JSL 016E53 prepare for nibble count (_NewHandle) 6D85: 68 PLA 6D86: 20 94 6D JSR 6D94 do disk check routine listed above 6D89: 48 PHA get results from routine 6D8A: DA PHX get results from routine 6D8B: 22 E4 6E 01 JSL 016EE4 restore things back to normal (_DisposeAll & _UnloadSeg) 6D8F: FA PLX 6D90: 68 PLA 6D91: 7A PLY 6D92: AB PLB 6D93: 6B RTL return to calling routine --disk check routine described first comes here-- I traced this routine to blocks $4A5-4A6 on Y's Data. Once again, I attempted to just place a RTL at the beginning of this routine, but that didn't work either so I did Brian's PLA PLX BRK trick again. This time I was rewarded with the following code. (This time, these line numbers are relative to the ones in the previous example.) bank 01- 6DED: 60 RTS end of subroutine before this one 6DEE: 50 52 4F 47 52 41 4D 00 "PROGRAM" in hex (C-String) 6DF6-6E13: miscellaneous code part of this routine, but not worthy of listing 6E14: 22 78 6D 01 JSL 016D78 go do routine transcribed above --more code-- I traced this routine to block $4A6 on Y's Data. This time, I attempted to NOP out the JSL at 6E14. Again, it didn't work, so there must be another important routine calling this one. So I used the PLA PLX BRK trick again and was rewarded another time! I found that the above routine was called from 0E/1363. Once again, these line numbers are relative to the subroutine above. Because of the length of this segment, I'm leaving out the hex opcodes. Here is the final code: bank 0E- 1363: jsl 016df6 do routine transcribed directly above 1367: stx d2 1369: sta d0 136B: stz e0 136D: lda e0 136F: beq 1374 go process results 1371: brl 1428 ONLY way to get out of this check loop (original disk) 1374: sec process results 1375: lda d0 1377: sbc #0000 137A: bne 1383 137C: lda d2 137E: sbc #0000 1381: bra 138a 1383: lda d2 1385: sbc #0000 1388: rep #02 138A: bvs 138f 138C: eor #8000 138F: bmi 13b3 1391: pea 0001 1394: pea 0060 1397: pea 0010 139A: pea 0002 139D: pea 33b2 13A0: jsl 0e10fb 13A4: ply 13A5: ply 13A6: ply 13A7: ply 13A8: ply 13A9: jsl 016df6 not original. prompt for original and check again 13AD: stx d2 13AF: sta d0 13B1: bra 1374 13B3: ldx d2 further process results 13B5: lda d0 13B7: stx de 13B9: sta dc 13BB: ldx de 13BD: lda dc 13BF: phx 13C0: pha 13C1: clc 13C2: adc #0002 13C5: sta dc 13C7: lda de 13C9: bcc 13cc 13CB: inc 13CC: sta de 13CE: pla 13CF: plx 13D0: sta f6 13D2: sts f8 13D4: lda [f6] 13D6: sta da 13D8: lda [dc] 13DA: sta d8 13DC: lda da 13DE: sec 13DF: sbc #206B 13E2: beq 141b 13E4: bvs 13e9 13E6: eor #8000 13E9: bpl 141b 13EB: lda da 13ED: sec 13EE: sbc #2103 13F1: bvs 13f6 13F3: eor #8000 13F6: bmi 141b 13F8: lda d8 13FA: sec 13FB: sbc #1daf 13FE: beq 141b 1400: bvs 1405 1402: eor #8000 1405: bpl 141b 1407: lda d8 1409: sec 140A: sbc #1e79 140D: bvs 1412 140F: eor #8000 1412: bmi 141b 1414: lda #0001 1417: sta e0 1419: bra 1425 141B: ldx #ffff 141E: lda #ffff 1421: stx d2 1423: sta d0 1425: brl 136d results processed further pass/fail value stored at $E0 1428: pea 0002 Original inserted, so continue loading... 142B: pea 33d7 142E: jsl 106e1c By careful examination, you can tell that there is only one way to get out of the check loop, and that is to have a non-zero result stored at $E0. The code checks to see if $E0 is zero or not at $136F, and brances to continue loading or continue disk checking depending on the result. So with this information, I just NOPed out the BEQ 1374 at $136F making the program always continue to load without doing the copy protection at all. Next I traced this code to block $3BF on Y's Data. So, after many hours of work, here is the patch! Block Bytes From To ---------- 3BF 70-71 F0 03 EA EA Or, if using Block Warden, go to relative block 9 of YSGS, relative bytes $1070-$1071. Or, if that doesn't do it for ya, try scanning for 85 D0 64 E0 A5 E0 F0 03 and changing it to 85 D0 64 E0 A5 E0 EA EA. You now have a deprotected copy! Enjoy! <> Not bad for a first crack!