0 Investigation: The Apple IIgs Memory Manager
Thomas Harte edited this page 2021-03-03 21:39:06 -05:00
This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

As of the first draft of this document, all parts are present for Apple IIgs emulation but bugs remain. At least one of those manifests as the in-ROM memory manager not responding as expected; in particular:

  • titles including Airball, Bouncing Bluster and Crystal Quest meet an unexpected BRK during startup, somewhere in the 00:BB or 00:BC page, dropping the user into the monitor; and
  • titles such as Defender of the Crown, Block Out and Bubble Ghost stop completely on an error of 'Unable to reserve memory segment $0201'.

The second set would appear overtly to be memory manager related; the former also seems to be.

Unexpected BRK

Digging down on Airball, the immediate progenitor of the error is this routine in the ROM's MoveUp (from mm.asm):

lda Count+2
adc Dest+2	;A = 00bank
xba	;A = bank00
ora #$44	;MVP opcode
pha
bra muFirst

i.e. the ROM is intending to assemble the sequence MVP, RTS on the stack, to which it later jumps. An ORA is used because a single-byte load isn't available. In my emulator the value at Dest+2 originates from whatever the contents of RAM were at power up rather than necessarily being 00 and as a result the generated opcode isn't MVP and the on-stack sequence that is jumped to runs off the rails.

Specifically the value at Dest+2 at that point in the code is 7f15.

Origin of the 7f15

By the time MoveUp is reached, the value is in Dest+2 (i.e. 00bcb1 and 00bcb2).

(Aside on cycle times below: they are relative to the 14Mhz bus, and depend on things like the exact disk rotation speeds I currently have, so should not be expected necessarily to be accurate in the future)

It was placed there by a STY at fc0d5f, 502081910 cycles since the machine launched. That immediately follows a load from 00bcc5/6.

The value was put into 00bcc5/6 by a STY at fc0d5f, 502078270 cycles since the machine launched. The value had been picked up by a LDY [$21] at fc0cb2, which read the value from 00bcc9/a.

It had been placed into 00bcc9/a by a STA at fc0fcb, 502077180 cycles since the machine launched. It picked the value up from from a LDA [$13],y with y=2 at fc0fc9, which read the value from e11806/7.

In context, that is likely to be the upper word of the block of memory pointed to by a memory handle; see précis on memory manager handles below.

The value was written to e11806/7 by a STA [$17],y at fc0dac with y=2, 497930810 cycles since machine launch. Its origin then was one instruction earlier, a LDA $03,x with x=2 and d=$bca4 at fc0daa, which accessed bca9/a.

7f15 had been stored to bca9/a at fc0da4 by a STA [$05], 497929740 cycles since machine launch, having been read from 00bcc1/2 one instruction earlier by a LDA [$1d].

It had been stored there by a STY [$1d] at fc0d5f, 497928970 cycles since machine launch, having been fetched by a LDY [$21] at fc0cb2, 497928450 cycles since machine launched, which fetched from 00bcc5/6.

That value was left by a STA [$21] at fc0fcb, 497927880 cycles since machine launch. It was fetched one instruction earlier by a LDA [$13], y with y=2, and d=$bca4 yielding a base for the long address of bcb7 which gave e119a8; that plus y leads to a two-byte fetch from e119aa/b.

Digging down on e119ab, logging reads and writes to it since launch until its relevant access at 497927875 cycles since launch shows:

e119ab <- 00 [15775430]
e119ab -> 00 [141578780]
e119ab -> 00 [141579715]
e119ab <- 00 [469272795]
e119ab -> 00 [469274435]
e119ab -> 00 [469274490]
e119ab -> 00 [473880845]
e119ab -> 00 [473881875]
e119ab -> 00 [473920325]
e119ab <- 00 [480022440]
e119ab <- 7f [495809345]
e119ab -> 7f [495811040]
e119ab -> 7f [495811095]
e119ab -> 7f [495820535]
e119ab -> 7f [495820590]
e119ab -> 7f [497927875]

Therefore: it looks like the handle map is properly cleared at startup, which at least takes guesses around detecting a cold start and with loop lengths off the table.

Digging down on cycle 495809345 after machine launch returns us to fc0dac, the same location that wrote to e11806/7 above; that instruction begins 495809310 cycles after machine launch.

This time the LDA $03,x at fc0daa with x=2 has d=$bc4a and therefore loads from 00bc4f and 00bc50.

The store at fc0da4 this time stores a value previously loaded from bc67.

bc67 was stored to by fc0d5f at 495807470, with the offending 7f15 having been picked up from bc6b/c by the LDY [$21] at fc0cb2 which read from bc6b. That instruction began at 495806950.

The fc0fc9/fc0fcb load and store which stored 7f15 to bc6b/bc6c occured from time 495806380, and specifically the LDA [$13], y at fc0fc9 occurred with d=$bc4a and y=2 so read from bc5d, bc5e and bc5f, which contained $755b4a. Which is not in the memory manager handle set.

I also don't currently believe that 755b4c has been initialised. Therefore it's likely to be the pointer to there that has been calculated or written incorrectly somehow.

755b4a was written in two steps, at times 495802640 and 495805825 for 00bc5d/00bc5e and at 495805880 for 00bc5f. These timings possibly aren't yet fixed, which might be a clue.

