Cleanup stream.cpp and sysMath.cpp

This commit is contained in:
intns 2024-06-09 23:00:07 +01:00
parent 60ec0577a1
commit 534586d595
10 changed files with 319 additions and 503 deletions

View File

@ -285,7 +285,7 @@ struct ShadowMgr : public CNode {
u8 mEnabled; // _3C
u8 mDoCheckCylinderType; // _3D
int mCylinderID; // _40
int _44; // _44, seems to be entirely unused
int mUnused0; // _44, seems to be entirely unused
Color4 mColor; // _48
ShadowParms* mParms; // _4C
};

View File

@ -21,27 +21,27 @@ struct Stream {
mPosition = 0;
setMode(STREAM_MODE_BINARY, 1);
}
Stream(int);
virtual void read(void*, int) = 0;
virtual void write(void*, int) = 0;
virtual bool eof();
virtual u32 getPending();
virtual void read(void*, int) = 0; // _04
virtual void write(void*, int) = 0; // _08
virtual bool eof(); // _0C
virtual u32 getPending(); // _10
void differentEndian(); // unused
bool isSpace(char); // inline
char skipSpace(); // inline
void copyToTextBuffer(); // inline
bool differentEndian() { return mEndian != STREAM_BIG_ENDIAN; }
bool isSpace(char);
char skipSpace();
void copyToTextBuffer();
char* getNextToken();
void textBeginGroup(char*);
void textEndGroup();
void printf(char*, ...);
void textWriteText(char*, ...);
void skipPadding(u32); // inline
void skipReading(u32);
void skipReadingText();
void _read(void*, int); // unused
void _write(void*, int); // unused
void _read(void* buffer, int length);
void _write(void*, int);
void textWriteTab(int);
u8 readByte();
@ -50,10 +50,8 @@ struct Stream {
int readInt();
f32 readFloat();
char* readString(char*, int);
void readFixedString(); // unused
void writeString(char*);
void writeFixedString(char*); // unused
void writeByte(u8);
void _writeByte(u8);
void writeShort(s16);
@ -99,12 +97,9 @@ struct Stream {
struct RamStream : Stream {
RamStream(void* bufferPointer, int bounds);
virtual void read(void*, int);
virtual void write(void*, int);
virtual bool eof();
// virtual void getPending(); // from Stream
void set(u8*, int);
virtual void read(void*, int); // _04
virtual void write(void*, int); // _08
virtual bool eof(); // _0C
void* mRamBufferStart; // _418
int mBounds; // _41C
@ -121,7 +116,7 @@ struct RamStream : Stream {
* @param nullCheck Should we check if the file was successfully mounted to RAM or not?
*/
template <typename T>
inline void loadAndRead(T* thisPtr, char* fname, JKRHeap* heap = nullptr, bool nullCheck = true)
inline void loadFromFile(T* thisPtr, char* fname, JKRHeap* heap = nullptr, bool nullCheck = true)
{
void* handle = JKRDvdRipper::loadToMainRAM(fname, 0, Switch_0, 0, heap, JKRDvdRipper::ALLOC_DIR_BOTTOM, 0, 0, 0);
if (nullCheck && !handle) {

View File

@ -23,15 +23,7 @@ AIConstants::AIConstants()
mCameraAngle.mData = 180.0f;
char* fileName = "/user/Kando/aiConstants.txt";
void* handle = JKRDvdToMainRam(fileName, nullptr, Switch_0, 0, 0, JKRDvdRipper::ALLOC_DIR_BOTTOM, 0, nullptr, nullptr);
if (handle) {
RamStream stream(handle, -1);
stream.setMode(STREAM_MODE_TEXT, 1);
read(stream);
delete[] handle;
}
loadFromFile(this, fileName);
}
/**

View File

@ -338,7 +338,7 @@ Stages::Stages()
_104 = 0;
_10A = 0;
loadAndRead(this, "user/Abe/stages.txt", nullptr, false);
loadFromFile(this, "user/Abe/stages.txt", nullptr, false);
}
/**

View File

@ -358,8 +358,9 @@ Mgr::Mgr()
setModelSize(1);
mObjectPathComponent = "user/Kando/objects/barrel";
mParms = new BarrelParms();
void* resource = JKRDvdRipper::loadToMainRAM("user/Abe/item/barrelParms.txt", nullptr, Switch_0, 0, nullptr,
JKRDvdRipper::ALLOC_DIR_BOTTOM, 0, nullptr, nullptr);
void* resource = JKRDvdRipper::loadToMainRAM("user/Abe/item/barrelParms.txt", nullptr, Switch_0, 0, nullptr,
JKRDvdRipper::ALLOC_DIR_BOTTOM, 0, nullptr, nullptr);
if (resource) {
RamStream stream(resource, -1);
stream.setMode(STREAM_MODE_TEXT, true);

View File

@ -499,8 +499,9 @@ Mgr::Mgr()
mObjectPathComponent = "user/Kando/objects/kanketusen";
mItemName = "AŠÒŠÔŒ‡<EFBFBD>ò"; // 'return geyser'
mParms = new FountainParms();
void* data = JKRDvdRipper::loadToMainRAM("user/Abe/item/fountainParms.txt", nullptr, Switch_0, 0, nullptr,
JKRDvdRipper::ALLOC_DIR_BOTTOM, 0, nullptr, nullptr);
void* data = JKRDvdRipper::loadToMainRAM("user/Abe/item/fountainParms.txt", nullptr, Switch_0, 0, nullptr,
JKRDvdRipper::ALLOC_DIR_BOTTOM, 0, nullptr, nullptr);
if (data != nullptr) {
RamStream input(data, -1);
input.setMode(STREAM_MODE_TEXT, 1);

View File

@ -125,7 +125,7 @@ ShadowMgr::ShadowMgr(int count)
mEnabled = true;
mDoCheckCylinderType = 1;
mCylinderID = 0;
_44 = 0;
mUnused0 = 0;
mName = "ShadowMgr";
}
@ -690,17 +690,7 @@ bool ShadowMgr::isDrawJointShadow(JointShadowRootNode* node, int vpNum)
* @note Address: 0x80242454
* @note Size: 0xAC
*/
void ShadowMgr::readShadowParms(char* fileName)
{
void* data = JKRDvdRipper::loadToMainRAM(fileName, nullptr, Switch_0, 0, nullptr, JKRDvdRipper::ALLOC_DIR_BOTTOM, 0, nullptr, nullptr);
if (data) {
RamStream input(data, -1);
input.setMode(STREAM_MODE_TEXT, 1);
read(input);
delete[] data;
}
}
void ShadowMgr::readShadowParms(char* fileName) { loadFromFile(this, fileName); }
/**
* @note Address: 0x80242500
@ -711,7 +701,7 @@ void ShadowMgr::write(Stream& output)
output.writeShort((u16)mEnabled);
output.writeShort((u16)mDoCheckCylinderType);
output.writeInt(mCylinderID);
output.writeInt(_44);
output.writeInt(mUnused0);
mColor.write(output);
mParms->write(output);
}
@ -725,7 +715,7 @@ void ShadowMgr::read(Stream& input)
mEnabled = input.readShort();
mDoCheckCylinderType = input.readShort();
mCylinderID = input.readInt();
_44 = input.readInt();
mUnused0 = input.readInt();
mColor.read(input);
mParms->read(input);
}

View File

@ -207,7 +207,7 @@ f32 TimeMgr::getRealDayTime()
*/
void TimeMgr::loadSettingFile(char* filename)
{
loadAndRead(&mParms.mParms, filename, JKRHeap::sSystemHeap);
loadFromFile(&mParms.mParms, filename, JKRHeap::sSystemHeap);
init();
}

View File

@ -3,52 +3,61 @@
#include "string.h"
/**
* Checks if the given character is a whitespace character.
*
* @note Also checks if the character is a comment or scope character. (i.e. '#', '{', '}')
* @param currByte The character to check.
* @return True if the character is a whitespace character, false otherwise.
*
* @note Address: N/A
* @note Size: 0x48
*/
bool Stream::isSpace(char currByte)
{
// check if current byte is whitespace/newline/hash/brackets
return ((currByte == '\r') || (currByte == ' ') || (currByte == '\n') || (currByte == '\t') || (currByte == '#') || (currByte == '{')
|| (currByte == '}'));
}
/**
* Skips any leading whitespace characters in the stream and returns the first non-whitespace character encountered.
*
* @return The first non-whitespace character encountered, or 0 if not text mode / EOF.
*
* @note Address: N/A
* @note Size: 0xEC
*/
// INLINE
char Stream::skipSpace()
{
// return next byte that isn't a 'space' or a comment
// if in binary mode (or end of file), return 0
char byte;
bool isComment = false;
mBufferPos = 0;
mBufferPos = 0;
// Spaces only occur in text mode
if (mMode == STREAM_MODE_TEXT) {
// check we're not at the end of the file
while (!eof()) {
char byte = _readByte(); // at 0x8
// if we're in a comment line, skip until we hit a new line
char currentChar = _readByte();
// If inside a comment, skip until a new line is encountered
if (isComment) {
if (byte == '\r' || byte == '\n') {
isComment = 0;
if (currentChar == '\r' || currentChar == '\n') {
isComment = false;
}
continue;
}
// flag if we're starting a comment line
if (byte == '#') {
// The start of a comment is indicated by a '#'
if (currentChar == '#') {
isComment = true;
continue;
}
// so long as we don't hit newline/whitespace/hash/{ or }, we have a token!
if (!isSpace(byte)) {
return byte;
// If the byte is not a space, return it
if (!isSpace(currentChar)) {
return currentChar;
}
}
}
// if we reach eof or are in binary mode, return a 0
return 0;
}
@ -59,48 +68,51 @@ char Stream::skipSpace()
bool Stream::eof() { return false; }
/**
* Copies the contents of the stream to the text buffer.
*
* This function reads bytes from the stream and copies them to the text buffer until it encounters a space character.
* If the space character is a '#' character, it treats the remaining bytes as a comment and stops copying.
*
* @note This function assumes that the text buffer has enough space to hold the copied bytes.
*
* @note Address: N/A
* @note Size: 0x214
*/
// INLINE
inline void Stream::copyToTextBuffer()
{
// copy next token (not starting with a 'space', not in a comment) to buffer
// panic if we hit eof
char nextByte;
// Skip any leading whitespace
mBuffer[mBufferPos++] = skipSpace();
while (!eof()) {
nextByte = _readByte(); // at 0xA
// if we hit a newline, whitespace, hash, { or }, put 0s until we hit something else
nextByte = _readByte();
// If the next byte is a space, check if comment and null terminate the buffer
if (isSpace(nextByte)) {
mBuffer[mBufferPos++] = 0;
// check if comment line
if (nextByte == '#') {
while (!eof()) {
nextByte = _readByte(); // at 0x9
nextByte = _readByte();
if ((nextByte != '\r') && (nextByte != '\n')) {
// skip through comment line
continue;
} else {
// we hit a new line! we're free from the comment
return;
}
}
return;
}
return;
} else { // we hit something else!
} else {
// If the next byte is not a space, add it to the buffer
mBuffer[mBufferPos++] = nextByte;
// if we hit a 0, exit
if (!nextByte) {
return;
}
}
}
// if we reach eof, panic
JUT_PANICLINE(98, "Reached EOF\n");
}
@ -110,22 +122,13 @@ inline void Stream::copyToTextBuffer()
*/
char* Stream::getNextToken()
{
// if we're in text mode:
// - writes next (non-comment/whitespace/newline/bracket) token into buffer
// - returns a pointer to start of buffer
// if we're in binary mode:
// - returns null pointer
// if we're in binary mode, exit
if (mMode == STREAM_MODE_BINARY) {
return 0;
// No tokenizing in binary mode
return nullptr;
} else {
copyToTextBuffer();
return mBuffer;
}
// check next byte(s)
copyToTextBuffer();
// return a pointer to beginning of buffer
return mBuffer;
}
/**
@ -134,7 +137,6 @@ char* Stream::getNextToken()
*/
void Stream::textBeginGroup(char* groupName)
{
// if in text mode, write 'beginning' characters
if (mMode != STREAM_MODE_BINARY) {
textWriteTab(mTabCount);
textWriteText("# %s\r\n", groupName);
@ -150,7 +152,6 @@ void Stream::textBeginGroup(char* groupName)
*/
void Stream::textEndGroup()
{
// if in text mode, write 'ending' characters
if (mMode != STREAM_MODE_BINARY) {
mTabCount--;
textWriteTab(mTabCount);
@ -159,20 +160,26 @@ void Stream::textEndGroup()
}
/**
* Prints formatted text to the stream.
*
* This function takes a format string and a variable number of arguments, similar to the standard
* C library function `printf`. The formatted text is written to the stream.
*
* @param format The format string specifying the text to be printed.
* @param ... The variable arguments to be formatted and printed.
*
* @note Address: 0x804140F8
* @note Size: 0xE4
*/
void Stream::printf(char* format, ...)
{
// prints text with given format information
// doesn't check for text or binary, prints just the same
char tempText[0x400];
va_list args;
va_start(args, format);
vsprintf(tempText, format, args);
int len = strlen(tempText);
int len = strlen(tempText);
if (len > 0) {
char* textPtr = tempText;
@ -184,132 +191,124 @@ void Stream::printf(char* format, ...)
}
/**
* Writes formatted text to the stream.
*
* This function writes formatted text to the stream using the specified format string and variable arguments.
* The format string is similar to the one used in the standard C library's `printf` function.
*
* @param format The format string specifying the text to be written.
* @param ... The variable arguments to be formatted and written to the stream.
*
* @remarks This function only writes text to the stream if the stream mode is not set to `STREAM_MODE_BINARY`.
* If the stream mode is `STREAM_MODE_BINARY`, this function does nothing.
*
* @note Address: 0x804141DC
* @note Size: 0xEC
*/
void Stream::textWriteText(char* format, ...)
{
// prints text with given format information
// only prints text - won't print binary
char tempText[0x400];
va_list args;
if (mMode != STREAM_MODE_BINARY) {
va_start(args, format);
vsprintf(tempText, format, args);
if (mMode == STREAM_MODE_BINARY) {
return;
}
int len = strlen(tempText);
if (len > 0) {
char* textPtr = tempText;
va_start(args, format);
vsprintf(tempText, format, args);
for (int i = 0; i < len; i++) {
_writeByte(*textPtr);
textPtr++;
}
int len = strlen(tempText);
if (len > 0) {
char* textPtr = tempText;
for (int i = 0; i < len; i++) {
_writeByte(*textPtr);
textPtr++;
}
}
}
// /**
// * @note Address: N/A
// * @note Size: 0x70
// */
// void Stream::writePadding(u32)
// {
// // UNUSED FUNCTION - in stream.h header
// }
/**
* @note Address: N/A
* @note Size: 0x6C
*/
// void Stream::skipPadding(u32)
// {
// // UNUSED FUNCTION
// }
/**
* Skips reading a specified number of bytes from the stream.
*
* @param len The number of bytes to skip.
*
* @note Address: 0x804142C8
* @note Size: 0xC4
*/
void Stream::skipReading(u32 len)
{
// 'skips' whatever is being streamed byte by byte
// need to handle differently if in text or binary mode
// skips to next line in text mode
// this version comes with a length 'len' for binary mode
// check mode
if (mMode == STREAM_MODE_TEXT) { // we're in text mode
// 'skip' through, but need to look out for new lines
if (mMode == STREAM_MODE_TEXT) {
while (!eof()) {
s8 currByte = _readByte();
// If it isn't whitespace, continue
if (currByte != '\r' && currByte != '\n') {
continue;
} else {
return;
}
// If it is whitespace, return (skipped text)
return;
}
} else { // we're in binary mode
// loop through the stream up to 'len' and 'skip' it
} else {
for (int i = 0; i < len && !eof(); i++) {
readByte();
}
}
return;
}
/**
* @brief Skips reading text or bytes from the stream based on the stream mode.
*
* This function handles two different modes: STREAM_MODE_TEXT and other modes.
* In STREAM_MODE_TEXT, it reads bytes until it encounters a newline ('\n') or carriage return ('\r') character.
* In other modes, it reads bytes until it encounters a null byte (0).
*
* @note Address: 0x8041438C
* @note Size: 0xA8
*/
void Stream::skipReadingText()
{
// 'skips' whatever is being streamed byte by byte
// need to handle differently if in text or binary mode
// skips to next line in text mode
// this version doesn't come with a length for binary mode
// check mode
if (mMode == STREAM_MODE_TEXT) { // we're in text mode
// 'skip' through, but need to look out for 0xD and 0xA markers
if (mMode == STREAM_MODE_TEXT) {
while (!eof()) {
s8 currByte = _readByte();
// If it isn't whitespace, continue
if (currByte != '\r' && currByte != '\n') {
continue;
} else {
return;
}
// If it is whitespace, return (skipped text)
return;
}
} else { // we're in binary mode
// we can just loop through the whole stream and 'skip' it
// so long as readByte returns something
} else {
while (!eof()) {
if (!readByte()) {
if (readByte() == 0) {
break;
}
}
}
return;
}
/**
* @note Address: N/A
* @note Size: 0x50
*/
// void Stream::_read(void*, int)
// {
// // UNUSED FUNCTION
// }
void Stream::_read(void* buffer, int length)
{
read(buffer, length);
mPosition += length;
}
/**
* @note Address: N/A
* @note Size: 0x50
*/
// void Stream::_write(void*, int)
// {
// // UNUSED FUNCTION
// }
void Stream::_write(void* buffer, int length)
{
write(buffer, length);
mPosition += length;
}
/**
* @note Address: 0x80414434
@ -330,29 +329,19 @@ void Stream::textWriteTab(int tabCount)
*/
u8 Stream::readByte()
{
// if we're in text mode:
// - returns next byte (assuming it's not a comment or special character)
// if we're in binary mode:
// - returns next byte with no checks
int scanOut;
// check if we're in text mode or binary mode
if (mMode == STREAM_MODE_TEXT) { // we're in text mode, need to do more checks
if (mMode == STREAM_MODE_TEXT) {
char* nextToken = getNextToken();
// if we have a null pointer, panic
if (!nextToken) {
JUT_PANICLINE(260, "readByte:Token Error\n");
}
// take byte from nextToken and put it into scanOut
sscanf(nextToken, "%d", &scanOut);
// return byte
return (u8)scanOut;
}
// we're in binary mode, who needs checks
return _readByte();
}
@ -362,12 +351,8 @@ u8 Stream::readByte()
*/
u8 Stream::_readByte()
{
// reads in the next byte with no checks
// returns byte being read and increments stream position
u8 currByte;
read(&currByte, 1);
mPosition++;
_read(&currByte, 1);
return currByte;
}
@ -375,38 +360,27 @@ u8 Stream::_readByte()
* @note Address: 0x80414764
* @note Size: 0x32C
*/
s16 Stream::readShort()
short Stream::readShort()
{
// if we're in text mode:
// - returns next 2 bytes, treated as short (assuming it's not a comment or special character)
// if we're in binary mode:
// - returns next 2 bytes with no checks
u16 outVal;
if (mMode == STREAM_MODE_TEXT) { // we're in text mode, need to do more checks
if (mMode == STREAM_MODE_TEXT) {
char* nextToken = getNextToken();
// if we have a null pointer, panic
if (!nextToken) {
JUT_PANICLINE(284, "readShort:Token Error\n");
}
int scanOut;
// take bytes from nextToken and put it into scanOut
sscanf(nextToken, "%d", &scanOut);
// return result
outVal = scanOut;
return outVal;
}
// we're in binary mode, who needs checks
read(&outVal, 2);
mPosition += 2;
// swap endian if necessary
if (mEndian != STREAM_BIG_ENDIAN) {
u32 byte1 = (outVal >> 8) & 0x000000FF;
u32 byte2 = (outVal << 8) & 0x0000FF00;
outVal = (byte2 | byte1);
_read(&outVal, sizeof(short));
if (differentEndian()) {
outVal = ((outVal << 8) & 0xFF00 | (outVal >> 8) & 0xFF);
}
return outVal;
@ -418,38 +392,27 @@ s16 Stream::readShort()
*/
int Stream::readInt()
{
// if we're in text mode:
// - returns next 4 bytes, treated as int (assuming it's not a comment or special character)
// if we're in binary mode:
// - returns next 4 bytes with no checks
int outVal;
if (mMode == STREAM_MODE_TEXT) { // we're in text mode, need to do more checks
if (mMode == STREAM_MODE_TEXT) {
char* nextToken = getNextToken();
// if we have a null pointer, panic
if (!nextToken) {
JUT_PANICLINE(306, "readInt:Token Error\n");
}
// take bytes from nextToken and put it into outVal
sscanf(nextToken, "%d", &outVal);
// return result
return outVal;
}
// we're in binary mode, who needs checks
read(&outVal, 4);
mPosition += 4;
// swap endian if necessary
if (mEndian != STREAM_BIG_ENDIAN) {
_read(&outVal, sizeof(int));
if (differentEndian()) {
int byte1 = ((u32)outVal >> 24) & 0x000000FF;
int byte2 = ((u32)outVal >> 8) & 0x0000FF00;
int byte3 = ((u32)outVal << 8) & 0x00FF0000;
int byte4 = ((u32)outVal << 24) & 0xFF000000;
outVal = (byte4 | byte3 | byte2 | byte1);
outVal = (byte4 | byte3 | byte2 | byte1);
}
return outVal;
@ -461,39 +424,30 @@ int Stream::readInt()
*/
f32 Stream::readFloat()
{
// if we're in text mode:
// - returns next 4 bytes, treated as float (assuming it's not a comment or special character)
// if we're in binary mode:
// - returns next 4 bytes with no checks
f32 outFloat;
int outInt;
if (mMode == STREAM_MODE_TEXT) { // we're in text mode, need to do more checks
if (mMode == STREAM_MODE_TEXT) {
char* nextToken = getNextToken();
// if we have a null pointer, panic
if (!nextToken) {
JUT_PANICLINE(324, "readFloat:Token Error\n");
}
// take bytes from bufferPtr and put it into outFloat
sscanf(nextToken, "%f", &outFloat);
// return result
return outFloat;
}
// we're in binary mode, who needs checks
read(&outFloat, 4);
mPosition += 4;
// swap endian if necessary
if (mEndian != STREAM_BIG_ENDIAN) {
_read(&outFloat, sizeof(float));
if (differentEndian()) {
int outInt = *(u32*)&outFloat;
int byte1 = ((u32)outInt >> 24) & 0x000000FF;
int byte2 = ((u32)outInt >> 8) & 0x0000FF00;
int byte3 = ((u32)outInt << 8) & 0x00FF0000;
int byte4 = ((u32)outInt << 24) & 0xFF000000;
outInt = (byte4 | byte3 | byte2 | byte1);
outFloat = *(f32*)&outInt;
outInt = (byte4 | byte3 | byte2 | byte1);
outFloat = *(f32*)&outInt;
}
return outFloat;
@ -503,62 +457,52 @@ f32 Stream::readFloat()
* @note Address: 0x804150D4
* @note Size: 0x4F8
*/
// only final for loop not matching
char* Stream::readString(char* str, int strLength)
{
// reads string from stream
// if str provided, stores in str text of length strLength
// if str 0, returns string to next token
char* outStr;
if (mMode == STREAM_MODE_TEXT) { // we're in text mode, need to do more checks
// get text
if (mMode == STREAM_MODE_TEXT) {
char* nextToken = getNextToken();
int strSize = strlen(nextToken);
int strSize = strlen(nextToken);
if (str) { // str provided, check size compared to text
if (str) {
P2ASSERTLINE(352, strLength >= strSize);
outStr = str;
} else { // no str provided, read in whole nextToken
} else {
outStr = new char[strSize + 1];
}
// put text byte by byte into outStr
for (int readLen = 0; readLen < strSize + 1; readLen++) {
outStr[readLen] = nextToken[readLen];
}
} else { // we're in binary mode, free-for-all
// read max of 0x400 bytes
return outStr;
} else /* Binary mode */ {
char tokenStore[0x400];
// read up to 0x400 bytes into tokenStore
int readLen = 0;
for (int i = 0; i < 0x400 || !eof(); i++) {
u8 byte = _readByte();
tokenStore[i] = byte;
if (!(tokenStore[i]))
tokenStore[i] = _readByte();
if (tokenStore[i] == '\0') {
break;
}
readLen++;
}
if (str) { // str provided, check size compared to text
if (str) {
P2ASSERTLINE(372, strLength >= readLen);
outStr = str;
} else { // no str provided, read in whole tokenStore
} else {
outStr = new char[readLen + 1];
}
// put text byte by byte into outStr
int i = 0;
char* outStrPtr = outStr;
for (i; i < readLen; i++) {
*outStrPtr = tokenStore[i];
outStrPtr++;
}
*outStrPtr = 0;
outStrPtr[0] = '\0';
}
return outStr;
@ -568,63 +512,50 @@ char* Stream::readString(char* str, int strLength)
* @note Address: N/A
* @note Size: 0x64C
*/
const char UNUSED_readFixedString[] = "can not use readFixedString in text mode\n";
// void Stream::readFixedString()
// {
//
// }
const char UNUSED_readFixedString[] = "can not use readFixedString in text mode\n";
/**
* @note Address: 0x804155CC
* @note Size: 0xA4
*/
void Stream::writeString(char* inputStr)
{
// write input string byte by byte
// binary output ends with 0, text with " "
// check length of string then loop over length
int len = strlen(inputStr);
for (int i = 0; i < len; i++) {
// write byte with no checks
_writeByte(inputStr[i]);
}
if (mMode == STREAM_MODE_TEXT) {
// end text mode output with space
printf(" ");
return;
} else {
_writeByte('\0');
}
// end binary mode output with 0
_writeByte(0);
}
/**
* @note Address: N/A
* @note Size: 0xBC
*/
const char UNUSED_writeFixedString[] = "can not use writeFixedString in text mode\n";
// void Stream::writeFixedString(char*)
// {
// // UNUSED FUNCTION
// }
const char UNUSED_writeFixedString[] = "can not use writeFixedString in text mode\n";
/**
* @note Address: 0x80415670
* @note Size: 0x70
*/
void Stream::writeByte(u8 c)
{
// write next byte + increment position
// check if we're in text or binary and write "%d " if in text
u8 buffer = c;
if (mMode == 1) {
if (mMode == STREAM_MODE_TEXT) {
printf("%d ", c);
} else {
write(&buffer, 1);
mPosition++;
_write(&c, sizeof(u8));
}
}
@ -634,11 +565,8 @@ void Stream::writeByte(u8 c)
*/
void Stream::_writeByte(u8 c)
{
// write next byte + increment position
// no checks for mode type
u8 buffer = c;
write(&buffer, 1);
mPosition++;
_write(&buffer, sizeof(u8));
}
/**
@ -647,25 +575,17 @@ void Stream::_writeByte(u8 c)
*/
void Stream::writeShort(s16 inputShort)
{
// write s16 (s16)
// need to handle text and binary mode differently
// by default, value to write should be inputShort
s16 outVal = inputShort;
if (mMode == STREAM_MODE_TEXT) {
// in text mode, write with "%d "
printf("%d ", inputShort);
return;
}
// make sure stream value is big endian
if (mEndian != STREAM_BIG_ENDIAN) {
// if it's not big endian, swap bytes to make it big endian
outVal = bswap16((s16)inputShort);
}
// write s16 (2 bytes) and increment stream position
write(&outVal, 2);
mPosition += 2;
if (mMode == STREAM_MODE_TEXT) {
printf("%d ", inputShort);
} else {
if (differentEndian()) {
outVal = bswap16((s16)inputShort);
}
_write(&outVal, sizeof(s16));
}
}
/**
@ -674,28 +594,21 @@ void Stream::writeShort(s16 inputShort)
*/
void Stream::writeInt(int inputInt)
{
// write int (4 bytes)
// need to handle text and binary mode differently
// by default, value to write should be inputInt
int outVal = inputInt;
if (mMode == STREAM_MODE_TEXT) {
// in text mode, write with "%d "
printf("%d ", inputInt);
return;
} else {
if (differentEndian()) {
int byte1 = ((u32)inputInt >> 24) & 0xFF;
int byte2 = ((u32)inputInt >> 8) & 0xFF00;
int byte3 = ((u32)inputInt << 8) & 0xFF0000;
int byte4 = ((u32)inputInt << 24) & 0xFF000000;
outVal = (byte4 | byte3 | byte2 | byte1);
}
_write(&outVal, sizeof(int));
}
// make sure stream value is big endian
if (mEndian != STREAM_BIG_ENDIAN) {
// if it's not big endian, swap bytes to make it big endian
int byte1 = ((u32)inputInt >> 24) & 0x000000FF;
int byte2 = ((u32)inputInt >> 8) & 0x0000FF00;
int byte3 = ((u32)inputInt << 8) & 0x00FF0000;
int byte4 = ((u32)inputInt << 24) & 0xFF000000;
outVal = (byte4 | byte3 | byte2 | byte1);
}
// write int (4 bytes) and increment stream position
write(&outVal, 4);
mPosition += 4;
}
/**
@ -704,33 +617,23 @@ void Stream::writeInt(int inputInt)
*/
void Stream::writeFloat(f32 inputFloat)
{
// write float (4 bytes)
// need to handle text and binary mode differently
// by default, value to write should be inputFloat
if (mMode == STREAM_MODE_TEXT) {
// in text mode, write with "%f "
printf("%f ", inputFloat);
return;
}
// check if stream value is big endian
if (mEndian != STREAM_BIG_ENDIAN) {
// if it's not big endian, swap bytes
u32 data = *(u32*)&inputFloat;
int byte1 = (data >> 24) & 0x000000FF;
int byte2 = (data >> 8) & 0x0000FF00;
int byte3 = (data << 8) & 0x00FF0000;
int byte4 = (data << 24) & 0xFF000000;
int intVal = (byte4 | byte3 | byte2 | byte1);
// write float (4 bytes) and increment stream position
write(&intVal, 4);
mPosition += 4;
return;
}
} else {
if (differentEndian()) {
u32 data = *(u32*)&inputFloat;
int byte1 = (data >> 24) & 0x000000FF;
int byte2 = (data >> 8) & 0x0000FF00;
int byte3 = (data << 8) & 0x00FF0000;
int byte4 = (data << 24) & 0xFF000000;
int intVal = (byte4 | byte3 | byte2 | byte1);
// write float (4 bytes) and increment stream position
write(&inputFloat, 4);
mPosition += 4;
_write(&intVal, sizeof(float));
return;
}
_write(&inputFloat, sizeof(float));
}
}
/**
@ -759,10 +662,10 @@ RamStream::RamStream(void* RamBufferPtr, int bounds)
*/
void RamStream::read(void* destMem, int numBytes)
{
if (eof()) { // if we're past the end of the file, panic
if (eof()) {
JUT_PANICLINE(523, "RamStream::read out of bounds (pos=%d,bound=%d)\n", mPosition, mBounds);
}
// read numBytes bytes from mRamBufferStart + mPosition to destMem in mem
memcpy(destMem, ((u8*)mRamBufferStart) + mPosition, numBytes);
}
@ -773,10 +676,10 @@ void RamStream::read(void* destMem, int numBytes)
void RamStream::write(void* srcMem, int numBytes)
{
if (eof()) { // if we're past the end of the file, panic
if (eof()) {
JUT_PANICLINE(534, "RamStream::write out of bounds (pos=%d,bound=%d)\n", mPosition, mBounds);
}
// write numBytes bytes from srcMem to mRamBufferStart + mPosition
memcpy(((u8*)mRamBufferStart) + mPosition, srcMem, numBytes);
}
@ -786,10 +689,10 @@ void RamStream::write(void* srcMem, int numBytes)
*/
bool RamStream::eof()
{
// check if we're at the end of the 'file'
if (mBounds != -1) {
return (mBounds <= mPosition);
}
return 0;
}

View File

@ -95,15 +95,15 @@ f32 pikmin2_sqrtf(register f32 x)
*/
f32 qdist2(f32 x1, f32 y1, f32 x2, f32 y2)
{
f32 deltaX = x2 - x1;
f32 deltaY = y2 - y1;
f32 xdiff = (x2 - x1);
f32 ydiff = (y2 - y1);
f32 dist = ((xdiff * xdiff) + (ydiff * ydiff));
f32 dist = SQUARE(deltaX) + SQUARE(deltaY);
if (dist > 0.0f) {
vf32 calcDist = dist * (__frsqrte(dist));
dist = calcDist;
}
return dist;
}
@ -113,11 +113,7 @@ f32 qdist2(f32 x1, f32 y1, f32 x2, f32 y2)
*/
f32 qdist3(f32 x1, f32 y1, f32 z1, f32 x2, f32 y2, f32 z2)
{
f32 xdiff = (x2 - x1);
f32 ydiff = (y2 - y1);
f32 zdiff = (z2 - z1);
Vector3f xyz(xdiff, ydiff, zdiff);
Vector3f xyz(x2 - x1, y2 - y1, z2 - z1);
return xyz.qLength();
}
@ -134,34 +130,34 @@ Vector3f CRSpline(f32 t, Vector3f* controls)
}
/**
* Calculates the tangent of a Catmull-Rom spline at a given parameter value.
*
* @param t The parameter value of the spline (between 0 and 1).
* @param controls An array of four control points that define the spline.
* @return The tangent vector at the given parameter value.
*
* @note Address: 0x80411858
* @note Size: 0xF4
*/
Vector3f CRSplineTangent(f32 t, Vector3f* controls)
/* == Centripetal Catmull-Rom Spline tangent calculation ==
Outputs tangent vector of desired point, given:
- coords for a set of 4 control points (controls[0] to controls[4]) for the curve, and
- a parameter for the curve, t, between 0 and 1
- t represents how 'far' between controls[1] and controls[2] the desired point is
- so t=0, point will be controls[1]; t=1, point will be controls[2]
*/
{
f32 tSqr = t * t;
Vector3f out;
// set coefficients - the floats are from centripetal CR matrices, assuming no tension
// (this is actually just drawn out matrix multiplication)
// Calculate the 4 basis functions for the Catmull-Rom spline
f32 f0 = (-1.5f * tSqr) + (2.0f * t) - 0.5f;
f32 f1 = (4.5f * tSqr) - 5.0f * t;
f32 f2 = (-4.5f * tSqr) + (4.0f * t) + 0.5f;
f32 f3 = (1.5f * tSqr) - t;
// Multiply each control point by its corresponding basis function
Vector3f ctr0 = controls[0] * f0;
Vector3f ctr1 = controls[1] * f1;
Vector3f ctr2 = controls[2] * f2;
Vector3f ctr3 = controls[3] * f3;
out = ctr0 + ctr1 + ctr2 + ctr3;
// Add the results together to get the tangent
out = ctr0 + ctr1 + ctr2 + ctr3;
return out;
}
@ -410,83 +406,9 @@ Quat::Quat(f32 _w, Vector3f vec)
*/
Quat::Quat(RPY& rpy)
{
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
FORCE_DONT_INLINE;
Quat quat(0.0f, Vector3f(0.0f, 0.0f, 0.0f));
Quat quat2(0.0f, Vector3f(0.0f, 0.0f, 0.0f));
*this = quat * quat2;
// this needs to spawn the operator* weak function somehow
// probably is recursive? this will do for now to match it
}
/**
@ -495,24 +417,24 @@ Quat::Quat(RPY& rpy)
*/
void Quat::set(Vector3f& vec)
{
Quat q1; // 0x48
Quat q2; // 0x38
Quat q3; // 0x28
Quat quatX;
Quat quatY;
Quat quatZ;
f32 cos_x = cos(0.5f * vec.x);
f32 sin_x = pikmin2_sinf(0.5f * vec.x);
q1.set(cos_x, sin_x, 0.0f, 0.0f);
f32 cosHalfX = cos(0.5f * vec.x);
f32 sinHalfX = pikmin2_sinf(0.5f * vec.x);
quatX.set(cosHalfX, sinHalfX, 0.0f, 0.0f);
f32 cos_y = cos(0.5f * vec.y);
f32 sin_y = pikmin2_sinf(0.5f * vec.y);
q2.set(cos_y, 0.0f, sin_y, 0.0f);
f32 cosHalfY = cos(0.5f * vec.y);
f32 sinHalfY = pikmin2_sinf(0.5f * vec.y);
quatY.set(cosHalfY, 0.0f, sinHalfY, 0.0f);
f32 cos_z = cos(0.5f * vec.z);
f32 sin_z = pikmin2_sinf(0.5f * vec.z);
q3.set(cos_z, 0.0f, 0.0f, sin_z);
f32 cosHalfZ = cos(0.5f * vec.z);
f32 sinHalfZ = pikmin2_sinf(0.5f * vec.z);
quatZ.set(cosHalfZ, 0.0f, 0.0f, sinHalfZ);
*this = q3 * q2;
*this = *this * q1;
*this = quatZ * quatY;
*this = *this * quatX;
}
/**
@ -620,10 +542,6 @@ void Quat::normalise()
*this = quat;
}
/**
* @note Address: 0x804128F0
* @note Size: 0x348
*/
/**
* Performs Spherical Linear Interpolation (SLERP) between two quaternions.
* This function calculates a quaternion that represents a rotation from the start point to the end point
@ -632,6 +550,9 @@ void Quat::normalise()
* @param q1 The end point of the path.
* @param t The linear interpolation parameter (how far from start to end do we want to be).
* @param qout The interpolated quaternion on the path, fraction t from start.
*
* @note Address: 0x804128F0
* @note Size: 0x348
*/
void Quat::slerp(Quat& q1, f32 t, Quat& qout)
{
@ -983,74 +904,87 @@ void Quat::toMatrix(Matrix3f& m)
*/
void Quat::fromMatrixf(Matrixf& mtx)
{
int case_var;
f32 temp_norm;
int maxElementCase;
f32 averageElement = 0.25f * (1.0f + (mtx.mMatrix.mtxView[2][2] + (mtx.mMatrix.mtxView[0][0] + mtx.mMatrix.mtxView[1][1])));
f32 element00 = -((0.5f * (mtx.mMatrix.mtxView[1][1] + mtx.mMatrix.mtxView[2][2])) - averageElement);
f32 element11 = -((0.5f * (mtx.mMatrix.mtxView[2][2] + mtx.mMatrix.mtxView[0][0])) - averageElement);
f32 element22 = -((0.5f * (mtx.mMatrix.mtxView[0][0] + mtx.mMatrix.mtxView[1][1])) - averageElement);
f32 avg_elem = 0.25f * (1.0f + (mtx.mMatrix.mtxView[2][2] + (mtx.mMatrix.mtxView[0][0] + mtx.mMatrix.mtxView[1][1])));
f32 var_00 = -((0.5f * (mtx.mMatrix.mtxView[1][1] + mtx.mMatrix.mtxView[2][2])) - avg_elem);
f32 var_11 = -((0.5f * (mtx.mMatrix.mtxView[2][2] + mtx.mMatrix.mtxView[0][0])) - avg_elem);
f32 var_22 = -((0.5f * (mtx.mMatrix.mtxView[0][0] + mtx.mMatrix.mtxView[1][1])) - avg_elem);
if (avg_elem > var_00) {
if (avg_elem > var_11) {
if (avg_elem > var_22) {
case_var = 0; // w norm
if (averageElement > element00) {
if (averageElement > element11) {
if (averageElement > element22) {
maxElementCase = 0; // w norm
} else {
case_var = 3; // z norm
maxElementCase = 3; // z norm
}
} else if (var_11 > var_22) {
case_var = 2; // y norm
} else if (element11 > element22) {
maxElementCase = 2; // y norm
} else {
case_var = 3; // z norm
maxElementCase = 3; // z norm
}
} else if (var_00 > var_11) {
if (var_00 > var_22) {
case_var = 1; // x norm
} else if (element00 > element11) {
if (element00 > element22) {
maxElementCase = 1; // x norm
} else {
case_var = 3; // z norm
maxElementCase = 3; // z norm
}
} else if (var_11 > var_22) {
case_var = 2; // y norm
} else if (element11 > element22) {
maxElementCase = 2; // y norm
} else {
case_var = 3; // z norm
maxElementCase = 3; // z norm
}
switch (case_var) {
// Normalise quaternion based on the maximum element index
switch (maxElementCase) {
case 0: // w norm
w = pikmin2_sqrtf(avg_elem);
temp_norm = 0.25f / w;
v.x = temp_norm * (mtx.mMatrix.mtxView[2][1] - mtx.mMatrix.mtxView[1][2]);
v.y = temp_norm * (mtx.mMatrix.mtxView[0][2] - mtx.mMatrix.mtxView[2][0]);
v.z = temp_norm * (mtx.mMatrix.mtxView[1][0] - mtx.mMatrix.mtxView[0][1]);
break;
case 1: // x norm
v.x = pikmin2_sqrtf(var_00);
temp_norm = 0.25f / v.x;
w = temp_norm * (mtx.mMatrix.mtxView[2][1] - mtx.mMatrix.mtxView[1][2]);
v.y = temp_norm * (mtx.mMatrix.mtxView[0][1] + mtx.mMatrix.mtxView[1][0]);
v.z = temp_norm * (mtx.mMatrix.mtxView[0][2] + mtx.mMatrix.mtxView[2][0]);
break;
case 2: // y norm
v.y = pikmin2_sqrtf(var_11);
temp_norm = 0.25f / v.y;
w = temp_norm * (mtx.mMatrix.mtxView[0][2] - mtx.mMatrix.mtxView[2][0]);
v.z = temp_norm * (mtx.mMatrix.mtxView[1][2] + mtx.mMatrix.mtxView[2][1]);
v.x = temp_norm * (mtx.mMatrix.mtxView[1][0] + mtx.mMatrix.mtxView[0][1]);
break;
case 3: // z norm
v.z = pikmin2_sqrtf(var_22);
temp_norm = 0.25f / v.z;
w = temp_norm * (mtx.mMatrix.mtxView[1][0] - mtx.mMatrix.mtxView[0][1]);
v.x = temp_norm * (mtx.mMatrix.mtxView[2][0] + mtx.mMatrix.mtxView[0][2]);
v.y = temp_norm * (mtx.mMatrix.mtxView[2][1] + mtx.mMatrix.mtxView[1][2]);
{
w = pikmin2_sqrtf(averageElement);
f32 temp_norm = 0.25f / w;
v.x = temp_norm * (mtx.mMatrix.mtxView[2][1] - mtx.mMatrix.mtxView[1][2]);
v.y = temp_norm * (mtx.mMatrix.mtxView[0][2] - mtx.mMatrix.mtxView[2][0]);
v.z = temp_norm * (mtx.mMatrix.mtxView[1][0] - mtx.mMatrix.mtxView[0][1]);
break;
}
case 1: // x norm
{
v.x = pikmin2_sqrtf(element00);
f32 temp_norm = 0.25f / v.x;
w = temp_norm * (mtx.mMatrix.mtxView[2][1] - mtx.mMatrix.mtxView[1][2]);
v.y = temp_norm * (mtx.mMatrix.mtxView[0][1] + mtx.mMatrix.mtxView[1][0]);
v.z = temp_norm * (mtx.mMatrix.mtxView[0][2] + mtx.mMatrix.mtxView[2][0]);
break;
}
case 2: // y norm
{
v.y = pikmin2_sqrtf(element11);
f32 temp_norm = 0.25f / v.y;
w = temp_norm * (mtx.mMatrix.mtxView[0][2] - mtx.mMatrix.mtxView[2][0]);
v.z = temp_norm * (mtx.mMatrix.mtxView[1][2] + mtx.mMatrix.mtxView[2][1]);
v.x = temp_norm * (mtx.mMatrix.mtxView[1][0] + mtx.mMatrix.mtxView[0][1]);
break;
}
case 3: // z norm
{
v.z = pikmin2_sqrtf(element22);
f32 temp_norm = 0.25f / v.z;
w = temp_norm * (mtx.mMatrix.mtxView[1][0] - mtx.mMatrix.mtxView[0][1]);
v.x = temp_norm * (mtx.mMatrix.mtxView[2][0] + mtx.mMatrix.mtxView[0][2]);
v.y = temp_norm * (mtx.mMatrix.mtxView[2][1] + mtx.mMatrix.mtxView[1][2]);
break;
}
}
if (w < 0.0f) {
w = -w;
v.x = -v.x;
v.y = -v.y;
v.z = -v.z;
}
f32 len_q = pikmin2_sqrtf(w * w + v.x * v.x + v.y * v.y + v.z * v.z);
f32 norm = 1.0f / len_q;
w *= norm;