Writing homebrew
This article provides a brief overview of the basics of writing homebrew for nileswan. For more detailed information, make sure to study the other articles in the developer guide.
Users of the Wonderful toolchain can use libnile, an official C library providing access to most of the cartridge’s functionality. Documentation for libnile is available here.
After launching a program, nileswan cartridge functionality is locked by default. There are two separate unlocks required to take advantage of all its features, listed below.
By default, nileswan I/O ports are locked, that is not writable by software. One can unlock these I/O ports by writing the magic value 0xDD
to port 0xE2
(POW_CNT
).
NoteOne can also write0x00DD
to disable any cartridge behavior emulation features enabled by the menu program by default.
Note that this also performs all the operations of this value: disables TF card power, enables 24 MHz clock power, enables SRAM access, disables EEPROM emulation, flash emulation, et cetera. If you’re using some of these features differently (such as not making use of the 24 MHz clock), it is recommended to follow this with a write that disables unused functionality.
In libnile, this corresponds to the nile_io_unlock();
function.
However, this doesn’t take care of banking. By default, a mask is applied which prohibits accessing banks outside of the cartridge image’s ROM and RAM space by mirroring that space.
In order to allow conveniently accessing nileswan-exclusive banks, functionality is provided to ignore this mask on a per-area basis (SRAM, ROM0, ROM1) via the BANK_MASK
I/O port. In addition, for ROM banks, one has to use the extended 2003 banking ports (0xD0
-0xD5
), as their range on nileswan extends past 8 bits.
CautionROM0 and ROM1 are typically allocated from bank0xFF
down; however, cartridge images are loaded from0x00
up. Disabling the bank mask on these areas can cause invalid data to be read unless the bank registers are adjusted to match.
In libnile, the nile_bank_unlock();
function is provided, which automatically adjusts and unlocks SRAM, ROM0 and ROM1.
If your homebrew requires nileswan-specific MCU functionality (such as USB access), remember that by default the MCU’s native protocol will not be available. If the homebrew program requested EEPROM or RTC access, the MCU will be running in an emulation mode for the respective peripheral; otherwise, it would have been shut down to conserve power. As such, accessing the native MCU protocol requires an MCU reset; such a reset will also break non-nileswan-specific EEPROM/RTC communication code from working correctly.
In libnile, the nile_mcu_reset(false);
function can be used to reset the MCU back to native mode.
By default, the MCU is configured to communicate at a frequency of 384 KHz
. In some circumstances, faster communication speeds may be possible. This requires two distinct steps:
- configuring the MCU to accept faster SPI transfers (libnile:
nile_mcu_native_mcu_spi_set_speed_sync(...);
), - configuring the FPGA and console to emit faster SPI clocks (libnile:
nile_spi_set_speed(...);
).