The former occurs at fc0fa2 from a STA [$13] with d=$bc4a, following a LDA [#0f] at fc0fa0; that is followed by a LDA [$11] at fc0fa4 which obtains $5575 and then writes that at fc0fa6 via STA [$15]. Therefore the 4-byte address at bc5d is copied from 00bc59.

That address ended up at bc59 from the instruction at fc0fb2 at time 495804590, which is a STA [$11] that follows the LDA [$13], y at fc0fb0, with y = $e following a direct LDY #$0e at fc0fae and d=$bc4a.

That LDA reads from $594816 which in context is likely part of the handle traversing based on its rough ROM location, possibly implying that something has broken a previous pointer somewhere in the handle chain.

Memory Manager Notes

The memory manager uses the region between e11700 and e11aff for a list of handles. Each handle is 20 bytes long and has the format:

  • 03: address of held memory;
  • 45: attributes;
  • 67: segment owner ID;
  • 811: size of held memory;
  • 1215: pointer to previous;
  • 1619: pointer to next.

e119aa/b is 682 bytes into the full list of handles; it is therefore the high two bytes of the first field — the address of the memory held — of the 34th handle.

Attempt 1: Verifying the Memory Manager Handle List

Adding code to sanity check the memory manager handle linked list whenever a write occurs to that section of memory, and attempting manually to filter for false positives, the first breakage appears to occur at time 495717310 when an earlier instance of fc0dacSTA [$17], y stores a value of 1f31, indicating a most significant address byte of 1f.

d=$bc59, y=$e so the base handle address is read from bc70 and is e11994, causing the back pointer at e11728 to be updated with an out-of-bounds address.

That address was read from bc6a/bc6b in the preceding instruction — a LDA $03,x with x=$e and d as just stated.

The corresponding offending fc0fb0/fc0fb2 start at 495715150 and reference bc6c which is pointing to 797c3b.

Skipping back a few steps: watching the history of values written to 00bc6e by fc0fa6, the first one that isn't a=00e1 occurs at time 492357210, where a=0000; it is followed by a write at 492358530 of a=6431.

So am I failing to apply the z flag properly somewhere perhaps?

Attempt 2: Verifying the Memory Manager Handle List

Believing the above to be flawed, I rewrote the list verification. The only thing initially unexpected seems to be that the first item in a list contains a back pointer to a not-yet-populated handle, which is always the next handle in linear memory after the first one in the list.

E.g. this is the initial state of the bank e1 handle list:

Bank e1: e11750 (<- e11764 | e1173c ->) [000000:000000] -> 
e1173c (<- e11750 | e11728 ->) [000000:000000] -> 
e11728 (<- e1173c | e11714 ->) [000000:000000] -> 
e11714 (<- e11728 | e11700 ->) [000000:000000] -> 
e11700 (<- e11714 | 000000 ->) [000000:000000] -> 
nil

i.e. the only surprising thing there is that the handle at e11750, which is the first in the list for bank e1, contains a back pointer to e11764, which is the next handle in memory after e11750 but is not initially populated.

Once all four linked lists are initially populated the full set looks like:

Bank 00: e11714 (<- e11728 | e11700 ->) [000000:000000] -> 
e11700 (<- e11714 | 000000 ->) [000000:000000] -> 
nil
Bank 01: e11728 (<- e1173c | e11714 ->) [000000:000000] -> 
e11714 (<- e11728 | e11700 ->) [000000:000000] -> 
e11700 (<- e11714 | 000000 ->) [000000:000000] -> 
nil
Bank e0: e1173c (<- e11750 | e11728 ->) [000000:000000] -> 
e11728 (<- e1173c | e11714 ->) [000000:000000] -> 
e11714 (<- e11728 | e11700 ->) [000000:000000] -> 
e11700 (<- e11714 | 000000 ->) [000000:000000] -> 
nil
Bank e1: e11750 (<- e11764 | e1173c ->) [000000:000000] -> 
e1173c (<- e11750 | e11728 ->) [000000:000000] -> 
e11728 (<- e1173c | e11714 ->) [000000:000000] -> 
e11714 (<- e11728 | e11700 ->) [000000:000000] -> 
e11700 (<- e11714 | 000000 ->) [000000:000000] -> 
nil

So the back pointer from the first handle on bank e1 remains invalid; for the preceding banks each points to the first in the list for the bank that was populated one before. But that's possibly a coincidental effect of the way that lists are first constructed.

Digging in further, the first writes to e11760 onwards (i.e. the previous pointer associated with the handle at e11750) occur from time 15820330; it looks like e11760 and e11761 are likely part of the same instruction, being written only 5 cycles apart. e11762 and e11763 occur at 15820375 and 15820380.

Digging into the ROM

Believing the initial list to be incorrectly formed, I determined which routine is running and looked up its expected results. Key takeaway: the documentation I had as handle layout had the next and previous pointers transposed. Therefore my traversal was still incorrect.

This puts me back at square 1 in terms of trying to find the actual issue. I can find no immediate persistent issue in handling of memory handles.

Redoubling

A new resource has been provided: an old comp.sys.apple2.programmer post on the handle list. New knowledge:

  • only the used, purge and free list are supposed to be complete;
  • i.e., implicitly, the per-bank lists just point into the used list.

That provides for two new tests: (i) do those all properly begin and end with nil pointers; and (ii) does the total number of handles remain correct (i.e. at 51 — floor(1024/20))?

At first blush, this appears to uncover a position of error.

The final time that both tests pass is at 492332040. Never again after that are the full 51 handles accounted for; assuming 492351475 is completion of the next list modify which begins at 492351410 (which is probably based on number of steps, and their proximity), one handle is lost.

Specifically, e119e4 never appears again (and other losses subsequently occur; only 42 handles remain at the point that BRK is reached).

Differencing

For the next route in: determine the first time that the program counter is in user program and the handle list looks incorrect. Backtrack from there to find the breaking call. Difference that with other instances of the same call to try to find the failing path.

That appears to suggest a first failure in the ROM call that terminates at 491037040. Backtracking from there, the problem seems to occur in a NewHandle call that begins at time 491026055; the previous successful call was at 467891275.

... and, specifically, the first bad dereference possibly traces to 491030230, when a first call to GetHandle has dropped back into the loop from SearchDown:LoopDF at its attempt to lda addr1+2 (i.e. inspect the top word of addr1 via stack-relative addressing) which loads $9e09 — an invalid top word in IIgs addressing.

That value is loaded from bc78/bc79; the 09 in bc78 is actually the 09 from the NewHandle function code, $0902 and the 9e in bc79 was left by a phd at time 491026400 which appears to come from a previous stack frame pointer. Both are leftover from the tool locator dispatcher from fe00c5 that user code reached via the indirection at e10000.

So: stack corruption?

Value of the direct register is bc5b, having been established at 491027685, following some arithmetic to create a new stack frame. bc78/bc79 aren't touched after that, so option #2 is bad control flow failing to initialise something?

Some places that potentially write to addr+2:

  • XCheckFit ('addr2 destroyed');
  • GetNext;
  • GetNextFree; and
  • GetPrevFree.

There is a call to GetNextFree from 491029890, but upon finding a nil pointer to hndl1, it doesn't ever write to addr2.

Current Trace

Memory manager state upon entry to the failing call is:

Number of banks: 128
Mem: e11700 (<- 000000 | e11818 ->) [000000:000800] -> 
e11818 (<- e11700 | e11714 ->) [009a00:002600] -> 
e11714 (<- e11818 | e11728 ->) [00c000:004800] -> 
e11728 (<- e11714 | e117a0 ->) [01c000:004000] -> 
e117a0 (<- e11728 | e11980 ->) [7d7838:000014] -> 
e11980 (<- e117a0 | e1196c ->) [7d784c:000004] -> 
e1196c (<- e11980 | e11958 ->) [7d7862:000130] -> 
e11958 (<- e1196c | e11944 ->) [7d79a2:000024] -> 
e11944 (<- e11958 | e11930 ->) [7d7a00:000068] -> 
e11930 (<- e11944 | e1191c ->) [7d7b00:000014] -> 
e1191c (<- e11930 | e11908 ->) [7d7c00:000014] -> 
e11908 (<- e1191c | e118e0 ->) [7d7d00:000014] -> 
e118e0 (<- e11908 | e1182c ->) [7d7e00:002000] -> 
e1182c (<- e118e0 | e118f4 ->) [7d9e00:000014] -> 
e118f4 (<- e1182c | e118cc ->) [7d9e79:00001c] -> 
e118cc (<- e118f4 | e118a4 ->) [7da0f5:000014] -> 
e118a4 (<- e118cc | e118b8 ->) [7da109:004aa4] -> 
e118b8 (<- e118a4 | e11890 ->) [7debb7:00001c] -> 
e11890 (<- e118b8 | e1187c ->) [7dee33:000014] -> 
e1187c (<- e11890 | e11868 ->) [7dee47:001015] -> 
e11868 (<- e1187c | e11854 ->) [7dfe5c:0000c4] -> 
e11854 (<- e11868 | e11840 ->) [7dff20:0000a4] -> 
e11840 (<- e11854 | e11804 ->) [7dffc4:00003c] -> 
e11804 (<- e11840 | e117f0 ->) [7ffde7:0000c4] -> 
e117f0 (<- e11804 | e117dc ->) [7ffeab:000002] -> 
e117dc (<- e117f0 | e117c8 ->) [7ffead:00005b] -> 
e117c8 (<- e117dc | e117b4 ->) [7fff08:00000e] -> 
e117b4 (<- e117c8 | e1178c ->) [7fff16:000020] -> 
e1178c (<- e117b4 | e11778 ->) [7fff38:000004] -> 
e11778 (<- e1178c | e1173c ->) [7fff3c:0000c4] -> 
e1173c (<- e11778 | e11750 ->) [800000:602000] -> 
e11750 (<- e1173c | e11764 ->) [e0c000:006000] -> 
e11764 (<- e11750 | 000000 ->) [e1c000:ff1e4000] -> 
nil
Purge: nil
Free: e119e4 (<- 000000 | e11a0c ->) [000000:000014] -> 
e11a0c (<- e119e4 | e119d0 ->) [000000:000040] -> 
e119d0 (<- e11a0c | e119f8 ->) [000000:000533] -> 
e119f8 (<- e119d0 | e119bc ->) [000000:000260] -> 
e119bc (<- e119f8 | e11994 ->) [000000:004000] -> 
e11994 (<- e119bc | e119a8 ->) [000000:000010] -> 
e119a8 (<- e11994 | e11a20 ->) [000000:000028] -> 
e11a20 (<- e119a8 | e11a34 ->) [000000:000000] -> 
e11a34 (<- e11a20 | e11a48 ->) [000000:000000] -> 
e11a48 (<- e11a34 | e11a5c ->) [000000:000000] -> 
e11a5c (<- e11a48 | e11a70 ->) [000000:000000] -> 
e11a70 (<- e11a5c | e11a84 ->) [000000:000000] -> 
e11a84 (<- e11a70 | e11a98 ->) [000000:000000] -> 
e11a98 (<- e11a84 | e11aac ->) [000000:000000] -> 
e11aac (<- e11a98 | e11ac0 ->) [000000:000000] -> 
e11ac0 (<- e11aac | e11ad4 ->) [000000:000000] -> 
e11ad4 (<- e11ac0 | e11ae8 ->) [000000:000000] -> 
e11ae8 (<- e11ad4 | 000000 ->) [000000:000000] -> 
nil
Total: 51

Execution appears to occur as:


; User code: x = $0902, JSR to $e10000 => call the tool locator, requesting
; routine NewHandle. Cf. Page 12-35 (i.e. Page 553) of Apple IIGS Toolbox Reference Volume 1.
;
; Stack pointer is bc87; therefore the arguments being supplied to NewHandle are:
;
; bc88, bc89, bc8a, bc8b:	$00000000
; locationPtr
; (ignored, because attributes doesn't specify a fixed address or bank)
;
; bc8c, bc8d:			$8000
; attributes
; i.e. "block is temporarily locked down; can't be moved or purged"
;
; bc8e, bc8f:			$7008
; user ID
;
; bc90, bc91, bc92, bc93:	$00000024
; requested size
;
; bc94, bc95, bc96, bc97
; (reserved storage for result)

01f1bd -> 22 [2.8] a:0024 x:0902 y:0000 s:bc87 e:0 p:00 db:01 pb:01 d:bc9e [tot:491026055]
01f1be -> 00 [2.8]
01f1bf -> 00 [2.8]
00bc87 <- 01 [2.8]
00bc86 -> 01 [2.8]
01f1c0 -> e1 [2.8]
00bc86 <- f1 [2.8]
00bc85 <- c0 [2.8]

;
; JMP $fe00c5; jump to the default in-ROM tool locator.
;

e10000 -> 5c [2.8] a:0024 x:0902 y:0000 s:bc84 e:0 p:00 db:01 pb:e1 d:bc9e [tot:491026095]
e10001 -> c5 [2.8]
e10002 -> 00 [2.8]
e10003 -> fe [2.8]


	; PEA $fe01
fe00c5 -> f4 [2.8] a:0024 x:0902 y:0000 s:bc84 e:0 p:00 db:01 pb:fe d:bc9e [tot:491026120]
fe00c6 -> 01 [2.8]
fe00c7 -> fe [2.8]
00bc84 <- fe [2.8]
00bc83 <- 01 [2.8]
	; PEA $3700
fe00c8 -> f4 [2.8] a:0024 x:0902 y:0000 s:bc82 e:0 p:00 db:01 pb:fe d:bc9e [tot:491026145]
fe00c9 -> 00 [2.8]
fe00ca -> 37 [2.8]
00bc82 <- 37 [2.8]
00bc81 <- 00 [2.8]
	; REP #$30, i.e. set 16-bit M and X
fe00cb -> c2 [2.8] a:0024 x:0902 y:0000 s:bc80 e:0 p:00 db:01 pb:fe d:bc9e [tot:491026170]
fe00cc -> 30 [2.8]
fe00cd -> af [2.8]
	; LDA $e103c0
fe00cd -> af [2.8] a:0024 x:0902 y:0000 s:bc80 e:0 p:00 db:01 pb:fe d:bc9e [tot:491026185]
fe00ce -> c0 [2.8]
fe00cf -> 03 [2.8]
fe00d0 -> e1 [2.8]
e103c0 -> 5c [2.8]
e103c1 -> fe [2.8]
	; PHA
fe00d1 -> 48 [2.8] a:fe5c x:0902 y:0000 s:bc80 e:0 p:80 db:01 pb:fe d:bc9e [tot:491026215]
fe00d2 -> af [2.8]
00bc80 <- fe [2.8]
00bc7f <- 5c [2.8]
	; LDA $e103c1
fe00d2 -> af [2.8] a:fe5c x:0902 y:0000 s:bc7e e:0 p:80 db:01 pb:fe d:bc9e [tot:491026235]
fe00d3 -> c1 [2.8]
fe00d4 -> 03 [2.8]
fe00d5 -> e1 [2.8]
e103c1 -> fe [2.8]
e103c2 -> 7d [2.8]
	 ; STA 2, s
fe00d6 -> 83 [2.8] a:7dfe x:0902 y:0000 s:bc7e e:0 p:00 db:01 pb:fe d:bc9e [tot:491026265]
fe00d7 -> 02 [2.8]
fe00d8 -> af [2.8]
00bc80 <- fe [2.8]
00bc81 <- 7d [2.8]
	; LDA $e103ca
fe00d8 -> af [2.8] a:7dfe x:0902 y:0000 s:bc7e e:0 p:00 db:01 pb:fe d:bc9e [tot:491026290]
fe00d9 -> ca [2.8]
fe00da -> 03 [2.8]
fe00db -> e1 [2.8]
e103ca -> 7f [2.8]
e103cb -> 00 [2.8]
	; PHA
fe00dc -> 48 [2.8] a:007f x:0902 y:0000 s:bc7e e:0 p:00 db:01 pb:fe d:bc9e [tot:491026320]
fe00dd -> af [2.8]
00bc7e <- 00 [2.8]
00bc7d <- 7f [2.8]
	; LDA $e103c8
fe00dd -> af [2.8] a:007f x:0902 y:0000 s:bc7c e:0 p:00 db:01 pb:fe d:bc9e [tot:491026340]
fe00de -> c8 [2.8]
fe00df -> 03 [2.8]
fe00e0 -> e1 [2.8]
e103c8 -> 3c [2.8]
e103c9 -> ff [2.8]
	; PHA
fe00e1 -> 48 [2.8] a:ff3c x:0902 y:0000 s:bc7c e:0 p:80 db:01 pb:fe d:bc9e [tot:491026370]
fe00e2 -> 3b [2.8]
00bc7c <- ff [2.8]
00bc7b <- 3c [2.8]
	; TSC
fe00e2 -> 3b [2.8] a:ff3c x:0902 y:0000 s:bc7a e:0 p:80 db:01 pb:fe d:bc9e [tot:491026390]
fe00e3 -> 0b [2.8]
	; PHD
fe00e3 -> 0b [2.8] a:bc7a x:0902 y:0000 s:bc7a e:0 p:80 db:01 pb:fe d:bc9e [tot:491026400]
fe00e4 -> 5b [2.8]
00bc7a <- bc [2.8]
00bc79 <- 9e [2.8]
	; TCD
fe00e4 -> 5b [2.8] a:bc7a x:0902 y:0000 s:bc78 e:0 p:80 db:01 pb:fe d:bc9e [tot:491026420]
fe00e5 -> 8a [2.8]
	; TXA
fe00e5 -> 8a [2.8] a:bc7a x:0902 y:0000 s:bc78 e:0 p:80 db:01 pb:fe d:bc7a [tot:491026430]
fe00e6 -> 48 [2.8]
	; PHA
fe00e6 -> 48 [2.8] a:0902 x:0902 y:0000 s:bc78 e:0 p:00 db:01 pb:fe d:bc7a [tot:491026440]
fe00e7 -> 29 [2.8]
00bc78 <- 09 [2.8]
00bc77 <- 02 [2.8]
	; AND #$00ff
fe00e7 -> 29 [2.8] a:0902 x:0902 y:0000 s:bc76 e:0 p:00 db:01 pb:fe d:bc7a [tot:491026460]
fe00e8 -> ff [2.8]
fe00e9 -> 00 [2.8]
	; BEQ $3a [not taken]
fe00ea -> f0 [2.8] a:0002 x:0902 y:0000 s:bc76 e:0 p:00 db:01 pb:fe d:bc7a [tot:491026475]
fe00eb -> 3a [2.8]
	; CMP [$05]
fe00ec -> c7 [2.8] a:0002 x:0902 y:0000 s:bc76 e:0 p:00 db:01 pb:fe d:bc7a [tot:491026485]
fe00ed -> 05 [2.8]
fe00ee -> b0 [2.8]
00bc7f -> 5c [2.8]
00bc80 -> fe [2.8]
00bc81 -> 7d [2.8]
7dfe5c -> 31 [2.8]
7dfe5d -> 00 [2.8]
	; BCS $36 [not taken]
fe00ee -> b0 [2.8] a:0002 x:0902 y:0000 s:bc76 e:0 p:80 db:01 pb:fe d:bc7a [tot:491026525]
fe00ef -> 36 [2.8]
	; ASL
fe00f0 -> 0a [2.8] a:0002 x:0902 y:0000 s:bc76 e:0 p:80 db:01 pb:fe d:bc7a [tot:491026535]
fe00f1 -> 0a [2.8]
	; ASL
fe00f1 -> 0a [2.8] a:0004 x:0902 y:0000 s:bc76 e:0 p:00 db:01 pb:fe d:bc7a [tot:491026545]
fe00f2 -> a8 [2.8]
	; TAY
fe00f2 -> a8 [2.8] a:0008 x:0902 y:0000 s:bc76 e:0 p:00 db:01 pb:fe d:bc7a [tot:491026555]
fe00f3 -> b7 [2.8]
	; LDA [$01]
fe00f3 -> b7 [2.8] a:0008 x:0902 y:0008 s:bc76 e:0 p:00 db:01 pb:fe d:bc7a [tot:491026565]
fe00f4 -> 01 [2.8]
fe00f5 -> aa [2.8]
00bc7b -> 3c [2.8]
00bc7c -> ff [2.8]
00bc7d -> 7f [2.8]
7fff44 -> 00 [2.8]
7fff45 -> 00 [2.8]
	; TAX
fe00f5 -> aa [2.8] a:0000 x:0902 y:0008 s:bc76 e:0 p:02 db:01 pb:fe d:bc7a [tot:491026610]
fe00f6 -> c8 [2.8]
	; INY
fe00f6 -> c8 [2.8] a:0000 x:0000 y:0008 s:bc76 e:0 p:02 db:01 pb:fe d:bc7a [tot:491026620]
fe00f7 -> c8 [2.8]
	; INY
fe00f7 -> c8 [2.8] a:0000 x:0000 y:0009 s:bc76 e:0 p:00 db:01 pb:fe d:bc7a [tot:491026630]
fe00f8 -> b7 [2.8]
	; LDA [$01]
fe00f8 -> b7 [2.8] a:0000 x:0000 y:000a s:bc76 e:0 p:00 db:01 pb:fe d:bc7a [tot:491026640]
fe00f9 -> 01 [2.8]
fe00fa -> 85 [2.8]
00bc7b -> 3c [2.8]
00bc7c -> ff [2.8]
00bc7d -> 7f [2.8]
7fff46 -> 00 [2.8]
7fff47 -> 00 [2.8]
	; STA $03
fe00fa -> 85 [2.8] a:0000 x:0000 y:000a s:bc76 e:0 p:02 db:01 pb:fe d:bc7a [tot:491026680]
fe00fb -> 03 [2.8]
fe00fc -> 86 [2.8]
00bc7d <- 00 [2.8]
00bc7e <- 00 [2.8]
	; STX $01
fe00fc -> 86 [2.8] a:0000 x:0000 y:000a s:bc76 e:0 p:02 db:01 pb:fe d:bc7a [tot:491026710]
fe00fd -> 01 [2.8]
fe00fe -> 88 [2.8]
00bc7b <- 00 [2.8]
00bc7c <- 00 [2.8]
	; DEY
fe00fe -> 88 [2.8] a:0000 x:0000 y:000a s:bc76 e:0 p:02 db:01 pb:fe d:bc7a [tot:491026735]
fe00ff -> b7 [2.8]
	; LDA [$05], y
fe00ff -> b7 [2.8] a:0000 x:0000 y:0009 s:bc76 e:0 p:00 db:01 pb:fe d:bc7a [tot:491026745]
fe0100 -> 05 [2.8]
fe0101 -> aa [2.8]
00bc7f -> 5c [2.8]
00bc80 -> fe [2.8]
00bc81 -> 7d [2.8]
7dfe65 -> 00 [2.8]
7dfe66 -> fc [2.8]
	; TAX
fe0101 -> aa [2.8] a:fc00 x:0000 y:0009 s:bc76 e:0 p:80 db:01 pb:fe d:bc7a [tot:491026785]
fe0102 -> 88 [2.8]
	; DEY
fe0102 -> 88 [2.8] a:fc00 x:fc00 y:0009 s:bc76 e:0 p:80 db:01 pb:fe d:bc7a [tot:491026795]
fe0103 -> b7 [2.8]
	; LDA [$05], y
fe0103 -> b7 [2.8] a:fc00 x:fc00 y:0008 s:bc76 e:0 p:00 db:01 pb:fe d:bc7a [tot:491026805]
fe0104 -> 05 [2.8]
fe0105 -> 85 [2.8]
00bc7f -> 5c [2.8]
00bc80 -> fe [2.8]
00bc81 -> 7d [2.8]
7dfe64 -> 00 [2.8]
7dfe65 -> 00 [2.8]
	; STA $05
fe0105 -> 85 [2.8] a:0000 x:fc00 y:0008 s:bc76 e:0 p:02 db:01 pb:fe d:bc7a [tot:491026845]
fe0106 -> 05 [2.8]
fe0107 -> 86 [2.8]
00bc7f <- 00 [2.8]
00bc80 <- 00 [2.8]
	; STX $06
fe0107 -> 86 [2.8] a:0000 x:fc00 y:0008 s:bc76 e:0 p:02 db:01 pb:fe d:bc7a [tot:491026870]
fe0108 -> 06 [2.8]
fe0109 -> a3 [2.8]
00bc80 <- 00 [2.8]
00bc81 <- fc [2.8]
	; LDA 2, s
fe0109 -> a3 [2.8] a:0000 x:fc00 y:0008 s:bc76 e:0 p:02 db:01 pb:fe d:bc7a [tot:491026895]
fe010a -> 02 [2.8]
fe010b -> 29 [2.8]
00bc78 -> 09 [2.8]
00bc79 -> 9e [2.8]
	; AND $00ff
fe010b -> 29 [2.8] a:9e09 x:fc00 y:0008 s:bc76 e:0 p:80 db:01 pb:fe d:bc7a [tot:491026920]
fe010c -> ff [2.8]
fe010d -> 00 [2.8]
	; BEQ $1b [not taken]
fe010e -> f0 [2.8] a:0009 x:fc00 y:0008 s:bc76 e:0 p:00 db:01 pb:fe d:bc7a [tot:491026935]
fe010f -> 1b [2.8]
	; CMP [$05]
fe0110 -> c7 [2.8] a:0009 x:fc00 y:0008 s:bc76 e:0 p:00 db:01 pb:fe d:bc7a [tot:491026945]
fe0111 -> 05 [2.8]
fe0112 -> b0 [2.8]
00bc7f -> 00 [2.8]
00bc80 -> 00 [2.8]
00bc81 -> fc [2.8]
fc0000 -> 30 [2.8]
fc0001 -> 00 [2.8]
	; BCS $17 [not taken]
fe0112 -> b0 [2.8] a:0009 x:fc00 y:0008 s:bc76 e:0 p:80 db:01 pb:fe d:bc7a [tot:491026985]
fe0113 -> 17 [2.8]
	; ASL
fe0114 -> 0a [2.8] a:0009 x:fc00 y:0008 s:bc76 e:0 p:80 db:01 pb:fe d:bc7a [tot:491026995]
fe0115 -> 0a [2.8]
	; ASL
fe0115 -> 0a [2.8] a:0012 x:fc00 y:0008 s:bc76 e:0 p:00 db:01 pb:fe d:bc7a [tot:491027005]
fe0116 -> a8 [2.8]
	; TAY
fe0116 -> a8 [2.8] a:0024 x:fc00 y:0008 s:bc76 e:0 p:00 db:01 pb:fe d:bc7a [tot:491027015]
fe0117 -> b7 [2.8]
	; LDA [$05], y
fe0117 -> b7 [2.8] a:0024 x:fc00 y:0024 s:bc76 e:0 p:00 db:01 pb:fe d:bc7a [tot:491027025]
fe0118 -> 05 [2.8]
fe0119 -> aa [2.8]
00bc7f -> 00 [2.8]
00bc80 -> 00 [2.8]
00bc81 -> fc [2.8]
fc0024 -> 22 [2.8]
fc0025 -> 05 [2.8]
	; TAX
fe0119 -> aa [2.8] a:0522 x:fc00 y:0024 s:bc76 e:0 p:00 db:01 pb:fe d:bc7a [tot:491027070]
fe011a -> c8 [2.8]
	; INY
fe011a -> c8 [2.8] a:0522 x:0522 y:0024 s:bc76 e:0 p:00 db:01 pb:fe d:bc7a [tot:491027080]
fe011b -> b7 [2.8]
	; LDA [$05], y
fe011b -> b7 [2.8] a:0522 x:0522 y:0025 s:bc76 e:0 p:00 db:01 pb:fe d:bc7a [tot:491027090]
fe011c -> 05 [2.8]
fe011d -> 85 [2.8]
00bc7f -> 00 [2.8]
00bc80 -> 00 [2.8]
00bc81 -> fc [2.8]
fc0025 -> 05 [2.8]
fc0026 -> fc [2.8]
	; STA $06
fe011d -> 85 [2.8] a:fc05 x:0522 y:0025 s:bc76 e:0 p:80 db:01 pb:fe d:bc7a [tot:491027130]
fe011e -> 06 [2.8]
fe011f -> 86 [2.8]
00bc80 <- 05 [2.8]
00bc81 <- fc [2.8]
	; STX $05
fe011f -> 86 [2.8] a:fc05 x:0522 y:0025 s:bc76 e:0 p:80 db:01 pb:fe d:bc7a [tot:491027160]
fe0120 -> 05 [2.8]
fe0121 -> fa [2.8]
00bc7f <- 22 [2.8]
00bc80 <- 05 [2.8]
	; PLX
fe0121 -> fa [2.8] a:fc05 x:0522 y:0025 s:bc76 e:0 p:80 db:01 pb:fe d:bc7a [tot:491027185]
fe0122 -> 2b [2.8]
fe0122 -> 2b [2.8]
00bc77 -> 02 [2.8]
00bc78 -> 09 [2.8]
	; PLD
fe0122 -> 2b [2.8] a:fc05 x:0902 y:0025 s:bc78 e:0 p:00 db:01 pb:fe d:bc7a [tot:491027210]
fe0123 -> 68 [2.8]
fe0123 -> 68 [2.8]
00bc79 -> 9e [2.8]
00bc7a -> bc [2.8]
	; PLA
fe0123 -> 68 [2.8] a:fc05 x:0902 y:0025 s:bc7a e:0 p:80 db:01 pb:fe d:bc9e [tot:491027235]
fe0124 -> 7a [2.8]
fe0124 -> 7a [2.8]
00bc7b -> 00 [2.8]
00bc7c -> 00 [2.8]
	; PLY
fe0124 -> 7a [2.8] a:0000 x:0902 y:0025 s:bc7c e:0 p:02 db:01 pb:fe d:bc9e [tot:491027260]
fe0125 -> 6b [2.8]
fe0125 -> 6b [2.8]
00bc7d -> 00 [2.8]
00bc7e -> 00 [2.8]
	; RTL
fe0125 -> 6b [2.8] a:0000 x:0902 y:0000 s:bc7e e:0 p:02 db:01 pb:fe d:bc9e [tot:491027285]
fe0126 -> a2 [2.8]
fe0127 -> 01 [2.8]
00bc7f -> 22 [2.8]
00bc80 -> 05 [2.8]
00bc81 -> fc [2.8]

;
; Entry point for NewHandle
;
; stack pointer is now three lower than it was upon entry into the tool locator.
;

	; JSL link	; "Fix stack etc."
fc0523 -> 22 [2.8] a:0000 x:0902 y:0000 s:bc81 e:0 p:02 db:01 pb:fc d:bc9e [tot:491027315]
fc0524 -> 88 [2.8]
fc0525 -> 16 [2.8]
00bc81 <- fc [2.8]
00bc80 -> 05 [2.8]
fc0526 -> e1 [2.8]
00bc80 <- 05 [2.8]
00bc7f <- 26 [2.8]

;
; Indirect entry for link
;

e11688 -> 5c [2.8] a:0000 x:0902 y:0000 s:bc7e e:0 p:02 db:01 pb:e1 d:bc9e [tot:491027360]
e11689 -> 99 [2.8]
e1168a -> 01 [2.8]
e1168b -> fc [2.8]

;
; XLink
;
	; txa
fc0199 -> 8a [2.8] a:0000 x:0902 y:0000 s:bc7e e:0 p:02 db:01 pb:fc d:bc9e [tot:491027380]
fc019a -> eb [2.8]
	; xba
fc019a -> eb [2.8] a:0902 x:0902 y:0000 s:bc7e e:0 p:00 db:01 pb:fc d:bc9e [tot:491027390]
fc019b -> e2 [2.8]
fc019b -> e2 [2.8]
	; sep #$30	; "Into 8 bit mode"
fc019b -> e2 [2.8] a:0209 x:0902 y:0000 s:bc7e e:0 p:00 db:01 pb:fc d:bc9e [tot:491027405]
fc019c -> 30 [2.8]
fc019d -> 29 [2.8]
	; and #$ff
fc019d -> 29 [2.8] a:0209 x:0002 y:0000 s:bc7e e:0 p:30 db:01 pb:fc d:bc9e [tot:491027420]
fc019e -> ff [2.8]
	; tax		; "X = Index for parm count"
fc019f -> aa [2.8] a:0209 x:0002 y:0000 s:bc7e e:0 p:30 db:01 pb:fc d:bc9e [tot:491027430]
fc01a0 -> a9 [2.8]
	; lda $#e1	; "Bank reg for later"
fc01a0 -> a9 [2.8] a:0209 x:0009 y:0000 s:bc7e e:0 p:30 db:01 pb:fc d:bc9e [tot:491027440]
fc01a1 -> e1 [2.8]
	; pha
fc01a2 -> 48 [2.8] a:02e1 x:0009 y:0000 s:bc7e e:0 p:b0 db:01 pb:fc d:bc9e [tot:491027450]
fc01a3 -> bf [2.8]
00bc7e <- e1 [2.8]
	; lda >ParmCnt-1,x	; "Get number of parameters"
fc01a3 -> bf [2.8] a:02e1 x:0009 y:0000 s:bc7d e:0 p:b0 db:01 pb:fc d:bc9e [tot:491027465]
fc01a4 -> 0e [2.8]
fc01a5 -> 01 [2.8]
fc01a6 -> fc [2.8]
fc0117 -> 0c [2.8]
	; rep #$30
fc01a7 -> c2 [2.8] a:020c x:0009 y:0000 s:bc7d e:0 p:30 db:01 pb:fc d:bc9e [tot:491027490]
fc01a8 -> 30 [2.8]
fc01a9 -> fa [2.8]
	; plx	; "Save return address"
fc01a9 -> fa [2.8] a:020c x:0009 y:0000 s:bc7d e:0 p:00 db:01 pb:fc d:bc9e [tot:491027505]
fc01aa -> 7a [2.8]
fc01aa -> 7a [2.8]
00bc7e -> e1 [2.8]
00bc7f -> 26 [2.8]
	; ply	; "and bank"
fc01aa -> 7a [2.8] a:020c x:26e1 y:0000 s:bc7f e:0 p:00 db:01 pb:fc d:bc9e [tot:491027530]
fc01ab -> 29 [2.8]
fc01ab -> 29 [2.8]
00bc80 -> 05 [2.8]
00bc81 -> fc [2.8]
	; and #$00ff	; "Lower byte valid"
fc01ab -> 29 [2.8] a:020c x:26e1 y:fc05 s:bc81 e:0 p:80 db:01 pb:fc d:bc9e [tot:491027560]
fc01ac -> ff [2.8]
fc01ad -> 00 [2.8]
	; pha
fc01ae -> 48 [2.8] a:000c x:26e1 y:fc05 s:bc81 e:0 p:00 db:01 pb:fc d:bc9e [tot:491027575]
fc01af -> 3b [2.8]
00bc81 <- 00 [2.8]
00bc80 <- 0c [2.8]
	; TSC	; "Pull stack down"
fc01af -> 3b [2.8] a:000c x:26e1 y:fc05 s:bc7f e:0 p:00 db:01 pb:fc d:bc9e [tot:491027595]
fc01b0 -> 38 [2.8]
	; sec
fc01b0 -> 38 [2.8] a:bc7f x:26e1 y:fc05 s:bc7f e:0 p:80 db:01 pb:fc d:bc9e [tot:491027605]
fc01b1 -> e9 [2.8]
	; sbc #ZPSize (#$0024)
fc01b1 -> e9 [2.8] a:bc7f x:26e1 y:fc05 s:bc7f e:0 p:81 db:01 pb:fc d:bc9e [tot:491027615]
fc01b2 -> 24 [2.8]
fc01b3 -> 00 [2.8]
	; TCS
fc01b4 -> 1b [2.8] a:bc5b x:26e1 y:fc05 s:bc7f e:0 p:81 db:01 pb:fc d:bc9e [tot:491027630]
fc01b5 -> 8b [2.8]
	; PHB
fc01b5 -> 8b [2.8] a:bc5b x:26e1 y:fc05 s:bc5b e:0 p:81 db:01 pb:fc d:bc9e [tot:491027640]
fc01b6 -> 0b [2.8]
00bc5b <- 01 [2.8]
	; PHD
fc01b6 -> 0b [2.8] a:bc5b x:26e1 y:fc05 s:bc5a e:0 p:81 db:01 pb:fc d:bc9e [tot:491027655]
fc01b7 -> 5b [2.8]
00bc5a <- bc [2.8]
00bc59 <- 9e [2.8]
	; TCD
fc01b7 -> 5b [2.8] a:bc5b x:26e1 y:fc05 s:bc58 e:0 p:81 db:01 pb:fc d:bc9e [tot:491027675]
fc01b8 -> 64 [2.8]
	; STZ retry (STZ $23)
fc01b8 -> 64 [2.8] a:bc5b x:26e1 y:fc05 s:bc58 e:0 p:81 db:01 pb:fc d:bc5b [tot:491027685]
fc01b9 -> 23 [2.8]
fc01ba -> 64 [2.8]
00bc7e <- 00 [2.8]
00bc7f <- 00 [2.8]
	; STZ error (STZ $01)	; "Clear the error"
fc01ba -> 64 [2.8] a:bc5b x:26e1 y:fc05 s:bc58 e:0 p:81 db:01 pb:fc d:bc5b [tot:491027710]
fc01bb -> 01 [2.8]
fc01bc -> 5a [2.8]
00bc5c <- 00 [2.8]
00bc5d <- 00 [2.8]
	; PHY	; "Push RTL addr and bank"
fc01bc -> 5a [2.8] a:bc5b x:26e1 y:fc05 s:bc58 e:0 p:81 db:01 pb:fc d:bc5b [tot:491027735]
fc01bd -> da [2.8]
00bc58 <- fc [2.8]
00bc57 <- 05 [2.8]
	; PHX
fc01bd -> da [2.8] a:bc5b x:26e1 y:fc05 s:bc56 e:0 p:81 db:01 pb:fc d:bc5b [tot:491027760]
fc01be -> 22 [2.8]
00bc56 <- 26 [2.8]
00bc55 <- e1 [2.8]
	; JSL IncBusyFlg
fc01be -> 22 [2.8] a:bc5b x:26e1 y:fc05 s:bc54 e:0 p:81 db:01 pb:fc d:bc5b [tot:491027780]
fc01bf -> 64 [2.8]
fc01c0 -> 00 [2.8]
00bc54 <- fc [2.8]
00bc53 -> 38 [2.8]
fc01c1 -> e1 [2.8]
00bc53 <- 01 [2.8]
00bc52 <- c1 [2.8]

;
; IncBusyFlg
;

e10064 -> 5c [2.8] a:bc5b x:26e1 y:fc05 s:bc51 e:0 p:81 db:01 pb:e1 d:bc5b [tot:491027825]
e10065 -> 07 [2.8]
e10066 -> dd [2.8]
e10067 -> fc [2.8]
fcdd07 -> 08 [2.8] a:bc5b x:26e1 y:fc05 s:bc51 e:0 p:81 db:01 pb:fc d:bc5b [tot:491027845]
fcdd08 -> 78 [2.8]
00bc51 <- 81 [2.8]
fcdd08 -> 78 [2.8] a:bc5b x:26e1 y:fc05 s:bc50 e:0 p:81 db:01 pb:fc d:bc5b [tot:491027860]
fcdd09 -> 48 [2.8]
fcdd09 -> 48 [2.8] a:bc5b x:26e1 y:fc05 s:bc50 e:0 p:85 db:01 pb:fc d:bc5b [tot:491027870]
fcdd0a -> af [2.8]
00bc50 <- bc [2.8]
00bc4f <- 5b [2.8]
fcdd0a -> af [2.8] a:bc5b x:26e1 y:fc05 s:bc4e e:0 p:85 db:01 pb:fc d:bc5b [tot:491027890]
fcdd0b -> ff [2.8]
fcdd0c -> 00 [2.8]
fcdd0d -> e1 [2.8]
e100ff -> 01 [2.8]
e10100 -> 00 [2.8]
fcdd0e -> 1a [2.8] a:0001 x:26e1 y:fc05 s:bc4e e:0 p:05 db:01 pb:fc d:bc5b [tot:491027920]
fcdd0f -> 8f [2.8]
fcdd0f -> 8f [2.8] a:0002 x:26e1 y:fc05 s:bc4e e:0 p:05 db:01 pb:fc d:bc5b [tot:491027930]
fcdd10 -> ff [2.8]
fcdd11 -> 00 [2.8]
fcdd12 -> e1 [2.8]
e100ff <- 02 [2.8]
e10100 <- 00 [2.8]
fcdd13 -> 68 [2.8] a:0002 x:26e1 y:fc05 s:bc4e e:0 p:05 db:01 pb:fc d:bc5b [tot:491027960]
fcdd14 -> 28 [2.8]
fcdd14 -> 28 [2.8]
00bc4f -> 5b [2.8]
00bc50 -> bc [2.8]
fcdd14 -> 28 [2.8] a:bc5b x:26e1 y:fc05 s:bc50 e:0 p:85 db:01 pb:fc d:bc5b [tot:491027985]
fcdd15 -> 6b [2.8]
fcdd15 -> 6b [2.8]
00bc51 -> 81 [2.8]
fcdd15 -> 6b [2.8] a:bc5b x:26e1 y:fc05 s:bc51 e:0 p:81 db:01 pb:fc d:bc5b [tot:491028005]
fcdd16 -> af [2.8]
fcdd17 -> ff [2.8]
00bc52 -> c1 [2.8]
00bc53 -> 01 [2.8]
00bc54 -> fc [2.8]

;
; Return to very end of XLink
;

	; PLB	; "B = $E1"
fc01c2 -> ab [2.8] a:bc5b x:26e1 y:fc05 s:bc54 e:0 p:81 db:01 pb:fc d:bc5b [tot:491028035]
fc01c3 -> 6b [2.8]
fc01c3 -> 6b [2.8]
00bc55 -> e1 [2.8]
	; RTL
fc01c3 -> 6b [2.8] a:bc5b x:26e1 y:fc05 s:bc55 e:0 p:81 db:e1 pb:fc d:bc5b [tot:491028055]
fc01c4 -> 22 [2.8]
fc01c5 -> 68 [2.8]
00bc56 -> 26 [2.8]
00bc57 -> 05 [2.8]
00bc58 -> fc [2.8]


;
; Return from link to NewHandle
;

	; lda #$ffff
fc0527 -> a9 [2.8] a:bc5b x:26e1 y:fc05 s:bc58 e:0 p:81 db:e1 pb:fc d:bc5b [tot:491028085]
fc0528 -> ff [2.8]
fc0529 -> ff [2.8]
	; sta Owner (sta $09)
fc052a -> 85 [2.8] a:ffff x:26e1 y:fc05 s:bc58 e:0 p:81 db:e1 pb:fc d:bc5b [tot:491028100]
fc052b -> 09 [2.8]
fc052c -> 22 [2.8]
00bc64 <- ff [2.8]
00bc65 <- ff [2.8]
	; jsl GetFree
fc052c -> 22 [2.8] a:ffff x:26e1 y:fc05 s:bc58 e:0 p:81 db:e1 pb:fc d:bc5b [tot:491028125]
fc052d -> 9c [2.8]
fc052e -> 16 [2.8]
00bc58 <- fc [2.8]
00bc57 -> 05 [2.8]
fc052f -> e1 [2.8]
00bc57 <- 05 [2.8]
00bc56 <- 2f [2.8]

;
; Indirect call to GetFree
;

e1169c -> 5c [2.8] a:ffff x:26e1 y:fc05 s:bc55 e:0 p:81 db:e1 pb:e1 d:bc5b [tot:491028170]
e1169d -> 4a [2.8]
e1169e -> 0e [2.8]
e1169f -> fc [2.8]


;
; GetFree
;

	; lda |FreeList	;Get pointer to free handles
fc0e4a -> ad [2.8] a:ffff x:26e1 y:fc05 s:bc55 e:0 p:81 db:e1 pb:fc d:bc5b [tot:491028190]
fc0e4b -> 08 [2.8]
fc0e4c -> 16 [2.8]
e11608 -> e4 [2.8]
e11609 -> 19 [2.8]
	; sta hndl
fc0e4d -> 85 [2.8] a:19e4 x:26e1 y:fc05 s:bc55 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491028215]
fc0e4e -> 17 [2.8]
fc0e4f -> ad [2.8]
00bc72 <- e4 [2.8]
00bc73 <- 19 [2.8]
	; lda |FreeList+2
fc0e4f -> ad [2.8] a:19e4 x:26e1 y:fc05 s:bc55 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491028240]
fc0e50 -> 0a [2.8]
fc0e51 -> 16 [2.8]
e1160a -> e1 [2.8]
e1160b -> 00 [2.8]
	; sta hndl+2
