9static __inline__
void Io_Set16(
s32 value,
volatile u16 *reg) { *reg = value; }
12static __inline__
void Io_Put16(
volatile u16 *reg,
s32 value) { *reg = value; }
25#define WORLD_MAP_BG_PALETTE ((s16 *)BG_PLTT)
27#define WORLD_MAP_CELLS ((struct WorldMapCell *)Ram_MapBlocks)
40 u32 *tileOffsets = perspective->
tiles;
52 shownQuarter = &perspective->
quarterTiles[(layer * 2 + y) * 2 + x];
53 if (update == 0 && tile == *shownQuarter)
62 sourceTiles = decodedTile;
63 quarterCells =
Ram_MapBlocks + (((layer * 2 + y) * 32 + x) << 6);
64 for (rowIndex = 0; rowIndex < 16; rowIndex++) {
77 sourceTiles = decodedTile;
78 for (rowIndex = 0; rowIndex < 16; rowIndex++) {
79 for (columnIndex = 0; columnIndex < 16; columnIndex++) {
82 metatileId = *sourceTiles;
85 bottomTiles = (
u16 *)((
u8 *)bottomTiles + metatileId * 4);
86 screenTiles[32] = *bottomTiles;
124 u16 *zoomTransitionFrames;
140 perspective->
viewX = 0;
141 perspective->
viewY = 0;
142 perspective->
scaleX = 0x200000;
143 perspective->
scaleY = 0x400000;
144 perspective->
limitX = 0x1fe00000;
145 perspective->
limitY = 0x1fe00000;
167 perspective->
fade = 0x1f00;
196 cameraPosition = camera->
pos;
197 affinePages = frameWork->
pages;
198 farPlane = 0x1fe0000;
201 *distance = farPlane;
202 perspective->
zoom = 0x10000;
206 *zoomTransitionFrames = 0;
216 yaw = &perspective->
yaw;
218 pitch = &perspective->
pitch;
222 eyeOffset.
z = farPlane;
246 eyeOffset.
z = *distance + 0x10000;
262 for (tileIndex = 255; tileIndex >= 0; tileIndex--)
263 perspective->
tileIds[tileIndex] = tileIndex;
273 s32 *followedPosition;
281 followedPosition = perspective->
origin;
282 if (followedPosition != 0) {
283 originX = *followedPosition++;
284 originY = followedPosition[1];
293 tileId = (y << 4) + x;
294 perspective->
tileIds[(((py / 2) & 15) << 4) + ((px / 2) & 15)] = tileId;
296 if (
ABS(originX - px) <= 1 &&
ABS(originY - py) <= 1) {
326 if (
WORLD_MAP_CELLS[((x / 0x200000) & 31) + (((z / 0x200000) & 31) << 5)]
333 *(
s16 *)buffer = backdropColor;
358 tilePair = 0x01a901a8;
359 for (screenRow = 0; screenRow < 20; screenRow++) {
360 for (screenColumn = 0; screenColumn < 15; screenColumn++) {
361 *screenTiles++ = tilePair;
362 tilePair += 0x00020002;
366 if (graphicsSet == 1) {
367 perspective->
tileIds[10] = 0x10a;
368 perspective->
tileIds[11] = 0x10b;
369 perspective->
tileIds[12] = 0x10c;
370 perspective->
tileIds[26] = 0x11a;
371 perspective->
tileIds[27] = 0x11b;
372 perspective->
tileIds[28] = 0x11c;
396 u32 nextDisplayControl;
404 if (affinePages !=
NULL) {
406 *affineRegisters++ = *affineSource++;
407 *affineRegisters++ = *affineSource++;
408 *affineRegisters++ = *affineSource++;
409 *affineRegisters++ = *affineSource++;
410 *affineRegisters++ = *affineSource++;
411 *affineRegisters++ = *affineSource++;
412 *affineRegisters++ = *affineSource++;
413 *affineRegisters = *affineSource++;
419 (
volatile u32 *)dma0);
430 mode = (bottom != 0) << 1;
437 displayControl |= mode;
438 nextDisplayControl = (
u16)displayControl;
445 u32 metatileIndex = *(
u16 *)cellBytes;
448 metatileTiles += metatileIndex * 2;
449 *(
u16 *)screenTile = *metatileTiles++;
450 *(
u16 *)(screenTile + 64) = *metatileTiles;
469 }
while (cellsCopied <= 31);
479 }
while (cellsCopied <= 31);
497 }
while (cellsCopied <= 63);
512 s32 *cameraPosition = camera->
pos;
513 s32 *followedPosition = perspective->
origin;
520 if (followedPosition !=
NULL) {
526 y = followedPosition[2];
527 x = followedPosition[0];
528 if (perspective->
shakeX != 0) {
533 shakeAmplitude = perspective->
shakeX;
538 if (perspective->
shakeY != 0) {
543 shakeAmplitude = perspective->
shakeY;
550 tileColumn =
x / 0x100000;
551 tileRow =
y / 0x100000;
552 if ((perspective->
viewX ^
x) & 0x100000) {
553 if (perspective->
viewX <
x)
558 if ((perspective->
viewY ^
y) & 0x100000) {
559 if (perspective->
viewY <
y)
575 SET_VECTOR(cameraPosition, *followedPosition++, 0, followedPosition[1]);
582 eyeOffset.
z = height + 0x10000;
598 camera, cameraPosition, frameWork->
scanlines,
609 s32 firstQuarterX = 0;
610 s32 firstQuarterY = 0;
618 s32 *followedPosition = perspective->
origin;
620 firstQuarterX = *followedPosition++;
621 firstQuarterY = followedPosition[1];
625 firstQuarterX = (firstQuarterX - 0x1000000) >> 25;
626 firstQuarterY = (firstQuarterY - 0x1400000) >> 25;
629 for (; layer < 2; layer++) {
630 for (row = 0; row < 2; row++) {
631 for (col = 0; col < 2; col++) {
633 (((firstQuarterY + row) & 15) << 4) + ((firstQuarterX + col) & 15);
634 tileId = perspective->
tileIds[tileId];
635 tileId += layerTileBase;
640 layerTileBase += 320;
650 s32 firstQuarterX = 0;
651 s32 firstQuarterY = 0;
658 s32 *followedPosition = perspective->
origin;
660 firstQuarterX = *followedPosition++;
661 firstQuarterY = followedPosition[1];
663 firstQuarterX = (firstQuarterX - 0x1000000) >> 25;
664 firstQuarterY = (firstQuarterY - 0x1400000) >> 25;
665 for (layer = 0; layer < 2; layer++) {
666 for (row = 0; row < 2; row++) {
667 for (col = 0; col < 2; col++) {
669 (((firstQuarterY + row) & 15) << 4) + ((firstQuarterX + col) & 15);
670 tileId = perspective->
tileIds[tileId];
671 tileId += layer * 320;
673 firstQuarterY + row, tileId, 0) != 0)
739 u32 *graphicsResources;
745 graphicsResources = perspective->
resources;
749 *(
s16 *)decodeBuffer = backdropColor;
793#undef WORLD_MAP_BG_PALETTE
794#undef WORLD_MAP_CELLS
#define Dma_Fill32Cell(cell, value, destination, size)
Dma_Fill32 through the caller's own volatile word cell, so a function that fills several blocks keeps...
static __inline__ void Dma_Set(const volatile void *source, volatile void *destination, u32 control, volatile u32 *channel)
Starts a DMA transfer: stores the source, destination and control words into channel's registers with...
#define Dma_Fill32(value, destination, size)
Fills size bytes at destination with the word value by DMA3.
void Fade_FromBlack(s32 frames)
Fades in from black.
void TileMap_DrawRowsFromRam(const struct MapAffinePair *lines, u8 *pixels)
Draws the current affine page into the world map's still-view pixels.
void WorldMap_BuildScanlineTable(s32 pitchSlope, s32 *position, struct MapScanline *scanline)
Rebuilds the ground plane's scanline terms when the world map pitch changes.
void Map_ShowBg1FromBuffer(void)
VBlank: shows BG1 and copies the area's tiles back into VRAM.
static __inline__ void Io_Set16(s32 value, volatile u16 *reg)
Writes a halfword register (value first).
void Map_RenderPaletteMappedColumn(u32 tileColumn)
Draws world map tileColumn into the BG map: 64 cells down.
s32 Map_InitializePerspectiveScene(void)
Sets up the world map's perspective view: BG2 and BG3 in affine mode, the camera work,...
void WorldMap_UpdateView(void)
Each frame on the world map: loads tiles as the view moves, shakes and follows the player,...
void Map_LoadAreaGraphics(void)
Reloads the world map area's palette and tiles after the still view, puts the default cells back and ...
void Map_SetWindowCellTile(s32 x, s32 y, s32 px, s32 py)
Puts world map tile (x / 16, y / 16) at cell (px / 16, py / 16) of the tile id grid,...
static __inline__ void Io_Put16(volatile u16 *reg, s32 value)
Writes a halfword register (register first).
#define WORLD_MAP_BG_PALETTE
void MapAnimation_ApplyAffineFrame(void)
HBlank setup each frame on the world map: copies the first scanline's BG2 and BG3 affine parameters,...
s32(*) WorldMapPlaneFn(void *camera, s32 *position, void *lines, void *out)
void Map_UpdateCurrentTileBlock(void)
Loads and draws the 2x2 world map tiles around the player in both layers.
void MapAnimation_PresentFrame(void)
VBlank: shows BG1 and copies the decoded frame's tiles into VRAM.
void Map_RenderPaletteMappedRow(u32 tileRow)
Draws world map tileRow into the BG map: 32 cells, then 32 more a screen block on.
static __inline__ void WorldMap_CopyCellTiles(u8 *cellBytes, u8 *screenTile)
Copies one world map cell's two tile entries (top and bottom) to a BG map.
void WorldMap_BeginStillView(void)
Freezes the world map's perspective view as a still picture on BG1: saves BG1's tiles,...
void Map_LoadDefaultCellsAndUpdateBlock(void)
Puts the default world map cells back after the still view and returns to the perspective view,...
void WorldMap_LoadGraphics(s32 x, s32 z)
Loads the world map's palette and tiles for the area at (x, z): the second set where the ground there...
s32 Map_WriteLayerCellTile(s32 layer, s32 x, s32 y, s32 tile, s32 update)
Loads world map tile tile into quarter (x & 1, y & 1) of a layer's block buffer, decompressing it fro...
void Map_PreloadCurrentTileBlock(void)
Loads the first of the 2x2 world map tiles around the player that is not shown yet (at most one a fra...
u8 Transform_UpdateVerticesSize
What every part of the field object shares: its includes and the few names more than one part uses.
void WaitFrames(s32 frames)
The game's frame loop: runs frames frames and returns.
void(*) gVBlankHook(void)
Run once by the next VBlank handler, which clears it first.
volatile u32 gFrameCount
Frames WaitFrames has finished.
struct EffectStep gMapCellBuffer[]
Map cells; battle effects reuse this as a particle array.
void * MemAlloc(s32 size)
Allocates size bytes (rounded up to words) with no slot, from IWRAM when they fit and EWRAM otherwise...
void * Runtime_AllocateBlock(s32 kind, s32 size)
As Runtime_AllocateHeapBlock, but tries EWRAM first, for blocks that need room more than speed: the b...
void * Runtime_AllocateHeapBlock(s32 kind, s32 size)
Returns heap slot kind's block, first allocating size bytes for it (rounded up to words),...
#define WORK_SLOT(n)
Reads slots through their own addresses; adjacent slots are reached by offsets.
#define BGCNT_CHAR_BASE(block)
#define BGCNT_PRIORITY(n)
#define BG_SCREEN_BLOCK(n)
#define DMA_START_TIMING_DRQ_REPEAT
A DMA control's start timing (bits 12 and 13), cartridge request (bit 11) and repeat (bit 9): the bit...
#define BGCNT_SIZE(n)
The background's size: for an affine one, 0 to 3 are 128, 256, 512 and 1024 pixels square.
@ DISPCNT_MODE_2
BG2 and BG3 affine.
#define BLDCNT_EFFECT_LIGHTEN
towards white by REG_BLDY
#define BLEND_ALPHA(top, bottom)
A REG_BLDALPHA value: top and bottom are the two targets' weights, out of 16.
#define BGCNT_SCREEN_BASE(block)
#define BGCNT_WRAP
Affine backgrounds only: wrap around instead of showing the backdrop.
#define Io_Write16(v, reg)
Writes a value to a 16-bit register or memory location.
static s32 Iwram_RatioMulQ14(s32 divisor, s32 value)
All calls go through this layer.
#define Iwram_MulQ16(left, right)
static s32 Iwram_TransformVector(const void *vector, s32 *result)
#define ABS(v)
The magnitude of v. v is read twice.
#define SET_VECTOR(v, x, y, z)
Sets the x, y and z of a three-part vector: a position about to be projected, a per-frame step,...
void MapAnimation_Update(void)
Each frame: runs the 16 tile animation channels.
void MapAnimation_StartChannels(const u16 *script)
Starts the tile animation channels a map's animation script lists: each 0xfdNN marker starts channel ...
u32 Random16(void)
Advances the game's random number generator (the C library's classic linear congruential one),...
void Runtime_ReleaseHeapBlock(s32 slot)
void MemFree(void *buffer)
struct Projection gProjection
#define Ram_MapCellBuffer
#define RamCode_LoadSlot(slot, code, bytes)
Allocates a work-slot copy; release it with Runtime_ReleaseHeapBlock.
char ResourceId_DefaultMetatileAttributes
char ResourceId_DefaultMapAnimation
char ResourceId_PerspectiveDataA
char ResourceId_DefaultMapCells
s32 Resource_DecodeType01(const void *source, void *destination)
Decodes a type-01 resource and returns its unpacked byte count.
s32 Resource_DecodeByteLz(const void *source, void *destination)
Decodes a byte-oriented LZ resource and returns its unpacked byte count.
s32 Scheduler_ResumeTasks(SchedulerCallback callback)
Resumes the task running callback, or every task when callback is null, by clearing bit 0 of its orde...
s32 Scheduler_AddOrUpdateCallback(SchedulerCallback callback, s32 order)
Schedules callback with order, or gives a task already running it the new order, and re-sorts the tab...
s32 Scheduler_SuspendTasks(SchedulerCallback callback)
Suspends the task running callback, or every task when callback is null, by setting bit 0 of its orde...
The battle camera: its eye, the focus it turns about, and its pitch, yaw and distance.
s32 * followPos
when set, the focus followed instead of pos
s32 pos[3]
the focus, 16.16 fixed-point pixels
s32 eye[3]
The eye, 16.16 fixed-point pixels: written each frame distance behind the focus along the turned view...
s32 unk18
cleared beside followPos; not read by name in TBS
A position in three coordinates, each in 16.16 fixed point.
One screen line's affine parameters for BG2 and BG3.
The world map's frame work in heap slot 7: the scanline terms and two pages of per-line affine parame...
struct MapScanline scanlines[160]
struct MapAffinePair pages[2][160]
The world map's perspective view: the followed position, screen shake, view position,...
s32 scaleX
0x200000 at load
u16 quarterTiles[8]
The tile each quarter of each layer's block buffer shows, so an unchanged quarter is not decoded agai...
s32 farPlane
0x1fe0000 at load
u16 windowPending
cleared by the frame update; not set by name
u32 * resources
a row of gWorldMap_GraphicsResources, by terrain
s8 animationActive
Set by WorldMap_BeginStillView while BG1 shows the drawn map; the tile animations are then neither su...
s32 limitY
0x1fe00000 at load
s32 zoom
16.16 fixed point, 0x10000 full size
s32 limitX
0x1fe00000 at load
u16 shownTop
windowTop as the frame update last applied it
s32 viewY
16.16 fixed-point pixels
u16 tileIds[256]
the world map tile in each of 16 by 16 cells
u8 fadeStep
MapScrollWork's wideTiles, 0x80 at load.
u16 windowTop
Screen rows, 0 and 159 at load and 200 and 255 from WorldMap_BeginStillView; each frame copies them t...
s32 scaleY
0x400000 at load
u16 shownBottom
windowBottom as the frame update last applied it
void * tiles
The world map's tile offsets (ResourceId_PerspectiveDataA), each tile LZ-compressed.
u16 fade
MapScrollWork's flags: REG_DISPCNT bits, 0x1f00 at load.
s32 * origin
the followed point, as in MapScrollWork
s32 shakeDecay
the screen shake, as in MapScrollWork
u16 zoomTransitionFrames
a zoom transition's length; 0 when none
s32 viewX
16.16 fixed-point pixels
s32 distance
farPlane scaled by the zoom
One 32-pixel cell of the world map: its tile, its kind (21 selects the second graphics set) and a fla...
void * Resource_GetTableEntry(s32 index)
Returns the ROM address of resource index from the resource directory.
void Transform_UpdateVertices(struct Position *eye, struct Position *target, struct ScanVertex *line, struct BgAffine *affine)
Builds the world map's per-scanline affine table for one frame: the ground plane seen from eye toward...
u32 gWorldMap_GraphicsResources[2][6]
Each set is a palette and five tile sets; WorldMap_LoadGraphics takes the second set when the cell it...