Jump to content
Mu0n

ok, "tutor me to bypass bad sector copy protection" challenge

Recommended Posts

Game: Winter Games

Year: 1985

Supported by: System 4.2 or earlier

Skills required: excellent knowledge of 68000 assembly

 

2020-05-08_0900

 

 

Share this post


Link to post
Share on other sites

I would enjoy figuring this out, but don’t have Winter Games on floppy handy or an old enough version of MacsBug, I think.

 

But here’s what I would do (may try this eventually if nobody else does):

 

1.  I would bet that CODE resource calls _ModalDialog (hex $A991) to display the “invalid copy” dialog box (is that what the DLOG resource includes?  Maybe a blank dialog with a static text field with “^0” in it?).  Since Winter Games doesn’t normally use the Dialog Manager, this might be the only call to _ModalDialog; if not, there probably are only a few to check.  But best would be to run Winter Games on an 800k disk with Macsbug installed, and hit the interrupt switch when the dialog appears and see where you are in the code (or, interrupt earlier and add a breakpoint that breaks on calls to _ModalDialog from Macsbug with “ATB A991”).

2.  Assuming that’s right, search the CODE 0 resource using the disassembler using the offset from above to find the corresponding $A991

3.  Probably the code just above the relevant $A991 gets conditionally-branched into from somewhere above that checks the copy protection, presumably with some traps that call the Disk Driver or similar.

4.  Poke around to find the right conditional branch, and neutralize it (for example by replacing it with a NOP, $4E71).

5.  Try it out

 

If not ModalDialog, there would definitely be a call to NewDialog or GetNewDialog or Alert etc. — and the same steps would apply

 

Edited by Crutch

Share this post


Link to post
Share on other sites
30 minutes ago, Crutch said:

I would enjoy figuring this out, but don’t have Winter Games on floppy handy or an old enough version of MacsBug, I think.

 

But here’s what I would do (may try this eventually if nobody else does):

 

1.  I would bet that CODE resource calls _ModalDialog (hex $A991) to display the “invalid copy” dialog box (is that what the DLOG resource includes?  Maybe a blank dialog with a static text field with “^0” in it?).  Since Winter Games doesn’t normally use the Dialog Manager, this might be the only call to _ModalDialog; if not, there probably are only a few to check.  But best would be to run Winter Games on an 800k disk with Macsbug installed, and hit the interrupt switch when the dialog appears and see where you are in the code (or, interrupt earlier and add a breakpoint that breaks on calls to _ModalDialog from Macsbug with “ATB A991”).

2.  Assuming that’s right, search the CODE 0 resource using the disassembler using the offset from above to find the corresponding $A991

3.  Probably the code just above the relevant $A991 gets conditionally-branched into from somewhere above that checks the copy protection, presumably with some traps that call the Disk Driver or similar.

4.  Poke around to find the right conditional branch, and neutralize it (for example by replacing it with a NOP, $4E71).

5.  Try it out

 

If not ModalDialog, there would definitely be a call to NewDialog or GetNewDialog or Alert etc. — and the same steps would apply

 

ResEdit crashed when I tried opening the Winter Games executable. I'm using Resorcerer 1.2.5 in my screencap. I can provide a virtual disk with both if you want to check it out.

 

Also, the physical copy I have of Winter Games is already hacked to run well. It doesn't show the dialog that complains about an unauthorized copy. It probably checks for a bad disk sector though, because the only way to play this game is with a physical medium. You can create new physical copies with CopyIIMac, but you can't run it on en emulator - that would be the goal - bypass disk reading that expects an error (the olden version of a try-catch block I guess?)

 

edit- yes, there are a bunch of dialogs, the last of them is the "unauthorized copy". That's a good lead to check out.

 

 

Edited by Mu0n

Share this post


Link to post
Share on other sites

If it’s not inconvenient to provide a virtual disk with Resourcerer + Winter Games I would love to poke around with it.  We should definitely be able to find a way to skip the disk checks, the ModalDialog call just gives a clue to where they are.  We can check the DLOG resource ID that’s pushed to the stack right before the ModalDialog call to ensure we’ve got the right one.

Share this post


Link to post
Share on other sites

The last post I made, this line prepares the right resource ID# 900 (hex $0384) for the "record" used by the Dialog loading trap, if I'm not mistaken?

 

move

move.w #$0384,-(sp)

so I'm looking for dialog ID #32386 (hex $7E82) somewhere else in the code....I'll send a PM when the virtual disk is ready

 