fc0e52 -> 85 [2.8] a:00e1 x:26e1 y:fc05 s:bc55 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491028265]
fc0e53 -> 19 [2.8]
fc0e54 -> 05 [2.8]
00bc74 <- e1 [2.8]
00bc75 <- 00 [2.8]
	; ora hndl	;Nil pointer?
fc0e54 -> 05 [2.8] a:00e1 x:26e1 y:fc05 s:bc55 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491028290]
fc0e55 -> 17 [2.8]
fc0e56 -> d0 [2.8]
00bc72 -> e4 [2.8]
00bc73 -> 19 [2.8]
	; bne HndlOk [taken]
fc0e56 -> d0 [2.8] a:19e5 x:26e1 y:fc05 s:bc55 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491028315]
fc0e57 -> 0e [2.8]
fc0e58 -> a9 [2.8]
fc0e58 -> a9 [2.8]

;
; i.e. hndl is at [$17], i.e. bc725, and is now 00e119e4, the first item in the free list.
; Code has confirmed that it is non-nil (i.e. there was a free handle).
;

	; ldy #hndl_next	;Get the next handle
fc0e66 -> a0 [2.8] a:19e5 x:26e1 y:fc05 s:bc55 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491028335]
fc0e67 -> 10 [2.8]
fc0e68 -> 00 [2.8]
	; lda [hndl],y
