Hurdles to making a multitasking environment on the NES
I’ve been thinking about what would be required to make a multitasking environment/platform on the NES.
Requirements:
- Can load applications on-demand as independent processes
- Can launch multiple instances of each application
- Uses cooperative multitasking
Realistically you’ll want the cartridge to have some RAM and allow bank switching for both RAM and ROM in order to increase the memory & storage available to programs.
- The 6502 has a single stack that’s fixed to live from $100 to $1ff. This is mapped to console RAM and can’t be bank-switched. Each process wants its own stack, so they’ll either have to share this very limited space, or you’ll have to swap the contents of the stack when switching tasks.
- Compared to x86, where you can update SS to any segment & SP to any location within the segment.
- Similarly, process memory stored in system RAM will need to be swapped out on task switch. Memory located above $4020 could be bank-switched instead.
- Accessing data in different banks is desirable so we can jump to code in a currently-unloaded bank, or simply access data from one.
- We can add code to perform this work and store it in a fixed bank that’s always available, and make the compiler use that instead of a plain JSR.
- Pointers will need to include bank information as well.
- Compared to x86, where you can jump to a different segment directly without losing access to the caller’s segment.
- Graphics/PPU state also needs to be associated with each process.
- It’s probably easiest to give the active process the full screen, instead of allowing background processes to share the display (eg. overlapping/tiled windows). The CHR ROM (or other video data) for a background application probably needs to get swapped out for the active process so it won’t be available to show properly, and there are challenges around sharing the current palette.
- It might be possible to switch banks/contexts between scanlines, which could require windows to be screen-width but let them successfully stack vertically.
- A system menu UI could be handled using code & data in reserved always-available banks, like the code we use to handle moves and jumps across banks.
- It’s probably easiest to give the active process the full screen, instead of allowing background processes to share the display (eg. overlapping/tiled windows). The CHR ROM (or other video data) for a background application probably needs to get swapped out for the active process so it won’t be available to show properly, and there are challenges around sharing the current palette.