diff options
author | ultima-soul <akshayjhanji@hotmail.com> | 2020-03-13 00:32:04 -0700 |
---|---|---|
committer | ultima-soul <akshayjhanji@hotmail.com> | 2020-03-13 00:32:04 -0700 |
commit | 99e4de062ae43aa978ad4f1a8cd70bc739c64c9d (patch) | |
tree | 1164d31577e6ebddc1cb313d40bb69ce0d426170 /src/field_camera.c | |
parent | 339c2914affc3c62ac9a5725aa1a0c7ccc3161ca (diff) | |
parent | 6af8c04d8fa6aaeaeb6c8b919e7770a65b9a883d (diff) |
Merge branch 'master' into event_object_movement
Diffstat (limited to 'src/field_camera.c')
-rw-r--r-- | src/field_camera.c | 572 |
1 files changed, 572 insertions, 0 deletions
diff --git a/src/field_camera.c b/src/field_camera.c new file mode 100644 index 000000000..40ab8f464 --- /dev/null +++ b/src/field_camera.c @@ -0,0 +1,572 @@ +#include "global.h" +#include "gflib.h" +#include "field_camera.h" +#include "field_player_avatar.h" +#include "fieldmap.h" +#include "event_object_movement.h" +#include "new_menu_helpers.h" +#include "overworld.h" + +EWRAM_DATA bool8 gUnusedBikeCameraAheadPanback = FALSE; + +// Static type declarations +struct FieldCameraOffset +{ + u8 xPixelOffset; + u8 yPixelOffset; + u8 xTileOffset; + u8 yTileOffset; + bool8 copyBGToVRAM; +}; + +// static functions +static void RedrawMapSliceNorth(struct FieldCameraOffset *cameraOffset, const struct MapLayout *mapLayout); +static void RedrawMapSliceSouth(struct FieldCameraOffset *cameraOffset, const struct MapLayout *mapLayout); +static void RedrawMapSliceEast(struct FieldCameraOffset *cameraOffset, const struct MapLayout *mapLayout); +static void RedrawMapSliceWest(struct FieldCameraOffset *cameraOffset, const struct MapLayout *mapLayout); +static s32 MapPosToBgTilemapOffset(struct FieldCameraOffset *a, s32 x, s32 y); +static void DrawWholeMapViewInternal(int x, int y, const struct MapLayout *mapLayout); +static void DrawMetatileAt(const struct MapLayout *mapLayout, u16, int, int); +static void DrawMetatile(s32 a, const u16 *b, u16 c); +static void CameraPanningCB_PanAhead(void); + +// IWRAM bss vars +static struct FieldCameraOffset sFieldCameraOffset; +static s16 sHorizontalCameraPan; +static s16 sVerticalCameraPan; +static u8 gUnknown_3000E9C; +static void (*sFieldCameraPanningCallback)(void); + +struct CameraObject gFieldCamera; +u16 gTotalCameraPixelOffsetY; +u16 gTotalCameraPixelOffsetX; + +// text +static void move_tilemap_camera_to_upper_left_corner_(struct FieldCameraOffset *cameraOffset) +{ + cameraOffset->xTileOffset = 0; + cameraOffset->yTileOffset = 0; + cameraOffset->xPixelOffset = 0; + cameraOffset->yPixelOffset = 0; + cameraOffset->copyBGToVRAM = TRUE; +} + +static void tilemap_move_something(struct FieldCameraOffset *cameraOffset, u32 b, u32 c) +{ + cameraOffset->xTileOffset += b; + cameraOffset->xTileOffset %= 32; + cameraOffset->yTileOffset += c; + cameraOffset->yTileOffset %= 32; +} + +static void coords8_add(struct FieldCameraOffset *cameraOffset, u32 b, u32 c) +{ + cameraOffset->xPixelOffset += b; + cameraOffset->yPixelOffset += c; +} + +void move_tilemap_camera_to_upper_left_corner(void) +{ + move_tilemap_camera_to_upper_left_corner_(&sFieldCameraOffset); +} + +void FieldUpdateBgTilemapScroll(void) +{ + u32 r4, r5; + r5 = sFieldCameraOffset.xPixelOffset + sHorizontalCameraPan; + r4 = sVerticalCameraPan + sFieldCameraOffset.yPixelOffset + 8; + + SetGpuReg(REG_OFFSET_BG1HOFS, r5); + SetGpuReg(REG_OFFSET_BG1VOFS, r4); + SetGpuReg(REG_OFFSET_BG2HOFS, r5); + SetGpuReg(REG_OFFSET_BG2VOFS, r4); + SetGpuReg(REG_OFFSET_BG3HOFS, r5); + SetGpuReg(REG_OFFSET_BG3VOFS, r4); +} + +void sub_805A658(s16 *a, s16 *b) +{ + *a = sFieldCameraOffset.xPixelOffset + sHorizontalCameraPan; + *b = sFieldCameraOffset.yPixelOffset + sVerticalCameraPan + 8; +} + +void DrawWholeMapView(void) +{ + DrawWholeMapViewInternal(gSaveBlock1Ptr->pos.x, gSaveBlock1Ptr->pos.y, gMapHeader.mapLayout); + // sFieldCameraOffset.copyBGToVRAM = TRUE; +} + +static void DrawWholeMapViewInternal(int x, int y, const struct MapLayout *mapLayout) +{ + u8 i; + u8 j; + u32 r6; + u8 temp; + + for (i = 0; i < 32; i += 2) + { + temp = sFieldCameraOffset.yTileOffset + i; + if (temp >= 32) + temp -= 32; + r6 = temp * 32; + for (j = 0; j < 32; j += 2) + { + temp = sFieldCameraOffset.xTileOffset + j; + if (temp >= 32) + temp -= 32; + DrawMetatileAt(mapLayout, r6 + temp, x + j / 2, y + i / 2); + } + } +} + +static void RedrawMapSlicesForCameraUpdate(struct FieldCameraOffset *cameraOffset, int x, int y) +{ + const struct MapLayout *mapLayout = gMapHeader.mapLayout; + + if (x > 0) + RedrawMapSliceWest(cameraOffset, mapLayout); + if (x < 0) + RedrawMapSliceEast(cameraOffset, mapLayout); + if (y > 0) + RedrawMapSliceNorth(cameraOffset, mapLayout); + if (y < 0) + RedrawMapSliceSouth(cameraOffset, mapLayout); + cameraOffset->copyBGToVRAM = TRUE; +} + +static void RedrawMapSliceNorth(struct FieldCameraOffset *cameraOffset, const struct MapLayout *mapLayout) +{ + u8 i; + u8 temp; + u32 r7; + + temp = cameraOffset->yTileOffset + 28; + if (temp >= 32) + temp -= 32; + r7 = temp * 32; + for (i = 0; i < 32; i += 2) + { + temp = cameraOffset->xTileOffset + i; + if (temp >= 32) + temp -= 32; + DrawMetatileAt(mapLayout, r7 + temp, gSaveBlock1Ptr->pos.x + i / 2, gSaveBlock1Ptr->pos.y + 14); + } +} + +static void RedrawMapSliceSouth(struct FieldCameraOffset *cameraOffset, const struct MapLayout *mapLayout) +{ + u8 i; + u8 temp; + u32 r7 = cameraOffset->yTileOffset * 32; + + for (i = 0; i < 32; i += 2) + { + temp = cameraOffset->xTileOffset + i; + if (temp >= 32) + temp -= 32; + DrawMetatileAt(mapLayout, r7 + temp, gSaveBlock1Ptr->pos.x + i / 2, gSaveBlock1Ptr->pos.y); + } +} + +static void RedrawMapSliceEast(struct FieldCameraOffset *cameraOffset, const struct MapLayout *mapLayout) +{ + u8 i; + u8 temp; + u32 r6 = cameraOffset->xTileOffset; + + for (i = 0; i < 32; i += 2) + { + temp = cameraOffset->yTileOffset + i; + if (temp >= 32) + temp -= 32; + DrawMetatileAt(mapLayout, temp * 32 + r6, gSaveBlock1Ptr->pos.x, gSaveBlock1Ptr->pos.y + i / 2); + } +} + +static void RedrawMapSliceWest(struct FieldCameraOffset *cameraOffset, const struct MapLayout *mapLayout) +{ + u8 i; + u8 temp; + u8 r5 = cameraOffset->xTileOffset + 28; + + if (r5 >= 32) + r5 -= 32; + for (i = 0; i < 32; i += 2) + { + temp = cameraOffset->yTileOffset + i; + if (temp >= 32) + temp -= 32; + DrawMetatileAt(mapLayout, temp * 32 + r5, gSaveBlock1Ptr->pos.x + 14, gSaveBlock1Ptr->pos.y + i / 2); + } +} + +void CurrentMapDrawMetatileAt(int x, int y) +{ + int offset = MapPosToBgTilemapOffset(&sFieldCameraOffset, x, y); + + if (offset >= 0) + { + DrawMetatileAt(gMapHeader.mapLayout, offset, x, y); + // sFieldCameraOffset.copyBGToVRAM = TRUE; + } +} + +void DrawDoorMetatileAt(int x, int y, const u16 *arr) +{ + int offset = MapPosToBgTilemapOffset(&sFieldCameraOffset, x, y); + + if (offset >= 0) + { + DrawMetatile(1, arr, offset); + // sFieldCameraOffset.copyBGToVRAM = TRUE; + } +} + +static void DrawMetatileAt(const struct MapLayout *mapLayout, u16 offset, int x, int y) +{ + u16 metatileId = MapGridGetMetatileIdAt(x, y); + u16 *metatiles; + + if (metatileId > NUM_METATILES_TOTAL) + metatileId = 0; + if (metatileId < NUM_METATILES_IN_PRIMARY) + metatiles = mapLayout->primaryTileset->metatiles; + else + { + metatiles = mapLayout->secondaryTileset->metatiles; + metatileId -= NUM_METATILES_IN_PRIMARY; + } + DrawMetatile(MapGridGetMetatileLayerTypeAt(x, y), metatiles + metatileId * 8, offset); +} + +static void DrawMetatile(s32 metatileLayerType, const u16 *metatiles, u16 offset) +{ + switch (metatileLayerType) + { + case 2: // LAYER_TYPE_ + // Draw metatile's bottom layer to the bottom background layer. + gBGTilemapBuffers3[offset] = metatiles[0]; + gBGTilemapBuffers3[offset + 1] = metatiles[1]; + gBGTilemapBuffers3[offset + 0x20] = metatiles[2]; + gBGTilemapBuffers3[offset + 0x21] = metatiles[3]; + + // Draw transparent tiles to the middle background layer. + gBGTilemapBuffers1[offset] = 0; + gBGTilemapBuffers1[offset + 1] = 0; + gBGTilemapBuffers1[offset + 0x20] = 0; + gBGTilemapBuffers1[offset + 0x21] = 0; + + // Draw metatile's top layer to the top background layer. + gBGTilemapBuffers2[offset] = metatiles[4]; + gBGTilemapBuffers2[offset + 1] = metatiles[5]; + gBGTilemapBuffers2[offset + 0x20] = metatiles[6]; + gBGTilemapBuffers2[offset + 0x21] = metatiles[7]; + break; + case 1: // LAYER_TYPE_COVERED_BY_OBJECTS + // Draw metatile's bottom layer to the bottom background layer. + gBGTilemapBuffers3[offset] = metatiles[0]; + gBGTilemapBuffers3[offset + 1] = metatiles[1]; + gBGTilemapBuffers3[offset + 0x20] = metatiles[2]; + gBGTilemapBuffers3[offset + 0x21] = metatiles[3]; + + // Draw metatile's top layer to the middle background layer. + gBGTilemapBuffers1[offset] = metatiles[4]; + gBGTilemapBuffers1[offset + 1] = metatiles[5]; + gBGTilemapBuffers1[offset + 0x20] = metatiles[6]; + gBGTilemapBuffers1[offset + 0x21] = metatiles[7]; + + // Draw transparent tiles to the top background layer. + gBGTilemapBuffers2[offset] = 0; + gBGTilemapBuffers2[offset + 1] = 0; + gBGTilemapBuffers2[offset + 0x20] = 0; + gBGTilemapBuffers2[offset + 0x21] = 0; + break; + case 0: // LAYER_TYPE_NORMAL + // Draw garbage to the bottom background layer. + gBGTilemapBuffers3[offset] = 0x3014; + gBGTilemapBuffers3[offset + 1] = 0x3014; + gBGTilemapBuffers3[offset + 0x20] = 0x3014; + gBGTilemapBuffers3[offset + 0x21] = 0x3014; + + // Draw metatile's bottom layer to the middle background layer. + gBGTilemapBuffers1[offset] = metatiles[0]; + gBGTilemapBuffers1[offset + 1] = metatiles[1]; + gBGTilemapBuffers1[offset + 0x20] = metatiles[2]; + gBGTilemapBuffers1[offset + 0x21] = metatiles[3]; + + // Draw metatile's top layer to the top background layer, which covers object event sprites. + gBGTilemapBuffers2[offset] = metatiles[4]; + gBGTilemapBuffers2[offset + 1] = metatiles[5]; + gBGTilemapBuffers2[offset + 0x20] = metatiles[6]; + gBGTilemapBuffers2[offset + 0x21] = metatiles[7]; + break; + } + ScheduleBgCopyTilemapToVram(1); + ScheduleBgCopyTilemapToVram(2); + ScheduleBgCopyTilemapToVram(3); +} + +static s32 MapPosToBgTilemapOffset(struct FieldCameraOffset *cameraOffset, s32 x, s32 y) +{ + x -= gSaveBlock1Ptr->pos.x; + x *= 2; + if (x >= 32 || x < 0) + return -1; + x = x + cameraOffset->xTileOffset; + if (x >= 32) + x -= 32; + + y = (y - gSaveBlock1Ptr->pos.y) * 2; + if (y >= 32 || y < 0) + return -1; + y = y + cameraOffset->yTileOffset; + if (y >= 32) + y -= 32; + + return y * 32 + x; +} + +static void CameraUpdateCallback(struct CameraObject *fieldCamera) +{ + if (fieldCamera->spriteId != 0) + { + fieldCamera->movementSpeedX = gSprites[fieldCamera->spriteId].data[2]; + fieldCamera->movementSpeedY = gSprites[fieldCamera->spriteId].data[3]; + } +} + +void ResetCameraUpdateInfo(void) +{ + gFieldCamera.movementSpeedX = 0; + gFieldCamera.movementSpeedY = 0; + gFieldCamera.x = 0; + gFieldCamera.y = 0; + gFieldCamera.spriteId = 0; + gFieldCamera.callback = NULL; +} + +u32 InitCameraUpdateCallback(u8 trackedSpriteId) +{ + if (gFieldCamera.spriteId != 0) + DestroySprite(&gSprites[gFieldCamera.spriteId]); + gFieldCamera.spriteId = AddCameraObject(trackedSpriteId); + gFieldCamera.callback = CameraUpdateCallback; + return 0; +} + +void CameraUpdate(void) +{ + int deltaX; + int deltaY; + int curMovementOffsetY; + int curMovementOffsetX; + int movementSpeedX; + int movementSpeedY; + + if (gFieldCamera.callback != NULL) + gFieldCamera.callback(&gFieldCamera); + movementSpeedX = gFieldCamera.movementSpeedX; + movementSpeedY = gFieldCamera.movementSpeedY; + deltaX = 0; + deltaY = 0; + curMovementOffsetX = gFieldCamera.x; + curMovementOffsetY = gFieldCamera.y; + + + if (curMovementOffsetX == 0 && movementSpeedX != 0) + { + if (movementSpeedX > 0) + deltaX = 1; + else + deltaX = -1; + } + if (curMovementOffsetY == 0 && movementSpeedY != 0) + { + if (movementSpeedY > 0) + deltaY = 1; + else + deltaY = -1; + } + if (curMovementOffsetX != 0 && curMovementOffsetX == -movementSpeedX) + { + if (movementSpeedX > 0) + deltaX = 1; + else + deltaX = -1; + } + if (curMovementOffsetY != 0 && curMovementOffsetY == -movementSpeedY) + { + if (movementSpeedY > 0) + deltaX = 1; + else + deltaX = -1; + } + + gFieldCamera.x += movementSpeedX; + gFieldCamera.x = gFieldCamera.x - 16 * (gFieldCamera.x / 16); + gFieldCamera.y += movementSpeedY; + gFieldCamera.y = gFieldCamera.y - 16 * (gFieldCamera.y / 16); + + if (deltaX != 0 || deltaY != 0) + { + CameraMove(deltaX, deltaY); + UpdateObjectEventsForCameraUpdate(deltaX, deltaY); + // RotatingGatePuzzleCameraUpdate(deltaX, deltaY); + // ResetBerryTreeSparkleFlags(); + tilemap_move_something(&sFieldCameraOffset, deltaX * 2, deltaY * 2); + RedrawMapSlicesForCameraUpdate(&sFieldCameraOffset, deltaX * 2, deltaY * 2); + } + + coords8_add(&sFieldCameraOffset, movementSpeedX, movementSpeedY); + gTotalCameraPixelOffsetX -= movementSpeedX; + gTotalCameraPixelOffsetY -= movementSpeedY; +} + +void MoveCameraAndRedrawMap(int deltaX, int deltaY) // unused +{ + CameraMove(deltaX, deltaY); + UpdateObjectEventsForCameraUpdate(deltaX, deltaY); + DrawWholeMapView(); + gTotalCameraPixelOffsetX -= deltaX * 16; + gTotalCameraPixelOffsetY -= deltaY * 16; +} + +void sub_805ACF0(void) +{ + int deltaX; + int deltaY; + int curMovementOffsetY; + int curMovementOffsetX; + int movementSpeedX; + int movementSpeedY; + + if (gFieldCamera.callback != NULL) + gFieldCamera.callback(&gFieldCamera); + movementSpeedX = gFieldCamera.movementSpeedX; + movementSpeedY = gFieldCamera.movementSpeedY; + deltaX = 0; + deltaY = 0; + curMovementOffsetX = gFieldCamera.x; + curMovementOffsetY = gFieldCamera.y; + + + if (curMovementOffsetX == 0 && movementSpeedX != 0) + { + if (movementSpeedX > 0) + deltaX = 1; + else + deltaX = -1; + } + if (curMovementOffsetY == 0 && movementSpeedY != 0) + { + if (movementSpeedY > 0) + deltaY = 1; + else + deltaY = -1; + } + if (curMovementOffsetX != 0 && curMovementOffsetX == -movementSpeedX) + { + if (movementSpeedX > 0) + deltaX = 1; + else + deltaX = -1; + } + if (curMovementOffsetY != 0 && curMovementOffsetY == -movementSpeedY) + { + if (movementSpeedY > 0) + deltaX = 1; + else + deltaX = -1; + } + + gFieldCamera.x += movementSpeedX; + gFieldCamera.x = gFieldCamera.x - 16 * (gFieldCamera.x / 16); + gFieldCamera.y += movementSpeedY; + gFieldCamera.y = gFieldCamera.y - 16 * (gFieldCamera.y / 16); + + if (deltaX != 0 || deltaY != 0) + { + CameraMove(deltaX, deltaY); + // UpdateObjectEventsForCameraUpdate(deltaX, deltaY); + // RotatingGatePuzzleCameraUpdate(deltaX, deltaY); + // ResetBerryTreeSparkleFlags(); + tilemap_move_something(&sFieldCameraOffset, deltaX * 2, deltaY * 2); + RedrawMapSlicesForCameraUpdate(&sFieldCameraOffset, deltaX * 2, deltaY * 2); + } + + coords8_add(&sFieldCameraOffset, movementSpeedX, movementSpeedY); + // gTotalCameraPixelOffsetX -= movementSpeedX; + // gTotalCameraPixelOffsetY -= movementSpeedY; +} + +void SetCameraPanningCallback(void (*a)(void)) +{ + sFieldCameraPanningCallback = a; +} + +void SetCameraPanning(s16 a, s16 b) +{ + sHorizontalCameraPan = a; + sVerticalCameraPan = b + 32; +} + +void InstallCameraPanAheadCallback(void) +{ + sFieldCameraPanningCallback = CameraPanningCB_PanAhead; + gUnknown_3000E9C = 0; + sHorizontalCameraPan = 0; + sVerticalCameraPan = 32; +} + +void UpdateCameraPanning(void) +{ + if (sFieldCameraPanningCallback != NULL) + sFieldCameraPanningCallback(); + // Update sprite offset of overworld objects + gSpriteCoordOffsetX = gTotalCameraPixelOffsetX - sHorizontalCameraPan; + gSpriteCoordOffsetY = gTotalCameraPixelOffsetY - sVerticalCameraPan - 8; +} + +static void CameraPanningCB_PanAhead(void) +{ + u8 var; + + if (gUnusedBikeCameraAheadPanback == FALSE) + { + InstallCameraPanAheadCallback(); + } + else + { + // this code is never reached. + if (gPlayerAvatar.tileTransitionState == 1) + { + gUnknown_3000E9C ^= 1; + if (gUnknown_3000E9C == 0) + return; + } + else + { + gUnknown_3000E9C = 0; + } + + var = GetPlayerMovementDirection(); + if (var == 2) + { + if (sVerticalCameraPan > -8) + sVerticalCameraPan -= 2; + } + else if (var == 1) + { + if (sVerticalCameraPan < 72) + sVerticalCameraPan += 2; + } + else if (sVerticalCameraPan < 32) + { + sVerticalCameraPan += 2; + } + else if (sVerticalCameraPan > 32) + { + sVerticalCameraPan -= 2; + } + } +} |