Move gflib srcs and headers to gflib subdir

This commit is contained in:
PikalaxALT
2019-09-08 21:07:54 -04:00
parent 95b805a425
commit 306ce048ad
123 changed files with 177 additions and 132 deletions
+1305
View File
File diff suppressed because it is too large Load Diff
+85
View File
@@ -0,0 +1,85 @@
#ifndef GUARD_BG_H
#define GUARD_BG_H
struct BGCntrlBitfield // for the I/O registers
{
volatile u16 priority:2;
volatile u16 charBaseBlock:2;
volatile u16 field_0_2:4;
volatile u16 field_1_0:5;
volatile u16 areaOverflowMode:1;
volatile u16 screenSize:2;
};
enum
{
BG_ATTR_CHARBASEINDEX = 1,
BG_ATTR_MAPBASEINDEX,
BG_ATTR_SCREENSIZE,
BG_ATTR_PALETTEMODE,
BG_ATTR_MOSAIC,
BG_ATTR_WRAPAROUND,
BG_ATTR_PRIORITY,
BG_ATTR_METRIC,
BG_ATTR_TYPE,
BG_ATTR_BASETILE,
};
struct BgTemplate
{
u16 bg:2; // 0x1, 0x2 -> 0x3
u16 charBaseIndex:2; // 0x4, 0x8 -> 0xC
u16 mapBaseIndex:5; // 0x10, 0x20, 0x40, 0x80, 0x100 -> 0x1F0
u16 screenSize:2; // 0x200, 0x400 -> 0x600
u16 paletteMode:1; // 0x800
u16 priority:2; // 0x1000, 0x2000 > 0x3000
u16 baseTile:10;
};
void ResetBgs(void);
u8 GetBgMode(void);
void ResetBgControlStructs(void);
void Unused_ResetBgControlStruct(u8 bg);
u8 LoadBgVram(u8 bg, const void *src, u16 size, u16 destOffset, u8 mode);
void SetTextModeAndHideBgs(void);
bool8 IsInvalidBg(u8 bg);
int DummiedOutFireRedLeafGreenTileAllocFunc(int a1, int a2, int a3, int a4);
void ResetBgsAndClearDma3BusyFlags(u32 leftoverFireRedLeafGreenVariable);
void InitBgsFromTemplates(u8 bgMode, const struct BgTemplate *templates, u8 numTemplates);
void InitBgFromTemplate(const struct BgTemplate *template);
void SetBgMode(u8 bgMode);
u16 LoadBgTiles(u8 bg, const void* src, u16 size, u16 destOffset);
u16 LoadBgTilemap(u8 bg, const void *src, u16 size, u16 destOffset);
u16 Unused_LoadBgPalette(u8 bg, const void *src, u16 size, u16 destOffset);
bool8 IsDma3ManagerBusyWithBgCopy(void);
void ShowBg(u8 bg);
void HideBg(u8 bg);
void SetBgAttribute(u8 bg, u8 attributeId, u8 value);
u16 GetBgAttribute(u8 bg, u8 attributeId);
s32 ChangeBgX(u8 bg, s32 value, u8 op);
s32 GetBgX(u8 bg);
s32 ChangeBgY(u8 bg, s32 value, u8 op);
s32 ChangeBgY_ScreenOff(u8 bg, u32 value, u8 op);
s32 GetBgY(u8 bg);
void SetBgAffine(u8 bg, s32 srcCenterX, s32 srcCenterY, s16 dispCenterX, s16 dispCenterY, s16 scaleX, s16 scaleY, u16 rotationAngle);
u8 Unused_AdjustBgMosaic(u8 a1, u8 a2);
void SetBgTilemapBuffer(u8 bg, void *tilemap);
void UnsetBgTilemapBuffer(u8 bg);
void* GetBgTilemapBuffer(u8 bg);
void CopyToBgTilemapBuffer(u8 bg, const void *src, u16 mode, u16 destOffset);
void CopyBgTilemapBufferToVram(u8 bg);
void CopyToBgTilemapBufferRect(u8 bg, const void* src, u8 destX, u8 destY, u8 width, u8 height);
void CopyToBgTilemapBufferRect_ChangePalette(u8 bg, const void *src, u8 destX, u8 destY, u8 rectWidth, u8 rectHeight, u8 palette);
void CopyRectToBgTilemapBufferRect(u8 bg, const void *src, u8 srcX, u8 srcY, u8 srcWidth, u8 unused, u8 srcHeight, u8 destX, u8 destY, u8 rectWidth, u8 rectHeight, s16 palette1, s16 tileOffset);
void FillBgTilemapBufferRect_Palette0(u8 bg, u16 tileNum, u8 x, u8 y, u8 width, u8 height);
void FillBgTilemapBufferRect(u8 bg, u16 tileNum, u8 x, u8 y, u8 width, u8 height, u8 palette);
void WriteSequenceToBgTilemapBuffer(u8 bg, u16 firstTileNum, u8 x, u8 y, u8 width, u8 height, u8 paletteSlot, s16 tileNumDelta);
u16 GetBgMetricTextMode(u8 bg, u8 whichMetric);
u32 GetBgMetricAffineMode(u8 bg, u8 whichMetric);
u32 GetTileMapIndexFromCoords(s32 x, s32 y, s32 screenSize, u32 screenWidth, u32 screenHeight);
void CopyTileMapEntry(const u16 *src, u16 *dest, s32 palette1, s32 tileOffset, s32 palette2);
u32 GetBgType(u8 bg);
bool32 IsInvalidBg32(u8 bg);
bool32 IsTileMapOutsideWram(u8 bg);
#endif // GUARD_BG_H
+209
View File
@@ -0,0 +1,209 @@
#include "global.h"
#include "blit.h"
void BlitBitmapRect4BitWithoutColorKey(const struct Bitmap *src, struct Bitmap *dst, u16 srcX, u16 srcY, u16 dstX, u16 dstY, u16 width, u16 height)
{
BlitBitmapRect4Bit(src, dst, srcX, srcY, dstX, dstY, width, height, 0xFF);
}
void BlitBitmapRect4Bit(const struct Bitmap *src, struct Bitmap *dst, u16 srcX, u16 srcY, u16 dstX, u16 dstY, u16 width, u16 height, u8 colorKey)
{
s32 xEnd;
s32 yEnd;
s32 multiplierSrcY;
s32 multiplierDstY;
s32 loopSrcY, loopDstY;
s32 loopSrcX, loopDstX;
const u8 *pixelsSrc;
u8 *pixelsDst;
s32 toOrr;
s32 toAnd;
s32 toShift;
if (dst->width - dstX < width)
xEnd = (dst->width - dstX) + srcX;
else
xEnd = srcX + width;
if (dst->height - dstY < height)
yEnd = (dst->height - dstY) + srcY;
else
yEnd = height + srcY;
multiplierSrcY = (src->width + (src->width & 7)) >> 3;
multiplierDstY = (dst->width + (dst->width & 7)) >> 3;
if (colorKey == 0xFF)
{
for (loopSrcY = srcY, loopDstY = dstY; loopSrcY < yEnd; loopSrcY++, loopDstY++)
{
for (loopSrcX = srcX, loopDstX = dstX; loopSrcX < xEnd; loopSrcX++, loopDstX++)
{
pixelsSrc = src->pixels + ((loopSrcX >> 1) & 3) + ((loopSrcX >> 3) << 5) + (((loopSrcY >> 3) * multiplierSrcY) << 5) + ((u32)(loopSrcY << 0x1d) >> 0x1B);
pixelsDst = dst->pixels + ((loopDstX >> 1) & 3) + ((loopDstX >> 3) << 5) + (((loopDstY >> 3) * multiplierDstY) << 5) + ((u32)(loopDstY << 0x1d) >> 0x1B);
toOrr = ((*pixelsSrc >> ((loopSrcX & 1) << 2)) & 0xF);
toShift = ((loopDstX & 1) << 2);
toOrr <<= toShift;
toAnd = 0xF0 >> (toShift);
*pixelsDst = toOrr | (*pixelsDst & toAnd);
}
}
}
else
{
for (loopSrcY = srcY, loopDstY = dstY; loopSrcY < yEnd; loopSrcY++, loopDstY++)
{
for (loopSrcX = srcX, loopDstX = dstX; loopSrcX < xEnd; loopSrcX++, loopDstX++)
{
pixelsSrc = src->pixels + ((loopSrcX >> 1) & 3) + ((loopSrcX >> 3) << 5) + (((loopSrcY >> 3) * multiplierSrcY) << 5) + ((u32)(loopSrcY << 0x1d) >> 0x1B);
pixelsDst = dst->pixels + ((loopDstX >> 1) & 3) + ((loopDstX >> 3) << 5) + (((loopDstY >> 3) * multiplierDstY) << 5) + ((u32)(loopDstY << 0x1d) >> 0x1B);
toOrr = ((*pixelsSrc >> ((loopSrcX & 1) << 2)) & 0xF);
if (toOrr != colorKey)
{
toShift = ((loopDstX & 1) << 2);
toOrr <<= toShift;
toAnd = 0xF0 >> (toShift);
*pixelsDst = toOrr | (*pixelsDst & toAnd);
}
}
}
}
}
void FillBitmapRect4Bit(struct Bitmap *surface, u16 x, u16 y, u16 width, u16 height, u8 fillValue)
{
s32 xEnd;
s32 yEnd;
s32 multiplierY;
s32 loopX, loopY;
s32 toOrr1, toOrr2;
xEnd = x + width;
if (xEnd > surface->width)
xEnd = surface->width;
yEnd = y + height;
if (yEnd > surface->height)
yEnd = surface->height;
multiplierY = (surface->width + (surface->width & 7)) >> 3;
toOrr1 = (u32)(fillValue << 0x1C) >> 0x18;
toOrr2 = (fillValue & 0xF);
for (loopY = y; loopY < yEnd; loopY++)
{
for (loopX = x; loopX < xEnd; loopX++)
{
u8 *pixels = surface->pixels + ((loopX >> 1) & 3) + ((loopX >> 3) << 5) + (((loopY >> 3) * multiplierY) << 5) + ((u32)(loopY << 0x1d) >> 0x1B);
if ((loopX << 0x1F) != 0)
*pixels = toOrr1 | (*pixels & 0xF);
else
*pixels = toOrr2 | (*pixels & 0xF0);
}
}
}
void BlitBitmapRect4BitTo8Bit(const struct Bitmap *src, struct Bitmap *dst, u16 srcX, u16 srcY, u16 dstX, u16 dstY, u16 width, u16 height, u8 colorKey, u8 paletteOffset)
{
s32 palOffsetBits;
s32 xEnd;
s32 yEnd;
s32 multiplierSrcY;
s32 multiplierDstY;
s32 loopSrcY, loopDstY;
s32 loopSrcX, loopDstX;
const u8 *pixelsSrc;
u8 *pixelsDst;
s32 colorKeyBits;
palOffsetBits = (u32)(paletteOffset << 0x1C) >> 0x18;
colorKeyBits = (u32)(colorKey << 0x1C) >> 0x18;
if (dst->width - dstX < width)
xEnd = (dst->width - dstX) + srcX;
else
xEnd = width + srcX;
if (dst->height - dstY < height)
yEnd = (srcY + dst->height) - dstY;
else
yEnd = srcY + height;
multiplierSrcY = (src->width + (src->width & 7)) >> 3;
multiplierDstY = (dst->width + (dst->width & 7)) >> 3;
if (colorKey == 0xFF)
{
for (loopSrcY = srcY, loopDstY = dstY; loopSrcY < yEnd; loopSrcY++, loopDstY++)
{
pixelsSrc = src->pixels + ((srcX >> 1) & 3) + ((srcX >> 3) << 5) + (((loopSrcY >> 3) * multiplierSrcY) << 5) + ((u32)(loopSrcY << 0x1d) >> 0x1b);
for (loopSrcX = srcX, loopDstX = dstX; loopSrcX < xEnd; loopSrcX++, loopDstX++)
{
pixelsDst = dst->pixels + (loopDstX & 7) + ((loopDstX >> 3) << 6) + (((loopDstY >> 3) * multiplierDstY) << 6) + ((u32)(loopDstY << 0x1d) >> 0x1a);
if (loopSrcX & 1)
{
*pixelsDst = palOffsetBits + (*pixelsSrc >> 4);
}
else
{
pixelsSrc = src->pixels + ((loopSrcX >> 1) & 3) + ((loopSrcX >> 3) << 5) + (((loopSrcY >> 3) * multiplierSrcY) << 5) + ((u32)(loopSrcY << 0x1d) >> 0x1b);
*pixelsDst = palOffsetBits + (*pixelsSrc & 0xF);
}
}
}
}
else
{
for (loopSrcY = srcY, loopDstY = dstY; loopSrcY < yEnd; loopSrcY++, loopDstY++)
{
pixelsSrc = src->pixels + ((srcX >> 1) & 3) + ((srcX >> 3) << 5) + (((loopSrcY >> 3) * multiplierSrcY) << 5) + ((u32)(loopSrcY << 0x1d) >> 0x1b);
for (loopSrcX = srcX, loopDstX = dstX; loopSrcX < xEnd; loopSrcX++, loopDstX++)
{
if (loopSrcX & 1)
{
if ((*pixelsSrc & 0xF0) != colorKeyBits)
{
pixelsDst = dst->pixels + (loopDstX & 7) + ((loopDstX >> 3) << 6) + (((loopDstY >> 3) * multiplierDstY) << 6) + ((u32)(loopDstY << 0x1d) >> 0x1a);
*pixelsDst = palOffsetBits + (*pixelsSrc >> 4);
}
}
else
{
pixelsSrc = src->pixels + ((loopSrcX >> 1) & 3) + ((loopSrcX >> 3) << 5) + (((loopSrcY >> 3) * multiplierSrcY) << 5) + ((u32)(loopSrcY << 0x1d) >> 0x1b);
if ((*pixelsSrc & 0xF) != colorKey)
{
pixelsDst = dst->pixels + (loopDstX & 7) + ((loopDstX >> 3) << 6) + (((loopDstY >> 3) * multiplierDstY) << 6) + ((u32)(loopDstY << 0x1d) >> 0x1a);
*pixelsDst = palOffsetBits + (*pixelsSrc & 0xF);
}
}
}
}
}
}
void FillBitmapRect8Bit(struct Bitmap *surface, u16 x, u16 y, u16 width, u16 height, u8 fillValue)
{
s32 xEnd;
s32 yEnd;
s32 multiplierY;
s32 loopX, loopY;
xEnd = x + width;
if (xEnd > surface->width)
xEnd = surface->width;
yEnd = y + height;
if (yEnd > surface->height)
yEnd = surface->height;
multiplierY = (surface->width + (surface->width & 7)) >> 3;
for (loopY = y; loopY < yEnd; loopY++)
{
for (loopX = x; loopX < xEnd; loopX++)
{
u8 *pixels = surface->pixels + (loopX & 7) + ((loopX >> 3) << 6) + (((loopY >> 3) * multiplierY) << 6) + ((u32)(loopY << 0x1d) >> 0x1a);
*pixels = fillValue;
}
}
}
+17
View File
@@ -0,0 +1,17 @@
#ifndef GUARD_BLIT_H
#define GUARD_BLIT_H
struct Bitmap
{
u8 *pixels;
u32 width:16;
u32 height:16;
};
void BlitBitmapRect4BitWithoutColorKey(const struct Bitmap *src, struct Bitmap *dst, u16 srcX, u16 srcY, u16 dstX, u16 dstY, u16 width, u16 height);
void BlitBitmapRect4Bit(const struct Bitmap *src, struct Bitmap *dst, u16 srcX, u16 srcY, u16 dstX, u16 dstY, u16 width, u16 height, u8 colorKey);
void FillBitmapRect4Bit(struct Bitmap *surface, u16 x, u16 y, u16 width, u16 height, u8 fillValue);
void BlitBitmapRect4BitTo8Bit(const struct Bitmap *src, struct Bitmap *dst, u16 srcX, u16 srcY, u16 dstX, u16 dstY, u16 width, u16 height, u8 colorKey, u8 paletteOffset);
void FillBitmapRect8Bit(struct Bitmap *surface, u16 x, u16 y, u16 width, u16 height, u8 fillValue);
#endif // GUARD_BLIT_H
+55
View File
@@ -0,0 +1,55 @@
#ifndef GUARD_DMA3_H
#define GUARD_DMA3_H
// Maximum amount of data we will transfer in one operation
#define MAX_DMA_BLOCK_SIZE 0x1000
#define Dma3CopyLarge_(src, dest, size, bit) \
{ \
const void *_src = src; \
void *_dest = dest; \
u32 _size = size; \
while (1) \
{ \
if (_size <= MAX_DMA_BLOCK_SIZE) \
{ \
DmaCopy##bit(3, _src, _dest, _size); \
break; \
} \
DmaCopy##bit(3, _src, _dest, MAX_DMA_BLOCK_SIZE); \
_src += MAX_DMA_BLOCK_SIZE; \
_dest += MAX_DMA_BLOCK_SIZE; \
_size -= MAX_DMA_BLOCK_SIZE; \
} \
}
#define Dma3CopyLarge16_(src, dest, size) Dma3CopyLarge_(src, dest, size, 16)
#define Dma3CopyLarge32_(src, dest, size) Dma3CopyLarge_(src, dest, size, 32)
#define Dma3FillLarge_(value, dest, size, bit) \
{ \
void *_dest = dest; \
u32 _size = size; \
while (1) \
{ \
if (_size <= MAX_DMA_BLOCK_SIZE) \
{ \
DmaFill##bit(3, value, _dest, _size); \
break; \
} \
DmaFill##bit(3, value, _dest, MAX_DMA_BLOCK_SIZE); \
_dest += MAX_DMA_BLOCK_SIZE; \
_size -= MAX_DMA_BLOCK_SIZE; \
} \
}
#define Dma3FillLarge16_(value, dest, size) Dma3FillLarge_(value, dest, size, 16)
#define Dma3FillLarge32_(value, dest, size) Dma3FillLarge_(value, dest, size, 32)
void ClearDma3Requests(void);
void ProcessDma3Requests(void);
s16 RequestDma3Copy(const void *src, void *dest, u16 size, u8 mode);
s16 RequestDma3Fill(s32 value, void *dest, u16 size, u8 mode);
s16 CheckForSpaceForDma3Request(s16 index);
#endif // GUARD_DMA3_H
+181
View File
@@ -0,0 +1,181 @@
#include "global.h"
#include "dma3.h"
#define MAX_DMA_REQUESTS 128
#define DMA_REQUEST_COPY32 1
#define DMA_REQUEST_FILL32 2
#define DMA_REQUEST_COPY16 3
#define DMA_REQUEST_FILL16 4
BSS_DATA struct
{
const u8 *src;
u8 *dest;
u16 size;
u16 mode;
u32 value;
} gDma3Requests[MAX_DMA_REQUESTS];
static volatile bool8 gDma3ManagerLocked;
static u8 gDma3RequestCursor;
void ClearDma3Requests(void)
{
int i;
gDma3ManagerLocked = TRUE;
gDma3RequestCursor = 0;
for (i = 0; i < MAX_DMA_REQUESTS; i++)
{
gDma3Requests[i].size = 0;
gDma3Requests[i].src = NULL;
gDma3Requests[i].dest = NULL;
}
gDma3ManagerLocked = FALSE;
}
void ProcessDma3Requests(void)
{
u16 bytesTransferred;
if (gDma3ManagerLocked)
return;
bytesTransferred = 0;
// as long as there are DMA requests to process (unless size or vblank is an issue), do not exit
while (gDma3Requests[gDma3RequestCursor].size != 0)
{
bytesTransferred += gDma3Requests[gDma3RequestCursor].size;
if (bytesTransferred > 40 * 1024)
return; // don't transfer more than 40 KiB
if (*(u8 *)REG_ADDR_VCOUNT > 224)
return; // we're about to leave vblank, stop
switch (gDma3Requests[gDma3RequestCursor].mode)
{
case DMA_REQUEST_COPY32: // regular 32-bit copy
Dma3CopyLarge32_(gDma3Requests[gDma3RequestCursor].src,
gDma3Requests[gDma3RequestCursor].dest,
gDma3Requests[gDma3RequestCursor].size);
break;
case DMA_REQUEST_FILL32: // repeat a single 32-bit value across RAM
Dma3FillLarge32_(gDma3Requests[gDma3RequestCursor].value,
gDma3Requests[gDma3RequestCursor].dest,
gDma3Requests[gDma3RequestCursor].size);
break;
case DMA_REQUEST_COPY16: // regular 16-bit copy
Dma3CopyLarge16_(gDma3Requests[gDma3RequestCursor].src,
gDma3Requests[gDma3RequestCursor].dest,
gDma3Requests[gDma3RequestCursor].size);
break;
case DMA_REQUEST_FILL16: // repeat a single 16-bit value across RAM
Dma3FillLarge16_(gDma3Requests[gDma3RequestCursor].value,
gDma3Requests[gDma3RequestCursor].dest,
gDma3Requests[gDma3RequestCursor].size);
break;
}
// Free the request
gDma3Requests[gDma3RequestCursor].src = NULL;
gDma3Requests[gDma3RequestCursor].dest = NULL;
gDma3Requests[gDma3RequestCursor].size = 0;
gDma3Requests[gDma3RequestCursor].mode = 0;
gDma3Requests[gDma3RequestCursor].value = 0;
gDma3RequestCursor++;
if (gDma3RequestCursor >= MAX_DMA_REQUESTS) // loop back to the first DMA request
gDma3RequestCursor = 0;
}
}
s16 RequestDma3Copy(const void *src, void *dest, u16 size, u8 mode)
{
int cursor;
int i = 0;
gDma3ManagerLocked = TRUE;
cursor = gDma3RequestCursor;
while (i < MAX_DMA_REQUESTS)
{
if (gDma3Requests[cursor].size == 0) // an empty request was found.
{
gDma3Requests[cursor].src = src;
gDma3Requests[cursor].dest = dest;
gDma3Requests[cursor].size = size;
if (mode == 1)
gDma3Requests[cursor].mode = DMA_REQUEST_COPY32;
else
gDma3Requests[cursor].mode = DMA_REQUEST_COPY16;
gDma3ManagerLocked = FALSE;
return cursor;
}
if (++cursor >= MAX_DMA_REQUESTS) // loop back to start.
cursor = 0;
i++;
}
gDma3ManagerLocked = FALSE;
return -1; // no free DMA request was found
}
s16 RequestDma3Fill(s32 value, void *dest, u16 size, u8 mode)
{
int cursor;
int i = 0;
cursor = gDma3RequestCursor;
gDma3ManagerLocked = TRUE;
while (i < MAX_DMA_REQUESTS)
{
if (gDma3Requests[cursor].size == 0) // an empty request was found.
{
gDma3Requests[cursor].dest = dest;
gDma3Requests[cursor].size = size;
gDma3Requests[cursor].mode = mode;
gDma3Requests[cursor].value = value;
if(mode == 1)
gDma3Requests[cursor].mode = DMA_REQUEST_FILL32;
else
gDma3Requests[cursor].mode = DMA_REQUEST_FILL16;
gDma3ManagerLocked = FALSE;
return cursor;
}
if (++cursor >= MAX_DMA_REQUESTS) // loop back to start.
cursor = 0;
i++;
}
gDma3ManagerLocked = FALSE;
return -1; // no free DMA request was found
}
s16 CheckForSpaceForDma3Request(s16 index)
{
int i = 0;
if (index == -1) // check if all requests are free
{
while (i < MAX_DMA_REQUESTS)
{
if (gDma3Requests[i].size != 0)
return -1;
i++;
}
return 0;
}
else // check the specified request
{
if (gDma3Requests[index].size != 0)
return -1;
return 0;
}
}
+195
View File
@@ -0,0 +1,195 @@
#include "global.h"
#include "gpu_regs.h"
#define GPU_REG_BUF_SIZE 0x60
#define GPU_REG_BUF(offset) (*(u16 *)(&sGpuRegBuffer[offset]))
#define GPU_REG(offset) (*(vu16 *)(REG_BASE + offset))
#define EMPTY_SLOT 0xFF
static u8 sGpuRegBuffer[GPU_REG_BUF_SIZE];
static u8 sGpuRegWaitingList[GPU_REG_BUF_SIZE];
static volatile bool8 sGpuRegBufferLocked;
static volatile bool8 sShouldSyncRegIE;
static vu16 sRegIE;
static void CopyBufferedValueToGpuReg(u8 regOffset);
static void SyncRegIE(void);
static void UpdateRegDispstatIntrBits(u16 regIE);
void InitGpuRegManager(void)
{
s32 i;
for (i = 0; i < GPU_REG_BUF_SIZE; i++)
{
sGpuRegBuffer[i] = 0;
sGpuRegWaitingList[i] = EMPTY_SLOT;
}
sGpuRegBufferLocked = FALSE;
sShouldSyncRegIE = FALSE;
sRegIE = 0;
}
static void CopyBufferedValueToGpuReg(u8 regOffset)
{
if (regOffset == REG_OFFSET_DISPSTAT)
{
REG_DISPSTAT &= ~(DISPSTAT_HBLANK_INTR | DISPSTAT_VBLANK_INTR);
REG_DISPSTAT |= GPU_REG_BUF(REG_OFFSET_DISPSTAT);
}
else
{
GPU_REG(regOffset) = GPU_REG_BUF(regOffset);
}
}
void CopyBufferedValuesToGpuRegs(void)
{
if (!sGpuRegBufferLocked)
{
s32 i;
for (i = 0; i < GPU_REG_BUF_SIZE; i++)
{
u8 regOffset = sGpuRegWaitingList[i];
if (regOffset == EMPTY_SLOT)
return;
CopyBufferedValueToGpuReg(regOffset);
sGpuRegWaitingList[i] = EMPTY_SLOT;
}
}
}
void SetGpuReg(u8 regOffset, u16 value)
{
if (regOffset < GPU_REG_BUF_SIZE)
{
u16 vcount;
GPU_REG_BUF(regOffset) = value;
vcount = REG_VCOUNT & 0xFF;
if ((vcount >= 161 && vcount <= 225) || (REG_DISPCNT & DISPCNT_FORCED_BLANK))
{
CopyBufferedValueToGpuReg(regOffset);
}
else
{
s32 i;
sGpuRegBufferLocked = TRUE;
for (i = 0; i < GPU_REG_BUF_SIZE && sGpuRegWaitingList[i] != EMPTY_SLOT; i++)
{
if (sGpuRegWaitingList[i] == regOffset)
{
sGpuRegBufferLocked = FALSE;
return;
}
}
sGpuRegWaitingList[i] = regOffset;
sGpuRegBufferLocked = FALSE;
}
}
}
void SetGpuReg_ForcedBlank(u8 regOffset, u16 value)
{
if (regOffset < GPU_REG_BUF_SIZE)
{
GPU_REG_BUF(regOffset) = value;
if (REG_DISPCNT & DISPCNT_FORCED_BLANK)
{
CopyBufferedValueToGpuReg(regOffset);
}
else
{
s32 i;
sGpuRegBufferLocked = TRUE;
for (i = 0; i < GPU_REG_BUF_SIZE && sGpuRegWaitingList[i] != EMPTY_SLOT; i++)
{
if (sGpuRegWaitingList[i] == regOffset)
{
sGpuRegBufferLocked = FALSE;
return;
}
}
sGpuRegWaitingList[i] = regOffset;
sGpuRegBufferLocked = FALSE;
}
}
}
u16 GetGpuReg(u8 regOffset)
{
if (regOffset == REG_OFFSET_DISPSTAT)
return REG_DISPSTAT;
if (regOffset == REG_OFFSET_VCOUNT)
return REG_VCOUNT;
return GPU_REG_BUF(regOffset);
}
void SetGpuRegBits(u8 regOffset, u16 mask)
{
u16 regValue = GPU_REG_BUF(regOffset);
SetGpuReg(regOffset, regValue | mask);
}
void ClearGpuRegBits(u8 regOffset, u16 mask)
{
u16 regValue = GPU_REG_BUF(regOffset);
SetGpuReg(regOffset, regValue & ~mask);
}
static void SyncRegIE(void)
{
if (sShouldSyncRegIE)
{
u16 temp = REG_IME;
REG_IME = 0;
REG_IE = sRegIE;
REG_IME = temp;
sShouldSyncRegIE = FALSE;
}
}
void EnableInterrupts(u16 mask)
{
sRegIE |= mask;
sShouldSyncRegIE = TRUE;
SyncRegIE();
UpdateRegDispstatIntrBits(sRegIE);
}
void DisableInterrupts(u16 mask)
{
sRegIE &= ~mask;
sShouldSyncRegIE = TRUE;
SyncRegIE();
UpdateRegDispstatIntrBits(sRegIE);
}
static void UpdateRegDispstatIntrBits(u16 regIE)
{
u16 oldValue = GetGpuReg(REG_OFFSET_DISPSTAT) & (DISPSTAT_HBLANK_INTR | DISPSTAT_VBLANK_INTR);
u16 newValue = 0;
if (regIE & INTR_FLAG_VBLANK)
newValue |= DISPSTAT_VBLANK_INTR;
if (regIE & INTR_FLAG_HBLANK)
newValue |= DISPSTAT_HBLANK_INTR;
if (oldValue != newValue)
SetGpuReg(REG_OFFSET_DISPSTAT, newValue);
}
+19
View File
@@ -0,0 +1,19 @@
#ifndef GUARD_GPU_REGS_H
#define GUARD_GPU_REGS_H
// Exported type declarations
// Exported RAM declarations
// Exported ROM declarations
void InitGpuRegManager(void);
void CopyBufferedValuesToGpuRegs(void);
void SetGpuReg(u8 regOffset, u16 value);
void SetGpuReg_ForcedBlank(u8 regOffset, u16 value);
u16 GetGpuReg(u8 regOffset);
void SetGpuRegBits(u8 regOffset, u16 mask);
void ClearGpuRegBits(u8 regOffset, u16 mask);
void EnableInterrupts(u16 mask);
void DisableInterrupts(u16 mask);
#endif //GUARD_GPU_REGS_H
+210
View File
@@ -0,0 +1,210 @@
#include "global.h"
static void *sHeapStart;
static u32 sHeapSize;
static u32 malloc_c_unused_0300000c; // needed to align dma3_manager.o(.bss)
#define MALLOC_SYSTEM_ID 0xA3A3
struct MemBlock {
// Whether this block is currently allocated.
bool16 flag;
// Magic number used for error checking. Should equal MALLOC_SYSTEM_ID.
u16 magic;
// Size of the block (not including this header struct).
u32 size;
// Previous block pointer. Equals sHeapStart if this is the first block.
struct MemBlock *prev;
// Next block pointer. Equals sHeapStart if this is the last block.
struct MemBlock *next;
// Data in the memory block. (Arrays of length 0 are a GNU extension.)
u8 data[0];
};
void PutMemBlockHeader(void *block, struct MemBlock *prev, struct MemBlock *next, u32 size)
{
struct MemBlock *header = (struct MemBlock *)block;
header->flag = FALSE;
header->magic = MALLOC_SYSTEM_ID;
header->size = size;
header->prev = prev;
header->next = next;
}
void PutFirstMemBlockHeader(void *block, u32 size)
{
PutMemBlockHeader(block, (struct MemBlock *)block, (struct MemBlock *)block, size - sizeof(struct MemBlock));
}
void *AllocInternal(void *heapStart, u32 size)
{
struct MemBlock *pos = (struct MemBlock *)heapStart;
struct MemBlock *head = pos;
struct MemBlock *splitBlock;
u32 foundBlockSize;
// Alignment
if (size & 3)
size = 4 * ((size / 4) + 1);
for (;;) {
// Loop through the blocks looking for unused block that's big enough.
if (!pos->flag) {
foundBlockSize = pos->size;
if (foundBlockSize >= size) {
if (foundBlockSize - size < 2 * sizeof(struct MemBlock)) {
// The block isn't much bigger than the requested size,
// so just use it.
pos->flag = TRUE;
} else {
// The block is significantly bigger than the requested
// size, so split the rest into a separate block.
foundBlockSize -= sizeof(struct MemBlock);
foundBlockSize -= size;
splitBlock = (struct MemBlock *)(pos->data + size);
pos->flag = TRUE;
pos->size = size;
PutMemBlockHeader(splitBlock, pos, pos->next, foundBlockSize);
pos->next = splitBlock;
if (splitBlock->next != head)
splitBlock->next->prev = splitBlock;
}
return pos->data;
}
}
if (pos->next == head)
return NULL;
pos = pos->next;
}
}
void FreeInternal(void *heapStart, void *pointer)
{
if (pointer) {
struct MemBlock *head = (struct MemBlock *)heapStart;
struct MemBlock *block = (struct MemBlock *)((u8 *)pointer - sizeof(struct MemBlock));
block->flag = FALSE;
// If the freed block isn't the last one, merge with the next block
// if it's not in use.
if (block->next != head) {
if (!block->next->flag) {
block->size += sizeof(struct MemBlock) + block->next->size;
block->next->magic = 0;
block->next = block->next->next;
if (block->next != head)
block->next->prev = block;
}
}
// If the freed block isn't the first one, merge with the previous block
// if it's not in use.
if (block != head) {
if (!block->prev->flag) {
block->prev->next = block->next;
if (block->next != head)
block->next->prev = block->prev;
block->magic = 0;
block->prev->size += sizeof(struct MemBlock) + block->size;
}
}
}
}
void *AllocZeroedInternal(void *heapStart, u32 size)
{
void *mem = AllocInternal(heapStart, size);
if (mem != NULL) {
if (size & 3)
size = 4 * ((size / 4) + 1);
CpuFill32(0, mem, size);
}
return mem;
}
bool32 CheckMemBlockInternal(void *heapStart, void *pointer)
{
struct MemBlock *head = (struct MemBlock *)heapStart;
struct MemBlock *block = (struct MemBlock *)((u8 *)pointer - sizeof(struct MemBlock));
if (block->magic != MALLOC_SYSTEM_ID)
return FALSE;
if (block->next->magic != MALLOC_SYSTEM_ID)
return FALSE;
if (block->next != head && block->next->prev != block)
return FALSE;
if (block->prev->magic != MALLOC_SYSTEM_ID)
return FALSE;
if (block->prev != head && block->prev->next != block)
return FALSE;
if (block->next != head && block->next != (struct MemBlock *)(block->data + block->size))
return FALSE;
return TRUE;
}
void InitHeap(void *heapStart, u32 heapSize)
{
sHeapStart = heapStart;
sHeapSize = heapSize;
PutFirstMemBlockHeader(heapStart, heapSize);
}
void *Alloc(u32 size)
{
return AllocInternal(sHeapStart, size);
}
void *AllocZeroed(u32 size)
{
return AllocZeroedInternal(sHeapStart, size);
}
void Free(void *pointer)
{
FreeInternal(sHeapStart, pointer);
}
bool32 CheckMemBlock(void *pointer)
{
return CheckMemBlockInternal(sHeapStart, pointer);
}
bool32 CheckHeap()
{
struct MemBlock *pos = (struct MemBlock *)sHeapStart;
do {
if (!CheckMemBlockInternal(sHeapStart, pos->data))
return FALSE;
pos = pos->next;
} while (pos != (struct MemBlock *)sHeapStart);
return TRUE;
}
+22
View File
@@ -0,0 +1,22 @@
#ifndef GUARD_ALLOC_H
#define GUARD_ALLOC_H
#define HEAP_SIZE 0x1C000
#define malloc Alloc
#define calloc(ct, sz) AllocZeroed((ct) * (sz))
#define free Free
#define FREE_AND_SET_NULL(ptr) \
{ \
free(ptr); \
ptr = NULL; \
}
extern u8 gHeap[];
void *Alloc(u32 size);
void *AllocZeroed(u32 size);
void Free(void *pointer);
void InitHeap(void *pointer, u32 size);
#endif // GUARD_ALLOC_H
+1758
View File
File diff suppressed because it is too large Load Diff
+319
View File
@@ -0,0 +1,319 @@
#ifndef GUARD_SPRITE_H
#define GUARD_SPRITE_H
#define MAX_SPRITES 64
#define SPRITE_INVALID_TAG 0xFFFF
struct SpriteSheet
{
const void *data; // Raw uncompressed pixel data
u16 size;
u16 tag;
};
struct CompressedSpriteSheet
{
const u32 *data; // LZ77 compressed pixel data
u16 size; // Uncompressed size of pixel data
u16 tag;
};
struct SpriteFrameImage
{
const void *data;
u16 size;
};
#define obj_frame_tiles(ptr) {.data = (u8 *)ptr, .size = sizeof ptr}
#define overworld_frame(ptr, width, height, frame) {.data = (u8 *)ptr + (width * height * frame * 64)/2, .size = (width * height * 64)/2}
struct SpritePalette
{
const u16 *data; // Raw uncompressed palette data
u16 tag;
};
struct CompressedSpritePalette
{
const u32 *data; // LZ77 compressed palette data
u16 tag;
};
struct AnimFrameCmd
{
// If the sprite has an array of images, this is the array index.
// If the sprite has a sheet, this is the tile offset.
u32 imageValue:16;
u32 duration:6;
u32 hFlip:1;
u32 vFlip:1;
};
struct AnimLoopCmd
{
u32 type:16;
u32 count:6;
};
struct AnimJumpCmd
{
u32 type:16;
u32 target:6;
};
// The first halfword of this union specifies the type of command.
// If it -2, then it is a jump command. If it is -1, then it is the end of the script.
// Otherwise, it is the imageValue for a frame command.
union AnimCmd
{
s16 type;
struct AnimFrameCmd frame;
struct AnimLoopCmd loop;
struct AnimJumpCmd jump;
};
#define ANIMCMD_FRAME(...) \
{.frame = {__VA_ARGS__}}
#define ANIMCMD_LOOP(_count) \
{.loop = {.type = -3, .count = _count}}
#define ANIMCMD_JUMP(_target) \
{.jump = {.type = -2, .target = _target}}
#define ANIMCMD_END \
{.type = -1}
struct AffineAnimFrameCmd
{
s16 xScale;
s16 yScale;
u8 rotation;
u8 duration;
};
struct AffineAnimLoopCmd
{
s16 type;
s16 count;
};
struct AffineAnimJumpCmd
{
s16 type;
u16 target;
};
struct AffineAnimEndCmdAlt
{
s16 type;
u16 val;
};
union AffineAnimCmd
{
s16 type;
struct AffineAnimFrameCmd frame;
struct AffineAnimLoopCmd loop;
struct AffineAnimJumpCmd jump;
struct AffineAnimEndCmdAlt end; // unused in code
};
#define AFFINEANIMCMDTYPE_LOOP 0x7FFD
#define AFFINEANIMCMDTYPE_JUMP 0x7FFE
#define AFFINEANIMCMDTYPE_END 0x7FFF
#define AFFINEANIMCMD_FRAME(_xScale, _yScale, _rotation, _duration) \
{.frame = {.xScale = _xScale, .yScale = _yScale, .rotation = _rotation, .duration = _duration}}
#define AFFINEANIMCMD_LOOP(_count) \
{.loop = {.type = AFFINEANIMCMDTYPE_LOOP, .count = _count}}
#define AFFINEANIMCMD_JUMP(_target) \
{.jump = {.type = AFFINEANIMCMDTYPE_JUMP, .target = _target}}
#define AFFINEANIMCMD_END \
{.type = AFFINEANIMCMDTYPE_END}
#define AFFINEANIMCMD_END_ALT(_val) \
{.end = {.type = AFFINEANIMCMDTYPE_END, .val = _val}}
struct AffineAnimState
{
u8 animNum;
u8 animCmdIndex;
u8 delayCounter;
u8 loopCounter;
s16 xScale;
s16 yScale;
u16 rotation;
};
enum
{
SUBSPRITES_OFF,
SUBSPRITES_ON,
SUBSPRITES_IGNORE_PRIORITY, // on but priority is ignored
};
struct Subsprite
{
s8 x; // was u16 in R/S
s8 y; // was u16 in R/S
u16 shape:2;
u16 size:2;
u16 tileOffset:10;
u16 priority:2;
};
struct SubspriteTable
{
u8 subspriteCount;
const struct Subsprite *subsprites;
};
struct Sprite;
typedef void (*SpriteCallback)(struct Sprite *);
struct SpriteTemplate
{
u16 tileTag;
u16 paletteTag;
const struct OamData *oam;
const union AnimCmd *const *anims;
const struct SpriteFrameImage *images;
const union AffineAnimCmd *const *affineAnims;
SpriteCallback callback;
};
struct Sprite
{
/*0x00*/ struct OamData oam;
/*0x08*/ const union AnimCmd *const *anims;
/*0x0C*/ const struct SpriteFrameImage *images;
/*0x10*/ const union AffineAnimCmd *const *affineAnims;
/*0x14*/ const struct SpriteTemplate *template;
/*0x18*/ const struct SubspriteTable *subspriteTables;
/*0x1C*/ SpriteCallback callback;
/*0x20*/ struct Coords16 pos1;
/*0x24*/ struct Coords16 pos2;
/*0x28*/ s8 centerToCornerVecX;
/*0x29*/ s8 centerToCornerVecY;
/*0x2A*/ u8 animNum;
/*0x2B*/ u8 animCmdIndex;
/*0x2C*/ u8 animDelayCounter:6;
bool8 animPaused:1;
bool8 affineAnimPaused:1;
/*0x2D*/ u8 animLoopCounter;
// general purpose data fields
/*0x2E*/ s16 data[8];
/*0x3E*/ bool16 inUse:1; //1
bool16 coordOffsetEnabled:1; //2
bool16 invisible:1; //4
bool16 flags_3:1; //8
bool16 flags_4:1; //0x10
bool16 flags_5:1; //0x20
bool16 flags_6:1; //0x40
bool16 flags_7:1; //0x80
/*0x3F*/ bool16 hFlip:1; //1
bool16 vFlip:1; //2
bool16 animBeginning:1; //4
bool16 affineAnimBeginning:1; //8
bool16 animEnded:1; //0x10
bool16 affineAnimEnded:1; //0x20
bool16 usingSheet:1; //0x40
bool16 flags_f:1; //0x80
/*0x40*/ u16 sheetTileStart;
/*0x42*/ u8 subspriteTableNum:6;
u8 subspriteMode:2;
/*0x43*/ u8 subpriority;
};
struct OamMatrix
{
s16 a;
s16 b;
s16 c;
s16 d;
};
extern const struct OamData gDummyOamData;
extern const union AnimCmd *const gDummySpriteAnimTable[];
extern const union AffineAnimCmd *const gDummySpriteAffineAnimTable[];
extern const struct SpriteTemplate gDummySpriteTemplate;
extern u8 gReservedSpritePaletteCount;
extern struct Sprite gSprites[];
extern u8 gOamLimit;
extern u16 gReservedSpriteTileCount;
extern s16 gSpriteCoordOffsetX;
extern s16 gSpriteCoordOffsetY;
extern struct OamMatrix gOamMatrices[];
extern bool8 gAffineAnimsDisabled;
void ResetSpriteData(void);
void AnimateSprites(void);
void BuildOamBuffer(void);
u8 CreateSprite(const struct SpriteTemplate *template, s16 x, s16 y, u8 subpriority);
u8 CreateSpriteAtEnd(const struct SpriteTemplate *template, s16 x, s16 y, u8 subpriority);
u8 CreateInvisibleSprite(void (*callback)(struct Sprite *));
u8 CreateSpriteAndAnimate(const struct SpriteTemplate *template, s16 x, s16 y, u8 subpriority);
void DestroySprite(struct Sprite *sprite);
void ResetOamRange(u8 a, u8 b);
void LoadOam(void);
void SetOamMatrix(u8 matrixNum, u16 a, u16 b, u16 c, u16 d);
void CalcCenterToCornerVec(struct Sprite *sprite, u8 shape, u8 size, u8 affineMode);
void SpriteCallbackDummy(struct Sprite *sprite);
void ProcessSpriteCopyRequests(void);
void RequestSpriteCopy(const u8 *src, u8 *dest, u16 size);
void FreeSpriteTiles(struct Sprite *sprite);
void FreeSpritePalette(struct Sprite *sprite);
void FreeSpriteOamMatrix(struct Sprite *sprite);
void DestroySpriteAndFreeResources(struct Sprite *sprite);
void sub_800142C(u32 a1, u32 a2, u16 *a3, u16 a4, u32 a5);
void AnimateSprite(struct Sprite *sprite);
void sub_8007E18(struct Sprite* sprite, s16 a2, s16 a3);
void StartSpriteAnim(struct Sprite *sprite, u8 animNum);
void StartSpriteAnimIfDifferent(struct Sprite *sprite, u8 animNum);
void SeekSpriteAnim(struct Sprite *sprite, u8 animCmdIndex);
void StartSpriteAffineAnim(struct Sprite *sprite, u8 animNum);
void StartSpriteAffineAnimIfDifferent(struct Sprite *sprite, u8 animNum);
void ChangeSpriteAffineAnim(struct Sprite *sprite, u8 animNum);
void ChangeSpriteAffineAnimIfDifferent(struct Sprite *sprite, u8 animNum);
void SetSpriteSheetFrameTileNum(struct Sprite *sprite);
u8 AllocOamMatrix(void);
void FreeOamMatrix(u8 matrixNum);
void InitSpriteAffineAnim(struct Sprite *sprite);
void SetOamMatrixRotationScaling(u8 matrixNum, s16 xScale, s16 yScale, u16 rotation);
u16 LoadSpriteSheet(const struct SpriteSheet *sheet);
void LoadSpriteSheets(const struct SpriteSheet *sheets);
u16 AllocTilesForSpriteSheet(struct SpriteSheet *sheet);
void AllocTilesForSpriteSheets(struct SpriteSheet *sheets);
void LoadTilesForSpriteSheet(const struct SpriteSheet *sheet);
void LoadTilesForSpriteSheets(struct SpriteSheet *sheets);
void FreeSpriteTilesByTag(u16 tag);
void FreeSpriteTileRanges(void);
u16 GetSpriteTileStartByTag(u16 tag);
u16 GetSpriteTileTagByTileStart(u16 start);
void RequestSpriteSheetCopy(const struct SpriteSheet *sheet);
u16 LoadSpriteSheetDeferred(const struct SpriteSheet *sheet);
void FreeAllSpritePalettes(void);
u8 LoadSpritePalette(const struct SpritePalette *palette);
void LoadSpritePalettes(const struct SpritePalette *palettes);
u8 AllocSpritePalette(u16 tag);
u8 IndexOfSpritePaletteTag(u16 tag);
u16 GetSpritePaletteTagByPaletteNum(u8 paletteNum);
void FreeSpritePaletteByTag(u16 tag);
void SetSubspriteTables(struct Sprite *sprite, const struct SubspriteTable *subspriteTables);
bool8 AddSpriteToOamBuffer(struct Sprite *object, u8 *oamIndex);
bool8 AddSubspritesToOamBuffer(struct Sprite *sprite, struct OamData *destOam, u8 *oamIndex);
void CopyToSprites(u8 *src);
void CopyFromSprites(u8 *dest);
u8 SpriteTileAllocBitmapOp(u16 bit, u8 op);
void ClearSpriteCopyRequests(void);
void ResetAffineAnimData(void);
#endif //GUARD_SPRITE_H
+784
View File
@@ -0,0 +1,784 @@
#include "global.h"
#include "string_util.h"
#include "text.h"
EWRAM_DATA u8 gStringVar1[0x100] = {0};
EWRAM_DATA u8 gStringVar2[0x100] = {0};
EWRAM_DATA u8 gStringVar3[0x100] = {0};
EWRAM_DATA u8 gStringVar4[0x3E8] = {0};
EWRAM_DATA static u8 sUnknownStringVar[16] = {0};
static const u8 sDigits[] = __("0123456789ABCDEF");
static const s32 sPowersOfTen[] =
{
1,
10,
100,
1000,
10000,
100000,
1000000,
10000000,
100000000,
1000000000,
};
extern const u8 gExpandedPlaceholder_Empty[];
extern const u8 gExpandedPlaceholder_Kun[];
extern const u8 gExpandedPlaceholder_Chan[];
extern const u8 gExpandedPlaceholder_Sapphire[];
extern const u8 gExpandedPlaceholder_Ruby[];
extern const u8 gExpandedPlaceholder_Emerald[];
extern const u8 gExpandedPlaceholder_Aqua[];
extern const u8 gExpandedPlaceholder_Magma[];
extern const u8 gExpandedPlaceholder_Archie[];
extern const u8 gExpandedPlaceholder_Maxie[];
extern const u8 gExpandedPlaceholder_Kyogre[];
extern const u8 gExpandedPlaceholder_Groudon[];
extern const u8 gExpandedPlaceholder_Brendan[];
extern const u8 gExpandedPlaceholder_May[];
u8 *StringCopy10(u8 *dest, const u8 *src)
{
u8 i;
u32 limit = 10;
for (i = 0; i < limit; i++)
{
dest[i] = src[i];
if (dest[i] == EOS)
return &dest[i];
}
dest[i] = EOS;
return &dest[i];
}
u8 *StringGetEnd10(u8 *str)
{
u8 i;
u32 limit = 10;
for (i = 0; i < limit; i++)
if (str[i] == EOS)
return &str[i];
str[i] = EOS;
return &str[i];
}
u8 *StringCopy7(u8 *dest, const u8 *src)
{
s32 i;
s32 limit = 7;
for (i = 0; i < limit; i++)
{
dest[i] = src[i];
if (dest[i] == EOS)
return &dest[i];
}
dest[i] = EOS;
return &dest[i];
}
u8 *StringCopy(u8 *dest, const u8 *src)
{
while (*src != EOS)
{
*dest = *src;
dest++;
src++;
}
*dest = EOS;
return dest;
}
u8 *StringAppend(u8 *dest, const u8 *src)
{
while (*dest != EOS)
dest++;
return StringCopy(dest, src);
}
u8 *StringCopyN(u8 *dest, const u8 *src, u8 n)
{
u16 i;
for (i = 0; i < n; i++)
dest[i] = src[i];
return &dest[n];
}
u8 *StringAppendN(u8 *dest, const u8 *src, u8 n)
{
while (*dest != EOS)
dest++;
return StringCopyN(dest, src, n);
}
u16 StringLength(const u8 *str)
{
u16 length = 0;
while (str[length] != EOS)
length++;
return length;
}
s32 StringCompare(const u8 *str1, const u8 *str2)
{
while (*str1 == *str2)
{
if (*str1 == EOS)
return 0;
str1++;
str2++;
}
return *str1 - *str2;
}
s32 StringCompareN(const u8 *str1, const u8 *str2, u32 n)
{
while (*str1 == *str2)
{
if (*str1 == EOS)
return 0;
str1++;
str2++;
if (--n == 0)
return 0;
}
return *str1 - *str2;
}
bool8 IsStringLengthAtLeast(const u8 *str, s32 n)
{
u8 i;
for (i = 0; i < n; i++)
if (str[i] && str[i] != EOS)
return TRUE;
return FALSE;
}
u8 *ConvertIntToDecimalStringN(u8 *dest, s32 value, enum StringConvertMode mode, u8 n)
{
enum { WAITING_FOR_NONZERO_DIGIT, WRITING_DIGITS, WRITING_SPACES } state;
s32 powerOfTen;
s32 largestPowerOfTen = sPowersOfTen[n - 1];
state = WAITING_FOR_NONZERO_DIGIT;
if (mode == STR_CONV_MODE_RIGHT_ALIGN)
state = WRITING_SPACES;
if (mode == STR_CONV_MODE_LEADING_ZEROS)
state = WRITING_DIGITS;
for (powerOfTen = largestPowerOfTen; powerOfTen > 0; powerOfTen /= 10)
{
u8 c;
u16 digit = value / powerOfTen;
s32 temp = value - (powerOfTen * digit);
if (state == WRITING_DIGITS)
{
u8 *out = dest++;
if (digit <= 9)
c = sDigits[digit];
else
c = CHAR_QUESTION_MARK;
*out = c;
}
else if (digit != 0 || powerOfTen == 1)
{
u8 *out;
state = WRITING_DIGITS;
out = dest++;
if (digit <= 9)
c = sDigits[digit];
else
c = CHAR_QUESTION_MARK;
*out = c;
}
else if (state == WRITING_SPACES)
{
*dest++ = 0x77;
}
value = temp;
}
*dest = EOS;
return dest;
}
u8 *ConvertUIntToDecimalStringN(u8 *dest, u32 value, enum StringConvertMode mode, u8 n)
{
enum { WAITING_FOR_NONZERO_DIGIT, WRITING_DIGITS, WRITING_SPACES } state;
s32 powerOfTen;
s32 largestPowerOfTen = sPowersOfTen[n - 1];
state = WAITING_FOR_NONZERO_DIGIT;
if (mode == STR_CONV_MODE_RIGHT_ALIGN)
state = WRITING_SPACES;
if (mode == STR_CONV_MODE_LEADING_ZEROS)
state = WRITING_DIGITS;
for (powerOfTen = largestPowerOfTen; powerOfTen > 0; powerOfTen /= 10)
{
u8 c;
u16 digit = value / powerOfTen;
u32 temp = value - (powerOfTen * digit);
if (state == WRITING_DIGITS)
{
u8 *out = dest++;
if (digit <= 9)
c = sDigits[digit];
else
c = CHAR_QUESTION_MARK;
*out = c;
}
else if (digit != 0 || powerOfTen == 1)
{
u8 *out;
state = WRITING_DIGITS;
out = dest++;
if (digit <= 9)
c = sDigits[digit];
else
c = CHAR_QUESTION_MARK;
*out = c;
}
else if (state == WRITING_SPACES)
{
*dest++ = 0x77;
}
value = temp;
}
*dest = EOS;
return dest;
}
u8 *ConvertIntToHexStringN(u8 *dest, s32 value, enum StringConvertMode mode, u8 n)
{
enum { WAITING_FOR_NONZERO_DIGIT, WRITING_DIGITS, WRITING_SPACES } state;
u8 i;
s32 powerOfSixteen;
s32 largestPowerOfSixteen = 1;
for (i = 1; i < n; i++)
largestPowerOfSixteen *= 16;
state = WAITING_FOR_NONZERO_DIGIT;
if (mode == STR_CONV_MODE_RIGHT_ALIGN)
state = WRITING_SPACES;
if (mode == STR_CONV_MODE_LEADING_ZEROS)
state = WRITING_DIGITS;
for (powerOfSixteen = largestPowerOfSixteen; powerOfSixteen > 0; powerOfSixteen /= 16)
{
u8 c;
u32 digit = value / powerOfSixteen;
s32 temp = value % powerOfSixteen;
if (state == WRITING_DIGITS)
{
char *out = dest++;
if (digit <= 0xF)
c = sDigits[digit];
else
c = CHAR_QUESTION_MARK;
*out = c;
}
else if (digit != 0 || powerOfSixteen == 1)
{
char *out;
state = WRITING_DIGITS;
out = dest++;
if (digit <= 0xF)
c = sDigits[digit];
else
c = CHAR_QUESTION_MARK;
*out = c;
}
else if (state == WRITING_SPACES)
{
*dest++ = 0x77;
}
value = temp;
}
*dest = EOS;
return dest;
}
u8 *StringExpandPlaceholders(u8 *dest, const u8 *src)
{
for (;;)
{
u8 c = *src++;
u8 placeholderId;
const u8 *expandedString;
switch (c)
{
case PLACEHOLDER_BEGIN:
placeholderId = *src++;
expandedString = GetExpandedPlaceholder(placeholderId);
dest = StringExpandPlaceholders(dest, expandedString);
break;
case EXT_CTRL_CODE_BEGIN:
*dest++ = c;
c = *src++;
*dest++ = c;
switch (c)
{
case 0x07:
case 0x09:
case 0x0F:
case 0x15:
case 0x16:
case 0x17:
case 0x18:
break;
case 0x04:
*dest++ = *src++;
case 0x0B:
*dest++ = *src++;
default:
*dest++ = *src++;
}
break;
case EOS:
*dest = EOS;
return dest;
case CHAR_PROMPT_SCROLL:
case CHAR_PROMPT_CLEAR:
case CHAR_NEWLINE:
default:
*dest++ = c;
}
}
}
u8 *StringBraille(u8 *dest, const u8 *src)
{
u8 setBrailleFont[] = { EXT_CTRL_CODE_BEGIN, 0x06, 0x06, EOS };
u8 gotoLine2[] = { CHAR_NEWLINE, EXT_CTRL_CODE_BEGIN, 0x0E, 0x02, EOS };
dest = StringCopy(dest, setBrailleFont);
for (;;)
{
u8 c = *src++;
switch (c)
{
case EOS:
*dest = c;
return dest;
case CHAR_NEWLINE:
dest = StringCopy(dest, gotoLine2);
break;
default:
*dest++ = c;
*dest++ = c + 0x40;
break;
}
}
}
static const u8 *ExpandPlaceholder_UnknownStringVar(void)
{
return sUnknownStringVar;
}
static const u8 *ExpandPlaceholder_PlayerName(void)
{
return gSaveBlock2Ptr->playerName;
}
static const u8 *ExpandPlaceholder_StringVar1(void)
{
return gStringVar1;
}
static const u8 *ExpandPlaceholder_StringVar2(void)
{
return gStringVar2;
}
static const u8 *ExpandPlaceholder_StringVar3(void)
{
return gStringVar3;
}
static const u8 *ExpandPlaceholder_KunChan(void)
{
if (gSaveBlock2Ptr->playerGender == MALE)
return gExpandedPlaceholder_Kun;
else
return gExpandedPlaceholder_Chan;
}
static const u8 *ExpandPlaceholder_RivalName(void)
{
if (gSaveBlock2Ptr->playerGender == MALE)
return gExpandedPlaceholder_May;
else
return gExpandedPlaceholder_Brendan;
}
static const u8 *ExpandPlaceholder_Version(void)
{
return gExpandedPlaceholder_Emerald;
}
static const u8 *ExpandPlaceholder_Aqua(void)
{
return gExpandedPlaceholder_Aqua;
}
static const u8 *ExpandPlaceholder_Magma(void)
{
return gExpandedPlaceholder_Magma;
}
static const u8 *ExpandPlaceholder_Archie(void)
{
return gExpandedPlaceholder_Archie;
}
static const u8 *ExpandPlaceholder_Maxie(void)
{
return gExpandedPlaceholder_Maxie;
}
static const u8 *ExpandPlaceholder_Kyogre(void)
{
return gExpandedPlaceholder_Kyogre;
}
static const u8 *ExpandPlaceholder_Groudon(void)
{
return gExpandedPlaceholder_Groudon;
}
const u8 *GetExpandedPlaceholder(u32 id)
{
typedef const u8 *(*ExpandPlaceholderFunc)(void);
static const ExpandPlaceholderFunc funcs[] =
{
ExpandPlaceholder_UnknownStringVar,
ExpandPlaceholder_PlayerName,
ExpandPlaceholder_StringVar1,
ExpandPlaceholder_StringVar2,
ExpandPlaceholder_StringVar3,
ExpandPlaceholder_KunChan,
ExpandPlaceholder_RivalName,
ExpandPlaceholder_Version,
ExpandPlaceholder_Aqua,
ExpandPlaceholder_Magma,
ExpandPlaceholder_Archie,
ExpandPlaceholder_Maxie,
ExpandPlaceholder_Kyogre,
ExpandPlaceholder_Groudon,
};
if (id >= ARRAY_COUNT(funcs))
return gExpandedPlaceholder_Empty;
else
return funcs[id]();
}
u8 *StringFill(u8 *dest, u8 c, u16 n)
{
u16 i;
for (i = 0; i < n; i++)
*dest++ = c;
*dest = EOS;
return dest;
}
u8 *StringCopyPadded(u8 *dest, const u8 *src, u8 c, u16 n)
{
while (*src != EOS)
{
*dest++ = *src++;
if (n)
n--;
}
n--;
while (n != (u16)-1)
{
*dest++ = c;
n--;
}
*dest = EOS;
return dest;
}
u8 *StringFillWithTerminator(u8 *dest, u16 n)
{
return StringFill(dest, EOS, n);
}
u8 *StringCopyN_Multibyte(u8 *dest, u8 *src, u32 n)
{
u32 i;
for (i = n - 1; i != (u32)-1; i--)
{
if (*src == EOS)
{
break;
}
else
{
*dest++ = *src++;
if (*(src - 1) == CHAR_SPECIAL_F9)
*dest++ = *src++;
}
}
*dest = EOS;
return dest;
}
u32 StringLength_Multibyte(const u8 *str)
{
u32 length = 0;
while (*str != EOS)
{
if (*str == CHAR_SPECIAL_F9)
str++;
str++;
length++;
}
return length;
}
u8 *WriteColorChangeControlCode(u8 *dest, u32 colorType, u8 color)
{
*dest = EXT_CTRL_CODE_BEGIN;
dest++;
switch (colorType)
{
case 0:
*dest = 1;
dest++;
break;
case 1:
*dest = 3;
dest++;
break;
case 2:
*dest = 2;
dest++;
break;
}
*dest = color;
dest++;
*dest = EOS;
return dest;
}
bool32 IsStringJapanese(u8 *str)
{
while (*str != EOS)
{
if (*str <= 0xA0)
if (*str != CHAR_SPACE)
return TRUE;
str++;
}
return FALSE;
}
bool32 sub_800924C(u8 *str, s32 n)
{
s32 i;
for (i = 0; *str != EOS && i < n; i++)
{
if (*str <= 0xA0)
if (*str != CHAR_SPACE)
return TRUE;
str++;
}
return FALSE;
}
u8 GetExtCtrlCodeLength(u8 code)
{
static const u8 lengths[] =
{
1,
2,
2,
2,
4,
2,
2,
1,
2,
1,
1,
3,
2,
2,
2,
1,
3,
2,
2,
2,
2,
1,
1,
1,
1,
};
u8 length = 0;
if (code < ARRAY_COUNT(lengths))
length = lengths[code];
return length;
}
static const u8 *SkipExtCtrlCode(const u8 *s)
{
while (*s == EXT_CTRL_CODE_BEGIN)
{
s++;
s += GetExtCtrlCodeLength(*s);
}
return s;
}
s32 StringCompareWithoutExtCtrlCodes(const u8 *str1, const u8 *str2)
{
s32 retVal = 0;
while (1)
{
str1 = SkipExtCtrlCode(str1);
str2 = SkipExtCtrlCode(str2);
if (*str1 > *str2)
break;
if (*str1 < *str2)
{
retVal = -1;
if (*str2 == EOS)
retVal = 1;
}
if (*str1 == EOS)
return retVal;
str1++;
str2++;
}
retVal = 1;
if (*str1 == EOS)
retVal = -1;
return retVal;
}
void ConvertInternationalString(u8 *s, u8 language)
{
if (language == LANGUAGE_JAPANESE)
{
u8 i;
StripExtCtrlCodes(s);
i = StringLength(s);
s[i++] = EXT_CTRL_CODE_BEGIN;
s[i++] = 22;
s[i++] = EOS;
i--;
while (i != (u8)-1)
{
s[i + 2] = s[i];
i--;
}
s[0] = EXT_CTRL_CODE_BEGIN;
s[1] = 21;
}
}
void StripExtCtrlCodes(u8 *str)
{
u16 srcIndex = 0;
u16 destIndex = 0;
while (str[srcIndex] != EOS)
{
if (str[srcIndex] == EXT_CTRL_CODE_BEGIN)
{
srcIndex++;
srcIndex += GetExtCtrlCodeLength(str[srcIndex]);
}
else
{
str[destIndex++] = str[srcIndex++];
}
}
str[destIndex] = EOS;
}
+46
View File
@@ -0,0 +1,46 @@
#ifndef GUARD_STRING_UTIL_H
#define GUARD_STRING_UTIL_H
extern u8 gStringVar1[];
extern u8 gStringVar2[];
extern u8 gStringVar3[];
extern u8 gStringVar4[];
enum StringConvertMode
{
STR_CONV_MODE_LEFT_ALIGN,
STR_CONV_MODE_RIGHT_ALIGN,
STR_CONV_MODE_LEADING_ZEROS
};
u8 *StringCopy10(u8 *dest, const u8 *src);
u8 *StringGetEnd10(u8 *str);
u8 *StringCopy7(u8 *dest, const u8 *src);
u8 *StringCopy(u8 *dest, const u8 *src);
u8 *StringAppend(u8 *dest, const u8 *src);
u8 *StringCopyN(u8 *dest, const u8 *src, u8 n);
u8 *StringAppendN(u8 *dest, const u8 *src, u8 n);
u16 StringLength(const u8 *str);
s32 StringCompare(const u8 *str1, const u8 *str2);
s32 StringCompareN(const u8 *str1, const u8 *str2, u32 n);
bool8 IsStringLengthAtLeast(const u8 *str, s32 n);
u8 *ConvertIntToDecimalStringN(u8 *dest, s32 value, enum StringConvertMode mode, u8 n);
u8 *ConvertUIntToDecimalStringN(u8 *dest, u32 value, enum StringConvertMode mode, u8 n);
u8 *ConvertIntToHexStringN(u8 *dest, s32 value, enum StringConvertMode mode, u8 n);
u8 *StringExpandPlaceholders(u8 *dest, const u8 *src);
u8 *StringBraille(u8 *dest, const u8 *src);
const u8 *GetExpandedPlaceholder(u32 id);
u8 *StringFill(u8 *dest, u8 c, u16 n);
u8 *StringCopyPadded(u8 *dest, const u8 *src, u8 c, u16 n);
u8 *StringFillWithTerminator(u8 *dest, u16 n);
u8 *StringCopyN_Multibyte(u8 *dest, u8 *src, u32 n);
u32 StringLength_Multibyte(const u8 *str);
u8 *WriteColorChangeControlCode(u8 *dest, u32 colorType, u8 color);
bool32 IsStringJapanese(u8 *str);
bool32 sub_800924C(u8 *str, s32 n);
u8 GetExtCtrlCodeLength(u8 code);
s32 StringCompareWithoutExtCtrlCodes(const u8 *str1, const u8 *str2);
void ConvertInternationalString(u8 *s, u8 language);
void StripExtCtrlCodes(u8 *str);
#endif // GUARD_STRING_UTIL_H
+2540
View File
File diff suppressed because it is too large Load Diff
+297
View File
@@ -0,0 +1,297 @@
#ifndef GUARD_TEXT_H
#define GUARD_TEXT_H
#define CHAR_SPACE 0x00
#define CHAR_PLUS 0x2E
#define CHAR_0 0xA1
#define CHAR_1 0xA2
#define CHAR_2 0xA3
#define CHAR_3 0xA4
#define CHAR_4 0xA5
#define CHAR_5 0xA6
#define CHAR_6 0xA7
#define CHAR_7 0xA8
#define CHAR_8 0xA9
#define CHAR_9 0xAA
#define CHAR_EXCL_MARK 0xAB
#define CHAR_QUESTION_MARK 0xAC
#define CHAR_PERIOD 0xAD
#define CHAR_HYPHEN 0xAE
#define CHAR_ELLIPSIS 0xB0
#define CHAR_DBL_QUOT_LEFT 0xB1
#define CHAR_DBL_QUOT_RIGHT 0xB2
#define CHAR_SGL_QUOT_LEFT 0xB3
#define CHAR_SGL_QUOT_RIGHT 0xB4
#define CHAR_MALE 0xB5
#define CHAR_FEMALE 0xB6
#define CHAR_CURRENCY 0xB7
#define CHAR_COMMA 0xB8
#define CHAR_MULT_SIGN 0xB9
#define CHAR_SLASH 0xBA
#define CHAR_A 0xBB
#define CHAR_B 0xBC
#define CHAR_C 0xBD
#define CHAR_D 0xBE
#define CHAR_E 0xBF
#define CHAR_F 0xC0
#define CHAR_G 0xC1
#define CHAR_H 0xC2
#define CHAR_I 0xC3
#define CHAR_J 0xC4
#define CHAR_K 0xC5
#define CHAR_L 0xC6
#define CHAR_M 0xC7
#define CHAR_N 0xC8
#define CHAR_O 0xC9
#define CHAR_P 0xCA
#define CHAR_Q 0xCB
#define CHAR_R 0xCC
#define CHAR_S 0xCD
#define CHAR_T 0xCE
#define CHAR_U 0xCF
#define CHAR_V 0xD0
#define CHAR_W 0xD1
#define CHAR_X 0xD2
#define CHAR_Y 0xD3
#define CHAR_Z 0xD4
#define CHAR_a 0xD5
#define CHAR_b 0xD6
#define CHAR_c 0xD7
#define CHAR_d 0xD8
#define CHAR_e 0xD9
#define CHAR_f 0xDA
#define CHAR_g 0xDB
#define CHAR_h 0xDC
#define CHAR_i 0xDD
#define CHAR_j 0xDE
#define CHAR_k 0xDF
#define CHAR_l 0xE0
#define CHAR_m 0xE1
#define CHAR_n 0xE2
#define CHAR_o 0xE3
#define CHAR_p 0xE4
#define CHAR_q 0xE5
#define CHAR_r 0xE6
#define CHAR_s 0xE7
#define CHAR_t 0xE8
#define CHAR_u 0xE9
#define CHAR_v 0xEA
#define CHAR_w 0xEB
#define CHAR_x 0xEC
#define CHAR_y 0xED
#define CHAR_z 0xEE
#define CHAR_SPECIAL_F7 0xF7
#define CHAR_SPECIAL_F8 0xF8
#define CHAR_SPECIAL_F9 0xF9
#define CHAR_COLON 0xF0
#define CHAR_PROMPT_SCROLL 0xFA // waits for button press and scrolls dialog
#define CHAR_PROMPT_CLEAR 0xFB // waits for button press and clears dialog
#define EXT_CTRL_CODE_BEGIN 0xFC // extended control code
#define PLACEHOLDER_BEGIN 0xFD // string placeholder
#define CHAR_NEWLINE 0xFE
#define EOS 0xFF // end of string
#define EXT_CTRL_CODE_COLOR 0x1
#define EXT_CTRL_CODE_HIGHLIGHT 0x2
#define EXT_CTRL_CODE_SHADOW 0x3
//
#define EXT_CTRL_CODE_UNKNOWN_7 0x7
//
#define EXT_CTRL_CODE_CLEAR 0x11
//
#define EXT_CTRL_CODE_CLEAR_TO 0x13
#define EXT_CTRL_CODE_MIN_LETTER_SPACING 0x14
#define EXT_CTRL_CODE_JPN 0x15
#define EXT_CTRL_CODE_ENG 0x16
#define TEXT_COLOR_TRANSPARENT 0x0
#define TEXT_COLOR_WHITE 0x1
#define TEXT_COLOR_DARK_GREY 0x2
// 0x3
#define TEXT_COLOR_RED 0x4
// 0x5
#define TEXT_COLOR_GREEN 0x6
// 0x7
#define TEXT_COLOR_BLUE 0x8
// battle placeholders are located in battle_message.h
#define NUM_TEXT_PRINTERS 32
#define TEXT_SPEED_FF 0xFF
enum
{
FONTATTR_MAX_LETTER_WIDTH,
FONTATTR_MAX_LETTER_HEIGHT,
FONTATTR_LETTER_SPACING,
FONTATTR_LINE_SPACING,
FONTATTR_UNKNOWN, // dunno what this is yet
FONTATTR_COLOR_FOREGROUND,
FONTATTR_COLOR_BACKGROUND,
FONTATTR_COLOR_SHADOW
};
struct TextPrinterSubStruct
{
u8 glyphId:4; // 0x14
bool8 hasPrintBeenSpedUp:1;
u8 unk:3;
u8 downArrowDelay:5;
u8 downArrowYPosIdx:2;
bool8 hasGlyphIdBeenSet:1;
u8 autoScrollDelay;
};
struct TextPrinterTemplate
{
const u8* currentChar;
u8 windowId;
u8 fontId;
u8 x;
u8 y;
u8 currentX; // 0x8
u8 currentY;
u8 letterSpacing;
u8 lineSpacing;
u8 unk:4; // 0xC
u8 fgColor:4;
u8 bgColor:4;
u8 shadowColor:4;
};
struct TextPrinter
{
struct TextPrinterTemplate printerTemplate;
void (*callback)(struct TextPrinterTemplate *, u16); // 0x10
union
#if !MODERN
__attribute__((packed))
#endif
{
struct TextPrinterSubStruct sub;
u8 fields[7];
} subUnion;
u8 active;
u8 state; // 0x1C
u8 textSpeed;
u8 delayCounter;
u8 scrollDistance;
u8 minLetterSpacing; // 0x20
u8 japanese;
};
struct FontInfo
{
u16 (*fontFunction)(struct TextPrinter *x);
u8 maxLetterWidth;
u8 maxLetterHeight;
u8 letterSpacing;
u8 lineSpacing;
u8 unk:4;
u8 fgColor:4;
u8 bgColor:4;
u8 shadowColor:4;
};
extern const struct FontInfo *gFonts;
struct GlyphWidthFunc
{
u32 fontId;
u32 (*func)(u16 glyphId, bool32 isJapanese);
};
struct KeypadIcon
{
u16 tileOffset;
u8 width;
u8 height;
};
typedef struct {
bool8 canABSpeedUpPrint:1;
bool8 useAlternateDownArrow:1;
bool8 autoScroll:1;
bool8 forceMidTextSpeed:1;
} TextFlags;
struct Struct_03002F90
{
u32 unk0[8];
u32 unk20[8];
u32 unk40[8];
u32 unk60[8];
u8 unk80;
u8 unk81;
};
extern TextFlags gTextFlags;
extern u8 gUnknown_03002F84;
extern struct Struct_03002F90 gUnknown_03002F90;
void SetFontsPointer(const struct FontInfo *fonts);
void DeactivateAllTextPrinters(void);
u16 AddTextPrinterParameterized(u8 windowId, u8 fontId, const u8 *str, u8 x, u8 y, u8 speed, void (*callback)(struct TextPrinterTemplate *, u16));
bool16 AddTextPrinter(struct TextPrinterTemplate *template, u8 speed, void (*callback)(struct TextPrinterTemplate *, u16));
void RunTextPrinters(void);
bool16 IsTextPrinterActive(u8 id);
u32 RenderFont(struct TextPrinter *textPrinter);
void GenerateFontHalfRowLookupTable(u8 fgColor, u8 bgColor, u8 shadowColor);
void SaveTextColors(u8 *fgColor, u8 *bgColor, u8 *shadowColor);
void RestoreTextColors(u8 *fgColor, u8 *bgColor, u8 *shadowColor);
void DecompressGlyphTile(const void *src_, void *dest_);
u8 GetLastTextColor(u8 colorType);
void CopyGlyphToWindow(struct TextPrinter *x);
void ClearTextSpan(struct TextPrinter *textPrinter, u32 width);
u8 GetMenuCursorDimensionByFont(u8, u8);
u16 Font0Func(struct TextPrinter *textPrinter);
u16 Font1Func(struct TextPrinter *textPrinter);
u16 Font2Func(struct TextPrinter *textPrinter);
u16 Font3Func(struct TextPrinter *textPrinter);
u16 Font4Func(struct TextPrinter *textPrinter);
u16 Font5Func(struct TextPrinter *textPrinter);
u16 Font7Func(struct TextPrinter *textPrinter);
u16 Font8Func(struct TextPrinter *textPrinter);
void TextPrinterInitDownArrowCounters(struct TextPrinter *textPrinter);
void TextPrinterDrawDownArrow(struct TextPrinter *textPrinter);
void TextPrinterClearDownArrow(struct TextPrinter *textPrinter);
bool8 TextPrinterWaitAutoMode(struct TextPrinter *textPrinter);
bool16 TextPrinterWaitWithDownArrow(struct TextPrinter *textPrinter);
bool16 TextPrinterWait(struct TextPrinter *textPrinter);
void DrawDownArrow(u8 windowId, u16 x, u16 y, u8 bgColor, bool8 drawArrow, u8 *counter, u8 *yCoordIndex);
u16 RenderText(struct TextPrinter *textPrinter);
u32 GetStringWidthFixedWidthFont(const u8 *str, u8 fontId, u8 letterSpacing);
u32 (*GetFontWidthFunc(u8 glyphId))(u16, bool32);
s32 GetStringWidth(u8 fontId, const u8 *str, s16 letterSpacing);
u8 RenderTextFont9(u8 *pixels, u8 fontId, u8 *str);
u8 DrawKeypadIcon(u8 windowId, u8 keypadIconId, u16 x, u16 y);
u8 GetKeypadIconTileOffset(u8 keypadIconId);
u8 GetKeypadIconWidth(u8 keypadIconId);
u8 GetKeypadIconHeight(u8 keypadIconId);
void SetDefaultFontsPointer(void);
u8 GetFontAttribute(u8 fontId, u8 attributeId);
u8 GetMenuCursorDimensionByFont(u8 fontId, u8 whichDimension);
void DecompressGlyphFont0(u16 glyphId, bool32 isJapanese);
u32 GetGlyphWidthFont0(u16 glyphId, bool32 isJapanese);
void DecompressGlyphFont7(u16 glyphId, bool32 isJapanese);
u32 GetGlyphWidthFont7(u16 glyphId, bool32 isJapanese);
void DecompressGlyphFont8(u16 glyphId, bool32 isJapanese);
u32 GetGlyphWidthFont8(u16 glyphId, bool32 isJapanese);
void DecompressGlyphFont2(u16 glyphId, bool32 isJapanese);
u32 GetGlyphWidthFont2(u16 glyphId, bool32 isJapanese);
void DecompressGlyphFont1(u16 glyphId, bool32 isJapanese);
u32 GetGlyphWidthFont1(u16 glyphId, bool32 isJapanese);
void DecompressGlyphFont9(u16 glyphId);
// unk_text_util_2.c
u16 Font6Func(struct TextPrinter *textPrinter);
u32 GetGlyphWidthFont6(u16 glyphId, bool32 isJapanese);
#endif // GUARD_TEXT_H
+721
View File
@@ -0,0 +1,721 @@
#include "global.h"
#include "window.h"
#include "malloc.h"
#include "bg.h"
#include "blit.h"
u32 filler_03002F58;
u32 filler_03002F5C;
// This global is set to 0 and never changed.
u8 gTransparentTileNumber;
u32 filler_03002F64;
void *gUnknown_03002F70[4];
extern u32 gUnneededFireRedVariable;
#define WINDOWS_MAX 32
EWRAM_DATA struct Window gWindows[WINDOWS_MAX] = {0};
EWRAM_DATA static struct Window* sWindowPtr = NULL;
EWRAM_DATA static u16 sWindowSize = 0;
static u8 GetNumActiveWindowsOnBg(u8 bgId);
static u8 GetNumActiveWindowsOnBg8Bit(u8 bgId);
static const struct WindowTemplate sDummyWindowTemplate = DUMMY_WIN_TEMPLATE;
static void nullsub_8(void)
{
}
bool16 InitWindows(const struct WindowTemplate *templates)
{
int i;
void *bgTilemapBuffer;
int j;
u8 bgLayer;
u16 attrib;
u8* allocatedTilemapBuffer;
int allocatedBaseBlock;
for (i = 0; i < 0x4; ++i)
{
bgTilemapBuffer = GetBgTilemapBuffer(i);
if (bgTilemapBuffer != NULL)
gUnknown_03002F70[i] = nullsub_8;
else
gUnknown_03002F70[i] = bgTilemapBuffer;
}
for (i = 0; i < 0x20; ++i)
{
gWindows[i].window = sDummyWindowTemplate;
gWindows[i].tileData = NULL;
}
for (i = 0, allocatedBaseBlock = 0, bgLayer = templates[i].bg; bgLayer != 0xFF && i < 0x20; ++i, bgLayer = templates[i].bg)
{
if (gUnneededFireRedVariable == 1)
{
allocatedBaseBlock = DummiedOutFireRedLeafGreenTileAllocFunc(bgLayer, 0, templates[i].width * templates[i].height, 0);
if (allocatedBaseBlock == -1)
return FALSE;
}
if (gUnknown_03002F70[bgLayer] == NULL)
{
attrib = GetBgAttribute(bgLayer, BG_ATTR_METRIC);
if (attrib != 0xFFFF)
{
allocatedTilemapBuffer = AllocZeroed(attrib);
if (allocatedTilemapBuffer == NULL)
{
FreeAllWindowBuffers();
return FALSE;
}
for (j = 0; j < attrib; ++j)
allocatedTilemapBuffer[j] = 0;
gUnknown_03002F70[bgLayer] = allocatedTilemapBuffer;
SetBgTilemapBuffer(bgLayer, allocatedTilemapBuffer);
}
}
allocatedTilemapBuffer = AllocZeroed((u16)(0x20 * (templates[i].width * templates[i].height)));
if (allocatedTilemapBuffer == NULL)
{
if ((GetNumActiveWindowsOnBg(bgLayer) == 0) && (gUnknown_03002F70[bgLayer] != nullsub_8))
{
Free(gUnknown_03002F70[bgLayer]);
gUnknown_03002F70[bgLayer] = allocatedTilemapBuffer;
}
return FALSE;
}
gWindows[i].tileData = allocatedTilemapBuffer;
gWindows[i].window = templates[i];
if (gUnneededFireRedVariable == 1)
{
gWindows[i].window.baseBlock = allocatedBaseBlock;
DummiedOutFireRedLeafGreenTileAllocFunc(bgLayer, allocatedBaseBlock, templates[i].width * templates[i].height, 1);
}
}
gTransparentTileNumber = 0;
return TRUE;
}
u16 AddWindow(const struct WindowTemplate *template)
{
u16 win;
u8 bgLayer;
int allocatedBaseBlock;
u16 attrib;
u8 *allocatedTilemapBuffer;
int i;
for (win = 0; win < WINDOWS_MAX; ++win)
{
if ((bgLayer = gWindows[win].window.bg) == 0xFF)
break;
}
if (win == WINDOWS_MAX)
return 0xFF;
bgLayer = template->bg;
allocatedBaseBlock = 0;
if (gUnneededFireRedVariable == 1)
{
allocatedBaseBlock = DummiedOutFireRedLeafGreenTileAllocFunc(bgLayer, 0, template->width * template->height, 0);
if (allocatedBaseBlock == -1)
return 0xFF;
}
if (gUnknown_03002F70[bgLayer] == NULL)
{
attrib = GetBgAttribute(bgLayer, BG_ATTR_METRIC);
if (attrib != 0xFFFF)
{
allocatedTilemapBuffer = AllocZeroed(attrib);
if (allocatedTilemapBuffer == NULL)
return 0xFF;
for (i = 0; i < attrib; ++i)
allocatedTilemapBuffer[i] = 0;
gUnknown_03002F70[bgLayer] = allocatedTilemapBuffer;
SetBgTilemapBuffer(bgLayer, allocatedTilemapBuffer);
}
}
allocatedTilemapBuffer = AllocZeroed((u16)(0x20 * (template->width * template->height)));
if (allocatedTilemapBuffer == NULL)
{
if ((GetNumActiveWindowsOnBg(bgLayer) == 0) && (gUnknown_03002F70[bgLayer] != nullsub_8))
{
Free(gUnknown_03002F70[bgLayer]);
gUnknown_03002F70[bgLayer] = allocatedTilemapBuffer;
}
return 0xFF;
}
gWindows[win].tileData = allocatedTilemapBuffer;
gWindows[win].window = *template;
if (gUnneededFireRedVariable == 1)
{
gWindows[win].window.baseBlock = allocatedBaseBlock;
DummiedOutFireRedLeafGreenTileAllocFunc(bgLayer, allocatedBaseBlock, gWindows[win].window.width * gWindows[win].window.height, 1);
}
return win;
}
int AddWindowWithoutTileMap(const struct WindowTemplate *template)
{
u16 win;
u8 bgLayer;
int allocatedBaseBlock;
for (win = 0; win < WINDOWS_MAX; ++win)
{
if (gWindows[win].window.bg == 0xFF)
break;
}
if (win == WINDOWS_MAX)
return 0xFF;
bgLayer = template->bg;
allocatedBaseBlock = 0;
if (gUnneededFireRedVariable == 1)
{
allocatedBaseBlock = DummiedOutFireRedLeafGreenTileAllocFunc(bgLayer, 0, template->width * template->height, 0);
if (allocatedBaseBlock == -1)
return 0xFF;
}
gWindows[win].window = *template;
if (gUnneededFireRedVariable == 1)
{
gWindows[win].window.baseBlock = allocatedBaseBlock;
DummiedOutFireRedLeafGreenTileAllocFunc(bgLayer, allocatedBaseBlock, gWindows[win].window.width * gWindows[win].window.height, 1);
}
return win;
}
void RemoveWindow(u8 windowId)
{
u8 bgLayer = gWindows[windowId].window.bg;
if (gUnneededFireRedVariable == 1)
{
DummiedOutFireRedLeafGreenTileAllocFunc(bgLayer, gWindows[windowId].window.baseBlock, gWindows[windowId].window.width * gWindows[windowId].window.height, 2);
}
gWindows[windowId].window = sDummyWindowTemplate;
if (GetNumActiveWindowsOnBg(bgLayer) == 0)
{
if (gUnknown_03002F70[bgLayer] != nullsub_8)
{
Free(gUnknown_03002F70[bgLayer]);
gUnknown_03002F70[bgLayer] = 0;
}
}
if (gWindows[windowId].tileData != NULL)
{
Free(gWindows[windowId].tileData);
gWindows[windowId].tileData = NULL;
}
}
void FreeAllWindowBuffers(void)
{
int i;
for (i = 0; i < 4; ++i)
{
if (gUnknown_03002F70[i] != NULL && gUnknown_03002F70[i] != nullsub_8)
{
Free(gUnknown_03002F70[i]);
gUnknown_03002F70[i] = NULL;
}
}
for (i = 0; i < 0x20; ++i)
{
if (gWindows[i].tileData != NULL)
{
Free(gWindows[i].tileData);
gWindows[i].tileData = NULL;
}
}
}
void CopyWindowToVram(u8 windowId, u8 mode)
{
struct Window windowLocal = gWindows[windowId];
u16 windowSize = 32 * (windowLocal.window.width * windowLocal.window.height);
switch (mode)
{
case 1:
CopyBgTilemapBufferToVram(windowLocal.window.bg);
break;
case 2:
LoadBgTiles(windowLocal.window.bg, windowLocal.tileData, windowSize, windowLocal.window.baseBlock);
break;
case 3:
LoadBgTiles(windowLocal.window.bg, windowLocal.tileData, windowSize, windowLocal.window.baseBlock);
CopyBgTilemapBufferToVram(windowLocal.window.bg);
break;
}
}
void CopyWindowRectToVram(u32 windowId, u32 mode, u32 x, u32 y, u32 w, u32 h)
{
struct Window windowLocal;
int rectSize;
int rectPos;
if (w != 0 && h != 0)
{
windowLocal = gWindows[windowId];
rectSize = ((h - 1) * windowLocal.window.width);
rectSize += (windowLocal.window.width - x);
rectSize -= (windowLocal.window.width - (x + w));
rectSize *= 32;
rectPos = (y * windowLocal.window.width) + x;
switch (mode)
{
case 1:
CopyBgTilemapBufferToVram(windowLocal.window.bg);
break;
case 2:
LoadBgTiles(windowLocal.window.bg, windowLocal.tileData + (rectPos * 32), rectSize, windowLocal.window.baseBlock + rectPos);
break;
case 3:
LoadBgTiles(windowLocal.window.bg, windowLocal.tileData + (rectPos * 32), rectSize, windowLocal.window.baseBlock + rectPos);
CopyBgTilemapBufferToVram(windowLocal.window.bg);
break;
}
}
}
void PutWindowTilemap(u8 windowId)
{
struct Window windowLocal = gWindows[windowId];
WriteSequenceToBgTilemapBuffer(
windowLocal.window.bg,
GetBgAttribute(windowLocal.window.bg, BG_ATTR_BASETILE) + windowLocal.window.baseBlock,
windowLocal.window.tilemapLeft,
windowLocal.window.tilemapTop,
windowLocal.window.width,
windowLocal.window.height,
windowLocal.window.paletteNum,
1);
}
void PutWindowRectTilemapOverridePalette(u8 windowId, u8 x, u8 y, u8 width, u8 height, u8 palette)
{
struct Window windowLocal = gWindows[windowId];
u16 currentRow = windowLocal.window.baseBlock + (y * windowLocal.window.width) + x + GetBgAttribute(windowLocal.window.bg, BG_ATTR_BASETILE);
int i;
for (i = 0; i < height; ++i)
{
WriteSequenceToBgTilemapBuffer(
windowLocal.window.bg,
currentRow,
windowLocal.window.tilemapLeft + x,
windowLocal.window.tilemapTop + y + i,
width,
1,
palette,
1);
currentRow += windowLocal.window.width;
}
}
// Fills a window with transparent tiles.
void ClearWindowTilemap(u8 windowId)
{
struct Window windowLocal = gWindows[windowId];
FillBgTilemapBufferRect(
windowLocal.window.bg,
gTransparentTileNumber,
windowLocal.window.tilemapLeft,
windowLocal.window.tilemapTop,
windowLocal.window.width,
windowLocal.window.height,
windowLocal.window.paletteNum);
}
void PutWindowRectTilemap(u8 windowId, u8 x, u8 y, u8 width, u8 height)
{
struct Window windowLocal = gWindows[windowId];
u16 currentRow = windowLocal.window.baseBlock + (y * windowLocal.window.width) + x + GetBgAttribute(windowLocal.window.bg, BG_ATTR_BASETILE);
int i;
for (i = 0; i < height; ++i)
{
WriteSequenceToBgTilemapBuffer(
windowLocal.window.bg,
currentRow,
windowLocal.window.tilemapLeft + x,
windowLocal.window.tilemapTop + y + i,
width,
1,
windowLocal.window.paletteNum,
1);
currentRow += windowLocal.window.width;
}
}
void BlitBitmapToWindow(u8 windowId, const u8 *pixels, u16 x, u16 y, u16 width, u16 height)
{
BlitBitmapRectToWindow(windowId, pixels, 0, 0, width, height, x, y, width, height);
}
void BlitBitmapRectToWindow(u8 windowId, const u8 *pixels, u16 srcX, u16 srcY, u16 srcWidth, int srcHeight, u16 destX, u16 destY, u16 rectWidth, u16 rectHeight)
{
struct Bitmap sourceRect;
struct Bitmap destRect;
sourceRect.pixels = (u8*)pixels;
sourceRect.width = srcWidth;
sourceRect.height = srcHeight;
destRect.pixels = gWindows[windowId].tileData;
destRect.width = 8 * gWindows[windowId].window.width;
destRect.height = 8 * gWindows[windowId].window.height;
BlitBitmapRect4Bit(&sourceRect, &destRect, srcX, srcY, destX, destY, rectWidth, rectHeight, 0);
}
static void BlitBitmapRectToWindowWithColorKey(u8 windowId, const u8 *pixels, u16 srcX, u16 srcY, u16 srcWidth, int srcHeight, u16 destX, u16 destY, u16 rectWidth, u16 rectHeight, u8 colorKey)
{
struct Bitmap sourceRect;
struct Bitmap destRect;
sourceRect.pixels = (u8*)pixels;
sourceRect.width = srcWidth;
sourceRect.height = srcHeight;
destRect.pixels = gWindows[windowId].tileData;
destRect.width = 8 * gWindows[windowId].window.width;
destRect.height = 8 * gWindows[windowId].window.height;
BlitBitmapRect4Bit(&sourceRect, &destRect, srcX, srcY, destX, destY, rectWidth, rectHeight, colorKey);
}
void FillWindowPixelRect(u8 windowId, u8 fillValue, u16 x, u16 y, u16 width, u16 height)
{
struct Bitmap pixelRect;
pixelRect.pixels = gWindows[windowId].tileData;
pixelRect.width = 8 * gWindows[windowId].window.width;
pixelRect.height = 8 * gWindows[windowId].window.height;
FillBitmapRect4Bit(&pixelRect, x, y, width, height, fillValue);
}
void CopyToWindowPixelBuffer(u8 windowId, const void *src, u16 size, u16 tileOffset)
{
if (size != 0)
CpuCopy16(src, gWindows[windowId].tileData + (0x20 * tileOffset), size);
else
LZ77UnCompWram(src, gWindows[windowId].tileData + (0x20 * tileOffset));
}
// Sets all pixels within the window to the fillValue color.
void FillWindowPixelBuffer(u8 windowId, u8 fillValue)
{
int fillSize = gWindows[windowId].window.width * gWindows[windowId].window.height;
CpuFastFill8(fillValue, gWindows[windowId].tileData, 0x20 * fillSize);
}
#define MOVE_TILES_DOWN(a) \
{ \
destOffset = i + (a); \
srcOffset = i + (((width * (distanceLoop & ~7)) | (distanceLoop & 7)) * 4); \
if (srcOffset < size) \
*(u32*)(tileData + destOffset) = *(u32*)(tileData + srcOffset); \
else \
*(u32*)(tileData + destOffset) = fillValue32; \
distanceLoop++; \
}
#define MOVE_TILES_UP(a) \
{ \
destOffset = i + (a); \
srcOffset = i + (((width * (distanceLoop & ~7)) | (distanceLoop & 7)) * 4); \
if (srcOffset < size) \
*(u32*)(tileData - destOffset) = *(u32*)(tileData - srcOffset); \
else \
*(u32*)(tileData - destOffset) = fillValue32; \
distanceLoop++; \
}
void ScrollWindow(u8 windowId, u8 direction, u8 distance, u8 fillValue)
{
struct WindowTemplate window = gWindows[windowId].window;
u8 *tileData = gWindows[windowId].tileData;
u32 fillValue32 = (fillValue << 24) | (fillValue << 16) | (fillValue << 8) | fillValue;
s32 size = window.height * window.width * 32;
u32 width = window.width;
s32 i;
s32 srcOffset, destOffset;
u32 distanceLoop;
switch (direction)
{
case 0:
for (i = 0; i < size; i += 32)
{
distanceLoop = distance;
MOVE_TILES_DOWN(0)
MOVE_TILES_DOWN(4)
MOVE_TILES_DOWN(8)
MOVE_TILES_DOWN(12)
MOVE_TILES_DOWN(16)
MOVE_TILES_DOWN(20)
MOVE_TILES_DOWN(24)
MOVE_TILES_DOWN(28)
}
break;
case 1:
tileData += size - 4;
for (i = 0; i < size; i += 32)
{
distanceLoop = distance;
MOVE_TILES_UP(0)
MOVE_TILES_UP(4)
MOVE_TILES_UP(8)
MOVE_TILES_UP(12)
MOVE_TILES_UP(16)
MOVE_TILES_UP(20)
MOVE_TILES_UP(24)
MOVE_TILES_UP(28)
}
break;
case 2:
break;
}
}
void CallWindowFunction(u8 windowId, void ( *func)(u8, u8, u8, u8, u8, u8))
{
struct WindowTemplate window = gWindows[windowId].window;
func(window.bg, window.tilemapLeft, window.tilemapTop, window.width, window.height, window.paletteNum);
}
bool8 SetWindowAttribute(u8 windowId, u8 attributeId, u32 value)
{
switch (attributeId)
{
case WINDOW_TILEMAP_LEFT:
gWindows[windowId].window.tilemapLeft = value;
return FALSE;
case WINDOW_TILEMAP_TOP:
gWindows[windowId].window.tilemapTop = value;
return FALSE;
case WINDOW_PALETTE_NUM:
gWindows[windowId].window.paletteNum = value;
return FALSE;
case WINDOW_BASE_BLOCK:
gWindows[windowId].window.baseBlock = value;
return FALSE;
case WINDOW_TILE_DATA:
gWindows[windowId].tileData = (u8*)(value);
return TRUE;
case WINDOW_BG:
case WINDOW_WIDTH:
case WINDOW_HEIGHT:
default:
return TRUE;
}
}
u32 GetWindowAttribute(u8 windowId, u8 attributeId)
{
switch (attributeId)
{
case WINDOW_BG:
return gWindows[windowId].window.bg;
case WINDOW_TILEMAP_LEFT:
return gWindows[windowId].window.tilemapLeft;
case WINDOW_TILEMAP_TOP:
return gWindows[windowId].window.tilemapTop;
case WINDOW_WIDTH:
return gWindows[windowId].window.width;
case WINDOW_HEIGHT:
return gWindows[windowId].window.height;
case WINDOW_PALETTE_NUM:
return gWindows[windowId].window.paletteNum;
case WINDOW_BASE_BLOCK:
return gWindows[windowId].window.baseBlock;
case WINDOW_TILE_DATA:
return (u32)(gWindows[windowId].tileData);
default:
return 0;
}
}
static u8 GetNumActiveWindowsOnBg(u8 bgId)
{
u8 windowsNum = 0;
s32 i;
for (i = 0; i < WINDOWS_MAX; i++)
{
if (gWindows[i].window.bg == bgId)
windowsNum++;
}
return windowsNum;
}
static void nullsub_9(void)
{
}
u16 AddWindow8Bit(const struct WindowTemplate *template)
{
u16 windowId;
u8* memAddress;
u8 bgLayer;
for (windowId = 0; windowId < 32; windowId++)
{
if (gWindows[windowId].window.bg == 0xFF)
break;
}
if (windowId == WINDOWS_MAX)
return 0xFF;
bgLayer = template->bg;
if (gUnknown_03002F70[bgLayer] == 0)
{
u16 attribute = GetBgAttribute(bgLayer, BG_ATTR_METRIC);
if (attribute != 0xFFFF)
{
s32 i;
memAddress = Alloc(attribute);
if (memAddress == NULL)
return 0xFF;
for (i = 0; i < attribute; i++) // if we're going to zero out the memory anyway, why not call AllocZeroed?
memAddress[i] = 0;
gUnknown_03002F70[bgLayer] = memAddress;
SetBgTilemapBuffer(bgLayer, memAddress);
}
}
memAddress = Alloc((u16)(0x40 * (template->width * template->height)));
if (memAddress == NULL)
{
if (GetNumActiveWindowsOnBg8Bit(bgLayer) == 0 && gUnknown_03002F70[bgLayer] != nullsub_9)
{
Free(gUnknown_03002F70[bgLayer]);
gUnknown_03002F70[bgLayer] = NULL;
}
return 0xFF;
}
else
{
gWindows[windowId].tileData = memAddress;
gWindows[windowId].window = *template;
return windowId;
}
}
void FillWindowPixelBuffer8Bit(u8 windowId, u8 fillValue)
{
s32 i;
s32 size;
size = (u16)(0x40 * (gWindows[windowId].window.width * gWindows[windowId].window.height));
for (i = 0; i < size; i++)
gWindows[windowId].tileData[i] = fillValue;
}
void FillWindowPixelRect8Bit(u8 windowId, u8 fillValue, u16 x, u16 y, u16 width, u16 height)
{
struct Bitmap pixelRect;
pixelRect.pixels = gWindows[windowId].tileData;
pixelRect.width = 8 * gWindows[windowId].window.width;
pixelRect.height = 8 * gWindows[windowId].window.height;
FillBitmapRect8Bit(&pixelRect, x, y, width, height, fillValue);
}
void BlitBitmapRectToWindow4BitTo8Bit(u8 windowId, const u8 *pixels, u16 srcX, u16 srcY, u16 srcWidth, int srcHeight, u16 destX, u16 destY, u16 rectWidth, u16 rectHeight, u8 paletteNum)
{
struct Bitmap sourceRect;
struct Bitmap destRect;
sourceRect.pixels = (u8*) pixels;
sourceRect.width = srcWidth;
sourceRect.height = srcHeight;
destRect.pixels = gWindows[windowId].tileData;
destRect.width = 8 * gWindows[windowId].window.width;
destRect.height = 8 * gWindows[windowId].window.height;
BlitBitmapRect4BitTo8Bit(&sourceRect, &destRect, srcX, srcY, destX, destY, rectWidth, rectHeight, 0, paletteNum);
}
void CopyWindowToVram8Bit(u8 windowId, u8 mode)
{
sWindowPtr = &gWindows[windowId];
sWindowSize = 0x40 * (sWindowPtr->window.width * sWindowPtr->window.height);
switch (mode)
{
case 1:
CopyBgTilemapBufferToVram(sWindowPtr->window.bg);
break;
case 2:
LoadBgTiles(sWindowPtr->window.bg, sWindowPtr->tileData, sWindowSize, sWindowPtr->window.baseBlock);
break;
case 3:
LoadBgTiles(sWindowPtr->window.bg, sWindowPtr->tileData, sWindowSize, sWindowPtr->window.baseBlock);
CopyBgTilemapBufferToVram(sWindowPtr->window.bg);
break;
}
}
static u8 GetNumActiveWindowsOnBg8Bit(u8 bgId)
{
u8 windowsNum = 0;
s32 i;
for (i = 0; i < WINDOWS_MAX; i++)
{
if (gWindows[i].window.bg == bgId)
windowsNum++;
}
return windowsNum;
}
+78
View File
@@ -0,0 +1,78 @@
#ifndef GUARD_WINDOW_H
#define GUARD_WINDOW_H
#define PIXEL_FILL(num) ((num) | ((num) << 4))
enum
{
WINDOW_BG,
WINDOW_TILEMAP_LEFT,
WINDOW_TILEMAP_TOP,
WINDOW_WIDTH,
WINDOW_HEIGHT,
WINDOW_PALETTE_NUM,
WINDOW_BASE_BLOCK,
WINDOW_TILE_DATA
};
struct WindowTemplate
{
u8 bg;
u8 tilemapLeft;
u8 tilemapTop;
u8 width;
u8 height;
u8 paletteNum;
u16 baseBlock;
};
#define DUMMY_WIN_TEMPLATE \
{ \
0xFF, \
0, \
0, \
0, \
0, \
0, \
0, \
}
struct Window
{
struct WindowTemplate window;
u8 *tileData;
};
bool16 InitWindows(const struct WindowTemplate *templates);
u16 AddWindow(const struct WindowTemplate *template);
int AddWindowWithoutTileMap(const struct WindowTemplate *template);
void RemoveWindow(u8 windowId);
void FreeAllWindowBuffers(void);
void CopyWindowToVram(u8 windowId, u8 mode);
void CopyWindowRectToVram(u32 windowId, u32 mode, u32 x, u32 y, u32 w, u32 h);
void PutWindowTilemap(u8 windowId);
void PutWindowRectTilemapOverridePalette(u8 windowId, u8 x, u8 y, u8 width, u8 height, u8 palette);
void ClearWindowTilemap(u8 windowId);
void PutWindowRectTilemap(u8 windowId, u8 x, u8 y, u8 width, u8 height);
void BlitBitmapToWindow(u8 windowId, const u8 *pixels, u16 x, u16 y, u16 width, u16 height);
void BlitBitmapRectToWindow(u8 windowId, const u8 *pixels, u16 srcX, u16 srcY, u16 srcWidth, int srcHeight, u16 destX, u16 destY, u16 rectWidth, u16 rectHeight);
void FillWindowPixelRect(u8 windowId, u8 fillValue, u16 x, u16 y, u16 width, u16 height);
void CopyToWindowPixelBuffer(u8 windowId, const void *src, u16 size, u16 tileOffset);
void FillWindowPixelBuffer(u8 windowId, u8 fillValue);
void ScrollWindow(u8 windowId, u8 direction, u8 distance, u8 fillValue);
void CallWindowFunction(u8 windowId, void ( *func)(u8, u8, u8, u8, u8, u8));
bool8 SetWindowAttribute(u8 windowId, u8 attributeId, u32 value);
u32 GetWindowAttribute(u8 windowId, u8 attributeId);
u16 AddWindow8Bit(const struct WindowTemplate *template);
void FillWindowPixelBuffer8Bit(u8 windowId, u8 fillValue);
void FillWindowPixelRect8Bit(u8 windowId, u8 fillValue, u16 x, u16 y, u16 width, u16 height);
void BlitBitmapRectToWindow4BitTo8Bit(u8 windowId, const u8 *pixels, u16 srcX, u16 srcY, u16 srcWidth, int srcHeight, u16 destX, u16 destY, u16 rectWidth, u16 rectHeight, u8 paletteNum);
void CopyWindowToVram8Bit(u8 windowId, u8 mode);
extern struct Window gWindows[];
extern void* gUnknown_03002F70[];
extern u32 filler_03002F58;
extern u32 filler_03002F5C;
extern u32 filler_03002F64;
#endif // GUARD_WINDOW_H