fc0e69 -> b7 [2.8] a:19e5 x:26e1 y:0010 s:bc55 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491028350]
fc0e6a -> 17 [2.8]
fc0e6b -> 85 [2.8]
00bc72 -> e4 [2.8]
00bc73 -> 19 [2.8]
00bc74 -> e1 [2.8]
e119f4 -> 0c [2.8]
e119f5 -> 1a [2.8]
	; sta hndl1	;Put it in hndl1 and freelist
fc0e6b -> 85 [2.8] a:1a0c x:26e1 y:0010 s:bc55 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491028390]
fc0e6c -> 0f [2.8]
fc0e6d -> 8d [2.8]
00bc6a <- 0c [2.8]
00bc6b <- 1a [2.8]
	; sta |FreeList
fc0e6d -> 8d [2.8] a:1a0c x:26e1 y:0010 s:bc55 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491028415]
fc0e6e -> 08 [2.8]
fc0e6f -> 16 [2.8]
e11608 <- 0c [2.8]
e11609 <- 1a [2.8]
	; iny
fc0e70 -> c8 [2.8] a:1a0c x:26e1 y:0010 s:bc55 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491028440]
fc0e71 -> c8 [2.8]
	; iny
fc0e71 -> c8 [2.8] a:1a0c x:26e1 y:0011 s:bc55 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491028450]
fc0e72 -> b7 [2.8]
	; lda [hndl],y
