Files
jak-project/game/kernel/common/Ptr.h
T
water111 4f537d4a71 [jak3] Set up ckernel (#3308)
This sets up the C Kernel for Jak 3, and makes it possible to build and
load code built with `goalc --jak3`.

There's not too much interesting here, other than they switched to a
system where symbol IDs (unique numbers less than 2^14) are generated at
compile time, and those get included in the object file itself.

This is kind of annoying, since it means all tools that produce a GOAL
object file need to work together to assign unique symbol IDs. And since
the symbol IDs can't conflict, and are only a number between 0 and 2^14,
you can't just hash and hope for no collisions.

We work around this by ignoring the IDs and re-assigning our own. I
think this is very similar to what the C Kernel did on early builds of
Jak 3 which supported loading old format level files, which didn't have
the IDs included.

As far as I can tell, this shouldn't cause any problems. It defeats all
of their fancy tricks to save memory by not storing the symbol string,
but we don't care.
2024-01-16 19:24:02 -05:00

90 lines
1.8 KiB
C++

#pragma once
/*!
* @file Ptr.h
* Representation of a GOAL pointer which can be converted to/from a C pointer.
*/
#include "common/common_types.h"
#include "common/util/Assert.h"
#include "game/runtime.h"
/*!
* GOAL pointer to a T. Represented as a 32-bit unsigned offset from g_ee_main_mem.
* A NULL pointer has an offset of 0.
*
* This doesn't have to be very efficient, as this implementation is only used in the C Kernel.
* The GOAL implementation is much more efficient.
*
* Consider putting size checks on these?
*/
template <typename T>
struct Ptr {
u32 offset;
/*!
* Default pointer is NULL.
*/
Ptr() { offset = 0; }
/*!
* Pointer from manual offset.
*/
explicit Ptr(u32 v) { offset = v; }
/*!
* Dereference a pointer. Will error if you do this on a null pointer.
*/
T* operator->() {
ASSERT(offset);
return (T*)(g_ee_main_mem + offset);
}
/*!
* Dereference a pointer. Will error if you do this on a null pointer.
*/
T& operator*() {
ASSERT(offset);
return *(T*)(g_ee_main_mem + offset);
}
// pointer math
Ptr operator+(s32 diff) { return Ptr(offset + diff); }
s32 operator-(Ptr<T> x) { return offset - x.offset; }
Ptr operator-(s32 diff) { return Ptr(offset - diff); }
bool operator==(const Ptr<T>& x) { return offset == x.offset; }
bool operator!=(const Ptr<T>& x) { return offset != x.offset; }
/*!
* Convert to a C pointer.
*/
T* c() {
if (!offset) {
return nullptr;
}
return (T*)(g_ee_main_mem + offset);
}
template <typename T2>
Ptr<T2> cast() {
return Ptr<T2>(offset);
}
};
template <typename T>
Ptr<T> make_ptr(T* x) {
if (!x) {
return Ptr<T>(0);
}
return Ptr<T>((u8*)x - g_ee_main_mem);
}
template <typename T>
Ptr<u8> make_u8_ptr(T* x) {
if (!x) {
return Ptr<u8>(0);
}
return Ptr<u8>((u8*)x - g_ee_main_mem);
}