pokeruby/src/field_camera.c
2017-07-20 20:13:02 -07:00

496 lines
12 KiB
C

#include "global.h"
#include "field_camera.h"
#include "berry.h"
#include "field_player_avatar.h"
#include "fieldmap.h"
#include "rotating_gate.h"
#include "sprite.h"
#include "text.h"
EWRAM_DATA u8 gUnknown_0202E854 = 0;
struct UnknownStruct
{
u8 unk0;
u8 unk1;
u8 unk2;
u8 unk3;
bool8 unk4;
};
static struct UnknownStruct gUnknown_03000590;
static u16 gUnknown_03000598;
static s16 gUnknown_0300059A;
static u8 gUnknown_0300059C;
static void (*gUnknown_030005A0)(void);
struct CameraSomething gUnknown_03004880;
u16 gUnknown_03004898;
u16 gUnknown_0300489C;
static void RedrawMapSliceNorth(struct UnknownStruct *a, struct MapData *mapData);
static void RedrawMapSliceSouth(struct UnknownStruct *a, struct MapData *mapData);
static void RedrawMapSliceEast(struct UnknownStruct *a, struct MapData *mapData);
static void RedrawMapSliceWest(struct UnknownStruct *a, struct MapData *mapData);
static s32 MapPosToBgTilemapOffset(struct UnknownStruct *a, s32 x, s32 y);
static void DrawWholeMapViewInternal(int x, int y, struct MapData *mapData);
static void DrawMetatileAt(struct MapData *mapData, u16, int, int);
static void DrawMetatile(s32 a, u16 *b, u16 c);
static void CameraPanningCB_PanAhead(void);
static void move_tilemap_camera_to_upper_left_corner_(struct UnknownStruct *a)
{
a->unk2 = 0;
a->unk3 = 0;
a->unk0 = 0;
a->unk1 = 0;
a->unk4 = TRUE;
}
static void tilemap_move_something(struct UnknownStruct *a, u32 b, u32 c)
{
a->unk2 += b;
a->unk2 %= 32;
a->unk3 += c;
a->unk3 %= 32;
}
static void coords8_add(struct UnknownStruct *a, u32 b, u32 c)
{
a->unk0 += b;
a->unk1 += c;
}
void move_tilemap_camera_to_upper_left_corner(void)
{
move_tilemap_camera_to_upper_left_corner_(&gUnknown_03000590);
CpuFill16(0, gBGTilemapBuffers[2], 0x800);
CpuFill16(0, gBGTilemapBuffers[1], 0x800);
CpuFill16(0x3014, gBGTilemapBuffers[3], 0x800);
}
void sub_8057A58(void)
{
*gBGHOffsetRegs[1] = gUnknown_03000590.unk0 + gUnknown_03000598;
*gBGVOffsetRegs[1] = gUnknown_03000590.unk1 + gUnknown_0300059A + 8;
*gBGHOffsetRegs[2] = gUnknown_03000590.unk0 + gUnknown_03000598;
*gBGVOffsetRegs[2] = gUnknown_03000590.unk1 + gUnknown_0300059A + 8;
*gBGHOffsetRegs[3] = gUnknown_03000590.unk0 + gUnknown_03000598;
*gBGVOffsetRegs[3] = gUnknown_03000590.unk1 + gUnknown_0300059A + 8;
if (gUnknown_03000590.unk4)
{
DmaCopy16(3, gBGTilemapBuffers[1], (void *)(VRAM + 0xE800), 0x800);
DmaCopy16(3, gBGTilemapBuffers[2], (void *)(VRAM + 0xE000), 0x800);
DmaCopy16(3, gBGTilemapBuffers[3], (void *)(VRAM + 0xF000), 0x800);
gUnknown_03000590.unk4 = FALSE;
}
}
void sub_8057B14(u16 *a, u16 *b)
{
*a = gUnknown_03000590.unk0 + gUnknown_03000598;
*b = gUnknown_03000590.unk1 + gUnknown_0300059A + 8;
}
void DrawWholeMapView(void)
{
DrawWholeMapViewInternal(gSaveBlock1.pos.x, gSaveBlock1.pos.y, gMapHeader.mapData);
gUnknown_03000590.unk4 = TRUE;
}
static void DrawWholeMapViewInternal(int x, int y, struct MapData *mapData)
{
u8 i;
u8 j;
u32 r6;
u8 temp;
for (i = 0; i < 32; i += 2)
{
temp = gUnknown_03000590.unk3 + i;
if (temp >= 32)
temp -= 32;
r6 = temp * 32;
for (j = 0; j < 32; j += 2)
{
temp = gUnknown_03000590.unk2 + j;
if (temp >= 32)
temp -= 32;
DrawMetatileAt(mapData, r6 + temp, x + j / 2, y + i / 2);
}
}
}
static void RedrawMapSlicesForCameraUpdate(struct UnknownStruct *a, int x, int y)
{
struct MapData *mapData = gMapHeader.mapData;
if (x > 0)
RedrawMapSliceWest(a, mapData);
if (x < 0)
RedrawMapSliceEast(a, mapData);
if (y > 0)
RedrawMapSliceNorth(a, mapData);
if (y < 0)
RedrawMapSliceSouth(a, mapData);
a->unk4 = TRUE;
}
static void RedrawMapSliceNorth(struct UnknownStruct *a, struct MapData *mapData)
{
u8 i;
u8 temp;
u32 r7;
temp = a->unk3 + 28;
if (temp >= 32)
temp -= 32;
r7 = temp * 32;
for (i = 0; i < 32; i += 2)
{
temp = a->unk2 + i;
if (temp >= 32)
temp -= 32;
DrawMetatileAt(mapData, r7 + temp, gSaveBlock1.pos.x + i / 2, gSaveBlock1.pos.y + 14);
}
}
static void RedrawMapSliceSouth(struct UnknownStruct *a, struct MapData *mapData)
{
u8 i;
u8 temp;
u32 r7 = a->unk3 * 32;
for (i = 0; i < 32; i += 2)
{
temp = a->unk2 + i;
if (temp >= 32)
temp -= 32;
DrawMetatileAt(mapData, r7 + temp, gSaveBlock1.pos.x + i / 2, gSaveBlock1.pos.y);
}
}
static void RedrawMapSliceEast(struct UnknownStruct *a, struct MapData *mapData)
{
u8 i;
u8 temp;
u32 r6 = a->unk2;
for (i = 0; i < 32; i += 2)
{
temp = a->unk3 + i;
if (temp >= 32)
temp -= 32;
DrawMetatileAt(mapData, temp * 32 + r6, gSaveBlock1.pos.x, gSaveBlock1.pos.y + i / 2);
}
}
static void RedrawMapSliceWest(struct UnknownStruct *a, struct MapData *mapData)
{
u8 i;
u8 temp;
u8 r5 = a->unk2 + 28;
if (r5 >= 32)
r5 -= 32;
for (i = 0; i < 32; i += 2)
{
temp = a->unk3 + i;
if (temp >= 32)
temp -= 32;
DrawMetatileAt(mapData, temp * 32 + r5, gSaveBlock1.pos.x + 14, gSaveBlock1.pos.y + i / 2);
}
}
void CurrentMapDrawMetatileAt(int a, int b)
{
int offset = MapPosToBgTilemapOffset(&gUnknown_03000590, a, b);
if (offset >= 0)
{
DrawMetatileAt(gMapHeader.mapData, offset, a, b);
gUnknown_03000590.unk4 = TRUE;
}
}
void DrawDoorMetatileAt(int x, int y, u16 *arr)
{
int offset = MapPosToBgTilemapOffset(&gUnknown_03000590, x, y);
if (offset >= 0)
{
DrawMetatile(1, arr, offset);
gUnknown_03000590.unk4 = TRUE;
}
}
static void DrawMetatileAt(struct MapData *mapData, u16 b, int c, int d)
{
u16 metatileId = MapGridGetMetatileIdAt(c, d);
u16 *metatiles;
if (metatileId > 1024)
metatileId = 0;
if (metatileId < 512)
metatiles = mapData->primaryTileset->metatiles;
else
{
metatiles = mapData->secondaryTileset->metatiles;
metatileId -= 512;
}
DrawMetatile(MapGridGetMetatileLayerTypeAt(c, d), metatiles + metatileId * 8, b);
}
static void DrawMetatile(s32 a, u16 *b, u16 c)
{
switch (a)
{
case 2:
gBGTilemapBuffers[3][c] = b[0];
gBGTilemapBuffers[3][c + 1] = b[1];
gBGTilemapBuffers[3][c + 0x20] = b[2];
gBGTilemapBuffers[3][c + 0x21] = b[3];
gBGTilemapBuffers[2][c] = 0;
gBGTilemapBuffers[2][c + 1] = 0;
gBGTilemapBuffers[2][c + 0x20] = 0;
gBGTilemapBuffers[2][c + 0x21] = 0;
gBGTilemapBuffers[1][c] = b[4];
gBGTilemapBuffers[1][c + 1] = b[5];
gBGTilemapBuffers[1][c + 0x20] = b[6];
gBGTilemapBuffers[1][c + 0x21] = b[7];
break;
case 1:
gBGTilemapBuffers[3][c] = b[0];
gBGTilemapBuffers[3][c + 1] = b[1];
gBGTilemapBuffers[3][c + 0x20] = b[2];
gBGTilemapBuffers[3][c + 0x21] = b[3];
gBGTilemapBuffers[2][c] = b[4];
gBGTilemapBuffers[2][c + 1] = b[5];
gBGTilemapBuffers[2][c + 0x20] = b[6];
gBGTilemapBuffers[2][c + 0x21] = b[7];
gBGTilemapBuffers[1][c] = 0;
gBGTilemapBuffers[1][c + 1] = 0;
gBGTilemapBuffers[1][c + 0x20] = 0;
gBGTilemapBuffers[1][c + 0x21] = 0;
break;
case 0:
gBGTilemapBuffers[3][c] = 0x3014;
gBGTilemapBuffers[3][c + 1] = 0x3014;
gBGTilemapBuffers[3][c + 0x20] = 0x3014;
gBGTilemapBuffers[3][c + 0x21] = 0x3014;
gBGTilemapBuffers[2][c] = b[0];
gBGTilemapBuffers[2][c + 1] = b[1];
gBGTilemapBuffers[2][c + 0x20] = b[2];
gBGTilemapBuffers[2][c + 0x21] = b[3];
gBGTilemapBuffers[1][c] = b[4];
gBGTilemapBuffers[1][c + 1] = b[5];
gBGTilemapBuffers[1][c + 0x20] = b[6];
gBGTilemapBuffers[1][c + 0x21] = b[7];
break;
}
}
static s32 MapPosToBgTilemapOffset(struct UnknownStruct *a, s32 x, s32 y)
{
x -= gSaveBlock1.pos.x;
x *= 2;
if (x >= 32 || x < 0)
return -1;
x = x + a->unk2;
if (x >= 32)
x -= 32;
y = (y - gSaveBlock1.pos.y) * 2;
if (y >= 32 || y < 0)
return -1;
y = y + a->unk3;
if (y >= 32)
y -= 32;
return y * 32 + x;
}
static void CameraUpdateCallback(struct CameraSomething *a)
{
if (a->unk4 != 0)
{
a->unk8 = gSprites[a->unk4].data2;
a->unkC = gSprites[a->unk4].data3;
}
}
void ResetCameraUpdateInfo(void)
{
gUnknown_03004880.unk8 = 0;
gUnknown_03004880.unkC = 0;
gUnknown_03004880.unk10 = 0;
gUnknown_03004880.unk14 = 0;
gUnknown_03004880.unk4 = 0;
gUnknown_03004880.callback = NULL;
}
u32 InitCameraUpdateCallback(u8 a)
{
if (gUnknown_03004880.unk4 != 0)
DestroySprite(&gSprites[gUnknown_03004880.unk4]);
gUnknown_03004880.unk4 = AddCameraObject(a);
gUnknown_03004880.callback = CameraUpdateCallback;
return 0;
}
void CameraUpdate(void)
{
int deltaX;
int deltaY;
int r0;
int r1;
int r7;
int r8;
if (gUnknown_03004880.callback != NULL)
gUnknown_03004880.callback(&gUnknown_03004880);
r7 = gUnknown_03004880.unk8;
r8 = gUnknown_03004880.unkC;
deltaX = 0;
deltaY = 0;
r1 = gUnknown_03004880.unk10;
r0 = gUnknown_03004880.unk14;
if (r1 == 0 && r7 != 0)
{
if (r7 > 0)
deltaX = 1;
else
deltaX = -1;
}
if (r0 == 0 && r8 != 0)
{
if (r8 > 0)
deltaY = 1;
else
deltaY = -1;
}
if (r1 != 0 && r1 == -r7)
{
if (r7 > 0)
deltaX = 1;
else
deltaX = -1;
}
if (r0 != 0 && r0 == -r8)
{
if (r8 > 0)
deltaX = 1;
else
deltaX = -1;
}
gUnknown_03004880.unk10 += r7;
gUnknown_03004880.unk10 = gUnknown_03004880.unk10 - 16 * (gUnknown_03004880.unk10 / 16);
gUnknown_03004880.unk14 += r8;
gUnknown_03004880.unk14 = gUnknown_03004880.unk14 - 16 * (gUnknown_03004880.unk14 / 16);
if (deltaX != 0 || deltaY != 0)
{
CameraMove(deltaX, deltaY);
UpdateFieldObjectsForCameraUpdate(deltaX, deltaY);
RotatingGatePuzzleCameraUpdate(deltaX, deltaY);
ResetBerryTreeSparkleFlags();
tilemap_move_something(&gUnknown_03000590, deltaX * 2, deltaY * 2);
RedrawMapSlicesForCameraUpdate(&gUnknown_03000590, deltaX * 2, deltaY * 2);
}
coords8_add(&gUnknown_03000590, r7, r8);
gUnknown_0300489C -= r7;
gUnknown_03004898 -= r8;
}
void camera_move_and_redraw(int a, int b)
{
CameraMove(a, b);
UpdateFieldObjectsForCameraUpdate(a, b);
DrawWholeMapView();
gUnknown_0300489C -= a * 16;
gUnknown_03004898 -= b * 16;
}
void SetCameraPanningCallback(void (*a)(void))
{
gUnknown_030005A0 = a;
}
void SetCameraPanning(s16 a, s16 b)
{
gUnknown_03000598 = a;
gUnknown_0300059A = b + 32;
}
void InstallCameraPanAheadCallback(void)
{
gUnknown_030005A0 = CameraPanningCB_PanAhead;
gUnknown_0300059C = 0;
gUnknown_03000598 = 0;
gUnknown_0300059A = 32;
}
void UpdateCameraPanning(void)
{
if (gUnknown_030005A0 != NULL)
gUnknown_030005A0();
//Update sprite offset of overworld objects
gSpriteCoordOffsetX = gUnknown_0300489C - gUnknown_03000598;
gSpriteCoordOffsetY = gUnknown_03004898 - gUnknown_0300059A - 8;
}
static void CameraPanningCB_PanAhead(void)
{
u8 var;
if (gUnknown_0202E854 == 0)
{
InstallCameraPanAheadCallback();
}
else
{
if (gPlayerAvatar.running1 == 1)
{
gUnknown_0300059C ^= 1;
if (gUnknown_0300059C == 0)
return;
}
else
{
gUnknown_0300059C = 0;
}
var = player_get_direction_upper_nybble();
if (var == 2)
{
if (gUnknown_0300059A > -8)
gUnknown_0300059A -= 2;
}
else if (var == 1)
{
if (gUnknown_0300059A < 72)
gUnknown_0300059A += 2;
}
else if (gUnknown_0300059A < 32)
{
gUnknown_0300059A += 2;
}
else if (gUnknown_0300059A > 32)
{
gUnknown_0300059A -= 2;
}
}
}