Document BDHC util

This documents the `bdhc_util.c` file, which mainly contains the
function used to calculated an object's height based on its 2D position
and the BDHC of the map its currently on.

Signed-off-by: Kuruyia <github@kuruyia.net>
This commit is contained in:
Kuruyia 2025-02-05 22:25:07 +01:00
parent 10c283da33
commit caa281efea
11 changed files with 489 additions and 516 deletions

View File

@ -2,11 +2,15 @@
#define POKEPLATINUM_OV5_BDHC_H
#include <nitro/fx/fx.h>
#include <nitro/types.h>
#include "narc.h"
#include "sys_task_manager.h"
typedef struct BDHCPlate {
u16 firstPointIndex;
u16 secondPointIndex;
u16 normalIndex;
u16 slopeIndex;
u16 heightIndex;
} BDHCPlate;
@ -32,4 +36,15 @@ typedef struct BDHC {
int stripsSize;
} BDHC;
BOOL CalculateObjectHeight(const fx32 objectHeight, const fx32 objectX, const fx32 objectZ, const BDHC *bdhc, fx32 *newObjectHeight);
void BDHC_Load(NARC *narc, const int bdhcSize, BDHC *bdhc, u8 *buffer);
SysTask *BDHC_LazyLoad(NARC *landDataNARC, const int unused1, BDHC *bdhc, int *param3, u8 **buffer, int *param5);
void BDHC_KillLoad(SysTask *sysTask);
void BDHC_MarkNotLoaded(BDHC *bdhc);
BDHC *BDHC_New(void);
void BDHC_Free(BDHC *bdhc);
void BDHC_Reset(BDHC *bdhc);
#endif // POKEPLATINUM_OV5_BDHC_H

View File

@ -1,18 +0,0 @@
#ifndef POKEPLATINUM_OV5_BDHC_LOADER_H
#define POKEPLATINUM_OV5_BDHC_LOADER_H
#include "overlay005/bdhc.h"
#include "narc.h"
#include "sys_task_manager.h"
void BDHCLoader_Load(NARC *narc, const int bdhcSize, BDHC *bdhc, u8 *buffer);
SysTask *BDHCLoader_StartTask(NARC *landDataNARC, const int param1, BDHC *bdhc, int *param3, u8 **buffer, int *param5);
void BDHCLoader_ForceExitTask(SysTask *sysTask);
void BDHCLoader_MarkBDHCNotLoaded(BDHC *bdhc);
BDHC *BDHC_New(void);
void BDHC_Free(BDHC *bdhc);
void BDHC_Reset(BDHC *bdhc);
#endif // POKEPLATINUM_OV5_BDHC_LOADER_H

View File

@ -1,8 +0,0 @@
#ifndef POKEPLATINUM_OV5_021EEC68_H
#define POKEPLATINUM_OV5_021EEC68_H
#include "overlay005/bdhc.h"
BOOL ov5_021EED9C(const fx32 param0, const fx32 param1, const fx32 param2, const BDHC *param3, fx32 *param4);
#endif // POKEPLATINUM_OV5_021EEC68_H

View File

@ -1,10 +0,0 @@
#ifndef POKEPLATINUM_STRUCT_OV5_021EED20_H
#define POKEPLATINUM_STRUCT_OV5_021EED20_H
typedef struct UnkStruct_ov5_021EED20_t {
fx32 unk_00;
int unk_04;
int unk_08;
} UnkStruct_ov5_021EED20;
#endif // POKEPLATINUM_STRUCT_OV5_021EED20_H

View File

@ -508,8 +508,7 @@ Overlay overlay5
Object main.nef.p/src_overlay005_ov5_021EE75C.c.o
Object main.nef.p/src_overlay005_ov5_021EE7D4.c.o
Object main.nef.p/src_overlay005_ov5_021EEAC8.c.o
Object main.nef.p/src_overlay005_ov5_021EEC68.c.o
Object main.nef.p/src_overlay005_bdhc_loader.c.o
Object main.nef.p/src_overlay005_bdhc.c.o
Object main.nef.p/src_overlay005_ov5_021EF250.c.o
Object main.nef.p/src_overlay005_hblank_system.c.o
Object main.nef.p/src_overlay005_ov5_021EF4BC.c.o

View File

