Screen handling
mode.c provides a very simple screen handling interface:
- mode_w, mode_h, mode_vsync and mode_freq contain the details of the configured screen mode.
- mode_enter() will attempt to enter the configured screen mode, and sets up the appropriate buffers. Returns 0 on success, 1 on failure. If the colour swapping state has changed since the mode was last loaded, it will trigger re-swapping of all loaded sprites and flushing of caches via a call to colswap_all().
- mode_exit() is used to free the buffers allocated by mode_enter(), and stop any other processes. It does not actually cause a screenmode change to occur.
- If mode_enter() completed successfully, scr will be a pointer to a gp_screen structure for the screen. bank0 is the bank to write to; bank1 is the bank currently being displayed onscreen. The buffers will be 16bpp with no mask.
- mode_swapbanks() performs buffer swapping. It forces any debug text to be displayed, flushes the debug buffer, and swaps the screen banks. It also manages the DMA transfer (if enabled), and waits for vsync (if enabled). It also replaces bank0 with a pointer to an offscreen buffer if offscreen buffering is enabled (and the buffer was allocated successfully). If offscreen buffers are in use it will also replace bank1 with the original bank0, which is later used in the bank copy code to get the destination for the offscreen buffer.
- mode_43_error() calculates how similar a given mode width and height value are to the 4:3 ratio. This is used during game initialisation, to attempt to auto-detect the correct screen mode to use if the user doesn't have a config file and the default mode (480x352) is unavailable.
- mode_dma() is an internal function used to perform a DMA transfer to copy the screen data from the offscreen buffer to screen memory. Currently this uses the IntelDMA module. The function deals with 3 eventualities:
- The DMA transfer succeeds
- The DMA transfer fails to execute
- The DMA transfer was unable to be setup
If conditions 2 or 3 occur, the function will use memcpy() to copy the data manually. If condition 3 occurs, the function will also clear the mode_usedma flag, as it's assumed that a failure to set up the DMA transfer is a fatal problem and so there's no point in trying it again. For example, failing a lookup of the IntelDMA SWI chunk base will cause the mode_usedma flag to be cleared.
- The flags mode_colourswap, mode_offscreen, and mode_usedma are used to enable/disable colour swapping, offscreen buffer usage, and DMA respectively. They can each be enabled/disabled independently of one another, although mode_usedma is ignored without mode_offscreen being set.
Colour swapping
R/B colour swapping is implemented in colswap.c. Colour swapping is performed at the sprite level, rather than the screen level; there are three ways in which this occurs:
- Palettised sprites have palettes produced in which the R/B channels are swapped
- Non-palettised sprites have the R/B channels of each pixel swapped. This is performed at loading time, and again whenever R/B swapping is turned on or off.
- Direct use of colour values (for example font and compass needle colours) are also swapped. In the case of the two examples just given, the colour values are applied to sprites which are already in the R/B swapped state. This is to ensure correct operation of the sprite isn't greyscale.
Whenever the user changes the R/B swapping state in the options, all cached sprites held by the game are deleted (or marked for deletion), and all static 16bit sprites have their R/B channels swapped.
TODO:
CODE: DELAYED: DMA support for A9. Need to find a module to use, or code to copy. And someone to test it!
CODE: QUICK: Improve default screen size detection - detect pre-StrongARM and use 320x256 as default resolution. Also, if possible, detect A9, and use Iyonix resolution.
???
Profit!