• Updated 2023-07-12: Hello, Guest! Welcome back, and be sure to check out this follow-up post about our outage a week or so ago.

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

blitter

Well-known member
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.

 
Last edited by a moderator:

Mu0n

Well-known member
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.

 

Crutch

Well-known member
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!

 

Crutch

Well-known member
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.

 
Last edited by a moderator:

blitter

Well-known member
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

 

Crutch

Well-known member
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.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...)

 

Mu0n

Well-known member
Great work, but I kinda refuse to let it go. Can't we uglily flip another bit in the hopes of grabbing an empty enough area of memory and hope it behaves well as a alternate screen buffer? We have the means of "destroying" an unlimited amount of virtual macs and disks if need be. Is it only possible to modify opcodes in Resorcerer while you preserve the amount of bytes used for your instructions and data? Inserting new instructions and/or modifying the total amount of bytes used would destroy any branching past your modifications, right?

Thanks for those links (especially the first) - they are super informative.

 

Crutch

Well-known member
Ha, I love your dedication!  Who am I kidding, I am of course totally going to keep poking at this ....

The problem with grabbing another area of memory for the screen buffer is that Winter Games is in fact using the "official" capital-letters Alternate Screen Buffer which you can (and it in fact does) tell the Mac to switch to using as the actual screen display.  Basically, Plus-and-earlier Macs had a built-in notion of the alternate screen buffer that you could write to and switch which was shown on the CRT, back-and-forth, instantly with the flip of a bit on the VIA.  So, if I were to grab another area and write graphics there -- you're right, a 4MB Mac Plus could easily handle it -- but it wouldn't show up anywhere when Winter Games flips the VIA bit, which tells the Mac to look for and use the One And Only True Official Alternate Screen Buffer, unless someone knows of a way to redirect that without moving BufPtr (?), which feels like it would cause other problems.  Some good discussion of it with sample code is here:  http://preserve.mactech.com/articles/mactech/Vol.02/02.06/VideoScreenAnim/index.html

Yes I don't know how to add opcodes in Resourcerer without ruining all the offsets from branches and jumps (and direct accesses to data-in-the-code, which Winter Games does a lot of).

I am thinking my next step is, remove that bit-flip that sets the portBits.baseAddr for the offscreen buffer in the GrafPtr at -$00CE(A5) so Winter Games keeps writing to the main screen (so doesn't nuke Macsbug), and also NOP out the BCHG instruction that tells the hardware to use the alternate screen buffer (so it doesn't show a visual representation of Macsbug code on the screen that looks like garbage and prevents us from seeing what we are doing in Macsbug!).  (Documenting for my own memory -- I found a good way to get to that BCHG is to [after NOPing that troublesome EraseRect] do "ATB _Open" and step into the next JSR, it's right there ... by the way, I wonder what device it is _Open'ing?)  Then I'm hoping that would let me see where Winter Games freezes Mini vMac.

 
Last edited by a moderator:

Mu0n

Well-known member
If we can't insert new lines of opcodes, can we dedicate one JSR to go to the end of the binary file and add all the code we want there?

 
Last edited by a moderator:

Crutch

Well-known member
I am thinking my next step is, remove that bit-flip that sets the portBits.baseAddr for the offscreen buffer in the GrafPtr at -$00CE(A5) so Winter Games keeps writing to the main screen (so doesn't nuke Macsbug), and also NOP out the BCHG instruction that tells the hardware to use the alternate screen buffer (so it doesn't show a visual representation of Macsbug code on the screen that looks like garbage and prevents us from seeing what we are doing in Macsbug!).  (Documenting for my own memory -- I found a good way to get to that BCHG is to [after NOPing that troublesome EraseRect] do "ATB _Open" and step into the next JSR, it's right there ... by the way, I wonder what device it is _Open'ing?)  Then I'm hoping that would let me see where Winter Games freezes Mini vMac.
OK, I did this thing I said was the next step.

Progress.  Here's what's happening:  in CODE #3 at offset 11A, Winter Games is going into an infinite loop waiting for a _Write call to the Sound Driver to terminate.  It looks like it wants to play a sound synchronously, but inside the ROM, repeated polling of the ParamBlockRec's ioResult field shows that it is always 1 (sound not done), so the ROM goes into a tight loop, waiting forever for ioResult == 0, which never happens.  This unsuccessful attempt at playing a sound synchronously is what's causing the "click" sound, followed by the freeze in Mini vMac.


View attachment IMG_4392.mov

If I NOP out the _Write call, Winter Games doesn't freeze here -- it waits for a mouse click, then gets as far as drawing the torch podium in Mini vMac!  Cool (see video)!  .... then ... it crashes again.  (If I'm running the debugger at this point, I again get a warning that Macsbug code has been changed.  If instead I run a version of Winter Games that's unpatched except for NOPing out the offending Sound Driver _Write, mini vMac restarts.)  Clearly there is more going on that I've found so far.







 
Last edited by a moderator:

