Overview
This web page describes the high-stage workings of Hyperlink’s Awakening game engine. It explains how the engine is structured, how the quite a lot of subsystems are made, and the arrangement in which the programming decisions impact the game draw itself.
(N.B.: for low-stage particulars or hacking notes, use extra detailed documentations, admire the Maps knowledge layout documentation.)
Summary
1. High-stage structure
Rendering on the Game Boy is difficult. It has no double-buffering, and the PPU (the graphics processor) can only be accessed precise by the short duration of time between two frames: the V-blank interval.
So the same outdated rendering setup is to pre-compute every physique whereas the outdated one is being drawn by the PPU – after which, when the short V-blank interval occurs, to replica all pre-computed sources and values to the now-unlocked VRAM on the PPU.
Right here is why Hyperlink’s Awakening engine has two major programs that impact these responsibilities: the Render loop and the V-blank interrupt handler.
The render loop
The major render loop is the part of code accountable for handling all the game good judgment. It runs whereas the PPU is rendering a physique (all by which entry to VRAM is locked). It’s accountable for:
- Reading joypad inputs,
- Executing the gameplay code,
- Configuring the audio output,
- Configuring the rendering of particular effects using H-blank manipulation.
The major render loop can also add incandescent chunks of graphics to VRAM, by temporarily disabling the LCD cloak (leer the “Graphics” allotment below).
On the live of the loop, it waits for V-Clean, then starts rendering a brand contemporary physique.
Glimpse https://kemenaran.winosx.com/posts/hyperlinks-awakening-render-loop/
The V-blank interrupt handler
The V-blank interrupt handler is a smaller part of code, called by the CPU as soon because the PPU enters the V-blank duration. One day of this short time, it will:
- Copy a exiguous quantity of tiles to VRAM,
- Replace interesting tiles,
- Replace the tiles representing Hyperlink’s sprite (searching on its animation express),
- Copy the palettes buffer to VRAM,
- Copy the sprites attributes buffer to the OAM memory in VRAM.
It’s some distance also accountable for handling some animations precise by the photos cutscenes.
2. Graphics
As we observed above, graphics can only be uploaded to VRAM precise by the V-blank interval, or whereas the LCD cloak is off. Right here is why the gameplay code by no strategy replica graphics straight away to VRAM: it as an different sets flags to divulge the engine which graphics wants to be uploaded at the next iteration of the render loop.
Hyperlink’s Awakening engine affords just a few assorted products and providers for this.
The gameplay code can location flag to request these sources to be loaded precise by the V-blank interval between two frames:
- Importing a brand contemporary objects tilesheet,
- Importing a brand contemporary entity spritesheet,
- Importing coloration palettes (CGB only).
However some graphics sources are rather incandescent, and importing them only using the few cycles accessible precise by the V-blank interval would take quite a lot of frames.
Right here is why the gameplay code can also request graphic sources to be loaded without warning, whereas the rendering is disabled. For this, the LCD cloak is shut down (which shows a white cloak, and unlocks VRAM), then graphics can also be copied to VRAM using an arbitrary duration of time. On the live of the replica, the cloak is enabled but again. This leads to a white cloak being displayed precise by the add, however it’s some distance some distance faster than using the V-blank time interval alone.
This strategy can also be utilized by the gameplay code to:
- Add a incandescent tileset,
- Add a incandescent tilemap (and, on GBC, the connected tilemap attributes).
2.1 Updating Objects tilesheets (precise by V-blank)
Rooms are displayed by composing two high-stage primitives: objects and entities. The objects are the static 16×16 blocks that produce the room development; they’re displayed using the Game Boy Background arrangement. Entities are the dynamic actors of the room (NPCs, enemies, and a entire lot of others); they’re displayed using sprites.
Objects in the overworld rooms are rendered using two sorts of tiles:
- A conventional location of overworld tiles shared between all overworld rooms;
- A location of tiles particular to the most contemporary allotment on the overworld.
So precise by a transition from a room to 1 more, the gameplay code can to request the tilesheet for the contemporary room to be loaded precise by the next V-blank duration.
Overworld rooms are grouped in 2×2 sections (i.e. 4 rooms). Every allotment has a tileset ID. When a room is transitioned to, sooner than starting the transition, the game checks if the tileset of the contemporary room is assorted from the most contemporary one, and if that is the case write to hNeedsUpdatingBGTiles
to request the 32 particular tiles for this allotment to be uploaded to VRAM precise by the next V-blank duration.
To steer determined of system defects precise by the transition, there is a assorted “Defend Contemporary” tileset, which instructs the engine no longer to trade the tileset, whichever it’s some distance. The area arrangement is constructed in direct that quite a lot of the time, the participant consistently walks by a “Defend Contemporary” allotment between two assorted sections, which avoids transition system defects. Glimpse “The hidden development of Hyperlink’s Awakening Overworld arrangement”
2.2 Updating entity spritesheets (precise by V-blank)
Entities are the dynamic actors in the game, in overall displayed using sprites.
At a given moment, 4 spritesheets of 16 tiles every are reserved for entity sprites. The gameplay code can write to hNeedsUpdatingEntityTilesA
or hNeedsUpdatingEntityTilesB
to request a spritesheet to be loaded.
One day of the following V-Clean classes, when the VRAM is unlocked, the interrupt code reads that request, and copies 4 tiles from the spritesheet to the requested situation. Solely 4 tiles are copied for the explanation that V-Clean duration is rather short; which strategy loading a full spritesheet spans in some unspecified time in the future of several frames.
2.3 Importing a coloration palette (precise by V-blank)
TODO: document utilization of wBGPal1
2.4 Importing a incandescent tileset (cloak off)
TODO: document utilization of wTilesetToLoad
2.5 Importing a incandescent tilemap and tilemap attributes (cloak off)
TODO: document utilization of wBGMapToLoad
2.6 Sharp tiles
TODO
3. Rooms
The major gameplay takes express in non-scrollable cloak-broad rooms. These rooms can also be out of doors (on the Overworld) or indoor (internal homes, dungeons, and a entire lot of others.)
Room groups
The game rooms are split into 3 room groups, of 256 rooms every (plus a assorted neighborhood):
- Rooms neighborhood 1: contains all the 256 Overworld rooms;
- Rooms neighborhood 2: contains rooms for dungeons 1 to 6, plus some caves;
- Rooms neighborhood 3: contains rooms for dungeons 7 and 8, and the closing of caves, homes, and a entire lot of others.;
- Special neighborhood: contains rooms for the coloration dungeon.
So a particular room can also be identified using its room neighborhood (1-3) and its room identification on this neighborhood (0-256).
The three room groups, and their respective rooms. The Color Dungeon particular neighborhood is rarely any longer represented right here. Credit ranking: Saver
Maps and layouts
TODO: maps
On the Overworld, rooms are kept as they’re laid out precise by the game, on a 16×16 grid of rooms.
However indoors, for residence effectivity, rooms are no longer kept consistently. As an instance, when intelligent by the suitable door of a dungeon room (e.g. room 0x34), the contemporary room might per chance per chance per chance be no longer the next room in the rooms neighborhood (that might per chance per chance be room 0x35).
To know which rooms are North, South, East and West of a given room, the game makes use of layouts. These stare admire the dungeons maps, however retailer the ids of every of the dungeons room as they’re arranged geographically.
The arrangement layout for the first dungeon.
Room development
A room is outlined by:
- The bottom object it makes use of;
- The interesting tiles it makes use of;
- A checklist of static objects in the room (partitions, trees, and a entire lot of others);
- The dynamic entities in the room (NPCs, enemies, and a entire lot of others.).
To load a given room, the game constructs an in-memory arrangement of the room objects. For this, the game:
- Reads the room ground object, and own the entire objects arrangement with it;
- For every object in the objects checklist:
- Be taught the object divulge (which object, the build, spanning what number of slots, vertical or horizontal);
- Write the objects to the arrangement.
3.1 Exhibiting a room straight away
After deciding on a spot file, when entering a door, or when warping to a brand contemporary situation, the game loads a brand contemporary room in a single skedaddle.
The Overworld gameplay handler is accountable for this: it will load a room’s knowledge without warning.
However this takes strategy beyond regular time than a single physique. To steer determined of blocking the major loop for a truly very lengthy time, which might per chance well cease the engine from processing audio, events, and a entire lot of others., the loading is split into several loading stages. When a room is loaded, the Overworld gameplay handler will enact indubitably this kind of stages, then be aware the stage as performed and return to the major loop. The subsequent iteration of the loop will then dispatch to the next loading stage. Every stage will maintain to unruffled then take no beyond regular time than a physique.
The loading stages are:
- Decode the room object arrangement to memory, and instanciate the room entities.
- Search for the room tileset to use, and request it to be copied to the VRAM. _(The replica will likely be requested using
hTilesetToLoad
, which is able to shut the console cloak off to unlock VRAM and impact the replica faster).
Once all the stages are done, it then transition to the 8 stage, which is the interactive gameplay.
3.2 Transitioning between rooms
Transitioning smoothly between rooms, using the translation animation considered in the game, is rather extra advanced.
Right here is for 2 causes:
- Because the transition is accurate, the game must render consistently: it will’t shut the cloak off to replica contemporary knowledge faster.
- One day of the transition, both the extinct and contemporary room will likely be visible. So graphics for both rooms wants to be accessible at the same time.
To enact this, the game will impact roughly the same steps, however with particular care to maintain all of them precise by the physique funds.
TODO: accurate loading steps
4. Entities
Entities are the dynamic actors show precise by the major gameplay (NPCs, enemies, and a entire lot of others); they’re displayed using sprites.
4.1 Loading entity graphics
Entities are displayed on cloak using sprites. On the Game Boy, sprites can also be either a single tile (8×8 px) or two tiles stacked vertically (8×16 px). And in overall, entities are silent of several sprites stitched together.
So for an entity to be displayed on-cloak, its tiles will maintain to unruffled be copied to VRAM, after which the tiles indices wants to be referenced properly (in overall searching on the entity build: dealing with frontward, backwards, left or appropriate).
As we observed above, at any point in the major gameplay, there are 4 slots accessible in VRAM, the same to 4 entity spritesheets. Every spritesheet has 16 tiles. A spritesheet might per chance per chance possess tiles for a single entity (admire a Moblin), for several entities (admire Keeses and Beetles, both on the same spritesheet), or for only phase of an entity (admire the Bottle Grotto genie, which makes use of 2 spritesheets, or the Angler Fish, which makes use of all 4).
Every room defines which spritesheets wants to be loaded for its entities to be displayed. For this, every room defines four connected spritesheet-ids. When transitioning from a room to 1 more, the game engine compares the spritesheets in the intervening time loaded in VRAM with the spritesheets requested by the contemporary room, and marks the non-loaded-but ones as wanting to be copied to VRAM (leer 2.2 Updating entity spritesheets (precise by V-blank)).
The fours spritesheets for room 07 on the Overworld.
Sequence of spritesheets accessible
One day of a scrolling transition from one room to 1 more, the spritesheets for both the extinct and the contemporary rooms will maintain to unruffled be accessible (in any other case entities from the extinct room would stare corrupted precise by the transition). So a room can only load two contemporary spritesheets: the opposite twos, utilized by the entities of the outdated room, must remain accessible.
This limitation would not be aware when warping straight away to a brand contemporary room, with out a scrolling transition (to illustrate when intelligent by stairs, or from the overworld to indoor rooms). If that is so, all four spritesheets are loaded straight away. Some incandescent entities are namely placed in rooms accessible only by warps, so they’ll use all four spritesheets (to illustrate Spoiled Eagle or Manbo the Sunfish).
Moreover, on the overworld, the first spritesheet is consistently overwritten with the sprites of the NPC following the participant (Bow-Wow, Marin, ghost, and a entire lot of others.). Inside dungeons and homes, even when, the first spritesheet can also be used to negate extra enemies.
Mapping an entity to tiles
Interestingly, there’s no dynamic allocation of sprite slots. For a given room, the spritesheets will consistently be loaded in the same slots. Numerous the entities require a particular slot to be used: to illustrate, Octorocks are anticipated to maintain their spritesheet loaded in slot 2, as well as Moblins. Which also strategy that Octorocks and Moblin can’t be displayed in the same room (because they both query the same spritesheet to be used).
(Some entities use assorted spriteslots searching on the room they’re in, however that’s an exception.)
Meaning the entity-to-sprite mapping is a easy array of tiles indices, difficult-coded searching on the anticipated spriteslot.
As an instance, shall we embrace the tiles for a front-dealing with Moblin are the tiles n° 2, 3, 4 and 5 in its spritesheet. We’re using 8x16px tiles, so referencing tiles 2 and 4 will likely be ample. As rooms load the Moblin spritesheet in slot 2, for our two sprites to reference these tiles, we will write one thing admire:
MoblinFrontFacingSprites:
db ($20 x 2) 2
db ($20 x 2) 4
Color dungeon particular cases
TODO
5. Audio
TODO
6. Color conversion
TODO
Coloring room objects require two extra pieces of info: tile attributes and coloration palettes.
6.1 Coloring Background objects
A tile attribute defines which palette is utilized to this tile. As an object is 2×2 tiles, every object wants 4 tile attributes.
Unlike the object-to-tilemap mapping, which is the same for all rooms of a arrangement neighborhood, the object-to-tile-attributes mapping is room-particular. This permits the game engine to, to illustrate, coloration the rocks of a undeniable room using the BG0
palette – however in a single extra space, to use the BG2
palette for these same rocks.
To use less residence, object-to-tile-attributes mappings are factored into groups, which will likely be utilized by several assorted rooms. Meaning that discovering the neutral tile attributes for an object is done with the following steps:
- Rep the arrangement neighborhood and room identification,
- Rating the pointer to the tile attributes mapping,
- Rep the object identification,
- Rating the tile attributes (4 bytes) in the mapping for this object identification,
- Copy the tile attributes to the BG VRAM.
6.2 Coloring sprites
6.3 Loading palettes
Which palette is used for a room is outlined by an index at 21: 42EF
(one byte per room) which is then used to index an table at 21: 402B
to receive the pointer to the actual palette in financial institution $21
.