Mode 74 Quickstart
Video mode 74's most notable feature is an extensive ability to configure it both compile-time and "on the fly", allowing for the creation of more complex games with multiple, differently configured screens. To support this, it employs different concepts than other Uzebox video modes.
Examples for the video mode are found in the repository, at [kernel/videoMode74/examples].
Documentations are provided in the video mode's various components:
- [Developer's manual]
- [videoMode74.s] Core functions and globals
- [videoMode74.def.h] Compile-time configurations (defines)
- [videoMode74_sprite.s] Sprite blitter functions and globals
- [videoMode74_vram.s] Video RAM management functions (such as scrolling)
Basic concepts: Memory allocation
Unlike other modes, this mode has an extensive set of configuration flags. They are documented in the respective source (videoMode74.def.h). To accommodate these flags, the best is to create an include file (as the examples do, in "m74cfg.h"), and force its inclusion by the makefile (adding "-include m74cfg.h" to CFLAGS). This prevents having long command lines, and is a bit cleaner as it is possible to comment the file.
Important things to set up are the start addresses of various memories, such as the tile row descriptor table (M74_ROMTD_OFF) which defines how 8 pixels tall display rows should be handled (for a complete overview, read the M74_Manual.rst file accompanying the mode and check the examples).
Here comes another big difference: with Mode 74, you have to manage the allocation of memories yourself, that is, not by the linker as it is normally done (that is, you just reserve some space by defining variables and arrays and let the linker locate those). This allows for more precise memory management and to overlay different distinct memory configurations for different screens on top of each other.
To do this proper, let's recall how the AVR's RAM memory is normally laid out and managed:
- 0x0000 - 0x00FF: I/O registers
- 0x0100 - 0x????: Linker's allocations (starting at 0x0100, growing upwards)
- 0x???? - 0x????: Unused RAM
- 0x???? - 0x10FF: Stack (starting at 0x10FF, growing downwards)
Basically it is possible to locate things at absolute offsets in the area marked as Unused RAM without problems. Mode 74 by default locates its 256 byte palette buffer at 0x0F00 - 0x0FFF, and offers a 16 color RAM palette at 0x1000 - 0x100F. The sprite engine also locates its workspace above that below the stack which may be fine if there aren't too many sprites.
With this image, usually the best may be locating the 64 RAM tiles at 0x0700 - 0x0EFF (or if less, aligning its end to 0x0EFF), this layout may be observed in the Sprite demo. The VRAM may be located below this area.
Tile rows and VRAM
The next important part is defining the tile rows, that is, what display mode each tile row uses, and where the VRAM for that should be located. Up to 32 tile rows may be defined of which any may be displayed anywhere (split screen; Y scrolling). Tile row 0 is special since it is used for the sprite engine to determine where the tile data is located (so it may compose sprites into RAM tiles). Tile row definitions and VRAM offsets can either sit in RAM or ROM (again check the Sprite demo where they are located in ROM).
To make the sprite engine functional, a rectangular VRAM layout is required (that is a layout which matches that of other video modes). This VRAM layout may also be constant (like other video modes) or dynamic. It can be defined by the usual Uzebox kernel defines to also allow some integration with the kernel's video functions.
The sprite demo
It might be a good idea to start a new game's development from the sprite demo (in the examples directory) as it contains suitable initialization for the most fundamental features a typical game may require. Studying it you can get a glimpse on how Mode 74's data structures interact to make up a screen. The sprite demo has two variants, the second one uses the frame reset concept of Mode 74 (when instead of returning, the video mode upon completing the frame rather resets the user code at a provided address). This feature might be used to gain more RAM (by reusing the main program stack) or more deterministic frame rate by the early termination of time consuming tasks. Mode 74's sprite blitter supports this feature properly.
Some more on sprites
Mode 74's sprite support contrary to the normal kernel doesn't provide "sprites" as such, it rather provides a capability to blit 8x8 transparent sprite tiles on the display (a bit lower level support). You can use this to realize your own high-level sprite support fitting for the game you are designing (see for example Flight of a Dragon. The RAM tile support however is very similar to that of the normal kernel, so it can semi-automatically restore the screen clearing away previously drawn sprites.
So a frame routine normally should restore the screen (M74_VramRestore()), perform any operation it wants to do with the VRAM (such as scrolling with M74_VramMove()), then blit sprites to their new locations (M74_BlitSprite()).