fc0e72 -> b7 [2.8] a:1a0c x:26e1 y:0012 s:bc55 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491028460]
fc0e73 -> 17 [2.8]
fc0e74 -> 8d [2.8]
00bc72 -> e4 [2.8]
00bc73 -> 19 [2.8]
00bc74 -> e1 [2.8]
e119f6 -> e1 [2.8]
e119f7 -> 00 [2.8]
	; sta |FreeList+2
fc0e74 -> 8d [2.8] a:00e1 x:26e1 y:0012 s:bc55 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491028505]
fc0e75 -> 0a [2.8]
fc0e76 -> 16 [2.8]
e1160a <- e1 [2.8]
e1160b <- 00 [2.8]
	; sta hndl1+2
fc0e77 -> 85 [2.8] a:00e1 x:26e1 y:0012 s:bc55 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491028530]
fc0e78 -> 11 [2.8]
fc0e79 -> 05 [2.8]
00bc6c <- e1 [2.8]
00bc6d <- 00 [2.8]
	; ora hndl1	;Was it nil?
fc0e79 -> 05 [2.8] a:00e1 x:26e1 y:0012 s:bc55 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491028560]
fc0e7a -> 0f [2.8]
fc0e7b -> f0 [2.8]
00bc6a -> 0c [2.8]
00bc6b -> 1a [2.8]
	; beq nomore [not taken]
