you can’t as easily place code outside the low 4k.
Ok this was bugging me for a while, but then I realized we can just split the RAM into banks, and swap them in and out as needed. This even works perfectly with the built-in web compiler if you keep you bank offsets at 0x1200, 0x2200, etc… (so that the jump addresses calculated by the compiler still work once “reallocated”). It’s quite convenient that the compiler still compiles all the jumps just fine, it just truncates the high bits (bits 13-16)… so in order to run the code all we need to do is copy it back into the 0x200 to 0xFFF range.
My proof of concept places the “loader” at 0xF00… which gives you 14 banks of 3328 bytes… of course the code in one bank can’t directly call another… they are more like 14 mini programs you can swap in and out on demand… The copy code could be faster, but I was optimizing for size (64 bytes currently), not speed. It currently takes 29,000 ticks now to switch banks, but you could easily reduce that by a factor of 10 if that was a requirement.
Update: Around 4,500 cycles when optimized for speed, so if you burned 100% “cpu” you could swap banks 4 times per frame running at ludicrous speed… so it would be possible to have rendering code and update code in different banks and swap them per frame… and still have 55% of the cycles available for your actual code to run…
And if you wanted the full 3584 bytes for each bank you could (with a tiny bit of effort) relocate the loader itself to < 0x200 (after boot)…
The proof of concept just places one of the demos at 0x1200… and then :main just sets the bank address and than calls swapbank
… after the bank is swapped in control returns to 0x200.
Proof of concept: