pokeemerald/gflib/window.c

717 lines
21 KiB
C
Raw Normal View History

2017-03-30 02:02:15 +02:00
#include "global.h"
#include "window.h"
#include "malloc.h"
2018-02-28 13:07:58 +01:00
#include "bg.h"
#include "blit.h"
2017-03-30 02:02:15 +02:00
// This global is set to 0 and never changed.
u8 gTransparentTileNumber;
2021-02-18 16:00:07 +01:00
void *gWindowBgTilemapBuffers[NUM_BACKGROUNDS];
2021-09-24 20:30:15 +02:00
extern u32 gWindowTileAutoAllocEnabled;
2017-09-01 16:53:06 +02:00
2017-09-01 17:38:28 +02:00
#define WINDOWS_MAX 32
2017-09-01 16:53:06 +02:00
EWRAM_DATA struct Window gWindows[WINDOWS_MAX] = {0};
EWRAM_DATA static struct Window* sWindowPtr = NULL;
EWRAM_DATA static u16 sWindowSize = 0;
2017-03-30 02:02:15 +02:00
2017-09-01 17:38:28 +02:00
static u8 GetNumActiveWindowsOnBg(u8 bgId);
static u8 GetNumActiveWindowsOnBg8Bit(u8 bgId);
2017-03-30 02:02:15 +02:00
static const struct WindowTemplate sDummyWindowTemplate = DUMMY_WIN_TEMPLATE;
2017-03-30 02:02:15 +02:00
2021-02-18 21:01:18 +01:00
static void DummyWindowBgTilemap(void)
2017-03-30 02:02:15 +02:00
{
2017-09-01 16:53:06 +02:00
2017-03-30 02:02:15 +02:00
}
bool16 InitWindows(const struct WindowTemplate *templates)
2017-03-30 02:02:15 +02:00
{
int i;
void *bgTilemapBuffer;
int j;
u8 bgLayer;
2020-08-25 21:56:17 +02:00
u16 attrib;
u8 *allocatedTilemapBuffer;
2017-03-30 02:02:15 +02:00
int allocatedBaseBlock;
2017-09-01 16:53:06 +02:00
2021-02-18 16:00:07 +01:00
for (i = 0; i < NUM_BACKGROUNDS; ++i)
2017-03-30 02:02:15 +02:00
{
bgTilemapBuffer = GetBgTilemapBuffer(i);
if (bgTilemapBuffer != NULL)
2021-02-18 21:01:18 +01:00
gWindowBgTilemapBuffers[i] = DummyWindowBgTilemap;
2017-03-30 02:02:15 +02:00
else
2021-02-18 16:00:07 +01:00
gWindowBgTilemapBuffers[i] = bgTilemapBuffer;
2017-03-30 02:02:15 +02:00
}
2017-09-01 16:53:06 +02:00
2021-02-18 16:00:07 +01:00
for (i = 0; i < WINDOWS_MAX; ++i)
2017-03-30 02:02:15 +02:00
{
2017-09-01 17:38:28 +02:00
gWindows[i].window = sDummyWindowTemplate;
2017-03-30 02:02:15 +02:00
gWindows[i].tileData = NULL;
}
2017-09-01 16:53:06 +02:00
2021-02-18 16:00:07 +01:00
for (i = 0, allocatedBaseBlock = 0, bgLayer = templates[i].bg; bgLayer != 0xFF && i < WINDOWS_MAX; ++i, bgLayer = templates[i].bg)
2017-03-30 02:02:15 +02:00
{
2021-09-24 20:30:15 +02:00
if (gWindowTileAutoAllocEnabled == TRUE)
2017-03-30 02:02:15 +02:00
{
2021-09-24 20:30:15 +02:00
allocatedBaseBlock = BgTileAllocOp(bgLayer, 0, templates[i].width * templates[i].height, 0);
if (allocatedBaseBlock == -1)
2017-03-30 02:02:15 +02:00
return FALSE;
}
2017-09-01 16:53:06 +02:00
2021-02-18 16:00:07 +01:00
if (gWindowBgTilemapBuffers[bgLayer] == NULL)
2017-03-30 02:02:15 +02:00
{
2018-12-26 13:05:02 +01:00
attrib = GetBgAttribute(bgLayer, BG_ATTR_METRIC);
2017-09-01 16:53:06 +02:00
if (attrib != 0xFFFF)
2017-03-30 02:02:15 +02:00
{
allocatedTilemapBuffer = AllocZeroed(attrib);
2017-09-01 16:53:06 +02:00
2017-03-30 02:02:15 +02:00
if (allocatedTilemapBuffer == NULL)
{
FreeAllWindowBuffers();
return FALSE;
}
2017-09-01 16:53:06 +02:00
2017-03-30 02:02:15 +02:00
for (j = 0; j < attrib; ++j)
allocatedTilemapBuffer[j] = 0;
2017-09-01 16:53:06 +02:00
2021-02-18 16:00:07 +01:00
gWindowBgTilemapBuffers[bgLayer] = allocatedTilemapBuffer;
2017-03-30 02:02:15 +02:00
SetBgTilemapBuffer(bgLayer, allocatedTilemapBuffer);
}
}
2017-09-01 16:53:06 +02:00
2021-02-18 21:01:18 +01:00
allocatedTilemapBuffer = AllocZeroed((u16)(32 * (templates[i].width * templates[i].height)));
2017-09-01 16:53:06 +02:00
2017-03-30 02:02:15 +02:00
if (allocatedTilemapBuffer == NULL)
{
2021-02-18 21:01:18 +01:00
if ((GetNumActiveWindowsOnBg(bgLayer) == 0) && (gWindowBgTilemapBuffers[bgLayer] != DummyWindowBgTilemap))
2017-03-30 02:02:15 +02:00
{
2021-02-18 16:00:07 +01:00
Free(gWindowBgTilemapBuffers[bgLayer]);
gWindowBgTilemapBuffers[bgLayer] = allocatedTilemapBuffer;
2017-03-30 02:02:15 +02:00
}
2017-09-01 16:53:06 +02:00
2017-03-30 02:02:15 +02:00
return FALSE;
}
2017-09-01 16:53:06 +02:00
2017-03-30 02:02:15 +02:00
gWindows[i].tileData = allocatedTilemapBuffer;
gWindows[i].window = templates[i];
2017-09-01 16:53:06 +02:00
2021-09-24 20:30:15 +02:00
if (gWindowTileAutoAllocEnabled == TRUE)
2017-03-30 02:02:15 +02:00
{
gWindows[i].window.baseBlock = allocatedBaseBlock;
2021-09-24 20:30:15 +02:00
BgTileAllocOp(bgLayer, allocatedBaseBlock, templates[i].width * templates[i].height, 1);
2017-03-30 02:02:15 +02:00
}
}
2017-09-01 16:53:06 +02:00
2019-02-22 05:27:12 +01:00
gTransparentTileNumber = 0;
2017-03-30 02:02:15 +02:00
return TRUE;
}
2017-09-05 13:01:24 +02:00
u16 AddWindow(const struct WindowTemplate *template)
2017-03-30 02:02:15 +02:00
{
u16 win;
u8 bgLayer;
int allocatedBaseBlock;
u16 attrib;
u8 *allocatedTilemapBuffer;
int i;
2018-02-28 13:07:58 +01:00
for (win = 0; win < WINDOWS_MAX; ++win)
2017-03-30 02:02:15 +02:00
{
if ((bgLayer = gWindows[win].window.bg) == 0xFF)
2017-03-30 02:02:15 +02:00
break;
}
2017-09-01 16:53:06 +02:00
2018-02-28 13:07:58 +01:00
if (win == WINDOWS_MAX)
2021-02-18 21:01:18 +01:00
return WINDOW_NONE;
2017-09-01 16:53:06 +02:00
2018-10-27 00:53:07 +02:00
bgLayer = template->bg;
2017-03-30 02:02:15 +02:00
allocatedBaseBlock = 0;
2017-09-01 16:53:06 +02:00
2021-09-24 20:30:15 +02:00
if (gWindowTileAutoAllocEnabled == TRUE)
2017-03-30 02:02:15 +02:00
{
2021-09-24 20:30:15 +02:00
allocatedBaseBlock = BgTileAllocOp(bgLayer, 0, template->width * template->height, 0);
2017-09-01 16:53:06 +02:00
if (allocatedBaseBlock == -1)
2021-02-18 21:01:18 +01:00
return WINDOW_NONE;
2017-03-30 02:02:15 +02:00
}
2017-09-01 16:53:06 +02:00
2021-02-18 16:00:07 +01:00
if (gWindowBgTilemapBuffers[bgLayer] == NULL)
2017-03-30 02:02:15 +02:00
{
2018-12-26 13:05:02 +01:00
attrib = GetBgAttribute(bgLayer, BG_ATTR_METRIC);
2017-09-01 16:53:06 +02:00
if (attrib != 0xFFFF)
2017-03-30 02:02:15 +02:00
{
allocatedTilemapBuffer = AllocZeroed(attrib);
2017-09-01 16:53:06 +02:00
2017-03-30 02:02:15 +02:00
if (allocatedTilemapBuffer == NULL)
2021-02-18 21:01:18 +01:00
return WINDOW_NONE;
2017-09-01 16:53:06 +02:00
2017-03-30 02:02:15 +02:00
for (i = 0; i < attrib; ++i)
allocatedTilemapBuffer[i] = 0;
2017-09-01 16:53:06 +02:00
2021-02-18 16:00:07 +01:00
gWindowBgTilemapBuffers[bgLayer] = allocatedTilemapBuffer;
2017-03-30 02:02:15 +02:00
SetBgTilemapBuffer(bgLayer, allocatedTilemapBuffer);
}
}
2017-09-01 16:53:06 +02:00
2021-02-18 21:01:18 +01:00
allocatedTilemapBuffer = AllocZeroed((u16)(32 * (template->width * template->height)));
2017-09-01 16:53:06 +02:00
2017-03-30 02:02:15 +02:00
if (allocatedTilemapBuffer == NULL)
{
2021-02-18 21:01:18 +01:00
if ((GetNumActiveWindowsOnBg(bgLayer) == 0) && (gWindowBgTilemapBuffers[bgLayer] != DummyWindowBgTilemap))
2017-03-30 02:02:15 +02:00
{
2021-02-18 16:00:07 +01:00
Free(gWindowBgTilemapBuffers[bgLayer]);
gWindowBgTilemapBuffers[bgLayer] = allocatedTilemapBuffer;
2017-03-30 02:02:15 +02:00
}
2021-02-18 21:01:18 +01:00
return WINDOW_NONE;
2017-03-30 02:02:15 +02:00
}
2017-09-01 16:53:06 +02:00
2017-03-30 02:02:15 +02:00
gWindows[win].tileData = allocatedTilemapBuffer;
gWindows[win].window = *template;
2017-09-01 16:53:06 +02:00
2021-09-24 20:30:15 +02:00
if (gWindowTileAutoAllocEnabled == TRUE)
2017-03-30 02:02:15 +02:00
{
gWindows[win].window.baseBlock = allocatedBaseBlock;
2021-09-24 20:30:15 +02:00
BgTileAllocOp(bgLayer, allocatedBaseBlock, gWindows[win].window.width * gWindows[win].window.height, 1);
2017-03-30 02:02:15 +02:00
}
return win;
}
2017-10-07 03:59:47 +02:00
int AddWindowWithoutTileMap(const struct WindowTemplate *template)
2017-03-30 02:02:15 +02:00
{
u16 win;
u8 bgLayer;
int allocatedBaseBlock;
2017-09-01 16:53:06 +02:00
2018-02-28 13:07:58 +01:00
for (win = 0; win < WINDOWS_MAX; ++win)
2017-03-30 02:02:15 +02:00
{
if (gWindows[win].window.bg == 0xFF)
2017-03-30 02:02:15 +02:00
break;
}
2017-09-01 16:53:06 +02:00
2018-02-28 13:07:58 +01:00
if (win == WINDOWS_MAX)
2021-02-18 21:01:18 +01:00
return WINDOW_NONE;
2017-09-01 16:53:06 +02:00
2018-10-27 00:53:07 +02:00
bgLayer = template->bg;
2017-03-30 02:02:15 +02:00
allocatedBaseBlock = 0;
2017-09-01 16:53:06 +02:00
2021-09-24 20:30:15 +02:00
if (gWindowTileAutoAllocEnabled == TRUE)
2017-03-30 02:02:15 +02:00
{
2021-09-24 20:30:15 +02:00
allocatedBaseBlock = BgTileAllocOp(bgLayer, 0, template->width * template->height, 0);
2017-09-01 16:53:06 +02:00
if (allocatedBaseBlock == -1)
2021-02-18 21:01:18 +01:00
return WINDOW_NONE;
2017-03-30 02:02:15 +02:00
}
2017-09-01 16:53:06 +02:00
2017-03-30 02:02:15 +02:00
gWindows[win].window = *template;
2017-09-01 16:53:06 +02:00
2021-09-24 20:30:15 +02:00
if (gWindowTileAutoAllocEnabled == TRUE)
2017-03-30 02:02:15 +02:00
{
gWindows[win].window.baseBlock = allocatedBaseBlock;
2021-09-24 20:30:15 +02:00
BgTileAllocOp(bgLayer, allocatedBaseBlock, gWindows[win].window.width * gWindows[win].window.height, 1);
2017-03-30 02:02:15 +02:00
}
return win;
}
void RemoveWindow(u8 windowId)
{
2018-10-27 00:53:07 +02:00
u8 bgLayer = gWindows[windowId].window.bg;
2017-09-01 16:53:06 +02:00
2021-09-24 20:30:15 +02:00
if (gWindowTileAutoAllocEnabled == TRUE)
BgTileAllocOp(bgLayer, gWindows[windowId].window.baseBlock, gWindows[windowId].window.width * gWindows[windowId].window.height, 2);
2017-09-01 16:53:06 +02:00
2017-09-01 17:38:28 +02:00
gWindows[windowId].window = sDummyWindowTemplate;
2017-09-01 16:53:06 +02:00
2017-03-30 02:02:15 +02:00
if (GetNumActiveWindowsOnBg(bgLayer) == 0)
{
2021-02-18 21:01:18 +01:00
if (gWindowBgTilemapBuffers[bgLayer] != DummyWindowBgTilemap)
2017-03-30 02:02:15 +02:00
{
2021-02-18 16:00:07 +01:00
Free(gWindowBgTilemapBuffers[bgLayer]);
2021-02-18 21:01:18 +01:00
gWindowBgTilemapBuffers[bgLayer] = NULL;
2017-03-30 02:02:15 +02:00
}
}
2017-09-01 16:53:06 +02:00
2017-03-30 02:02:15 +02:00
if (gWindows[windowId].tileData != NULL)
{
Free(gWindows[windowId].tileData);
gWindows[windowId].tileData = NULL;
}
}
void FreeAllWindowBuffers(void)
{
int i;
2017-09-01 16:53:06 +02:00
2021-02-18 16:00:07 +01:00
for (i = 0; i < NUM_BACKGROUNDS; ++i)
2017-03-30 02:02:15 +02:00
{
2021-02-18 21:01:18 +01:00
if (gWindowBgTilemapBuffers[i] != NULL && gWindowBgTilemapBuffers[i] != DummyWindowBgTilemap)
2017-03-30 02:02:15 +02:00
{
2021-02-18 16:00:07 +01:00
Free(gWindowBgTilemapBuffers[i]);
gWindowBgTilemapBuffers[i] = NULL;
2017-03-30 02:02:15 +02:00
}
}
2017-09-01 16:53:06 +02:00
2021-02-18 16:00:07 +01:00
for (i = 0; i < WINDOWS_MAX; ++i)
2017-03-30 02:02:15 +02:00
{
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)
{
2021-11-03 20:29:18 +01:00
case COPYWIN_MAP:
2018-12-17 23:00:08 +01:00
CopyBgTilemapBufferToVram(windowLocal.window.bg);
break;
2021-11-03 20:29:18 +01:00
case COPYWIN_GFX:
2018-12-17 23:00:08 +01:00
LoadBgTiles(windowLocal.window.bg, windowLocal.tileData, windowSize, windowLocal.window.baseBlock);
break;
2021-11-03 20:29:18 +01:00
case COPYWIN_FULL:
2018-12-17 23:00:08 +01:00
LoadBgTiles(windowLocal.window.bg, windowLocal.tileData, windowSize, windowLocal.window.baseBlock);
CopyBgTilemapBufferToVram(windowLocal.window.bg);
break;
2017-03-30 02:02:15 +02:00
}
}
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];
2017-09-01 16:53:06 +02:00
2017-03-30 02:02:15 +02:00
rectSize = ((h - 1) * windowLocal.window.width);
rectSize += (windowLocal.window.width - x);
rectSize -= (windowLocal.window.width - (x + w));
rectSize *= 32;
2017-09-01 16:53:06 +02:00
2017-03-30 02:02:15 +02:00
rectPos = (y * windowLocal.window.width) + x;
2017-09-01 16:53:06 +02:00
2017-03-30 02:02:15 +02:00
switch (mode)
{
2021-11-03 20:29:18 +01:00
case COPYWIN_MAP:
2018-12-17 23:00:08 +01:00
CopyBgTilemapBufferToVram(windowLocal.window.bg);
break;
2021-11-03 20:29:18 +01:00
case COPYWIN_GFX:
2018-12-17 23:00:08 +01:00
LoadBgTiles(windowLocal.window.bg, windowLocal.tileData + (rectPos * 32), rectSize, windowLocal.window.baseBlock + rectPos);
break;
2021-11-03 20:29:18 +01:00
case COPYWIN_FULL:
2018-12-17 23:00:08 +01:00
LoadBgTiles(windowLocal.window.bg, windowLocal.tileData + (rectPos * 32), rectSize, windowLocal.window.baseBlock + rectPos);
CopyBgTilemapBufferToVram(windowLocal.window.bg);
break;
2017-03-30 02:02:15 +02:00
}
}
}
void PutWindowTilemap(u8 windowId)
{
struct Window windowLocal = gWindows[windowId];
2017-09-01 16:53:06 +02:00
2017-03-30 02:02:15 +02:00
WriteSequenceToBgTilemapBuffer(
2018-10-27 00:53:07 +02:00
windowLocal.window.bg,
2018-12-26 13:05:02 +01:00
GetBgAttribute(windowLocal.window.bg, BG_ATTR_BASETILE) + windowLocal.window.baseBlock,
2017-03-30 02:02:15 +02:00
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];
2018-12-26 13:05:02 +01:00
u16 currentRow = windowLocal.window.baseBlock + (y * windowLocal.window.width) + x + GetBgAttribute(windowLocal.window.bg, BG_ATTR_BASETILE);
2017-03-30 02:02:15 +02:00
int i;
2017-09-01 16:53:06 +02:00
2017-03-30 02:02:15 +02:00
for (i = 0; i < height; ++i)
{
WriteSequenceToBgTilemapBuffer(
2018-10-27 00:53:07 +02:00
windowLocal.window.bg,
2017-03-30 02:02:15 +02:00
currentRow,
windowLocal.window.tilemapLeft + x,
windowLocal.window.tilemapTop + y + i,
width,
1,
palette,
1);
2017-09-01 16:53:06 +02:00
2017-03-30 02:02:15 +02:00
currentRow += windowLocal.window.width;
}
}
// Fills a window with transparent tiles.
2017-03-30 02:02:15 +02:00
void ClearWindowTilemap(u8 windowId)
{
struct Window windowLocal = gWindows[windowId];
2017-09-01 16:53:06 +02:00
2017-03-30 02:02:15 +02:00
FillBgTilemapBufferRect(
2018-10-27 00:53:07 +02:00
windowLocal.window.bg,
gTransparentTileNumber,
2017-03-30 02:02:15 +02:00
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];
2018-12-26 13:05:02 +01:00
u16 currentRow = windowLocal.window.baseBlock + (y * windowLocal.window.width) + x + GetBgAttribute(windowLocal.window.bg, BG_ATTR_BASETILE);
2017-03-30 02:02:15 +02:00
int i;
2017-09-01 16:53:06 +02:00
2017-03-30 02:02:15 +02:00
for (i = 0; i < height; ++i)
{
WriteSequenceToBgTilemapBuffer(
2018-10-27 00:53:07 +02:00
windowLocal.window.bg,
2017-03-30 02:02:15 +02:00
currentRow,
windowLocal.window.tilemapLeft + x,
windowLocal.window.tilemapTop + y + i,
width,
1,
windowLocal.window.paletteNum,
1);
2017-09-01 16:53:06 +02:00
2017-03-30 02:02:15 +02:00
currentRow += windowLocal.window.width;
}
}
2018-02-07 03:37:54 +01:00
void BlitBitmapToWindow(u8 windowId, const u8 *pixels, u16 x, u16 y, u16 width, u16 height)
2017-03-30 02:02:15 +02:00
{
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;
2017-03-30 02:02:15 +02:00
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;
2017-09-01 16:53:06 +02:00
2017-03-30 02:02:15 +02:00
BlitBitmapRect4Bit(&sourceRect, &destRect, srcX, srcY, destX, destY, rectWidth, rectHeight, 0);
}
2017-09-01 17:38:28 +02:00
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)
2017-03-30 02:02:15 +02:00
{
struct Bitmap sourceRect;
struct Bitmap destRect;
sourceRect.pixels = (u8 *)pixels;
2017-03-30 02:02:15 +02:00
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;
2017-09-01 16:53:06 +02:00
2017-03-30 02:02:15 +02:00
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;
2017-09-01 16:53:06 +02:00
2017-03-30 02:02:15 +02:00
FillBitmapRect4Bit(&pixelRect, x, y, width, height, fillValue);
}
2018-10-21 09:24:57 +02:00
void CopyToWindowPixelBuffer(u8 windowId, const void *src, u16 size, u16 tileOffset)
2017-03-30 02:02:15 +02:00
{
if (size != 0)
2021-02-18 21:01:18 +01:00
CpuCopy16(src, gWindows[windowId].tileData + (32 * tileOffset), size);
2017-03-30 02:02:15 +02:00
else
2021-02-18 21:01:18 +01:00
LZ77UnCompWram(src, gWindows[windowId].tileData + (32 * tileOffset));
2017-03-30 02:02:15 +02:00
}
// Sets all pixels within the window to the fillValue color.
2017-03-30 02:02:15 +02:00
void FillWindowPixelBuffer(u8 windowId, u8 fillValue)
{
int fillSize = gWindows[windowId].window.width * gWindows[windowId].window.height;
2021-02-18 21:01:18 +01:00
CpuFastFill8(fillValue, gWindows[windowId].tileData, 32 * fillSize);
2017-03-30 02:02:15 +02:00
}
2017-09-01 16:53:06 +02:00
2018-01-07 23:58:20 +01:00
#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); \
2018-01-07 23:58:20 +01:00
else \
*(u32 *)(tileData + destOffset) = fillValue32; \
2018-01-07 23:58:20 +01:00
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); \
2018-01-07 23:58:20 +01:00
else \
*(u32 *)(tileData - destOffset) = fillValue32; \
2018-01-07 23:58:20 +01:00
distanceLoop++; \
}
2017-09-01 16:53:06 +02:00
void ScrollWindow(u8 windowId, u8 direction, u8 distance, u8 fillValue)
{
2018-01-07 23:58:20 +01:00
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)
2017-09-01 16:53:06 +02:00
{
2018-01-07 23:58:20 +01:00
case 0:
for (i = 0; i < size; i += 32)
2017-09-01 16:53:06 +02:00
{
2018-01-07 23:58:20 +01:00
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)
2017-09-01 16:53:06 +02:00
}
2018-01-07 23:58:20 +01:00
break;
case 1:
2017-09-01 16:53:06 +02:00
tileData += size - 4;
2018-01-07 23:58:20 +01:00
for (i = 0; i < size; i += 32)
2017-09-01 16:53:06 +02:00
{
distanceLoop = distance;
2018-01-07 23:58:20 +01:00
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)
2017-09-01 16:53:06 +02:00
}
2018-01-07 23:58:20 +01:00
break;
case 2:
break;
2017-09-01 16:53:06 +02:00
}
}
void CallWindowFunction(u8 windowId, void ( *func)(u8, u8, u8, u8, u8, u8))
{
struct WindowTemplate window = gWindows[windowId].window;
2018-10-27 00:53:07 +02:00
func(window.bg, window.tilemapLeft, window.tilemapTop, window.width, window.height, window.paletteNum);
2017-09-01 16:53:06 +02:00
}
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);
2017-09-01 16:53:06 +02:00
return TRUE;
2018-10-27 00:53:07 +02:00
case WINDOW_BG:
2017-09-01 16:53:06 +02:00
case WINDOW_WIDTH:
case WINDOW_HEIGHT:
default:
return TRUE;
}
}
u32 GetWindowAttribute(u8 windowId, u8 attributeId)
{
switch (attributeId)
{
2018-10-27 00:53:07 +02:00
case WINDOW_BG:
return gWindows[windowId].window.bg;
2017-09-01 16:53:06 +02:00
case WINDOW_TILEMAP_LEFT:
return gWindows[windowId].window.tilemapLeft;
2017-09-01 16:53:06 +02:00
case WINDOW_TILEMAP_TOP:
return gWindows[windowId].window.tilemapTop;
2017-09-01 16:53:06 +02:00
case WINDOW_WIDTH:
return gWindows[windowId].window.width;
2017-09-01 16:53:06 +02:00
case WINDOW_HEIGHT:
return gWindows[windowId].window.height;
2017-09-01 16:53:06 +02:00
case WINDOW_PALETTE_NUM:
return gWindows[windowId].window.paletteNum;
2017-09-01 16:53:06 +02:00
case WINDOW_BASE_BLOCK:
return gWindows[windowId].window.baseBlock;
2017-09-01 16:53:06 +02:00
case WINDOW_TILE_DATA:
return (u32)(gWindows[windowId].tileData);
default:
return 0;
}
}
2017-09-01 17:38:28 +02:00
static u8 GetNumActiveWindowsOnBg(u8 bgId)
2017-09-01 16:53:06 +02:00
{
u8 windowsNum = 0;
s32 i;
for (i = 0; i < WINDOWS_MAX; i++)
{
2018-10-27 00:53:07 +02:00
if (gWindows[i].window.bg == bgId)
2017-09-01 16:53:06 +02:00
windowsNum++;
}
return windowsNum;
}
2021-02-18 21:01:18 +01:00
static void DummyWindowBgTilemap8Bit(void)
2017-09-01 16:53:06 +02:00
{
}
2018-12-17 23:00:08 +01:00
u16 AddWindow8Bit(const struct WindowTemplate *template)
2017-09-01 16:53:06 +02:00
{
u16 windowId;
u8 *memAddress;
2017-09-01 16:53:06 +02:00
u8 bgLayer;
2021-02-18 16:00:07 +01:00
for (windowId = 0; windowId < WINDOWS_MAX; windowId++)
2017-09-01 16:53:06 +02:00
{
if (gWindows[windowId].window.bg == 0xFF)
2017-09-01 16:53:06 +02:00
break;
}
if (windowId == WINDOWS_MAX)
2021-02-18 21:01:18 +01:00
return WINDOW_NONE;
2018-10-27 00:53:07 +02:00
bgLayer = template->bg;
2021-02-18 21:01:18 +01:00
if (gWindowBgTilemapBuffers[bgLayer] == NULL)
2017-09-01 16:53:06 +02:00
{
2018-12-26 13:05:02 +01:00
u16 attribute = GetBgAttribute(bgLayer, BG_ATTR_METRIC);
if (attribute != 0xFFFF)
2017-09-01 16:53:06 +02:00
{
s32 i;
memAddress = Alloc(attribute);
if (memAddress == NULL)
2021-02-18 21:01:18 +01:00
return WINDOW_NONE;
2017-09-01 16:53:06 +02:00
for (i = 0; i < attribute; i++) // if we're going to zero out the memory anyway, why not call AllocZeroed?
memAddress[i] = 0;
2021-02-18 16:00:07 +01:00
gWindowBgTilemapBuffers[bgLayer] = memAddress;
2017-09-01 16:53:06 +02:00
SetBgTilemapBuffer(bgLayer, memAddress);
}
}
2021-02-18 21:01:18 +01:00
memAddress = Alloc((u16)(64 * (template->width * template->height)));
2017-09-01 16:53:06 +02:00
if (memAddress == NULL)
{
2021-02-18 21:01:18 +01:00
if (GetNumActiveWindowsOnBg8Bit(bgLayer) == 0 && gWindowBgTilemapBuffers[bgLayer] != DummyWindowBgTilemap8Bit)
2017-09-01 16:53:06 +02:00
{
2021-02-18 16:00:07 +01:00
Free(gWindowBgTilemapBuffers[bgLayer]);
gWindowBgTilemapBuffers[bgLayer] = NULL;
2017-09-01 16:53:06 +02:00
}
2021-02-18 21:01:18 +01:00
return WINDOW_NONE;
2017-09-01 16:53:06 +02:00
}
else
{
gWindows[windowId].tileData = memAddress;
gWindows[windowId].window = *template;
return windowId;
}
2017-09-01 16:53:06 +02:00
}
void FillWindowPixelBuffer8Bit(u8 windowId, u8 fillValue)
{
s32 i;
s32 size;
2021-02-18 21:01:18 +01:00
size = (u16)(64 * (gWindows[windowId].window.width * gWindows[windowId].window.height));
2017-09-01 16:53:06 +02:00
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);
}
2018-12-17 23:00:08 +01:00
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)
2017-09-01 16:53:06 +02:00
{
struct Bitmap sourceRect;
struct Bitmap destRect;
sourceRect.pixels = (u8 *) pixels;
2017-09-01 16:53:06 +02:00
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];
2021-02-18 21:01:18 +01:00
sWindowSize = 64 * (sWindowPtr->window.width * sWindowPtr->window.height);
2017-09-01 16:53:06 +02:00
switch (mode)
{
2021-11-03 20:29:18 +01:00
case COPYWIN_MAP:
2018-12-17 23:00:08 +01:00
CopyBgTilemapBufferToVram(sWindowPtr->window.bg);
break;
2021-11-03 20:29:18 +01:00
case COPYWIN_GFX:
2018-12-17 23:00:08 +01:00
LoadBgTiles(sWindowPtr->window.bg, sWindowPtr->tileData, sWindowSize, sWindowPtr->window.baseBlock);
break;
2021-11-03 20:29:18 +01:00
case COPYWIN_FULL:
2018-12-17 23:00:08 +01:00
LoadBgTiles(sWindowPtr->window.bg, sWindowPtr->tileData, sWindowSize, sWindowPtr->window.baseBlock);
CopyBgTilemapBufferToVram(sWindowPtr->window.bg);
break;
2017-09-01 16:53:06 +02:00
}
}
2017-09-01 17:38:28 +02:00
static u8 GetNumActiveWindowsOnBg8Bit(u8 bgId)
2017-09-01 16:53:06 +02:00
{
u8 windowsNum = 0;
s32 i;
for (i = 0; i < WINDOWS_MAX; i++)
{
2018-10-27 00:53:07 +02:00
if (gWindows[i].window.bg == bgId)
2017-09-01 16:53:06 +02:00
windowsNum++;
}
return windowsNum;
}