DragonMinded / libdragon

Open source library for N64 development.
https://libdragon.dev
The Unlicense
709 stars 102 forks source link

Preventing the Expansion Pak from being utilized #425

Open danbolt opened 1 year ago

danbolt commented 1 year ago

I'm curious if it'd be possible to opt-out of using the Expansion Pak's memory at runtime.

When working on a homebrew title, a developer might wish to target (or simply test for) Nintendo 64 consoles that don't have the Expansion Pak. This can be done by re-inserting the Jumper Pak, but it's a solution that's cumbersome or sometimes infeasible. An example that comes to mind is Bug Game releasing a hotfix to shrink its memory footprint after community reports of crashes without the Expansion Pak.

9nova had an interesting comment in the N64Brew Discord:

i kind of wish there was a convenient way to test without it, i dont have a jumper pak so for testing i just commented out the line in get_memory_size and made it always return 4mb

9nova's solution struck me as pretty clever. Or since sbrk uses the function for allocating memory, a developer with only an Expansion Pak could simulate using a Jumper Pak. This could save a lot of testing time in situations where resources are limited, such as a game jam.

A crude example might be:

/**
 * @brief Disables the Expansion Pak if it happens to be inserted.
 */
void set_4mb_mode(void) {
 // set some flag that `get_memory_size` checks against
}

:point_up: A developer might call this at the start of main while working on debug builds of their game.

I can think of a few reasons why this might not be the best idea for inclusion, but I wanted to bring it up as I think it'd benefit smaller works and game jam submissions.

meeq commented 1 year ago

This may make more sense as a compile-time flag, but overall I think this is a solid suggestion.

danbolt commented 1 year ago

Compile time would work as well, but I'd think that a developer would need to rebuild Libdragon themselves, right?

rasky commented 1 year ago

the above suggestion is a quick hack but it's not sufficient to really prevent libdragon from using > 4 MiB. In fact, the stack pointer is set in entrypoint.S depending on the amount of memory detected by IPL3 (written at 0x80000318), which is also used by get_memory_size().

The easiest way to really test a 4MiB configuration is to add these lines at the top of entrypoint:

li t0, 4*1024*1024
sw t0, 0x80000318

If we want to turn this into a feature, one idea that comes to mind is to set some special bit in the header, and read that in entrypoint.S. This can then be set via a new command line flag by n64tool, and in turn exposed as an option via a Makefile variable by n64.mk.

UPDATE Apr 2024: The suggested change isn't relevant anymore in the preview branch, because the entry point does things differently with the open source IPL3.