Recently, I shared this way to crash a CoCo 3 in three easy steps:
- Turn it on.
- Type in “CLEAR 16500:WIDTH 40”
- There is no step three.
I expected to do a follow-up once I had time to look at the Super Extended Color BASIC Unraveled book and try to figure out what was causing this crash. I also planned to figure out what value triggered the first crash. I discovered this in a program that did a “CLEAR 17000” and I just went up and down trying to find a threshold where it crashed, and gave up at 16500.
But I am lazy.
And sometimes dense. It didn’t dawn on me that I might have been able to have the computer try to figure out when it crashed. But it did to Juan Castro. In the comments, Juan wrote:
First thing I thought was to increase the value of CLEAR in a loop to see exactly when it crashes… oops, you can’t, you nuked your loop counter with the CLEAR.
No problem, let’s use fixed memory for the counter. &H400, the start of the (now unused) text screen. We’ll start with 16000 (=&H3E80) and increment by one.
10 WIDTH 40
20 POKE &H400,&H3E:POKE &H401,&H80
30 GOSUB 80
40 AD=AD+1
50 GOSUB 90
60 PRINT AD:CLEAR AD
70 GOTO 30
80 AD=PEEK(&H400)*256+PEEK(&H401):RETURN
90 HI=INT(AD/256)
100 LO=AD-256HI
110 POKE &H400,HI:POKE &H401,LO
120 RETURNIt locks up at 16356 — suspiciously close to 16384. Only 28 bytes off. That’s probably close to how much the stack occupies. (Modulo some buffer headers, variable descriptors, and maybe some non-fatal stack corruption.)
– Juan Castro
Brilliant!
And I bet once we dig in (I believe William Astle has done this work in the past) we will find that location is where an 8K MMU block gets mapped in/out for manipulating the high res text screens. Or some other words to that affect that I do not know how to properly articulate.
More to come on this…
Your suspicion about the cause is exactly correct. The screen gets mapped in the $2000-$3FFF block. The 28 or so bytes short of 16K are exactly the right number to push the stack below $4000 in the routine that swaps the MMU block so when it returns, it goes to aone garbage address that isn’t the correct return address.
Can you see any easy patch around this issue? Could they have done some trick and swapped out part of the upper 32K, like assuming the ROM memory would not be active when doing screen IO? I recall the IO is really slow, mapping for every character, and someone did a speed up that mapped in, did the IO, then mapped out, and I want to find whatever that was and see if it also fixes this issue.
I think it was probably me that did the speedup. No, it didn’t the crash issue. The patch to fix this is a bit more involved than you might think but in principle it can be done. Disabling interrupts and mapping over disk basic would probably sort it, which you can do even if ROMs are enabled as long as the MMU is enabled.
There may have been a commercial one two. But perhaps I am confusing these types of optimizations with the 6309 patches. Pretty sure Burke & Burke had some kind of 6309 patches for BASIC. If only something like that was available free, so anyone could include it with their program. We could all be running software with bugs fixed.
That could potentially mess up with the timer interrupt, maybe that’s why they did it char by char. Bank switching is messy.
Would anything during the IRQ in BASIC be doing anything other than incrementing the TIMER? What else is it used for?