Skip to content

Commit

Permalink
s3air
Browse files Browse the repository at this point in the history
  • Loading branch information
CCIGAMES committed Mar 2, 2024
1 parent b88d6fb commit 622e463
Show file tree
Hide file tree
Showing 9 changed files with 1,807 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Part of the Oxygen Engine / Sonic 3 A.I.R. software distribution.
* Copyright (C) 2017-2024 by Eukaryot
*
* Published under the GNU GPLv3 open source software license, see license.txt
* or https://www.gnu.org/licenses/gpl-3.0.en.html
*/

#pragma once

#include "lemon/runtime/RuntimeOpcode.h"

// Experimental change of conditional jump to being executed as a runtime opcode function
// -> It works, but has a negative impact on performance
//#define USE_JUMP_CONDITIONAL_RUNTIME_EXEC


namespace lemon
{
class Program;
class ScriptFunction;

struct RuntimeOpcodeBuffer
{
public:
~RuntimeOpcodeBuffer();

inline bool empty() const { return mSize == 0; }
inline size_t size() const { return mSize; }
inline const uint8* getStart() const { return mBuffer; }
inline const uint8* getEnd() const { return mBuffer + mSize; }

inline const uint8& operator[](size_t offset) const { return mBuffer[offset]; }

inline const std::vector<RuntimeOpcode*>& getOpcodePointers() const { return mOpcodePointers; }

void clear();
void reserveForOpcodes(size_t numOpcodes);
RuntimeOpcode& addOpcode(size_t parameterSize);

void copyFrom(const RuntimeOpcodeBuffer& other, rmx::OneTimeAllocPool& memoryPool);

public:
std::vector<RuntimeOpcode*> mOpcodePointers; // Direct pointers to runtime opcodes

private:
uint8* mBuffer = nullptr;
bool mSelfManagedBuffer = false;
size_t mSize = 0; // In bytes
size_t mReserved = 0; // In bytes
};


class API_EXPORT RuntimeFunction
{
public:
void build(Runtime& runtime);

const uint8* getFirstRuntimeOpcode() const { return mRuntimeOpcodeBuffer.getStart(); }

size_t translateFromRuntimeProgramCounter(const uint8* runtimeProgramCounter) const;
int translateFromRuntimeProgramCounterOptional(const uint8* runtimeProgramCounter) const;
const uint8* translateToRuntimeProgramCounter(size_t originalProgramCounter) const;

private:
void createRuntimeOpcode(RuntimeOpcodeBuffer& buffer, const Opcode* opcodes, int numOpcodesAvailable, int firstOpcodeIndex, int& outNumOpcodesConsumed, const Runtime& runtime);
const uint8* translateJumpTarget(uint32 targetOpcodeIndex) const;

public:
const ScriptFunction* mFunction = nullptr;
RuntimeOpcodeBuffer mRuntimeOpcodeBuffer;
std::vector<size_t> mProgramCounterByOpcodeIndex; // Program counter (= byte index inside "mRuntimeOpcodeData") where runtime opcode for given original opcode index starts
};

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* Part of the Oxygen Engine / Sonic 3 A.I.R. software distribution.
* Copyright (C) 2017-2024 by Eukaryot
*
* Published under the GNU GPLv3 open source software license, see license.txt
* or https://www.gnu.org/licenses/gpl-3.0.en.html
*/

#pragma once

#include "lemon/program/Opcode.h"
#include "lemon/runtime/Runtime.h"


namespace lemon
{
class Runtime;
struct RuntimeOpcode;
struct RuntimeOpcodeBuffer;
struct RuntimeOpcodeContext;


typedef void(*ExecFunc)(const RuntimeOpcodeContext context);

class API_EXPORT RuntimeOpcodeProvider
{
public:
virtual bool buildRuntimeOpcode(RuntimeOpcodeBuffer& buffer, const Opcode* opcodes, int numOpcodesAvailable, int firstOpcodeIndex, int& outNumOpcodesConsumed, const Runtime& runtime) = 0;
};


struct API_EXPORT RuntimeOpcodeBase
{
public:
enum class Flag : uint8
{
CALL_IS_BASE_CALL = 0x20, // For CALL opcodes only: It is a base call
CALL_TARGET_RESOLVED = 0x40, // For CALL opcodes only: Call target is already resolved and can be found in the parameter (as pointer)
CALL_TARGET_RUNTIME_FUNC = 0x80 // For CALL opcodes only: Call target is resolved and is a RuntimeFunction, not a Function
};

ExecFunc mExecFunc;
RuntimeOpcode* mNext = nullptr;
Opcode::Type mOpcodeType = Opcode::Type::NOP;
uint8 mSize = 0;
BitFlagSet<Flag> mFlags;
uint8 mSuccessiveHandledOpcodes = 0; // Number of internally handled opcodes (i.e. not manipulating control flow) in a row from this one -- including this one, so if this is 0, the opcode is not handled
};

struct API_EXPORT RuntimeOpcode : public RuntimeOpcodeBase
{
public:
static const constexpr size_t PARAMETER_OFFSET = sizeof(RuntimeOpcodeBase);

template<typename T> FORCE_INLINE T getParameter() const
{
return *reinterpret_cast<const T*>((uint8*)this + PARAMETER_OFFSET);
}

template<typename T> FORCE_INLINE T getParameter(size_t offset) const
{
return *reinterpret_cast<const T*>((uint8*)this + PARAMETER_OFFSET + offset);
}

template<typename T> void setParameter(T value)
{
*reinterpret_cast<T*>((uint8*)this + PARAMETER_OFFSET) = value;
}

template<typename T> void setParameter(T value, size_t offset)
{
*reinterpret_cast<T*>((uint8*)this + PARAMETER_OFFSET + offset) = value;
}
};

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Part of the Oxygen Engine / Sonic 3 A.I.R. software distribution.
* Copyright (C) 2017-2024 by Eukaryot
*
* Published under the GNU GPLv3 open source software license, see license.txt
* or https://www.gnu.org/licenses/gpl-3.0.en.html
*/

#pragma once

#include "lemon/runtime/Runtime.h"
#include "lemon/runtime/RuntimeOpcode.h"
#include "lemon/utility/AnyBaseValue.h"


namespace lemon
{
struct API_EXPORT RuntimeOpcodeContext
{
ControlFlow* mControlFlow = nullptr;
const RuntimeOpcode* mOpcode = nullptr;

template<typename T>
FORCE_INLINE T getParameter() const
{
return mOpcode->getParameter<T>();
}

template<typename T>
FORCE_INLINE T getParameter(size_t offset) const
{
return mOpcode->getParameter<T>(offset);
}

template<typename T>
FORCE_INLINE T readValueStack(int offset) const
{
return mControlFlow->readValueStack<T>(offset);
}

template<typename T>
FORCE_INLINE void writeValueStack(int offset, T value) const
{
mControlFlow->writeValueStack<T>(offset, value);
}

FORCE_INLINE void moveValueStack(int change) const
{
mControlFlow->moveValueStack(change);
}

template<typename T>
FORCE_INLINE T readLocalVariable(size_t index) const
{
return BaseTypeConversion::convert<int64, T>(mControlFlow->mCurrentLocalVariables[index]);
}

template<typename T>
FORCE_INLINE void writeLocalVariable(size_t index, T value) const
{
mControlFlow->mCurrentLocalVariables[index] = BaseTypeConversion::convert<T, int64>(value);
}
};
}
Loading

0 comments on commit 622e463

Please sign in to comment.