Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 1 addition & 15 deletions include/Common.hh
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,13 @@

#pragma once

#include <Logger.hh>
#include <Types.hh>

#include <egg/core/Heap.hh>

#include <array>
#include <cassert>
#include <limits>

typedef int8_t s8;
typedef int16_t s16;
typedef int32_t s32;
typedef int64_t s64;

typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;

typedef float f32;
typedef double f64;

enum class Course {
Mario_Circuit = 0,
Moo_Moo_Meadows = 1,
Expand Down
187 changes: 187 additions & 0 deletions include/Types.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
#pragma once

#include <Logger.hh>

#include <cstdint>
#include <utility>

typedef int8_t s8;
typedef int16_t s16;
typedef int32_t s32;
typedef int64_t s64;

typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;

typedef float f32;
typedef double f64;

/// @brief Dynamically sized array that only allocates once.
/// @details It's possible that only an upper bound is known for a given vector.
/// However, in the event that there are more objects than expected, we want to error.
/// @tparam T The type of objects in the array.
template <typename T>
class fixed_vector {
public:
/// @brief Non-initializing constructor.
fixed_vector() : m_data(nullptr), m_size(0), m_capacity(0) {}

/// @brief Initializing constructor.
/// @param capacity The number of elements to initialize the vector with.
fixed_vector(size_t capacity) : fixed_vector() {
allocate(capacity);
}

/// @brief Destructor.
/// @details Destroys all existing elements in the array in-place from the end to the start.
~fixed_vector() {
while (m_size > 0) {
pop_back();
}

operator delete(m_data);
}

/// @brief Copies a new element into the array.
/// @param obj The object to copy.
/// @return A reference to the object.
T &push_back(const T &obj) {
ASSERT(initialized() && !full());
new (m_data + m_size++) T(obj);
return back();
}

/// @brief Moves a new element into the array.
/// @param obj The object to move.
/// @return A reference to the object.
T &push_back(T &&obj) {
ASSERT(initialized() && !full());
new (m_data + m_size++) T(std::move(obj));
return back();
}

/// @brief Creates a new element in-place in the array.
/// @tparam ...Args Variadic template for packing.
/// @param ...args Arguments to the constructor.
/// @return A reference to the object.
template <typename... Args>
T &emplace_back(Args &&...args) {
ASSERT(initialized() && !full());
new (m_data + m_size++) T(std::forward<Args>(args)...);
return back();
}

/// @brief Deletes the last existing element from the array.
void pop_back() {
ASSERT(initialized() && !empty());
m_data[--m_size].~T();
}

/// @brief Initializes the vector with the provided capacity.
/// @param capacity The number of elements to initialize the vector with.
void reserve(size_t capacity) {
ASSERT(!initialized());
allocate(capacity);
}

/// @brief Checks if there are no existing elements in the array.
/// @return True if the array is empty, otherwise false.
bool empty() const {
return m_size == 0;
}

/// @brief Checks if all elements exist in the array.
/// @return True if the array is full, otherwise false.
bool full() const {
return m_size == m_capacity;
}

/// @brief Checks if the array exists and if the capacity is non-zero.
/// @return True if the array is initialized, otherwise false.
bool initialized() const {
return m_data && m_capacity != 0;
}

/// @brief Gets the first element in the array, whether it exists or not.
/// @return The first element in the array.
T &front() {
return *m_data;
}

/// @brief Gets the first element in the array, whether it exists or not.
/// @return The first element in the array.
const T &front() const {
return *m_data;
}

/// @brief Gets the last existing element in the array, or the first element if none exist.
/// @return The last existing element in the array.
T &back() {
return *(m_data + m_size);
}

/// @brief Gets the last existing element in the array, or the first element if none exist.
/// @return The last existing element in the array.
const T &back() const {
return *(m_data + m_size);
}
Comment on lines +121 to +129
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you have an off-by-one error. back() should not return the same as end()

Suggested change
T &back() {
return *(m_data + m_size);
}
/// @brief Gets the last existing element in the array, or the first element if none exist.
/// @return The last existing element in the array.
const T &back() const {
return *(m_data + m_size);
}
T &back() {
return m_size > 0 ? *(m_data + m_size - 1) : *m_data;
}
/// @brief Gets the last existing element in the array, or the first element if none exist.
/// @return The last existing element in the array.
const T &back() const {
return m_size > 0 ? *(m_data + m_size - 1) : *m_data;
}


/// @brief Indexes the array. Validates that the object exists.
/// @param idx The index to the array.
/// @return A reference to the object at the corresponding index.
T &operator[](size_t idx) {
ASSERT(idx < m_size);
return m_data[idx];
}

/// @brief Indexes the array. Validates that the object exists.
/// @param idx The index to the array.
/// @return A reference to the object at the corresponding index.
const T &operator[](size_t idx) const {
ASSERT(idx < m_size);
return m_data[idx];
}

/// @brief Iterator for the beginning of the existing array.
/// @return Iterator.
T *begin() noexcept {
ASSERT(initialized());
return m_data;
}

/// @brief Iterator for the beginning of the existing array.
/// @return Const iterator.
const T *begin() const noexcept {
ASSERT(initialized());
return m_data;
}

/// @brief Iterator for the end of the existing array.
/// @return Iterator.
T *end() noexcept {
ASSERT(initialized());
return m_data + m_size;
}

/// @brief Iterator for the end of the existing array.
/// @return Const iterator.
const T *end() const noexcept {
ASSERT(initialized());
return m_data + m_size;
}

private:
/// @brief Allocates the array.
/// @param capacity The number of elements to initialize the vector with.
void allocate(size_t capacity) {
ASSERT(!initialized());
m_data = reinterpret_cast<T *>(operator new(sizeof(T) * capacity));
m_capacity = capacity;
}

T *m_data; // The underlying array pointer.
size_t m_size; // The number of existing elements in the array.
size_t m_capacity; // The maximum number of elements that can exist in the array.
};
10 changes: 2 additions & 8 deletions source/game/field/ObjectDirector.cc
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,8 @@ ObjectDirector *ObjectDirector::Instance() {
/// @addr{0x8082A38C}
ObjectDirector::ObjectDirector()
: m_flowTable("ObjFlow.bin"), m_hitTableKart("GeoHitTableKart.bin"),
m_hitTableKartObject("GeoHitTableKartObj.bin") {}
m_hitTableKartObject("GeoHitTableKartObj.bin"), m_objects(MAX_UNIT_COUNT),
m_calcObjects(MAX_UNIT_COUNT), m_collisionObjects(MAX_UNIT_COUNT) {}

/// @addr{0x8082A694}
ObjectDirector::~ObjectDirector() {
Expand All @@ -157,13 +158,6 @@ void ObjectDirector::createObjects() {
const auto *courseMap = System::CourseMap::Instance();
size_t objectCount = courseMap->getGeoObjCount();

// It's possible for the KMP to specify settings for objects that aren't tracked here
// MAX_UNIT_COUNT is the upper bound for tracked object count, so we reserve the minimum
size_t maxCount = std::min(objectCount, MAX_UNIT_COUNT);
m_objects.reserve(maxCount);
m_calcObjects.reserve(maxCount);
m_collisionObjects.reserve(maxCount);

for (size_t i = 0; i < objectCount; ++i) {
const auto *pObj = courseMap->getGeoObj(i);
ASSERT(pObj);
Expand Down
8 changes: 3 additions & 5 deletions source/game/field/ObjectDirector.hh
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
#include "game/field/ObjectHitTable.hh"
#include "game/field/obj/ObjectCollidable.hh"

#include <vector>

namespace Field {

class ObjectDirector : EGG::Disposer {
Expand Down Expand Up @@ -38,9 +36,9 @@ private:
ObjectHitTable m_hitTableKart;
ObjectHitTable m_hitTableKartObject;

std::vector<ObjectBase *> m_objects; ///< All objects live here
std::vector<ObjectBase *> m_calcObjects; ///< Objects needing calc() live here too.
std::vector<ObjectBase *> m_collisionObjects; ///< Objects having collision live here too
fixed_vector<ObjectBase *> m_objects; ///< All objects live here
fixed_vector<ObjectBase *> m_calcObjects; ///< Objects needing calc() live here too.
fixed_vector<ObjectBase *> m_collisionObjects; ///< Objects having collision live here too

static constexpr size_t MAX_UNIT_COUNT = 0x100;

Expand Down
16 changes: 6 additions & 10 deletions source/game/kart/KartMove.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1253,18 +1253,14 @@ f32 KartMove::calcVehicleAcceleration() const {
return 1.0f;
}

std::vector<f32> as;
std::vector<f32> ts;
std::span<const f32> as;
std::span<const f32> ts;
if (state()->isDrifting()) {
const auto &as_arr = param()->stats().accelerationDriftA;
const auto &ts_arr = param()->stats().accelerationDriftT;
as = {as_arr.begin(), as_arr.end()};
ts = {ts_arr.begin(), ts_arr.end()};
as = param()->stats().accelerationDriftA;
ts = param()->stats().accelerationDriftT;
} else {
const auto &as_arr = param()->stats().accelerationStandardA;
const auto &ts_arr = param()->stats().accelerationStandardT;
as = {as_arr.begin(), as_arr.end()};
ts = {ts_arr.begin(), ts_arr.end()};
as = param()->stats().accelerationStandardA;
ts = param()->stats().accelerationStandardT;
}

size_t i = 0;
Expand Down
3 changes: 3 additions & 0 deletions source/game/kart/KartObject.cc
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ void KartObject::prepareTiresAndSuspensions() {

m_pointers.param->setTireCount(wheelCount);
m_pointers.param->setSuspCount(wheelCount);

m_pointers.tires.reserve(wheelCount);
m_pointers.suspensions.reserve(wheelCount);
}

/// @addr{0x8058E724}
Expand Down
5 changes: 2 additions & 3 deletions source/game/kart/KartObjectProxy.hh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#include <egg/math/Matrix.hh>

#include <list>
#include <vector>

namespace Field {

Expand Down Expand Up @@ -51,8 +50,8 @@ struct KartAccessor {
Field::ObjectCollisionKart *objectCollisionKart;
KartState *state;

std::vector<KartSuspension *> suspensions;
std::vector<KartTire *> tires;
fixed_vector<KartSuspension *> suspensions;
fixed_vector<KartTire *> tires;

Field::BoxColUnit *boxColUnit;
};
Expand Down