fc0e7b -> f0 [2.8] a:1aed x:26e1 y:0012 s:bc55 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491028585]
fc0e7c -> 0c [2.8]

;
; The head of the free list has now been advanced to 00e11a0c, and this has also been
; stored to hndl1, which is [$0f], or bc6ad
;

	; lda #nil	;Make its previous nil
fc0e7d -> a9 [2.8] a:1aed x:26e1 y:0012 s:bc55 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491028595]
fc0e7e -> 00 [2.8]
fc0e7f -> 00 [2.8]
	; ldy #hndl_prev
fc0e80 -> a0 [2.8] a:0000 x:26e1 y:0012 s:bc55 e:0 p:03 db:e1 pb:fc d:bc5b [tot:491028610]
fc0e81 -> 0c [2.8]
fc0e82 -> 00 [2.8]
	; sta [hndl1],y
fc0e83 -> 97 [2.8] a:0000 x:26e1 y:000c s:bc55 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491028625]
fc0e84 -> 0f [2.8]
fc0e85 -> c8 [2.8]
00bc6a -> 0c [2.8]
00bc6b -> 1a [2.8]
00bc6c -> e1 [2.8]
e11a18 <- 00 [2.8]
e11a19 <- 00 [2.8]
	; iny
fc0e85 -> c8 [2.8] a:0000 x:26e1 y:000c s:bc55 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491028670]
fc0e86 -> c8 [2.8]
	; iny