@ -401,8 +401,7 @@ pokeplatinum_c = files(
'overlay005/ov5_021EE75C.c',
'overlay005/ov5_021EE7D4.c',
'overlay005/ov5_021EEAC8.c',
'overlay005/ov5_021EEC68.c',
'overlay005/bdhc_loader.c',
'overlay005/bdhc.c',
'overlay005/ov5_021EF250.c',
'overlay005/hblank_system.c',
'overlay005/ov5_021EF4BC.c',

462
src/overlay005/bdhc.c Normal file
View File

@ -0,0 +1,462 @@
#include "overlay005/bdhc.h"
#include <nitro.h>
#include <string.h>
#include "constants/bdhc.h"
#include "constants/heap.h"
#include "fx_util.h"
#include "heap.h"
#include "narc.h"
#include "sys_task.h"
#include "sys_task_manager.h"
#define BDHC_NEW_OBJECT_HEIGHT_CANDIDATES_ARRAY_SIZE 10
enum BDHCSubTask {
BDHC_LOADER_SUBTASK_PREPARE_FILE_LOAD = 0,
BDHC_LOADER_SUBTASK_LOAD_FILE,
BDHC_LOADER_SUBTASK_END_TASK,
};
typedef struct {
int pointsSize;
int slopesSize;
int heightsSize;
int platesSize;
int stripsSize;
int accessListSize;
} BDHCHeader;
typedef struct {
FSFile dummy00;
int dummyAC;
BDHCHeader bdhcHeader;
BOOL dummyC8;
u8 currentSubTask;
u8 *buffer;
BDHC *bdhc;
BOOL killLoadTask;
int *unk_DC;
NARC *landDataNARC;
int dummyE4;
int *unk_E8;
} BDHCLoaderTaskContext;
typedef struct {
fx32 val;
int dummy04;
int dummy08;
} BDHCCandidateObjectHeight;
static BOOL BDHC_FindStripIndexByLowerBound(const BDHCStrip *strips, const u16 stripsSize, const fx32 targetLowerBound, u16 *stripIndex);
static void BDHC_PrepareBuffers(const BDHCHeader *bdhcHeader, BDHC *bdhc, void **buffer);
static void BDHC_LoadPoints(NARC *narc, BDHC *bdhc, const BDHCHeader *bdhcHeader);
static void BDHC_LoadSlopes(NARC *narc, BDHC *bdhc, const BDHCHeader *bdhcHeader);
static void BDHC_LoadHeights(NARC *narc, BDHC *bdhc, const BDHCHeader *bdhcHeader);
static void BDHC_LoadPlates(NARC *narc, BDHC *bdhc, const BDHCHeader *bdhcHeader);
static void BDHC_LoadStrips(NARC *narc, BDHC *bdhc, const BDHCHeader *bdhcHeader);
static void BDHC_LoadAccessList(NARC *narc, BDHC *bdhc, const BDHCHeader *bdhcHeader);
static BOOL BDHC_IsPointInBoundingBox(const BDHCPoint *boundingBoxFirstPoint, const BDHCPoint *boundingBoxSecondPoint, const BDHCPoint *point)
{
const fx32 *boundingBoxLeft, *boundingBoxRight, *boundingBoxUp, *boundingBoxDown;
if (boundingBoxFirstPoint->x <= boundingBoxSecondPoint->x) {
boundingBoxLeft = &boundingBoxFirstPoint->x;
boundingBoxRight = &boundingBoxSecondPoint->x;
} else {
boundingBoxLeft = &boundingBoxSecondPoint->x;
boundingBoxRight = &boundingBoxFirstPoint->x;
}
if (boundingBoxFirstPoint->y <= boundingBoxSecondPoint->y) {
boundingBoxUp = &boundingBoxFirstPoint->y;
boundingBoxDown = &boundingBoxSecondPoint->y;
} else {
boundingBoxUp = &boundingBoxSecondPoint->y;
boundingBoxDown = &boundingBoxFirstPoint->y;
}
if (((*boundingBoxLeft <= point->x) && (point->x <= *boundingBoxRight)) && ((*boundingBoxUp <= point->y) && (point->y <= *boundingBoxDown))) {
return TRUE;
}
return FALSE;
}
static void BDHC_GetPointsFromPlate(const BDHC *bdhc, u16 plateIndex, BDHCPoint *platePoints)
{
platePoints[0] = bdhc->points[bdhc->plates[plateIndex].firstPointIndex];
platePoints[1] = bdhc->points[bdhc->plates[plateIndex].secondPointIndex];
}
static void BDHC_GetSlopeFromPlate(const BDHC *bdhc, u16 plateIndex, VecFx32 *slope)
{
*slope = bdhc->slopes[bdhc->plates[plateIndex].slopeIndex];
}
static void BDHC_GetHeightFromPlate(const BDHC *bdhc, u16 plateIndex, fx32 *height)
{
*height = bdhc->heights[bdhc->plates[plateIndex].heightIndex];
}
static void BDHC_InitCandidateObjectHeightsArray(BDHCCandidateObjectHeight *candidateObjectHeights)
{
for (int i = 0; i < BDHC_NEW_OBJECT_HEIGHT_CANDIDATES_ARRAY_SIZE; i++) {
candidateObjectHeights[i].val = 0;
candidateObjectHeights[i].dummy04 = -1;
candidateObjectHeights[i].dummy08 = -1;
}
}
static BOOL BDHC_FindStripIndexByLowerBound(const BDHCStrip *strips, const u16 stripsSize, const fx32 targetLowerBound, u16 *stripIndex)
{
int low, high;
u32 mid;
if (stripsSize == 0) {
return FALSE;
} else if (stripsSize == 1) {
*stripIndex = 0;
return TRUE;
}
// Simple binary search.
low = 0;
high = stripsSize - 1;
mid = high / 2;
do {
if (strips[mid].lowerBound > targetLowerBound) {
if (high - 1 > low) {
high = mid;
mid = (low + high) / 2;
} else {
*stripIndex = mid;
return TRUE;
}
} else {
if (low + 1 < high) {
low = mid;
mid = (low + high) / 2;
} else {
*stripIndex = mid + 1;
return TRUE;
}
}
} while (TRUE);
return FALSE;
}
BOOL CalculateObjectHeight(const fx32 objectHeight, const fx32 objectX, const fx32 objectZ, const BDHC *bdhc, fx32 *newObjectHeight)
{
BDHCPoint platePoints[2];
BDHCPoint objectPosition;
VecFx32 slope;
fx32 minObjectHeightDiff, objectHeightDiff;
BOOL isPointInBoundingBox;
u16 i, plateIndex;
fx32 height, calculatedObjectHeight;
int newObjectHeightCandidateCount;
u32 stripsSize;
BDHCCandidateObjectHeight newObjectHeightCandidates[BDHC_NEW_OBJECT_HEIGHT_CANDIDATES_ARRAY_SIZE];
u32 accessListStartIndex;
u16 stripIndex;
u16 accessListElementCount;
const BDHCStrip *strips;
if (bdhc->loaded == FALSE) {
return FALSE;
}
isPointInBoundingBox = FALSE;
objectPosition.x = objectX;
objectPosition.y = objectZ;
newObjectHeightCandidateCount = 0;
BDHC_InitCandidateObjectHeightsArray(newObjectHeightCandidates);
stripsSize = bdhc->stripsSize;
strips = bdhc->strips;
if (BDHC_FindStripIndexByLowerBound(strips, stripsSize, objectPosition.y, &stripIndex) == FALSE) {
return FALSE;
}
accessListElementCount = strips[stripIndex].accessListElementCount;
accessListStartIndex = strips[stripIndex].accessListStartIndex;
for (i = 0; i < accessListElementCount; i++) {
plateIndex = bdhc->accessList[accessListStartIndex + i];
BDHC_GetPointsFromPlate(bdhc, plateIndex, platePoints);
isPointInBoundingBox = BDHC_IsPointInBoundingBox(&platePoints[0], &platePoints[1], &objectPosition);
if (isPointInBoundingBox == TRUE) {
BDHC_GetSlopeFromPlate(bdhc, plateIndex, &slope);
BDHC_GetHeightFromPlate(bdhc, plateIndex, &height);
// On the next line, `slope.z` and `objectPosition.y` represent the same axis.
// Remember that `objectPosition.y` is, in fact, `objectZ`.
// Also, remember that `slope` is a normal vector, pointing upwards for a flat surface.
calculatedObjectHeight = -(FX_Mul(slope.x, objectPosition.x) + FX_Mul(slope.z, objectPosition.y) + height);
calculatedObjectHeight = FX_Div(calculatedObjectHeight, slope.y);
newObjectHeightCandidates[newObjectHeightCandidateCount].val = calculatedObjectHeight;
newObjectHeightCandidateCount++;
if (newObjectHeightCandidateCount >= BDHC_NEW_OBJECT_HEIGHT_CANDIDATES_ARRAY_SIZE) {
break;
}
}
}
if (newObjectHeightCandidateCount > 1) {
// Find the candidate with the smallest difference between the object's current height and the calculated height.
plateIndex = 0;
minObjectHeightDiff = FX_Max(objectHeight, newObjectHeightCandidates[0].val) - FX_Min(objectHeight, newObjectHeightCandidates[0].val);
for (i = 1; i < newObjectHeightCandidateCount; i++) {
objectHeightDiff = FX_Max(objectHeight, newObjectHeightCandidates[i].val) - FX_Min(objectHeight, newObjectHeightCandidates[i].val);
if (minObjectHeightDiff > objectHeightDiff) {
minObjectHeightDiff = objectHeightDiff;
plateIndex = i;
}
}
*newObjectHeight = newObjectHeightCandidates[plateIndex].val;
return TRUE;
} else if (newObjectHeightCandidateCount == 1) {
*newObjectHeight = newObjectHeightCandidates[0].val;
return TRUE;
}
if (newObjectHeightCandidateCount != 0) {
*newObjectHeight = newObjectHeightCandidates[0].val;
return TRUE;
}
return FALSE;
}
static void BDHC_LoadHeader(NARC *narc, BDHCHeader *bdhcHeader)
{
u16 magic[BDHC_MAGIC_LENGTH];
MI_CpuClear32(bdhcHeader, sizeof(BDHCHeader));
NARC_ReadFile(narc, BDHC_MAGIC_LENGTH, magic);
NARC_ReadFile(narc, 2, &bdhcHeader->pointsSize);
NARC_ReadFile(narc, 2, &bdhcHeader->slopesSize);
NARC_ReadFile(narc, 2, &bdhcHeader->heightsSize);
NARC_ReadFile(narc, 2, &bdhcHeader->platesSize);
NARC_ReadFile(narc, 2, &bdhcHeader->stripsSize);
NARC_ReadFile(narc, 2, &bdhcHeader->accessListSize);
}
static void BDHC_PrepareBuffers(const BDHCHeader *bdhcHeader, BDHC *bdhc, void **buffer)
{
void *ptr;
int offset = 0;
ptr = (u8 *)*buffer;
bdhc->points = ptr;
offset += (sizeof(BDHCPoint) * bdhcHeader->pointsSize);
ptr = (u8 *)*buffer + offset;
bdhc->slopes = ptr;
offset += (sizeof(VecFx32) * bdhcHeader->slopesSize);
ptr = (u8 *)*buffer + offset;
bdhc->heights = ptr;
offset += (sizeof(fx32) * bdhcHeader->heightsSize);
ptr = (u8 *)*buffer + offset;
bdhc->plates = ptr;
offset += (sizeof(BDHCPlate) * bdhcHeader->platesSize);
ptr = (u8 *)*buffer + offset;
bdhc->strips = ptr;
offset += sizeof(BDHCStrip) * bdhcHeader->stripsSize;
ptr = (u8 *)*buffer + offset;
bdhc->accessList = ptr;
offset += sizeof(u16) * bdhcHeader->accessListSize;
GF_ASSERT(offset <= BDHC_BUFFER_SIZE);
}
static void BDHC_LoadPoints(NARC *narc, BDHC *bdhc, const BDHCHeader *bdhcHeader)
{
NARC_ReadFile(narc, sizeof(BDHCPoint) * bdhcHeader->pointsSize, bdhc->points);
}
static void BDHC_LoadSlopes(NARC *narc, BDHC *bdhc, const BDHCHeader *bdhcHeader)
{
NARC_ReadFile(narc, sizeof(VecFx32) * bdhcHeader->slopesSize, bdhc->slopes);
}
static void BDHC_LoadHeights(NARC *narc, BDHC *bdhc, const BDHCHeader *bdhcHeader)
{
NARC_ReadFile(narc, sizeof(fx32) * bdhcHeader->heightsSize, bdhc->heights);
}
static void BDHC_LoadPlates(NARC *narc, BDHC *bdhc, const BDHCHeader *bdhcHeader)
{
NARC_ReadFile(narc, sizeof(BDHCPlate) * bdhcHeader->platesSize, bdhc->plates);
}
static void BDHC_LoadStrips(NARC *narc, BDHC *bdhc, const BDHCHeader *bdhcHeader)
{
NARC_ReadFile(narc, sizeof(BDHCStrip) * bdhcHeader->stripsSize, bdhc->strips);
}
static void BDHC_LoadAccessList(NARC *narc, BDHC *bdhc, const BDHCHeader *bdhcHeader)
{
NARC_ReadFile(narc, sizeof(u16) * bdhcHeader->accessListSize, bdhc->accessList);
}
static void BDHC_LazyLoadTask(SysTask *sysTask, void *sysTaskParam)
{
BOOL subTaskCompleted;
BDHCLoaderTaskContext *ctx = (BDHCLoaderTaskContext *)sysTaskParam;
if (ctx->killLoadTask == TRUE) {
ctx->currentSubTask = BDHC_LOADER_SUBTASK_END_TASK;
}
switch (ctx->currentSubTask) {
case BDHC_LOADER_SUBTASK_PREPARE_FILE_LOAD:
if (*ctx->unk_E8) {
subTaskCompleted = FALSE;
break;
}
BDHC_LoadHeader(ctx->landDataNARC, &ctx->bdhcHeader);
ctx->bdhc->stripsSize = ctx->bdhcHeader.stripsSize;
BDHC_PrepareBuffers(&ctx->bdhcHeader, ctx->bdhc, (void **)&ctx->buffer);
subTaskCompleted = TRUE;
break;
case BDHC_LOADER_SUBTASK_LOAD_FILE:
BDHC_LoadPoints(ctx->landDataNARC, ctx->bdhc, &ctx->bdhcHeader);
BDHC_LoadSlopes(ctx->landDataNARC, ctx->bdhc, &ctx->bdhcHeader);
BDHC_LoadHeights(ctx->landDataNARC, ctx->bdhc, &ctx->bdhcHeader);
BDHC_LoadPlates(ctx->landDataNARC, ctx->bdhc, &ctx->bdhcHeader);
BDHC_LoadStrips(ctx->landDataNARC, ctx->bdhc, &ctx->bdhcHeader);
BDHC_LoadAccessList(ctx->landDataNARC, ctx->bdhc, &ctx->bdhcHeader);
subTaskCompleted = TRUE;
break;
case BDHC_LOADER_SUBTASK_END_TASK:
*ctx->unk_DC = 0;
Heap_FreeToHeap((void *)sysTaskParam);
SysTask_Done(sysTask);
return;
}
if (subTaskCompleted == TRUE) {
ctx->currentSubTask++;
if (ctx->currentSubTask == BDHC_LOADER_SUBTASK_END_TASK) {
ctx->bdhc->loaded = TRUE;
}
}
}
BDHC *BDHC_New(void)
{
BDHC *bdhc = Heap_AllocFromHeap(HEAP_ID_FIELD, sizeof(BDHC));
bdhc->points = NULL;
bdhc->slopes = NULL;
bdhc->plates = NULL;
bdhc->strips = NULL;
bdhc->accessList = NULL;
bdhc->accessList = NULL;
bdhc->loaded = FALSE;
bdhc->stripsSize = 0;
return bdhc;
}
void BDHC_Load(NARC *narc, const int bdhcSize, BDHC *bdhc, u8 *buffer)
{
BDHCHeader *bdhcHeader = Heap_AllocFromHeapAtEnd(HEAP_ID_FIELD, sizeof(BDHCHeader));
BDHC_LoadHeader(narc, bdhcHeader);
bdhc->stripsSize = bdhcHeader->stripsSize;
BDHC_PrepareBuffers(bdhcHeader, bdhc, (void **)&buffer);
BDHC_LoadPoints(narc, bdhc, bdhcHeader);
BDHC_LoadSlopes(narc, bdhc, bdhcHeader);
BDHC_LoadHeights(narc, bdhc, bdhcHeader);
BDHC_LoadPlates(narc, bdhc, bdhcHeader);
BDHC_LoadStrips(narc, bdhc, bdhcHeader);
BDHC_LoadAccessList(narc, bdhc, bdhcHeader);
Heap_FreeToHeap(bdhcHeader);
bdhc->loaded = TRUE;
}
void BDHC_Free(BDHC *bdhc)
{
if (bdhc == NULL) {
return;
}
Heap_FreeToHeap(bdhc);
bdhc = NULL;
}
void BDHC_Reset(BDHC *bdhc)
{
if (bdhc == NULL) {
return;
}
bdhc->loaded = FALSE;
bdhc->points = NULL;
bdhc->slopes = NULL;
bdhc->plates = NULL;
bdhc->strips = NULL;
bdhc->accessList = NULL;
}
SysTask *BDHC_LazyLoad(NARC *landDataNARC, const int unused1, BDHC *bdhc, int *param3, u8 **buffer, int *param5)
{
BDHCLoaderTaskContext *ctx = Heap_AllocFromHeapAtEnd(HEAP_ID_FIELD, sizeof(BDHCLoaderTaskContext));
ctx->currentSubTask = BDHC_LOADER_SUBTASK_PREPARE_FILE_LOAD;
ctx->landDataNARC = landDataNARC;
ctx->dummyE4 = unused1;
ctx->bdhc = bdhc;
ctx->unk_DC = param3;
ctx->killLoadTask = FALSE;
ctx->dummyC8 = FALSE;
ctx->dummyAC = 0;
ctx->buffer = *buffer;
ctx->unk_E8 = param5;
return SysTask_Start(BDHC_LazyLoadTask, (void *)ctx, 1);
}
void BDHC_KillLoad(SysTask *sysTask)
{
BDHCLoaderTaskContext *ctx = SysTask_GetParam(sysTask);
ctx->killLoadTask = TRUE;
}
void BDHC_MarkNotLoaded(BDHC *bdhc)
{
bdhc->loaded = FALSE;
}

View File

@ -1,269 +0,0 @@
#include "overlay005/bdhc_loader.h"
#include <nitro.h>
#include <string.h>
#include "constants/bdhc.h"
#include "constants/heap.h"
#include "overlay005/bdhc.h"
#include "heap.h"
#include "narc.h"
#include "sys_task.h"
#include "sys_task_manager.h"
enum BDHCSubTask {
BDHC_LOADER_SUBTASK_PREPARE_FILE_LOAD = 0,
BDHC_LOADER_SUBTASK_LOAD_FILE,
BDHC_LOADER_SUBTASK_END_TASK,
};
typedef struct {
int pointsSize;
int slopesSize;
int heightsSize;
int platesSize;
int stripsSize;
int accessListSize;
} BDHCHeader;
typedef struct {
FSFile unk_00;
int unk_AC;
BDHCHeader bdhcHeader;
BOOL unk_C8;
u8 currentSubTask;
u8 *buffer;
BDHC *bdhc;
BOOL forceExit;
int *unk_DC;
NARC *landDataNARC;
int unk_E4;
int *unk_E8;
} BDHCLoaderTaskContext;
static void BDHCLoader_PrepareBuffers(const BDHCHeader *bdhcHeader, BDHC *bdhc, void **buffer);
static void BDHCLoader_LoadPoints(NARC *narc, BDHC *bdhc, const BDHCHeader *bdhcHeader);
static void BDHCLoader_LoadSlopes(NARC *narc, BDHC *bdhc, const BDHCHeader *bdhcHeader);
static void BDHCLoader_LoadHeights(NARC *narc, BDHC *bdhc, const BDHCHeader *bdhcHeader);
static void BDHCLoader_LoadPlates(NARC *narc, BDHC *bdhc, const BDHCHeader *bdhcHeader);
static void BDHCLoader_LoadStrips(NARC *narc, BDHC *bdhc, const BDHCHeader *bdhcHeader);
static void BDHCLoader_LoadAccessList(NARC *narc, BDHC *bdhc, const BDHCHeader *bdhcHeader);
static void BDHCLoader_LoadHeader(NARC *narc, BDHCHeader *bdhcHeader)
{
u16 magic[BDHC_MAGIC_LENGTH];
MI_CpuClear32(bdhcHeader, sizeof(BDHCHeader));
NARC_ReadFile(narc, BDHC_MAGIC_LENGTH, magic);
NARC_ReadFile(narc, 2, &bdhcHeader->pointsSize);
NARC_ReadFile(narc, 2, &bdhcHeader->slopesSize);
NARC_ReadFile(narc, 2, &bdhcHeader->heightsSize);
NARC_ReadFile(narc, 2, &bdhcHeader->platesSize);
NARC_ReadFile(narc, 2, &bdhcHeader->stripsSize);
NARC_ReadFile(narc, 2, &bdhcHeader->accessListSize);
}
static void BDHCLoader_PrepareBuffers(const BDHCHeader *bdhcHeader, BDHC *bdhc, void **buffer)
{
void *ptr;
int offset = 0;
ptr = (u8 *)*buffer;
bdhc->points = ptr;
offset += (sizeof(BDHCPoint) * bdhcHeader->pointsSize);
ptr = (u8 *)*buffer + offset;
bdhc->slopes = ptr;
offset += (sizeof(VecFx32) * bdhcHeader->slopesSize);
ptr = (u8 *)*buffer + offset;
bdhc->heights = ptr;
offset += (sizeof(fx32) * bdhcHeader->heightsSize);
ptr = (u8 *)*buffer + offset;
bdhc->plates = ptr;
offset += (sizeof(BDHCPlate) * bdhcHeader->platesSize);
ptr = (u8 *)*buffer + offset;
bdhc->strips = ptr;
offset += sizeof(BDHCStrip) * bdhcHeader->stripsSize;
ptr = (u8 *)*buffer + offset;
bdhc->accessList = ptr;
offset += sizeof(u16) * bdhcHeader->accessListSize;
GF_ASSERT(offset <= BDHC_BUFFER_SIZE);
}
static void BDHCLoader_LoadPoints(NARC *narc, BDHC *bdhc, const BDHCHeader *bdhcHeader)
{
NARC_ReadFile(narc, sizeof(BDHCPoint) * bdhcHeader->pointsSize, bdhc->points);
}
static void BDHCLoader_LoadSlopes(NARC *narc, BDHC *bdhc, const BDHCHeader *bdhcHeader)
{
NARC_ReadFile(narc, sizeof(VecFx32) * bdhcHeader->slopesSize, bdhc->slopes);
}
static void BDHCLoader_LoadHeights(NARC *narc, BDHC *bdhc, const BDHCHeader *bdhcHeader)
{
NARC_ReadFile(narc, sizeof(fx32) * bdhcHeader->heightsSize, bdhc->heights);
}
static void BDHCLoader_LoadPlates(NARC *narc, BDHC *bdhc, const BDHCHeader *bdhcHeader)
{
NARC_ReadFile(narc, sizeof(BDHCPlate) * bdhcHeader->platesSize, bdhc->plates);
}
static void BDHCLoader_LoadStrips(NARC *narc, BDHC *bdhc, const BDHCHeader *bdhcHeader)
{
NARC_ReadFile(narc, sizeof(BDHCStrip) * bdhcHeader->stripsSize, bdhc->strips);
}
static void BDHCLoader_LoadAccessList(NARC *narc, BDHC *bdhc, const BDHCHeader *bdhcHeader)
{
NARC_ReadFile(narc, sizeof(u16) * bdhcHeader->accessListSize, bdhc->accessList);
}
static void BDHCLoader_RunTask(SysTask *sysTask, void *sysTaskParam)
{
BOOL subTaskCompleted;
BDHCLoaderTaskContext *ctx = (BDHCLoaderTaskContext *)sysTaskParam;
if (ctx->forceExit == TRUE) {
ctx->currentSubTask = BDHC_LOADER_SUBTASK_END_TASK;
}
switch (ctx->currentSubTask) {
case BDHC_LOADER_SUBTASK_PREPARE_FILE_LOAD:
if (*ctx->unk_E8) {
subTaskCompleted = FALSE;
break;
}
BDHCLoader_LoadHeader(ctx->landDataNARC, &ctx->bdhcHeader);
ctx->bdhc->stripsSize = ctx->bdhcHeader.stripsSize;
BDHCLoader_PrepareBuffers(&ctx->bdhcHeader, ctx->bdhc, (void **)&ctx->buffer);
subTaskCompleted = TRUE;
break;
case BDHC_LOADER_SUBTASK_LOAD_FILE:
BDHCLoader_LoadPoints(ctx->landDataNARC, ctx->bdhc, &ctx->bdhcHeader);
BDHCLoader_LoadSlopes(ctx->landDataNARC, ctx->bdhc, &ctx->bdhcHeader);
BDHCLoader_LoadHeights(ctx->landDataNARC, ctx->bdhc, &ctx->bdhcHeader);
BDHCLoader_LoadPlates(ctx->landDataNARC, ctx->bdhc, &ctx->bdhcHeader);
BDHCLoader_LoadStrips(ctx->landDataNARC, ctx->bdhc, &ctx->bdhcHeader);
BDHCLoader_LoadAccessList(ctx->landDataNARC, ctx->bdhc, &ctx->bdhcHeader);
subTaskCompleted = TRUE;
break;
case BDHC_LOADER_SUBTASK_END_TASK:
*ctx->unk_DC = 0;
Heap_FreeToHeap((void *)sysTaskParam);
SysTask_Done(sysTask);
return;
}
if (subTaskCompleted == TRUE) {
ctx->currentSubTask++;
if (ctx->currentSubTask == BDHC_LOADER_SUBTASK_END_TASK) {
ctx->bdhc->loaded = TRUE;
}
}
}
BDHC *BDHC_New(void)
{
BDHC *bdhc = Heap_AllocFromHeap(HEAP_ID_FIELD, sizeof(BDHC));
bdhc->points = NULL;
bdhc->slopes = NULL;
bdhc->plates = NULL;
bdhc->strips = NULL;
bdhc->accessList = NULL;
bdhc->accessList = NULL;
bdhc->loaded = FALSE;
bdhc->stripsSize = 0;
return bdhc;
}
void BDHCLoader_Load(NARC *narc, const int bdhcSize, BDHC *bdhc, u8 *buffer)
{
BDHCHeader *bdhcHeader = Heap_AllocFromHeapAtEnd(HEAP_ID_FIELD, sizeof(BDHCHeader));
BDHCLoader_LoadHeader(narc, bdhcHeader);
bdhc->stripsSize = bdhcHeader->stripsSize;
BDHCLoader_PrepareBuffers(bdhcHeader, bdhc, (void **)&buffer);
BDHCLoader_LoadPoints(narc, bdhc, bdhcHeader);
BDHCLoader_LoadSlopes(narc, bdhc, bdhcHeader);
BDHCLoader_LoadHeights(narc, bdhc, bdhcHeader);
BDHCLoader_LoadPlates(narc, bdhc, bdhcHeader);
BDHCLoader_LoadStrips(narc, bdhc, bdhcHeader);
BDHCLoader_LoadAccessList(narc, bdhc, bdhcHeader);
Heap_FreeToHeap(bdhcHeader);
bdhc->loaded = TRUE;
}
void BDHC_Free(BDHC *bdhc)
{
if (bdhc == NULL) {
return;
}
Heap_FreeToHeap(bdhc);
bdhc = NULL;
}
void BDHC_Reset(BDHC *bdhc)
{
if (bdhc == NULL) {
return;
}
bdhc->loaded = FALSE;
bdhc->points = NULL;
bdhc->slopes = NULL;
bdhc->plates = NULL;
bdhc->strips = NULL;
bdhc->accessList = NULL;
}
SysTask *BDHCLoader_StartTask(NARC *landDataNARC, const int param1, BDHC *bdhc, int *param3, u8 **buffer, int *param5)
{
BDHCLoaderTaskContext *ctx = Heap_AllocFromHeapAtEnd(HEAP_ID_FIELD, sizeof(BDHCLoaderTaskContext));
ctx->currentSubTask = BDHC_LOADER_SUBTASK_PREPARE_FILE_LOAD;
ctx->landDataNARC = landDataNARC;
ctx->unk_E4 = param1;
ctx->bdhc = bdhc;
ctx->unk_DC = param3;
ctx->forceExit = FALSE;
ctx->unk_C8 = FALSE;
ctx->unk_AC = 0;
ctx->buffer = *buffer;
ctx->unk_E8 = param5;
return SysTask_Start(BDHCLoader_RunTask, (void *)ctx, 1);
}
void BDHCLoader_ForceExitTask(SysTask *sysTask)
{
BDHCLoaderTaskContext *ctx = SysTask_GetParam(sysTask);
ctx->forceExit = TRUE;
}
void BDHCLoader_MarkBDHCNotLoaded(BDHC *bdhc)
{
bdhc->loaded = FALSE;
}

View File

@ -5,7 +5,6 @@
#include "field/field_system.h"
#include "overlay005/bdhc.h"
#include "overlay005/bdhc_loader.h"
#include "overlay005/funcptr_ov5_021E9630.h"
#include "overlay005/ov5_021D521C.h"
#include "overlay005/ov5_021E15F4.h"
@ -215,7 +214,7 @@ static void ov5_021E77E4(UnkStruct_ov5_021E8F60 *param0, const u8 param1)
}
if (param0->unk_04[param1].unk_00.unk_10.unk_04 != 0) {
BDHCLoader_ForceExitTask(param0->unk_04[param1].unk_00.unk_0C);
BDHC_KillLoad(param0->unk_04[param1].unk_00.unk_0C);
}
param0->unk_04[param1].unk_00.unk_24 = 1;
@ -228,7 +227,7 @@ static void ov5_021E7814(UnkStruct_ov5_021E7814 *param0)
}
if (param0->unk_10.unk_04 != 0) {
BDHCLoader_ForceExitTask(param0->unk_0C);
BDHC_KillLoad(param0->unk_0C);
}
param0->unk_10.unk_00 = 0;
@ -500,7 +499,7 @@ static void ov5_021E7C00(const u8 param0, UnkStruct_ov5_021EF76C *const param1,
{
param6->unk_10.unk_04++;
param6->unk_0C = BDHCLoader_StartTask(param5->unk_EC, v3.unk_08, param6->unk_00[param0]->bdhc, &param6->unk_10.unk_04, &param6->unk_00[param0]->bdhcBuffer, &param6->unk_10.unk_00);
param6->unk_0C = BDHC_LazyLoad(param5->unk_EC, v3.unk_08, param6->unk_00[param0]->bdhc, &param6->unk_10.unk_04, &param6->unk_00[param0]->bdhcBuffer, &param6->unk_10.unk_00);
}
}
@ -610,7 +609,7 @@ static void ov5_021E7E28(const int param0, const u8 param1, UnkStruct_ov5_021EF7
}
{
BDHCLoader_Load(param7->unk_EC, v2.unk_08, param7->unk_84[param1]->bdhc, param7->unk_84[param1]->bdhcBuffer);
BDHC_Load(param7->unk_EC, v2.unk_08, param7->unk_84[param1]->bdhc, param7->unk_84[param1]->bdhcBuffer);
}
param7->unk_84[param1]->unk_860 = param0;
@ -691,7 +690,7 @@ static void ov5_021E7FF0(const int param0, const u8 param1, UnkStruct_ov5_021EF7
NARC_Seek(param7->unk_EC, v1.unk_04);
{
BDHCLoader_Load(param7->unk_EC, v1.unk_08, param7->unk_84[param1]->bdhc, param7->unk_84[param1]->bdhcBuffer);
BDHC_Load(param7->unk_EC, v1.unk_08, param7->unk_84[param1]->bdhc, param7->unk_84[param1]->bdhcBuffer);
}
param7->unk_84[param1]->unk_860 = param0;
@ -1443,7 +1442,7 @@ static void ov5_021E8E28(UnkStruct_ov5_021E8F60 *param0, const int param1, const
for (v0 = 0; v0 < 4; v0++) {
param0->unk_84[v0]->bdhc = BDHC_New();
BDHCLoader_MarkBDHCNotLoaded(param0->unk_84[v0]->bdhc);
BDHC_MarkNotLoaded(param0->unk_84[v0]->bdhc);
ov5_021E7E28(v1[v0], v0, param0->unk_AC, param0->unk_B0, param0->unk_B4, param0->unk_B8, ov5_021EFAC0(param0->unk_AC), param0);
}
}
@ -2234,7 +2233,7 @@ void ov5_021E9D3C(MapMatrix *param0, UnkStruct_ov5_021EF76C *param1, UnkStruct_o
for (v0 = 0; v0 < 4; v0++) {
v1[v0] = param3->unk_84[v0]->unk_860;
BDHCLoader_MarkBDHCNotLoaded(param3->unk_84[v0]->bdhc);
BDHC_MarkNotLoaded(param3->unk_84[v0]->bdhc);
}
for (v0 = 0; v0 < 4; v0++) {
@ -2486,7 +2485,7 @@ void ov5_021EA5E0(UnkStruct_ov5_021E8F60 *param0, int param1, int param2)
MI_CpuFillFast(param0->unk_84[param1]->unk_00, 0xffffffff, 2 * 32 * 32);
BDHCLoader_MarkBDHCNotLoaded(param0->unk_84[param1]->bdhc);
BDHC_MarkNotLoaded(param0->unk_84[param1]->bdhc);
ov5_021E7E28(param2, param1, param0->unk_AC, param0->unk_B0, param0->unk_B4, param0->unk_B8, ov5_021EFAC0(param0->unk_AC), param0);
}

View File

@ -1,195 +0,0 @@
#include "overlay005/ov5_021EEC68.h"
#include <nitro.h>
#include <string.h>
#include "overlay005/bdhc.h"
#include "overlay005/struct_ov5_021EED20.h"
#include "fx_util.h"
static BOOL ov5_021EED38(const BDHCStrip *param0, const u16 param1, const fx32 param2, u16 *param3);
static BOOL ov5_021EEC68(const BDHCPoint *param0, const BDHCPoint *param1, const BDHCPoint *param2)
{
const fx32 *v0, *v1, *v2, *v3;
if (param0->x <= param1->x) {
v0 = &param0->x;
v1 = &param1->x;
} else {
v0 = &param1->x;
v1 = &param0->x;
}
if (param0->y <= param1->y) {
v2 = &param0->y;
v3 = &param1->y;
} else {
v2 = &param1->y;
v3 = &param0->y;
}
if (((*v0 <= param2->x) && (param2->x <= *v1)) && ((*v2 <= param2->y) && (param2->y <= *v3))) {
return 1;
}
return 0;
}
static void ov5_021EECB8(const BDHC *param0, u16 param1, BDHCPoint *param2)
{
param2[0] = param0->points[param0->plates[param1].firstPointIndex];
param2[1] = param0->points[param0->plates[param1].secondPointIndex];
}
static void ov5_021EECE8(const BDHC *param0, u16 param1, VecFx32 *param2)
{
*param2 = param0->slopes[param0->plates[param1].normalIndex];
}
static void ov5_021EED08(const BDHC *param0, u16 param1, fx32 *param2)
{
*param2 = param0->heights[param0->plates[param1].heightIndex];
}
static void ov5_021EED20(UnkStruct_ov5_021EED20 *param0)
{
int v0;
for (v0 = 0; v0 < 10; v0++) {
param0[v0].unk_00 = 0;
param0[v0].unk_04 = -1;
param0[v0].unk_08 = -1;
}
}
static BOOL ov5_021EED38(const BDHCStrip *param0, const u16 param1, const fx32 param2, u16 *param3)
{
int v0, v1;
u32 v2;
fx32 v3;
if (param1 == 0) {
return 0;
} else if (param1 == 1) {
*param3 = 0;
return 1;
}
v0 = 0;
v1 = param1 - 1;
v2 = v1 / 2;
do {
v3 = param0[v2].lowerBound;
if (v3 > param2) {
if (v1 - 1 > v0) {
v1 = v2;
v2 = (v0 + v1) / 2;
} else {
*param3 = v2;
return 1;
}
} else {
if (v0 + 1 < v1) {
v0 = v2;
v2 = (v0 + v1) / 2;
} else {
*param3 = v2 + 1;
return 1;
}
}
} while (TRUE);
return 0;
}
BOOL ov5_021EED9C(const fx32 param0, const fx32 param1, const fx32 param2, const BDHC *param3, fx32 *param4)
{
BDHCPoint v0[2];
BDHCPoint v1;
VecFx32 v2;
fx32 v3, v4;
BOOL v5;
u16 v6, v7;
fx32 v8, v9;
int v10;
u32 v11, v12, v13, v14;
UnkStruct_ov5_021EED20 v15[10];
fx32 v16, v17;
u32 v18;
u16 v19;
u16 v20;
u16 v21;
const BDHCStrip *v22;
if (param3->loaded == 0) {
return 0;
}
v5 = 0;
v1.x = param1;
v1.y = param2;
v10 = 0;
ov5_021EED20(v15);
v11 = param3->stripsSize;
v22 = param3->strips;
if (ov5_021EED38(v22, v11, v1.y, &v20) == 0) {
return 0;
}
v21 = v22[v20].accessListElementCount;
v18 = v22[v20].accessListStartIndex;
for (v6 = 0; v6 < v21; v6++) {
v7 = param3->accessList[v18 + v6];
ov5_021EECB8(param3, v7, v0);
v5 = ov5_021EEC68(&v0[0], &v0[1], &v1);
if (v5 == 1) {
ov5_021EECE8(param3, v7, &v2);
ov5_021EED08(param3, v7, &v8);
v9 = -(FX_Mul(v2.x, v1.x) + FX_Mul(v2.z, v1.y) + v8);
v9 = FX_Div(v9, v2.y);
v15[v10].unk_00 = v9;
v10++;
if (v10 >= 10) {
break;
}
}
}
if (v10 > 1) {
v7 = 0;
v3 = FX_Max(param0, v15[0].unk_00) - FX_Min(param0, v15[0].unk_00);
for (v6 = 1; v6 < v10; v6++) {
v4 = FX_Max(param0, v15[v6].unk_00) - FX_Min(param0, v15[v6].unk_00);
if (v3 > v4) {
v3 = v4;
v7 = v6;
}
}
*param4 = v15[v7].unk_00;
return 1;
} else if (v10 == 1) {
*param4 = v15[0].unk_00;
return 1;
}
if (v10 != 0) {
*param4 = v15[0].unk_00;
return 1;
}
return 0;
}

View File

@ -9,7 +9,6 @@
#include "overlay005/bdhc.h"
#include "overlay005/ov5_021E15F4.h"
#include "overlay005/ov5_021E779C.h"
#include "overlay005/ov5_021EEC68.h"
#include "overlay005/ov5_021EF250.h"
#include "overlay005/struct_ov5_021E1608_decl.h"
#include "overlay005/struct_ov5_021E1890_decl.h"
@ -105,7 +104,7 @@ static const fx32 sub_02054D0C(const FieldSystem *fieldSystem, const fx32 param1
} else {
{
const BDHC *v21 = ov5_021E9610(v18, v8);
v1 = ov5_021EED9C(v16, v11.x, v11.z, v21, &v11.y);
v1 = CalculateObjectHeight(v16, v11.x, v11.z, v21, &v11.y);
}
}
}