Edited by Mu0n

Share this post


Link to post
Share on other sites

PM received - checking it out now.  Wow, it's been a while, I forgot you need to explicitly call GetNewDialog before ModalDialog, oops.  

 

It looks like CODE 489 in Anon_04 calls _GetNewDialog with a resource ID that's been previously stored on the stack.  CODE 4 has a similar call to _GetNewDialog.  So, not obvious to find the right spot.  Unfortunately I only see the resource ID $7E82 in one spot in the whole file, in an ORI instruction which is also kind of nonobvious what it's doing.

 

I poked around in the code and there are some funny things going on.  There's a check to ROM85 which, if negative (128k ROM installed), skips over a direct Sound Driver _Control call and does some other mucking about with the Sound Driver -- probably resulting in that "thump" we hear.  There is also some tick counting and quick creating/deleting a file with checking of GetFileInfo around load time.  I would need to be able to run Macsbug in order to make further progress.  I'm working in Mini vMac ... any advice how to get a Mini vMac readable disk image with Macsbug on it on a modern Mac?

 

 

 

Share this post


Link to post
Share on other sites

Oh.  Huh.  It disables debuggers, as you said before.  When I press the interrupt switch, it just restarts?  Weird ... I want to figure how it does that now.

Share this post


Link to post
Share on other sites

Per Inside Mac II-197 you can disable the debugger by wiping out the interrupt handler vectors at low memory locations $70 to $7C with a pointer to your own code, but I don't immediately see where that's done in Winter Games.

Share this post


Link to post
Share on other sites

OK, progress.  Epyx used some really dodgy techniques to prevent anyone using Macsbug while running Winter Games!

 

Here's just part of it:

 

I dropped into Macsbug from the Finder and did "ATB _Launch" to break when launching an application, then "G" to return to the Finder and double-clicked Winter Games.  Then I did "SS $64 $7C" to step-spy until anything in the low memory range $64-$7C (the interrupt vector table per Inside Macintosh II-197) changed.  Sure enough, Winter Games' CODE #489 at offset $31E is changing some of the interrupt vectors to $40000A, in other words it redirects the code to the start of ROM -- which reboots the system!  (See Inside Macintosh II-386.)  This instruction I circled here just moved $40000A into low-memory location $70, which is completely rude:  (it's inside a loop so it threw that same address into a bunch of other low-memory locations I didn't recognize, based on the array-of-bytes constant data embedded in this CODE resource at offset $32C -- by NOP'ing out this instruction, I prevented all that)

 

DD0299E3-05B0-425B-B23C-88FF4A1E9D98_1_201_a.thumb.jpeg.be5a216cdace618a2a33aafe2aea38fd.jpeg

 

So I NOP'ed out that instruction with Resourcerer, patted myself on the back and thought Macsbug would now work inside Winter Games and I could figure out why it was freezing ...

 

NOPE.  Now, instead of restarting the Mac, the interrupt switch from the Winter Games splash screen does nothing at all.  How is that possible?  I repeated my earlier steps and kept stepping through the code after my NOP ... lo and behold the subroutine in CODE #489 at offset $384 is changing Macsbug code.  Talk about belt & suspenders, Epyx first destroyed the interrupt vector table then, it seems, erased parts of Macsbug itself in RAM just in case someone like me came long 35 years later and fixed the interrupt vectors!  Need more investigation to rectify this.  Will try to pick it back up over the weekend.  Damn '80s programmers!!

 

2703814F-63F7-40BD-A09E-468EE17A5BDF_1_201_a.thumb.jpeg.813ef958526bcac087168d36cd823fcc.jpeg

Edited by Crutch

Share this post


Link to post
Share on other sites

If I had a copy of the game, I could Flux image the disk and provide you with a Disk Copy 4.2 image containing "bad" sectors and all.

 

Alternatively, have you tried using DiskDup+?  Before I got my AppleSauce, I had good success copying sector protected games.  It has an option to ignore + copy bad sectors to a disk image.

Share this post


Link to post
Share on other sites

Also, this thread is super nostalgic. :D  I used to watch my neighbor krack Apple II games for hours on end.  I didn't know what he was doing (still don't), but man I thought he was the coolest guy in the world.

Share this post


Link to post
Share on other sites
12 hours ago, olePigeon said:

If I had a copy of the game, I could Flux image the disk and provide you with a Disk Copy 4.2 image containing "bad" sectors and all.

 