fc0e86 -> c8 [2.8] a:0000 x:26e1 y:000d s:bc55 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491028680]
fc0e87 -> 97 [2.8]
	; sta [hndl1],y
fc0e87 -> 97 [2.8] a:0000 x:26e1 y:000e s:bc55 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491028690]
fc0e88 -> 0f [2.8]
fc0e89 -> 38 [2.8]
00bc6a -> 0c [2.8]
00bc6b -> 1a [2.8]
00bc6c -> e1 [2.8]
e11a1a <- 00 [2.8]
e11a1b <- 00 [2.8]
	; sec	;No error
fc0e89 -> 38 [2.8] a:0000 x:26e1 y:000e s:bc55 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491028730]
fc0e8a -> 6b [2.8]
	; rtl
fc0e8a -> 6b [2.8] a:0000 x:26e1 y:000e s:bc55 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491028740]
fc0e8b -> a0 [2.8]
fc0e8c -> 14 [2.8]
00bc56 -> 2f [2.8]
00bc57 -> 05 [2.8]
00bc58 -> fc [2.8]

;
; Nils out the back pointer from what is now the head of the free list.
;

;
; So, upon exiting GetFree:
;
; hndl points to a new handle, in which the back pointer is 0 and the forward pointer
; is still what is now at the head of the free list.
;
; the free list has lost its first member. 
;



;
; Return from GetFree to NewHandle
;

	; bcc full	;Br if err [not taken]
fc0530 -> 90 [2.8] a:0000 x:26e1 y:000e s:bc58 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491028770]
fc0531 -> 25 [2.8]
	; ldx #10	;Move parameters
fc0532 -> a2 [2.8] a:0000 x:26e1 y:000e s:bc58 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491028780]
fc0533 -> 0a [2.8]
fc0534 -> 00 [2.8]


	; MoveParms	lda parms,x (lda $2d, x)
fc0535 -> b5 [2.8] a:0000 x:000a y:000e s:bc58 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491028795]
fc0536 -> 2d [2.8]
fc0537 -> 95 [2.8]
fc0537 -> 95 [2.8]
00bc92 -> 00 [2.8]
00bc93 -> 00 [2.8]
	; sta addr,x
fc0537 -> 95 [2.8] a:0000 x:000a y:000e s:bc58 e:0 p:03 db:e1 pb:fc d:bc5b [tot:491028825]
fc0538 -> 03 [2.8]
fc0539 -> ca [2.8]
fc0539 -> ca [2.8]
00bc68 <- 00 [2.8]
00bc69 <- 00 [2.8]
	; dex
fc0539 -> ca [2.8] a:0000 x:000a y:000e s:bc58 e:0 p:03 db:e1 pb:fc d:bc5b [tot:491028860]
fc053a -> ca [2.8]
	; dex
fc053a -> ca [2.8] a:0000 x:0009 y:000e s:bc58 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491028870]
fc053b -> 10 [2.8]
	; bpl MoveParms
fc053b -> 10 [2.8] a:0000 x:0008 y:000e s:bc58 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491028880]
fc053c -> f8 [2.8]
fc053d -> a5 [2.8]
fc053d -> a5 [2.8]

[... * 10]
;
; Copies 12 bytes from [d+]$2d to [d+]$03, i.e. what was at bc88bc93 is now
; duplicated at bc5ebc69.
;
; bc88bc93 is the original parameter block for NewHandle. It's now accessible
; from either location.
;
; So:
;
; [bc88bc8b] = [bc5ebc61] = locationPtr = 0
; [bc8cbc8d] = [bc62bc63] = attributes = $8000
; [bc8ebc8f] = [bc64bc65] = user ID = $7008
; [bc90bc93] = [bc66bc69] = size requested = $00000024
;
; Final iteration of loop:

fc0535 -> b5 [2.8] a:0000 x:0000 y:000e s:bc58 e:0 p:03 db:e1 pb:fc d:bc5b [tot:491029300]
fc0536 -> 2d [2.8]
fc0537 -> 95 [2.8]
fc0537 -> 95 [2.8]
00bc88 -> 00 [2.8]
00bc89 -> 00 [2.8]
fc0537 -> 95 [2.8] a:0000 x:0000 y:000e s:bc58 e:0 p:03 db:e1 pb:fc d:bc5b [tot:491029330]
fc0538 -> 03 [2.8]
fc0539 -> ca [2.8]
fc0539 -> ca [2.8]
00bc5e <- 00 [2.8]
00bc5f <- 00 [2.8]
fc0539 -> ca [2.8] a:0000 x:0000 y:000e s:bc58 e:0 p:03 db:e1 pb:fc d:bc5b [tot:491029360]
fc053a -> ca [2.8]
fc053a -> ca [2.8] a:0000 x:ffff y:000e s:bc58 e:0 p:81 db:e1 pb:fc d:bc5b [tot:491029370]
fc053b -> 10 [2.8]
fc053b -> 10 [2.8] a:0000 x:fffe y:000e s:bc58 e:0 p:81 db:e1 pb:fc d:bc5b [tot:491029380]
fc053c -> f8 [2.8]


	lda owner	;If owner = 0 somethings wrong
fc053d -> a5 [2.8] a:0000 x:fffe y:000e s:bc58 e:0 p:81 db:e1 pb:fc d:bc5b [tot:491029390]
fc053e -> 09 [2.8]
fc053f -> f0 [2.8]
00bc64 -> 08 [2.8]
00bc65 -> 70 [2.8]
	beq BadID
fc053f -> f0 [2.8] a:7008 x:fffe y:000e s:bc58 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491029415]
fc0540 -> 11 [2.8]
	lda size	;Making an empty handle?
fc0541 -> a5 [2.8] a:7008 x:fffe y:000e s:bc58 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491029425]
fc0542 -> 0b [2.8]
fc0543 -> 05 [2.8]
00bc66 -> 24 [2.8]
00bc67 -> 00 [2.8]
	ora size+2
fc0543 -> 05 [2.8] a:0024 x:fffe y:000e s:bc58 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491029455]
fc0544 -> 0d [2.8]
fc0545 -> f0 [2.8]
00bc68 -> 00 [2.8]
00bc69 -> 00 [2.8]
	beq MakeEmpty
fc0545 -> f0 [2.8] a:0024 x:fffe y:000e s:bc58 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491029480]
fc0546 -> 34 [2.8]
	jsl Search	;Go get the segment
fc0547 -> 22 [2.8] a:0024 x:fffe y:000e s:bc58 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491029490]
fc0548 -> 90 [2.8]
fc0549 -> 16 [2.8]
00bc58 <- fc [2.8]
00bc57 -> 05 [2.8]
fc054a -> e1 [2.8]
00bc57 <- 05 [2.8]
00bc56 <- 4a [2.8]


;
; Indirect entry point for Search
;

e11690 -> 5c [2.8] a:0024 x:fffe y:000e s:bc55 e:0 p:01 db:e1 pb:e1 d:bc5b [tot:491029530]
e11691 -> f2 [2.8]
e11692 -> 0a [2.8]
e11693 -> fc [2.8]

;
; Entry point for XSearch
;

fc0af2 -> ee [2.8] a:0024 x:fffe y:000e s:bc55 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491029555]
fc0af3 -> 30 [2.8]
fc0af4 -> 16 [2.8]
e11630 -> 36 [2.8]
e11631 -> 00 [2.8]
e11631 -> 00 [2.8]
e11631 <- 00 [2.8]
e11630 <- 37 [2.8]
fc0af5 -> d0 [2.8] a:0024 x:fffe y:000e s:bc55 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491029595]
fc0af6 -> 03 [2.8]
fc0af7 -> ee [2.8]
fc0af7 -> ee [2.8]
fc0afa -> a5 [2.8] a:0024 x:fffe y:000e s:bc55 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491029615]
fc0afb -> 07 [2.8]
fc0afc -> 89 [2.8]
00bc62 -> 00 [2.8]
00bc63 -> 80 [2.8]
fc0afc -> 89 [2.8] a:8000 x:fffe y:000e s:bc55 e:0 p:81 db:e1 pb:fc d:bc5b [tot:491029640]
fc0afd -> 02 [2.8]
fc0afe -> 00 [2.8]
fc0aff -> f0 [2.8] a:8000 x:fffe y:000e s:bc55 e:0 p:83 db:e1 pb:fc d:bc5b [tot:491029655]
fc0b00 -> 05 [2.8]
fc0b01 -> 09 [2.8]
fc0b01 -> 09 [2.8]
fc0b06 -> 89 [2.8] a:8000 x:fffe y:000e s:bc55 e:0 p:83 db:e1 pb:fc d:bc5b [tot:491029675]
fc0b07 -> 00 [2.8]
fc0b08 -> 40 [2.8]
fc0b09 -> d0 [2.8] a:8000 x:fffe y:000e s:bc55 e:0 p:83 db:e1 pb:fc d:bc5b [tot:491029690]
fc0b0a -> 03 [2.8]
fc0b0b -> 4c [2.8] a:8000 x:fffe y:000e s:bc55 e:0 p:83 db:e1 pb:fc d:bc5b [tot:491029700]
fc0b0c -> e6 [2.8]
fc0b0d -> 0b [2.8]