Crutch

Well-known member
You're looking at local offsets there relative to the start of Anon_01, which starts a few bytes into CODE 3.  Hit command-G and enter offset 11A in the bottom field.  You'l see it's the _Write instruction at relative offset 116 in your view there.

 

blitter

Well-known member
I do know that the Sound Driver implementation in Mini vMac is buggy / incomplete-- Lode Runner running in AMS for example more accurately reproduces what a real Mac sounds like, whereas in Mini vMac some sounds are incorrect.

 

Mu0n

Well-known member
@Crutch have you considered using TMON 2.8? It has a relocation feature which might clinch it. Mac Garden has it and its manual, and if need be, an even older version which might be more suited for Winter Games. (But the manual is for 2.8)

CamScanner 05-12-2020 13.04.22.jpg

 
Last edited by a moderator:

Crutch

Well-known member
Cool.  I've been wanting to learn TMON forever.  Had no idea it could run in the system heap - that could be very useful here.  I do love Macsbug though ....

 

Mu0n

Well-known member
It seems that on Mac Garden, tmon.sit is just 2.8 all over again. I'm having issues running it under an old System version.

System 4.2: won't even see TMON 2.8's folder and expects every file in the root

System 5.5: can it even run Winter Games? Can see TMON's folder but most icons don't appear

so far, I've done this under mini-vMac

-boot with System 5.5

-launch TMON (seems ok)

-launch Winter Games, but it insta-boots

I'm currently foraging into my old retromac68k backups in the hopes of seeing a 1.0 version of TMON, one that would have been of the era of that mactech article and of Winter Games

 

Mu0n

Well-known member
I just made some new attempts with TMON 2.8.1, inside a 3 meg virtual disk that has System 5.5.

-I've put both TMON and TMON startup inside the System 5.5 folder

-I've loaded up TMON by holding Cmd to go into its setup. I've tried flicking "do not refresh vectors" on as well as "load into system heap" instead of high memory; then I saved this 'User Area' configuration straight into the sytem folder so that it uses these options when it loads

-I've both tried opening up TMON manually, then Winter Games, or letting it open up right away during a boot while I also set Winter Games as the startup app

When Winter Games loads, it does even less than your Macsbug attempts, it just goes to a black screen for a few seconds, then boots back to the idle insert disk screen of the mac but it hard freezes there.




 
Last edited by a moderator:

zydeco

Well-known member
I couldn't let it go either  :)

Screenshot 2020-09-21 at 22.21.28.png

When Wintergames inserts its VBL task into the queue directly, bypassing _VInstall, it breaks the queue:

On a real mac, the queue would have a task installed by the floppy disk driver to measure the speed, but the replacement driver in Mini vMac doesn't install this task, so the VBL queue starts empty (both the head and tail pointers are zero). Then, Wintergames will insert its task into the queue (by writing to the head pointer) before calling _Write to play sound, and _Write will in turn call E_Sound_Prime in the ROM, which itself calls _VInstall to install the SoundVBL task. At this point, the queue is in an inconsistent state: the head pointer points to Wintergames' task, but the tail pointer is zero, because Wintergames didn't change it (it didn't expect the queue to be empty), so the call to _VInstall does not install the SoundVBL task, and the sound never plays, so the call to _Write never returns. The click you can hear is because the sound output is enabled, but because the sound task doesn't actually run, no sound is played.

I patched this in Mini vMac's disk driver (by adding a VBL task that does nothing, to keep the queue from being empty), you can download my wintergames branch and build it:

https://github.com/zydeco/minivmac/commit/53c291ac120a036131a73cb2e568b57c493f51d7

Alternatively, you can patch Wintergames itself by replacing the VBL task installation with a call to VInstall (in CODE 1 and 3, or you can edit the disk image):

Search: 40 C0 00 40 07 00 46 C0 43 F8 01 62 20 91 22 88 40 C0 02 40 F8 FF 46 C0

Code:
; disable interrupts
+000C  0000DA  MOVE       SR,D0                                    | 40C0
+000E  0000DC  ORI.W      #$0700,D0                                | 0040 0700
+0012  0000E0  MOVE       D0,SR                                    | 46C0
; prepend VBL task record in A0 to queue
+0014  0000E2  LEA        $0162,A1                                 | 43F8 0162
+0018  0000E6  MOVE.L     (A1),(A0)                                | 2091
+001A  0000E8  MOVE.L     A0,(A1)                                  | 2288
; reenable interrupts
+001C  0000EA  MOVE       SR,D0                                    | 40C0
+001E  0000EC  ANDI.W     #$F8FF,D0                                | 0240 F8FF
+0022  0000F0  MOVE       D0,SR                                    | 46C0
Replace with: A0 33 4E 71 4E 71 4E 71 4E 71 4E 71 4E 71 4E 71 4E 71 4E 71 4E 71 4E 71

(a call to _VInstall and NOPs to match the size)

 
Last edited by a moderator:
Top