MEGA65 / mega65-user-guide

MEGA65 User Guide
75 stars 51 forks source link

Add a section about the base page to the Memory chapter #564

Open dansanderson opened 1 year ago

dansanderson commented 1 year ago

I just noticed that the Memory chapter does not describe the base page feature of the CPU directly. It should, especially with regards to base page indexing, the KERNAL's use of page 0, and how to use an alternate base page with the KERNAL IRQ resident, i.e. disable interrupts while accessing, reset to 0 before enabling. Base page $16 is used in an example on base page indexing, but there is no other discussion, nor a mention of KERNAL IRQ compatibility.

A quick review of the MEGA65 ROM IRQ handler shows that there are a few uses of base page variables in the handler code, e.g. cursor blinking uses attptr ($00e0). Just one such use directly implies that any program that runs with the KERNAL IRQ active must be defensive about the B register, only change it with interrupts disabled, and always change it back to 0 when re-enabling interrupts. That feels like a heavyweight way to use base page indexing, but I don't see how this isn't necessary when keeping the KERNAL active.

Pimau commented 1 year ago

Very interesting note. It seems to be exactly the issue I ran into this week and which really cost me a lot patience. All my IRQ code which was placed behind my Basic in $2300 was resulting in an unwanted BRK. I was not able to prevent this and the BRK was not resumable in any scenario I tried.

Finally I found out that when my IRQ code goes to $1600, it just works without BRK and complains, but the Basic part had to run with BANK 128 active - otherwise my IRQ branching is not triggered at all. Is this the problem you are describing above? Sounds very near for my ears.

Memory on M65 is very confusing! You hear it in my question above, I am far not as ready as I should be to write the docs for it. But when it is not done in a time where I sorted all this out, I am in to help. Nevertheless, I can support before, when something must be tested. E.g. the demo code of somebody else who is documenting it ... let me know ... or maybe somebody else sees this note.

dansanderson commented 1 year ago

@Pimau That sounds more like MAP register state than base page B register state, but yes, the general idea is the same. It is difficult to combine machine code and KERNAL code without knowing a great deal about how the CPU and KERNAL behave. Some of these behaviors are not yet stable API surfaces, and so not yet documented. In your case, the KERNAL keeps MAPL set to E300 when running BASIC, which hides most RAM in $2000-$7FFF from the CPU. You don't mention how you're installing your IRQ handler, but if you're also engaging the KERNAL IRQ routines and BASIC, you'll need to manage the MAP register so it is what the KERNAL expects when it is time to run its code.

The Commodore 64 KERNAL has a "soft IRQ" installation vector, a memory location where you can set an address for some code that runs during the KERNAL IRQ handler. While Commodore intended a similar facility for the C65, this is not yet officially documented for the MEGA65 KERNAL, partly for this reason: the needs of a "soft IRQ" API are much more complex for the MEGA65 than for the C64, and we need to design, test, and document this API to be practical to use, such as the pre- and post-conditions of register state for the soft IRQ routine. For example, it would be an improvement for the KERNAL to take care of resetting MAP and B on return from the soft IRQ.

For what it's worth, the BASIC BANK command only affects how address arguments to BASIC commands are interpreted. It does not change the state of any CPU registers. See the Memory chapter for details.

dansanderson commented 1 year ago

Some good news: I confirmed that the IRQ handler stashes and restore the program's B register. A program does not need to disable interrupts to set its own base page.

As far as I can tell, the same is not true of the MAP register. The MAP register requires delicate handling anyway, and is probably best used by programs that ditch the KERNAL entirely. We'll have to think about and document best practices for using MAP with the KERNAL resident.