;
; SearchDownFast
;

fc0be6 -> 89 [2.8] a:8000 x:fffe y:000e s:bc55 e:0 p:83 db:e1 pb:fc d:bc5b [tot:491029715]
fc0be7 -> 01 [2.8]
fc0be8 -> 00 [2.8]
fc0be9 -> d0 [2.8] a:8000 x:fffe y:000e s:bc55 e:0 p:83 db:e1 pb:fc d:bc5b [tot:491029730]
fc0bea -> 33 [2.8]
fc0beb -> ad [2.8] a:8000 x:fffe y:000e s:bc55 e:0 p:83 db:e1 pb:fc d:bc5b [tot:491029740]
fc0bec -> 2e [2.8]
fc0bed -> 16 [2.8]
e1162e -> e1 [2.8]
e1162f -> 00 [2.8]
fc0bee -> f0 [2.8] a:00e1 x:fffe y:000e s:bc55 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491029765]
fc0bef -> 2e [2.8]
fc0bf0 -> 85 [2.8] a:00e1 x:fffe y:000e s:bc55 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491029775]
fc0bf1 -> 11 [2.8]
fc0bf2 -> ad [2.8]
00bc6c <- e1 [2.8]
00bc6d <- 00 [2.8]
fc0bf2 -> ad [2.8] a:00e1 x:fffe y:000e s:bc55 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491029805]
fc0bf3 -> 2c [2.8]
fc0bf4 -> 16 [2.8]
e1162c -> e4 [2.8]
e1162d -> 19 [2.8]
fc0bf5 -> 85 [2.8] a:19e4 x:fffe y:000e s:bc55 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491029830]
fc0bf6 -> 0f [2.8]
fc0bf7 -> 20 [2.8]
00bc6a <- e4 [2.8]
00bc6b <- 19 [2.8]
fc0bf7 -> 20 [2.8] a:19e4 x:fffe y:000e s:bc55 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491029860]
fc0bf8 -> 9e [2.8]
fc0bf9 -> 0f [2.8]
fc0bf9 -> 0f [2.8]
00bc55 <- 0b [2.8]
00bc54 <- f9 [2.8]

;
; This appears to have tried to use |LastHighHandle, e1162ce1162f, to start a
; downward search, but from there it got e119e4, which is not currently linked
; into memory at all.
;
; So: the problem could be maintenance of LastHighHandle?
;


;
; GetPrevFree
;

fc0f9e -> e2 [2.8] a:19e4 x:fffe y:000e s:bc53 e:0 p:01 db:e1 pb:fc d:bc5b [tot:491029890]
fc0f9f -> 10 [2.8]
fc0fa0 -> a5 [2.8]
fc0fa0 -> a5 [2.8] a:19e4 x:00fe y:000e s:bc53 e:0 p:11 db:e1 pb:fc d:bc5b [tot:491029905]
fc0fa1 -> 0f [2.8]
fc0fa2 -> 85 [2.8]
00bc6a -> e4 [2.8]
00bc6b -> 19 [2.8]
fc0fa2 -> 85 [2.8] a:19e4 x:00fe y:000e s:bc53 e:0 p:11 db:e1 pb:fc d:bc5b [tot:491029930]
fc0fa3 -> 13 [2.8]
fc0fa4 -> a5 [2.8]
00bc6e <- e4 [2.8]
00bc6f <- 19 [2.8]
fc0fa4 -> a5 [2.8] a:19e4 x:00fe y:000e s:bc53 e:0 p:11 db:e1 pb:fc d:bc5b [tot:491029960]
fc0fa5 -> 11 [2.8]
fc0fa6 -> 85 [2.8]
00bc6c -> e1 [2.8]
00bc6d -> 00 [2.8]
fc0fa6 -> 85 [2.8] a:00e1 x:00fe y:000e s:bc53 e:0 p:11 db:e1 pb:fc d:bc5b [tot:491029985]
fc0fa7 -> 15 [2.8]
fc0fa8 -> a0 [2.8]
00bc70 <- e1 [2.8]
00bc71 <- 00 [2.8]
fc0fa8 -> a0 [2.8] a:00e1 x:00fe y:000e s:bc53 e:0 p:11 db:e1 pb:fc d:bc5b [tot:491030010]
fc0fa9 -> 0c [2.8]
fc0faa -> b7 [2.8] a:00e1 x:00fe y:000c s:bc53 e:0 p:11 db:e1 pb:fc d:bc5b [tot:491030020]
fc0fab -> 13 [2.8]
fc0fac -> 85 [2.8]
00bc6e -> e4 [2.8]
00bc6f -> 19 [2.8]
00bc70 -> e1 [2.8]
e119f0 -> 00 [2.8]
e119f1 -> 00 [2.8]
fc0fac -> 85 [2.8] a:0000 x:00fe y:000c s:bc53 e:0 p:13 db:e1 pb:fc d:bc5b [tot:491030065]
fc0fad -> 0f [2.8]
fc0fae -> a0 [2.8]
00bc6a <- 00 [2.8]
00bc6b <- 00 [2.8]
fc0fae -> a0 [2.8] a:0000 x:00fe y:000c s:bc53 e:0 p:13 db:e1 pb:fc d:bc5b [tot:491030090]
fc0faf -> 0e [2.8]
fc0fb0 -> b7 [2.8] a:0000 x:00fe y:000e s:bc53 e:0 p:11 db:e1 pb:fc d:bc5b [tot:491030100]
fc0fb1 -> 13 [2.8]
fc0fb2 -> 85 [2.8]
00bc6e -> e4 [2.8]
00bc6f -> 19 [2.8]
00bc70 -> e1 [2.8]
e119f2 -> 00 [2.8]
e119f3 -> 00 [2.8]
fc0fb2 -> 85 [2.8] a:0000 x:00fe y:000e s:bc53 e:0 p:13 db:e1 pb:fc d:bc5b [tot:491030140]
fc0fb3 -> 11 [2.8]
fc0fb4 -> f0 [2.8]
00bc6c <- 00 [2.8]
00bc6d <- 00 [2.8]
fc0fb4 -> f0 [2.8] a:0000 x:00fe y:000e s:bc53 e:0 p:13 db:e1 pb:fc d:bc5b [tot:491030165]
fc0fb5 -> e5 [2.8]
fc0fb6 -> a0 [2.8]
fc0fb6 -> a0 [2.8]
fc0f9b -> c2 [2.8] a:0000 x:00fe y:000e s:bc53 e:0 p:13 db:e1 pb:fc d:bc5b [tot:491030185]
fc0f9c -> 10 [2.8]
fc0f9d -> 60 [2.8]
fc0f9d -> 60 [2.8] a:0000 x:00fe y:000e s:bc53 e:0 p:03 db:e1 pb:fc d:bc5b [tot:491030200]
fc0f9e -> e2 [2.8]
fc0f9e -> e2 [2.8]
00bc54 -> f9 [2.8]
00bc55 -> 0b [2.8]
00bc55 -> 0b [2.8]

;	Probable point of failure:
;
;	lda addr1+2	;If bank 0 DF - 1 done
;
;	... but nobody has written there yet?
fc0bfa -> a5 [2.8] a:0000 x:00fe y:000e s:bc55 e:0 p:03 db:e1 pb:fc d:bc5b [tot:491030230]
fc0bfb -> 1d [2.8]
fc0bfc -> f0 [2.8]
00bc78 -> 09 [2.8]
00bc79 -> 9e [2.8]

Investigating LastHighHandle

The trace above seems to imply that LastHighHandle has an unexpected value. So the next step is to dig down on that.

Discovered, a comment in CheckRecent:

*** Removed this BRA 14-Sep-91 DAL.  Memory Manager was exploding if the
*** high and low hints "crossed," then became equal, and then somebody
*** disposed of the handle that both hints were pointing at.  Only the
*** low one was getting bumped, leaving us with a high hint that was
*** actually the first handle on the free list (so the backwards link is
*** nil)!  If the very next NewHandle was for non-fixed memory, it would
*** get Very Confused when finding a nil backwards link on what should be
*** a valid used handle.

The high-and-low crossing thing doesn't seem relevant, but everything from "leaving us with a high hint that was actually..." is exactly the issue diagnosed above. LastHighHandle does somehow point to the first handle on the free list, such that the backwards link is nil, and the next NewHandle is for non-fixed memory.

First stop was a routine called CheckRecent which resides at fc1464; it appears to do the right thing.

Looking for when LastHighHandle is written to, the relevant writes seem to be (times on the right):

e1162c <- e4 [483807080]
e1162d <- 19 [483807085]
e1162e <- e1 [483807160]
e1162f <- 00 [483807165]