Alternatively, have you tried using DiskDup+?  Before I got my AppleSauce, I had good success copying sector protected games.  It has an option to ignore + copy bad sectors to a disk image.

It may not be bad sectors after all. Someone wrote me a pretty informative reply on Facebook and it makes sense; the online (cracked) disk image copy we have on the web CAN be written to a physical medium and be made to work on real hardware. The different goal at hand is to make it work inside an emulator. Here's what the guy had to say:

 

Quote

FWIW if a DSK image written to a real disk works on a real Mac, then it's not weak bits protection. DiskDup can replace weak bits but cannot replicate them. It's likely something low-level like an alternate nibble table and/or reading the otherwise-unused tag bytes.

 

Share this post


Link to post
Share on other sites

Crutch, I am seriously in awe of your skills with the debugger. I feel like I'm months/year behind the level where it all gels together naturally for you. You have intuition about this.

 

 

Share this post


Link to post
Share on other sites

FWIW Apple’s “Macsbug Reference and Debugging Guide” is really, really excellent and loaded with great examples.  I always keep a (physical) copy handy when poking around in Macsbug.

 

Agreed about the copy protection - my goal is to get Macsbug working while running Winter Games so I can see where it’s freezing with the ultimate hope of running it in an emulator so I can play the Bobsled mini-game, which is clearly the best one....

Share this post


Link to post
Share on other sites

Well, I have unexciting news I'm afraid.

 

In addition to the change above, I found the instruction in the same CODE resource at offset $162 was writing junk into low memory.  Once I removed that, I was able to continue tracing into the Winter Games code with Macsbug without a "*** Macsbug code has been changed" warning.  However, the emulated Mac would then freeze inside an innocent-looking call to EraseRect (specifically, inside a call to PtInRect within that EraseRect...) with no way to get back into Macsbug.

 

Alternately, if I just double-click the modded Winter Games app, it will freeze at the title screen as usual -- but using the interrupt switch has no effect.  It doesn't reboot the emulated machine anymore (which is good!), but it doesn't pull up Macsbug either.

 

So, I'm not sure if Winter Games is taking other measures to prevent debugger use that I can't figure out, or ... as I'm starting to think ... there's just something weird going on in the code the miniVMac doesn't like somehow.  I can't think why else there would be a crash inside PtInRect.  Unless Winter Games is messing with other low-memory areas that I didn't notice, perhaps in a way that worked fine on a 128k-512k Mac but breaks on my emulated Plus under miniVMac, and somehow that's breaking basic QuickDraw operations.

 

I will probably shelve this investigation for now, but it would be fun to figure it out eventually.

Share this post


Link to post
Share on other sites

On thinking about this further, I am pretty sure Winter Games is still screwing with Macsbug somehow.  Why else would (1) EraseRect crash unrecoverably only when I step into it from MacsBug but (2) if I run the app normally, it gets further (to the title screen) but then I can't drop into the debugger?

 

@Dog Cow Do you know where Macsbug lives in the System Heap?  I want to Step-Spy and figure out if its code is still being overwritten somehow.  But I can't find any documentation on where it lives (its code doesn't run as a CODE resource so I can't use HD CODE to find it).

Share this post


Link to post
Share on other sites

FWIW, I ran Winter Games just fine with my Macintosh Plus. My father did upgrade it to 2.5 MB of RAM, so the Plus isn't an issue.

Would you want to try it out with different builds of mini-vMac that are closer to the 128k and 512k nonetheless? I built them myself like 15 years ago on Windows XP, but they still run fine under Windows 10. Either that, or the mini-vMac had an automated service that built and provided those executables by having you fill out a form.

 

Share this post


Link to post
Share on other sites

MacsBug doesn't live in the system heap. It lives in high memory above (BufPtr). The address stored at location $120 in low memory (if not null) points to where a debugger is installed.

 

I would check to make sure there isn't a VBL task installed somewhere. I'm reverse engineering a different app that installs a VBL task that checks every other tick to make sure the replacement vectors haven't been tampered with. Such a thing could interrupt ordinary Toolbox calls, causing problems.

Edited by blitter

Share this post


Link to post
Share on other sites

It might be a naive question that I could possibly answer myself, but is there an obligation to use Macsbug, other than convenience? Can't we simply trace out the whole code ourselves and skip the unimportant parts, carefully acknowledging any vectors along the way and where the origin of the code is (I don't know much about 68k assembly but I assume there's an address in the code that tells where to start, otherwise, chaos?). Is the reason that it would just be freaking too long?

 

....but not impossible.

Share this post


Link to post
Share on other sites
2 hours ago, blitter said:

MacsBug doesn't live in the system heap. It lives in high memory above (BufPtr). The address stored at location $120 in low memory (if not null) points to where a debugger is installed.

 

I would check to make sure there isn't a VBL task installed somewhere. I'm reverse engineering a different app that installs a VBL task that checks every other tick to make sure the replacement vectors haven't been tampered with. Such a thing could interrupt ordinary Toolbox calls, causing problems.

This is awesome. I totally noticed a call to VInstall and was wondering what the hell it was doing there, but blithely assumed it was some innocent thing to ensure flicker free animation. I will go back and check it out - I bet you are right. 
 

@Mu0n yeah. That would work in theory but be just about impossible in practice I think. I have no idea exactly where the thing is freezing and without Macsbug I would take a year to work it out. Reading someone else’s full fledged assembly code is hard!

Share this post


Link to post
Share on other sites

OK @blitter thanks again for that great tip.  I misspoke earlier - I hadn't noticed a VInstall (if I had, maybe I would have investigated) ... but I did notice a VRemove.  So I investigated just now and there is no VInstall to be found anywhere ... instead, Winter Games in CODE #1 at offset $718 writes directly to the pointer member of the first element of the VBL queue record (which is at $0160), i.e. at $0162 following a two-byte flags field, to install its own VBL task.  (I didn't yet around to working out what the task does exactly, it seems to execute some self-modifying code at what Resourcer identifies at Anon_17 + $DA, so it's a bit confusing.)  Seems like an odd thing to do when there is a perfectly good trap called VInstall for that, but anyway. This was particularly devious because I had thought to search the code for the value of VBLQueue i.e. $0160 but not $0162!

 

Anyway:  Unfortunately, NOPing out that instruction doesn't solve the problem - Macsbug still can't be activated past a certain point in the code.

 

The mystery continues.

Edited by Crutch

Share this post


Link to post
Share on other sites

Of course it modifies the VBLQueue directly-- it would be a dead giveaway seeing a call to _VInstall. ;) You thought they'd make this easy? :p

Share this post


Link to post
Share on other sites

OK, I figured out what's going on.  

 

Winter Games is wiping out Macsbug by allocating a GrafPort, setting its portBits.baseAddr to an area of high memory that's inside Macsbug, then calling EraseRect.  This is why it looked like a simple EraseRect call was freezing the debugger ... because that call was in fact wiping out the debugger!!  I finally worked this out by setting a breakpoint to EraseRect calls with "ATB _EraseRect" then examining "thePort" and doing "WH 3f2700" (that being its baseAddr):

 

D2A99999-A04E-4A38-A145-75BA4882F94B_1_201_a.thumb.jpeg.cb4115e3fd7c18892d2f2d09772b7cdc.jpeg

 

Realizing the EraseRect call in question was right after a call to SetPort with a GrafPtr obtained from -$00CE(A5), I used "SS A5-CE" from an earlier point in the code to figure out when that application global was getting set.  The bit of code in question turns out to grab ScrnBase, then flips bit 15 to get a chunk of memory in which to draw things.  It took me a while to work out something that would have been obvious if I was a Mac games developer in the '80s ... this is a way to get at the alternate screen buffer on a Mac 128k, 512k, or Plus.  (Flipping bit 15 in ScrnBase is a quick way to get the address of the alternate screen buffer, whose address on various models of Mac Plus is documented here http://www.mac.linux-m68k.org/devel/plushw.php.)  Unfortunately, it looks like the standard location for the alternate screen buffer above BufPtr is also where Macsbug is getting loaded -- at least on the 4MB Mac Plus I'm emulating in Mini vMac.

 

It turns out that this incompatibility of Macsbug and programs using the alternate screen buffer was a known fact in the '80s, per this quote a Google search turned up from MacTutor volume 1, number 13:  "Some programs will not work with the debugger installed. These programs include those that use the alternate screen buffer. Apparently the debugger and the alternate screen live in the same area in memory."  Oops.  http://preserve.mactech.com/articles/mactech/Vol.01/01.13/MacsbugforModula-2/index.html

 

So, my goal of debugging Winter Games in Mini vMac with Macsbug may be dead for now.  Oh well, it was fun and educational chasing this down so far!  (I wonder if Winter Games might be exposing a Mini vMac issue with the alternate screen buffer, somehow?  I'm sure lots of other games of the era used that too, though...)

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×