17 remaining = byteCount - 1;
18 if (remaining != -1) {
21 *cursor = remapTable[*cursor];
23 }
while (remaining != -1);
40 u16 *destinationWords;
47 wordCount = (size - 1) / 2;
51 for (i = 0; i < wordCount; i++)
52 *destinationWords++ = *sourceWords++;
57 u8 *lowBytes = highBytes + wordCount;
59 for (i = 0; i < wordCount; i++) {
60 u32 decodedWord = ((*highBytes++ << 8) | *lowBytes++) ^ previousWord;
61 *destinationWords++ = decodedWord;
62 previousWord = decodedWord;
69 for (i = 0; i < wordCount; i++) {
70 s32 decodedWord = *sourceWords++ ^ previousWord;
71 *destinationWords++ = decodedWord;
72 previousWord = decodedWord;
86 u32 remaining = 128 << 7;
88 s32 nextPlaceholderBlock = -1;
92 u32 blockId = value & mask;
94 if (blockId == mask) {
95 if (nextPlaceholderBlock != blockId) {
96 nextPlaceholderBlock++;
98 value = value + nextPlaceholderBlock - blockId;
102 }
while (remaining != 0);
128 u32 screenColumnOffset,
132 u32 index = ((*cell << 20) >> 18) + tileHalf;
135 metatileEntry += index;
137 screenMap + (screenRowOffset + screenColumnOffset + tileHalf) * 2;
138 *(
u16 *)screenTile = *metatileEntry;
140 metatileEntry += index;
141 *(
u16 *)(screenTile + 64) = *metatileEntry;
148 u32 screenColumnOffset) {
151 u32 index = (*cell << 20) >> 19;
154 metatileRows += index;
155 screenTile = screenMap + screenRowOffset * 2 + screenColumnOffset * 2;
156 *(
u32 *)screenTile = *metatileRows;
158 metatileRows += index;
159 *(
u32 *)(screenTile + 64) = *metatileRows;
236 encodedData = (
u8 *)sceneHeader + sceneHeader->
tiles;
239 encodedData = (
u8 *)sceneHeader + sceneHeader->
collision;
241 encodedData = (
u8 *)sceneHeader + sceneHeader->
tilemap;
247 encodedData = (
u8 *)sceneHeader + sceneHeader->
animation;
251 if (sceneHeader->
blend != 0) {
252 encodedData = (
u8 *)sceneHeader + sceneHeader->
blend;
265 viewX = &work->
viewX;
267 viewY = &work->
viewY;
273 layerSource = sceneHeader->
layers;
274 for (layerIndex = 0; layerIndex < 3; layerIndex++) {
275 u32 x = layerSource->
x;
276 u32 y = layerSource->
y;
282 mapLayer->
offsetX = baseX = x << 19;
283 mapLayer->
offsetY = baseY = y << 19;
285 scrollX = layerSource->
scrollX * 4096;
286 scrollY = layerSource->
scrollY * 4096;
287 mapLayer->
scaleX = scrollX;
288 mapLayer->
scaleY = scrollY;
333 if (graphicsBuffer !=
NULL) {
340 *(
s16 *)graphicsBuffer = backdrop;
392 s32 *followedPosition;
394 followedPosition = work->
origin;
398 if (followedPosition !=
NULL) {
399 x = *followedPosition++;
400 height = *followedPosition++;
401 depth = *followedPosition;
413 u32 sourceRow = ((tileY / 2) & 0x7F) << 7;
414 u32 screenRowOffset = (tileY & 30) << 5;
415 u32 sourceColumn = (tileX / 2) & 0x7F;
416 u32 screenColumnOffset = tileX & 30;
419 for (metatileIndex = 0; metatileIndex <= 15; metatileIndex++) {
423 u32 metatileWordOffset;
425 sourceCell += sourceRow + sourceColumn;
426 metatileWordOffset = (*sourceCell << 20) >> 19;
428 metatileRows += metatileWordOffset;
429 screenTile = screenMap + (screenRowOffset + screenColumnOffset) * 2;
430 *(
u32 *)screenTile = *metatileRows;
432 metatileRows += metatileWordOffset;
433 *(
u32 *)(screenTile + 64) = *metatileRows;
434 sourceColumn = (sourceColumn + 1) & 0x7F;
435 screenColumnOffset = (screenColumnOffset + 2) & 30;
445 u32 sourceRow = ((tileY / 2) & 0x7F) << 7;
446 u32 screenRowOffset = (tileY & 30) << 5;
447 u32 sourceColumn = (tileX / 2) & 0x7F;
448 u32 screenColumnOffset = tileX & 30;
449 u32 tileHalf = tileX & 1;
452 for (metatileIndex = 0; metatileIndex <= 10; metatileIndex++) {
455 sourceCell += sourceRow + sourceColumn;
457 screenColumnOffset, tileHalf);
459 sourceRow = (sourceRow + 128) & 0x3F80;
460 screenRowOffset = (screenRowOffset + 64) & 0x3C0;
479 s32 minX, minY, maxX, maxY;
492 s32 height = *origin++;
506 CLAMP(baseX, minX, maxX);
507 CLAMP(baseY, minY, maxY);
516 baseX +=
Iwram_MulQ16(shakeAmplitude, shakeRollA - shakeRollB);
523 baseY +=
Iwram_MulQ16(shakeAmplitude, shakeRollA - shakeRollB);
528 for (layerIndex = 0; layerIndex < 3; layerIndex++, layer++) {
535 baseX = (baseX + layer->
phaseX) & ((layer->
maskX << 19) | 0x7ffff);
539 baseY = (baseY + layer->
phaseY) & ((layer->
maskY << 19) | 0x7ffff);
548 if ((layer->
x ^ baseX) & 0x80000) {
549 if (layer->
x < baseX)
554 if ((layer->
y ^ baseY) & 0x100000) {
555 if (layer->
y < baseY)
585 for (layerIndex = 0; layerIndex < 3; layerIndex++) {
586 if (work->
enabled[layerIndex]) {
588 u32 sourceRow, sourceColumn, screenRowOffset, screenColumnOffset,
589 metatileRow, metatileColumn;
612 sourceRow = ((
y / 2) & 127) << 7;
613 screenRowOffset = (
y & 30) << 5;
614 for (metatileRow = 0; metatileRow < rows / 2; metatileRow++) {
615 sourceColumn = (
x / 2) & 127;
616 screenColumnOffset =
x & 30;
617 for (metatileColumn = 0; metatileColumn <= 15; metatileColumn++) {
619 map += sourceRow + sourceColumn;
622 sourceColumn = (sourceColumn + 1) & 127;
623 screenColumnOffset = (screenColumnOffset + 2) & 30;
625 sourceRow = (sourceRow + 128) & 0x3f80;
626 screenRowOffset = (screenRowOffset + 64) & 0x3c0;
654 struct MapTilePos *visibleLayer = visibleLayers;
659 for (i = 2; i >= 0; i--) {
660 visibleLayer->
x = layer->
x >> 20;
661 visibleLayer->
y = layer->
y >> 20;
665 for (
y = dstY;
y < dstY + height;
y++) {
666 for (
x = dstX;
x < dstX + width;
x++) {
667 u32 sourceCell = *sourceCells++;
668 u32 metatileId = sourceCell & 0xfff;
678 tmp9 = *destinationCells;
679 tmp3 = tmp9 & -0x1000;
681 destinationCells[0] = metatileId | tmp3;
687 visibleLayer = visibleLayers;
700 if (visibleLayer->
x <= (
s32)
x && 16 + visibleLayer->
x > (
s32)
x &&
701 visibleLayer->
y <= (
s32)
y && visibleLayer->
y + 12 > (
s32)
y) {
702 u32 screenAddress, metatileAddress;
703 u8 *screenTile, *metatileRows;
705 screenAddress = 0x06002800;
706 screenTile = (
u8 *)screenAddress;
707 screenTile += offset;
708 tmp11 = metatileId * 8;
710 metatileRows = (
u8 *)metatileAddress;
711 metatileRows += tmp11;
712 *(
u32 *)screenTile = *(
u32 *)metatileRows;
715 metatileRows = (
u8 *)metatileAddress;
716 metatileRows += tmp11;
717 screenAddress = 0x06002840;
718 screenTile = (
u8 *)screenAddress;
719 screenTile += offset;
720 *(
u32 *)screenTile = *(
u32 *)metatileRows;
727 sourceCells += 128 - width;
728 destinationCells += 128 - width;
737} __attribute__((packed, aligned(2)));
752 u32 endMarker = 0xffff;
753 u32 firstSourceCopy = sourceX;
759 sourceX ^= firstSourceCopy;
760 sourceX ^= firstSourceCopy;
762 if (firstSourceCopy != endMarker) {
763 u32 endMarkerCopy = endMarker;
764 s16 *rectangleArgs = (
s16 *)(sequence + 1);
767 s32 sourceY = rectangleArgs[0];
777 sourceX = copyCommand->
source;
779 u32 nextSourceCopy = sourceX;
784 __asm__(
"" :
"+r"(nextSourceCopy));
785 if (nextSourceCopy == endMarkerCopy)
794#define MAP_CELLS ((u32 *)gMapCellBuffer)
795#define MAP_CELL_TILE_MASK 0x00000fff
796#define MAP_CELL_ATTRIBUTE_MASK 0xfffff000
811 struct MapTilePos *visibleLayer = visibleLayers;
819 tmp5 = layer->
x >> 20;
820 visibleLayer->
x = tmp5;
822 visibleLayer->
y = tmp5 >> 20;
827 if (
y < dstY + height) {
829 for (
x = dstX;
x < dstX + width;
x++) {
830 u32 sourceCell = *sourceCells++;
841 destinationCells[0] = sourceCell;
842 metatileId = sourceCell & 0xfff;
845 destinationCells += 1;
848 visibleLayer = visibleLayers;
858 for (; i < 3; i += 1) {
859 if (visibleLayer->
x <=
x && 16 + (*visibleLayer).x >
x &&
860 visibleLayer->
y <=
y && visibleLayer->
y + 12 >
y) {
873 u32 bytes = metatileId * 8;
877 metatileId = bytes / 8;
879 tmp8 = 0x06002800 + offset;
884 metatileRows = (
u32 *)((
u8 *)metatileRows + bytes);
885 tmp16 = *metatileRows;
887 tmp17 = 0x06002840 + offset;
892 metatileRows = (
u32 *)((
u8 *)metatileRows + bytes);
895 tmp17 = metatileRows[0];
911 sourceCells += (128 - width);
912 destinationCells = 128 - width + destinationCells;
914 }
while (
y < dstY + height);
926 u32 *sourceCells = destinationCells;
930 destinationCells += (dstY << 7) + dstX;
931 sourceCells += (srcY << 7) + srcX;
933 for (rowIndex = 0; rowIndex < height; rowIndex++) {
934 u32 *destinationCell = destinationCells + (rowIndex << 7);
935 u32 *sourceCell = sourceCells + (rowIndex << 7);
937 for (columnIndex = 0; columnIndex < width; columnIndex++) {
961 struct MapTilePos *visibleLayer = visibleLayers;
969 tmp5 = layer->
x >> 20;
970 visibleLayer->
x = tmp5;
972 visibleLayer->
y = tmp5 >> 20;
978 if (
y < dstY + height) {
980 for (
x = dstX;
x < dstX + width;
x++) {
981 u32 sourceCell = *sourceCells++;
991 destinationCells[0] =
995 destinationCells += 1;
999 visibleLayer = visibleLayers;
1008 for (; i < 3; i += 1) {
1009 if (visibleLayer->
x <=
x && 16 + (*visibleLayer).x >
x &&
1010 visibleLayer->
y <=
y && visibleLayer->
y + 12 >
y) {
1013 u32 screenAddress, metatileAddress;
1014 u8 *screenTile, *metatileRows;
1016 screenAddress = 0x06002800;
1017 screenTile = (
u8 *)screenAddress;
1018 screenTile += offset;
1019 tmp13 = metatileId * 8;
1021 metatileRows = (
u8 *)metatileAddress;
1022 metatileRows += tmp13;
1023 *(
u32 *)screenTile = *(
u32 *)metatileRows;
1026 metatileRows = (
u8 *)metatileAddress;
1027 metatileRows += tmp13;
1028 screenAddress = 0x06002840;
1029 screenTile = (
u8 *)screenAddress;
1030 screenTile += offset;
1031 *(
u32 *)screenTile = *(
u32 *)metatileRows;
1039 sourceCells = sourceCells + (128 - width);
1040 destinationCells = 128 - width + destinationCells;
1042 }
while (
y < dstY + height);
1063#undef MAP_CELL_TILE_MASK
1064#undef MAP_CELL_ATTRIBUTE_MASK
void Fade_FromBlack(s32 frames)
Fades in from black.
s32 GameFlag_TestFar(s32 flag)
void GameFlag_ClearBitFar(s32 flag)
u8 gRuntime_ByteRemapTable[]
What every part of the field object shares: its includes and the few names more than one part uses.
#define FLAG_KEEP_LAYER_GRAPHICS
void WaitFrames(s32 frames)
The game's frame loop: runs frames frames and returns.
struct EffectStep gMapCellBuffer[]
Map cells; battle effects reuse this as a particle array.
u8 Tile_ConvertMapCodeSize[]
const u8 Tile_ConvertMap[]
void * Runtime_BumpAllocateAlternatePool(s32 size)
As MemAlloc, but tries EWRAM first.
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...
#define BGCNT_CHAR_BASE(block)
#define BG_SCREEN_BLOCK(n)
#define BGCNT_SCREEN_BASE(block)
#define Io_Write16(v, reg)
Writes a value to a 16-bit register or memory location.
static s32 Iwram_CopyWords(volatile void *destination, const volatile void *source, s32 size)
#define Iwram_CopyWordsEntry
#define Iwram_MulQ16(left, right)
static s32 Iwram_ClearWords(void *destination, s32 size)
#define CLAMP(v, low, high)
Keeps v within low to high, the low bound tested first.
void DisplayBlend_StartScript(u16 *script)
Starts a map's blend script, unless it is empty.
void MapAnimation_StartChannels(const u16 *script)
Starts the tile animation channels a map's animation script lists: each 0xfdNN marker starts channel ...
struct LayeredSceneEntry gMap_LayeredScenes[]
void Map_SetCameraCenter(s32 x, s32 y)
Centres the view on (x, y) in 16.16 pixels, clamped to the map's bounds, and redraws every enabled la...
void Tilemap_DecodeStagedBuffer(s32 size)
Unpacks the staged block data into gMapBlocks.
void Map_CopyMetatileCellsRect(s32 srcX, s32 srcY, s32 width, s32 height, s32 dstX, s32 dstY)
Copies a rectangle of cells (16x16 pixels each) as they are, from (srcX, srcY) to (dstX,...
char MapCopyCommandSize[(sizeof(struct MapCopyCommand)==10) ? 1 :-1]
static __inline__ void Map_CopyMetatileHalfColumn(u32 *cell, u8 *screenMap, u32 screenRowOffset, u32 screenColumnOffset, u32 tileHalf)
Copies one tile column of a block (metatile) into a BG map: its top and bottom tile entries,...
void Map_CopyCellIndexRect(s32 srcX, s32 srcY, s32 width, s32 height, s32 dstX, s32 dstY)
Copies only the block numbers of a rectangle of cells, from (srcX, srcY) to (dstX,...
static __inline__ void Map_CopyMetatileToScreen(u32 *cell, u8 *screenMap, u32 screenRowOffset, u32 screenColumnOffset)
Copies a whole block (metatile) into a BG map: its top two tile entries and its bottom two,...
void Tilemap_ConvertBuffer(void)
Converts the map's cells in place with Tile_ConvertMap, run from RAM, from a saved copy of the staged...
void Map_CopyMetatileIndicesRect(s32 srcX, s32 srcY, u32 dstX, u32 dstY, u32 width, u32 height)
Copies the block numbers of a rectangle of cells from (srcX, srcY) to (dstX, dstY),...
void Map_UpdateLayerScroll(void)
Each frame on a layered map: centres the view on the point the map follows (origin),...
void Map_RenderMetatileRow(u32 layer, s32 tileX, s32 tileY)
Draws a row of 16 blocks (32 tiles) of a layer's cells into its BG map (screen block 5 + layer),...
#define MAP_CELL_ATTRIBUTE_MASK
the cell's attributes
void Map_RenderMetatileColumn(u32 layer, s32 tileX, s32 tileY)
Draws a column of 11 blocks of a layer's cells, one tile wide, into its BG map, starting at tile (til...
#define MAP_CELL_TILE_MASK
the block (metatile) number
void Map_PlayMetatileCopySequence(u16 *sequence, s32 destinationX, u32 destinationY)
Plays a map edit sequence (struct MapCopyCommand records, ended by a source of 0xffff): copies each r...
void Map_CenterOnFollowedPoint(void)
Centres the camera on the point the map follows (origin: x, height, z), or on (0, 0) when there is no...
void Map_SetShownLayers(u32 layerFlags)
Sets which of BG1-BG3 the map shows (bits 9-11 of its display flags, as in REG_DISPCNT) from layerFla...
s32 Map_LoadLayeredScene(s32 index)
Loads layered scene index from gMap_LayeredScenes: its blocks, collision, cells, tile animations,...
void Runtime_RemapBytesByTable(u8 *bytes, s32 byteCount)
Remaps byteCount bytes in place through gRuntime_ByteRemapTable.
void Map_CopyCellAttributeRect(s32 srcX, s32 srcY, s32 width, s32 height, s32 dstX, s32 dstY)
Copies only the attributes of a rectangle of cells, from (srcX, srcY) to (dstX, dstY),...
void(*) TilemapConvertFn(void *dst, const void *src, const void *saved)
UNUSED void Tilemap_NumberPlaceholderBlocks(void)
Gives each map cell whose block number is 0xfff (a placeholder) a number of its own,...
u32 Random16(void)
Advances the game's random number generator (the C library's classic linear congruential one),...
void MemFree(void *buffer)
#define Ram_MapCellBuffer
#define RamCode_Load(to, code, bytes)
Allocates a heap copy; release it with MemFree when finished.
s32 Resource_DecodeType01(const void *source, void *destination)
Decodes a type-01 resource and returns its unpacked byte count.
s32 Resource_DecodeType2(const void *source, void *destination)
Decodes a type-02 resource and returns its unpacked byte count.
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...
A row of gMap_LayeredScenes: a layered map's resources, counted from ResourceId_Map001: its header,...
One background layer's setup in a layered map's header: its origin, its parallax and drift,...
s8 scrollX
sixteenths of the view's motion
s8 speedY
1/16 pixels per frame
s8 speedX
1/16 pixels per frame
s8 scrollY
sixteenths of the view's motion
One cell of a map layer: its metatile and flags, its collision code and an attribute indexing the col...
One step of a map edit sequence: the rectangle of cells to copy from and the wait after it.
The map work in heap slot 8 (struct MapScrollWork), seen as its tile animation channels,...
u16 flags
REG_DISPCNT bits; Map_SetShownLayers sets BG1 to BG3.
The top left of a layer's visible area, in cells.
void * Resource_GetTableEntry(s32 index)
Returns the ROM address of resource index from the resource directory.