summaryrefslogtreecommitdiff
path: root/src/engine
diff options
context:
space:
mode:
authorMegaMech <MegaMech@users.noreply.github.com>2025-05-14 18:30:32 -0600
committerGitHub <noreply@github.com>2025-05-14 18:30:32 -0600
commit32632cacdb316d7f2d3b6ecdb634f0ef9aebadf0 (patch)
treed374a84675fc0f49100c275aa34828bc9db538f8 /src/engine
parent70f049cb6c326dede27e0ba7e88ac0d67b7651a4 (diff)
Impl new intro (#193)
* Update menus * Update CMakeLists.txt * Add Ship * Impl hm ship actors * Update HM course * Impl new intro * Finish intro scene * Rename * Start Editor Work * raycast works * Fix ScreenRayTrace in widescreen * Basic Actor Picking * wip * Editor use vtx collision * gizmo work * otr works for object picking * Impl objects for editor * actor init * Update * Add all axis move (freemove) * Docking Windows works here * Setup imgui layout for editor * Editor Snap to Ground works * Basic Scene Explorer Works * Editor get actor names * Impl editor object names * impl Editor Play and Pause buttons * Editor translate works while paused * Fix freecam lighting * Added adjustable track properties to editor * Editor matrix, icons, rotation, impl light * Setup Track Properties 1 * Editor tooling wip * Load modded o2rs * Don't enable hud if editor is enabled * Updates * SceneManager nearly working * Fix mario kart 64 intro logo sizing * Fix Rotator * Finish new matrix translation code * Cleanup headers * Cleanup * Cleanup 2 * Cleanup 3 * Prevent divize by zero crash * Add visible circle for translate in all axis * Editor scaling/rot works properly now * Scale All_Axis evenly * Fixes to includes to work on Linux. * Removed overfilled arguments in gfx_create_framebuffer() * Added missing function definitions to Game.h * Editor sun face the camera * Add rotation model to gizmo * Add new handles * Failed attempt at transforming collision * Impl water volume * Import fast64 paths * water surface * Scene Setup 1 * Custom Track O2R almost working needs testing * Custom Track Load path O2r * Render custom track. Wip collision * Add missing function * Debug Spawning Custom O2R Track * Import courses working now * Fix memory leak * Remove New Track Button * Engine.cpp more consistent with sf64 * Fix Editor Enable Button * Editor Accurate mouse click drag objects * Editor selects closest object and cleanup * Gizmo rot and scale collision working * Remove constexpr from IRotator * Impl properties for location/rot/scale * Better Properties display, swap rot handles * Fix content browser dock and editor now disabled by default * Remove GameInfoWindow, Multiplayer Button, and FPS Slider * Disable Editor when its disabled * Add new logo to hm intro * Fix pause menu item box cursor * Remove minimap from Course::from_json and to_json * Impl Import Minimap * Fix custom minimap rendering * minimap uses extension .png * Refactor minimap * Freecam only for player 1 * GrandPrix Balloons work in custom track * Track Id is now std::string and outside of Props * Moved editor assets to be included in ship.o2r * Fixed GenerateO2R to package the correct folder and save to the correct filename * Linux specific changes. * Added "#include <stdio.h>" that required them * Changed how the "ship.o2r" file is loaded to allow it to load the file from within appimages. * Changed the Linuxdeploy version to avoid errors later when the Github Actions creates appimages(same fix applied to other ports.) * Revert "Moved editor assets to be included in ship.o2r" This reverts commit 05704c01f761baa67a83e357d9765f5c6b5e3fdb. * Added back files(this time without LUS changes) * Changed workflow file to use correct filename for assets file. * Missed a few spots in the workflow file. * Added .desktop file and made corrections to the main workflow. * Added the rest of upstream CMakeLists.txt * disabled USE_NETWORKING * New InverseMatrix * Renamed both .o2r files to be more accurate to its contents. * Reverted CmakeList.txt --------- Co-authored-by: MegaMech <7255464+MegaMech@users.noreply.github.com> Co-authored-by: sitton76 <58642183+sitton76@users.noreply.github.com>
Diffstat (limited to 'src/engine')
-rw-r--r--src/engine/Actor.cpp29
-rw-r--r--src/engine/Actor.h7
-rw-r--r--src/engine/AllActors.h39
-rw-r--r--src/engine/CoreMath.h143
-rw-r--r--src/engine/Cup.cpp2
-rw-r--r--src/engine/Cup.h4
-rw-r--r--src/engine/GarbageCollector.cpp18
-rw-r--r--src/engine/GarbageCollector.h1
-rw-r--r--src/engine/HM_Intro.cpp183
-rw-r--r--src/engine/HM_Intro.h78
-rw-r--r--src/engine/Matrix.cpp75
-rw-r--r--src/engine/Matrix.h3
-rw-r--r--src/engine/Registry.cpp59
-rw-r--r--src/engine/Registry.h33
-rw-r--r--src/engine/StaticMeshActor.cpp29
-rw-r--r--src/engine/StaticMeshActor.h61
-rw-r--r--src/engine/World.cpp84
-rw-r--r--src/engine/World.h17
-rw-r--r--src/engine/actors/Banana.cpp (renamed from src/engine/actors/ABanana.cpp)3
-rw-r--r--src/engine/actors/Banana.h (renamed from src/engine/actors/ABanana.h)1
-rw-r--r--src/engine/actors/BowserStatue.cpp1
-rw-r--r--src/engine/actors/Cloud.cpp (renamed from src/engine/actors/ACloud.cpp)11
-rw-r--r--src/engine/actors/Cloud.h (renamed from src/engine/actors/ACloud.h)3
-rw-r--r--src/engine/actors/Finishline.cpp (renamed from src/engine/actors/AFinishline.cpp)3
-rw-r--r--src/engine/actors/Finishline.h (renamed from src/engine/actors/AFinishline.h)0
-rw-r--r--src/engine/actors/MarioSign.cpp56
-rw-r--r--src/engine/actors/MarioSign.h19
-rw-r--r--src/engine/actors/Ship.cpp45
-rw-r--r--src/engine/actors/Ship.h6
-rw-r--r--src/engine/actors/SpaghettiShip.cpp37
-rw-r--r--src/engine/actors/SpaghettiShip.h6
-rw-r--r--src/engine/actors/Starship.cpp31
-rw-r--r--src/engine/actors/Starship.h3
-rw-r--r--src/engine/actors/Tree.cpp (renamed from src/engine/actors/ATree.cpp)3
-rw-r--r--src/engine/actors/Tree.h (renamed from src/engine/actors/ATree.h)0
-rw-r--r--src/engine/actors/WarioSign.cpp (renamed from src/engine/actors/AWarioSign.cpp)14
-rw-r--r--src/engine/actors/WarioSign.h (renamed from src/engine/actors/AWarioSign.h)4
-rw-r--r--src/engine/courses/BansheeBoardwalk.cpp58
-rw-r--r--src/engine/courses/BansheeBoardwalk.h3
-rw-r--r--src/engine/courses/BigDonut.cpp55
-rw-r--r--src/engine/courses/BigDonut.h14
-rw-r--r--src/engine/courses/BlockFort.cpp59
-rw-r--r--src/engine/courses/BlockFort.h11
-rw-r--r--src/engine/courses/BowsersCastle.cpp72
-rw-r--r--src/engine/courses/BowsersCastle.h4
-rw-r--r--src/engine/courses/ChocoMountain.cpp50
-rw-r--r--src/engine/courses/ChocoMountain.h3
-rw-r--r--src/engine/courses/Course.cpp178
-rw-r--r--src/engine/courses/Course.h210
-rw-r--r--src/engine/courses/DKJungle.cpp84
-rw-r--r--src/engine/courses/DKJungle.h4
-rw-r--r--src/engine/courses/DoubleDeck.cpp44
-rw-r--r--src/engine/courses/DoubleDeck.h4
-rw-r--r--src/engine/courses/FrappeSnowland.cpp68
-rw-r--r--src/engine/courses/FrappeSnowland.h14
-rw-r--r--src/engine/courses/Harbour.cpp100
-rw-r--r--src/engine/courses/Harbour.h7
-rw-r--r--src/engine/courses/KalimariDesert.cpp52
-rw-r--r--src/engine/courses/KalimariDesert.h3
-rw-r--r--src/engine/courses/KoopaTroopaBeach.cpp64
-rw-r--r--src/engine/courses/KoopaTroopaBeach.h3
-rw-r--r--src/engine/courses/LuigiRaceway.cpp72
-rw-r--r--src/engine/courses/LuigiRaceway.h6
-rw-r--r--src/engine/courses/MarioRaceway.cpp65
-rw-r--r--src/engine/courses/MarioRaceway.h3
-rw-r--r--src/engine/courses/MooMooFarm.cpp51
-rw-r--r--src/engine/courses/MooMooFarm.h3
-rw-r--r--src/engine/courses/PodiumCeremony.cpp56
-rw-r--r--src/engine/courses/PodiumCeremony.h3
-rw-r--r--src/engine/courses/RainbowRoad.cpp49
-rw-r--r--src/engine/courses/RainbowRoad.h3
-rw-r--r--src/engine/courses/RoyalRaceway.cpp66
-rw-r--r--src/engine/courses/RoyalRaceway.h5
-rw-r--r--src/engine/courses/SherbetLand.cpp99
-rw-r--r--src/engine/courses/SherbetLand.h10
-rw-r--r--src/engine/courses/Skyscraper.cpp45
-rw-r--r--src/engine/courses/Skyscraper.h3
-rw-r--r--src/engine/courses/TestCourse.cpp83
-rw-r--r--src/engine/courses/TestCourse.h7
-rw-r--r--src/engine/courses/ToadsTurnpike.cpp50
-rw-r--r--src/engine/courses/ToadsTurnpike.h3
-rw-r--r--src/engine/courses/WarioStadium.cpp64
-rw-r--r--src/engine/courses/WarioStadium.h3
-rw-r--r--src/engine/courses/YoshiValley.cpp60
-rw-r--r--src/engine/courses/YoshiValley.h3
-rw-r--r--src/engine/editor/Collision.cpp188
-rw-r--r--src/engine/editor/Collision.h23
-rw-r--r--src/engine/editor/Editor.cpp166
-rw-r--r--src/engine/editor/Editor.h47
-rw-r--r--src/engine/editor/EditorMath.cpp427
-rw-r--r--src/engine/editor/EditorMath.h58
-rw-r--r--src/engine/editor/GameObject.cpp30
-rw-r--r--src/engine/editor/GameObject.h44
-rw-r--r--src/engine/editor/Gizmo.cpp348
-rw-r--r--src/engine/editor/Gizmo.h85
-rw-r--r--src/engine/editor/Handles.cpp23
-rw-r--r--src/engine/editor/Handles.h19
-rw-r--r--src/engine/editor/Light.cpp84
-rw-r--r--src/engine/editor/Light.h2143
-rw-r--r--src/engine/editor/ObjectPicker.cpp207
-rw-r--r--src/engine/editor/ObjectPicker.h28
-rw-r--r--src/engine/editor/SceneManager.cpp156
-rw-r--r--src/engine/editor/SceneManager.h13
-rw-r--r--src/engine/objects/Bat.cpp4
-rw-r--r--src/engine/objects/Bat.h6
-rw-r--r--src/engine/objects/BombKart.cpp39
-rw-r--r--src/engine/objects/BombKart.h3
-rw-r--r--src/engine/objects/Boos.cpp1
-rw-r--r--src/engine/objects/ChainChomp.cpp3
-rw-r--r--src/engine/objects/CheepCheep.cpp1
-rw-r--r--src/engine/objects/Crab.cpp1
-rw-r--r--src/engine/objects/Crab.h1
-rw-r--r--src/engine/objects/Flagpole.cpp1
-rw-r--r--src/engine/objects/Flagpole.h1
-rw-r--r--src/engine/objects/GrandPrixBalloons.cpp231
-rw-r--r--src/engine/objects/GrandPrixBalloons.h55
-rw-r--r--src/engine/objects/Hedgehog.cpp2
-rw-r--r--src/engine/objects/HotAirBalloon.cpp1
-rw-r--r--src/engine/objects/HotAirBalloon.h1
-rw-r--r--src/engine/objects/Lakitu.cpp1
-rw-r--r--src/engine/objects/Mole.cpp1
-rw-r--r--src/engine/objects/Mole.h1
-rw-r--r--src/engine/objects/Object.cpp2
-rw-r--r--src/engine/objects/Object.h4
-rw-r--r--src/engine/objects/Penguin.cpp9
-rw-r--r--src/engine/objects/Penguin.h3
-rw-r--r--src/engine/objects/Podium.cpp2
-rw-r--r--src/engine/objects/Seagull.cpp1
-rw-r--r--src/engine/objects/Seagull.h1
-rw-r--r--src/engine/objects/Snowman.cpp2
-rw-r--r--src/engine/objects/Snowman.h1
-rw-r--r--src/engine/objects/Thwomp.cpp1
-rw-r--r--src/engine/objects/Thwomp.h1
-rw-r--r--src/engine/objects/TrashBin.cpp3
-rw-r--r--src/engine/objects/TrashBin.h5
-rw-r--r--src/engine/objects/Trophy.cpp1
-rw-r--r--src/engine/objects/Trophy.h1
-rw-r--r--src/engine/vehicles/Boat.cpp1
-rw-r--r--src/engine/vehicles/Bus.cpp1
-rw-r--r--src/engine/vehicles/Car.cpp1
-rw-r--r--src/engine/vehicles/TankerTruck.cpp1
-rw-r--r--src/engine/vehicles/Train.cpp1
-rw-r--r--src/engine/vehicles/Truck.cpp1
143 files changed, 6386 insertions, 1187 deletions
diff --git a/src/engine/Actor.cpp b/src/engine/Actor.cpp
index be86d2a5f..f3254fed0 100644
--- a/src/engine/Actor.cpp
+++ b/src/engine/Actor.cpp
@@ -1,16 +1,41 @@
#include <libultraship.h>
+#include "Matrix.h"
#include "Actor.h"
+extern "C" {
+#include "math_util.h"
+}
+
AActor::AActor() {}
// Virtual functions to be overridden by derived classes
void AActor::Tick() { }
-void AActor::Draw(Camera *camera) { }
+void AActor::Draw(Camera *camera) {
+ if (Model) {
+ Mat4 mtx;
+
+ gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
+ gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
+
+ ApplyMatrixTransformations(mtx, *(FVector*)Pos, *(IRotator*)Rot, Scale);
+ if (render_set_position(mtx, 0) != 0) {
+ gSPDisplayList(gDisplayListHead++, Model);
+ }
+ }
+}
void AActor::Collision(Player* player, AActor* actor) {}
void AActor::VehicleCollision(s32 playerId, Player* player){}
void AActor::Destroy() {
// Set uuid to zero.
memset(uuid, 0, sizeof(uuid));
}
-bool AActor::IsMod() { return false; } \ No newline at end of file
+bool AActor::IsMod() { return false; }
+void AActor::SetLocation(FVector pos) {
+ Pos[0] = pos.x;
+ Pos[1] = pos.y;
+ Pos[2] = pos.z;
+}
+FVector AActor::GetLocation() const {
+ return FVector(Pos[0], Pos[1], Pos[2]);
+}
diff --git a/src/engine/Actor.h b/src/engine/Actor.h
index a74ed74e0..fb0a9f89e 100644
--- a/src/engine/Actor.h
+++ b/src/engine/Actor.h
@@ -1,6 +1,7 @@
#pragma once
#include <libultraship.h>
+#include "CoreMath.h"
extern "C" {
#include "macros.h"
@@ -24,6 +25,10 @@ public:
/* 0x24 */ Vec3f Velocity = {0, 0, 0};
/* 0x30 */ Collision Unk30;
uint8_t uuid[16];
+ const char* Name = "";
+ FVector Scale = {1, 1, 1};
+
+ Gfx* Model = NULL;
virtual ~AActor() = default; // Virtual destructor for proper cleanup in derived classes
@@ -33,6 +38,8 @@ public:
virtual void Draw(Camera*);
virtual void Collision(Player* player, AActor* actor);
virtual void VehicleCollision(s32 playerId, Player* player);
+ void SetLocation(FVector pos);
+ FVector GetLocation() const;
virtual void Destroy();
virtual bool IsMod();
diff --git a/src/engine/AllActors.h b/src/engine/AllActors.h
new file mode 100644
index 000000000..f2b228b57
--- /dev/null
+++ b/src/engine/AllActors.h
@@ -0,0 +1,39 @@
+#pragma once
+
+#include "actors/MarioSign.h"
+#include "actors/WarioSign.h"
+#include "actors/Cloud.h"
+#include "actors/Finishline.h"
+#include "actors/SpaghettiShip.h"
+#include "actors/Starship.h"
+#include "actors/Ship.h"
+#include "actors/Tree.h"
+#include "vehicles/Train.h"
+#include "vehicles/Boat.h"
+#include "vehicles/Bus.h"
+#include "vehicles/Truck.h"
+#include "vehicles/Car.h"
+#include "vehicles/Truck.h"
+#include "vehicles/TankerTruck.h"
+
+#include "objects/Bat.h"
+#include "objects/BombKart.h"
+#include "objects/Boos.h"
+#include "objects/CheepCheep.h"
+#include "objects/Crab.h"
+#include "objects/ChainChomp.h"
+#include "objects/Flagpole.h"
+#include "objects/Hedgehog.h"
+#include "objects/HotAirBalloon.h"
+#include "objects/Lakitu.h"
+#include "objects/Mole.h"
+#include "objects/Penguin.h"
+#include "objects/Seagull.h"
+#include "objects/Thwomp.h"
+#include "objects/Seagull.h"
+#include "objects/TrashBin.h"
+#include "objects/Trophy.h"
+#include "objects/Snowman.h"
+#include "objects/Podium.h"
+#include "objects/GrandPrixBalloons.h"
+
diff --git a/src/engine/CoreMath.h b/src/engine/CoreMath.h
index ea74dd9a4..2c232aab9 100644
--- a/src/engine/CoreMath.h
+++ b/src/engine/CoreMath.h
@@ -10,16 +10,55 @@
*
*/
-
+/**
+ *
+ * Applies pos, rot, and scale
+ *
+ */
struct FVector {
float x, y, z;
#ifdef __cplusplus
- FVector& operator=(const FVector& other) {
- x = other.x;
- y = other.y;
- z = other.z;
- return *this;
+ // Operator to add two FVector objects
+ FVector operator+(const FVector& other) const {
+ return FVector(x + other.x, y + other.y, z + other.z);
+ }
+
+ // Operator to subtract two FVector objects
+ FVector operator-(const FVector& other) const {
+ return FVector(x - other.x, y - other.y, z - other.z);
+ }
+
+ // Operator to multiply a FVector by a scalar (float)
+ FVector operator*(float scalar) const {
+ return FVector(x * scalar, y * scalar, z * scalar);
+ }
+
+ float Dot(const FVector& other) const {
+ return x * other.x + y * other.y + z * other.z;
+ }
+
+
+ FVector Cross(const FVector& other) const {
+ return FVector(
+ y * other.z - z * other.y,
+ z * other.x - x * other.z,
+ x * other.y - y * other.x
+ );
+ }
+
+ float Magnitude() const {
+ return std::sqrt(x * x + y * y + z * z);
+ }
+
+ FVector Normalize() const {
+ float len = std::sqrt(x * x + y * y + z * z);
+ if (len > 0.0001f) {
+ return FVector(
+ x / len, y / len, z / len
+ );
+ }
+ return FVector(0, 0, 0);
}
FVector() : x(0), y(0), z(0) {}
@@ -27,6 +66,16 @@ struct FVector {
#endif // __cplusplus
};
+struct FVector4 {
+ float x, y, z, w;
+
+#ifdef __cplusplus
+
+ FVector4() : x(0), y(0), z(0), w(0) {}
+ FVector4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}
+#endif // __cplusplus
+};
+
/**
* For providing X and Z when you do not need Y
* Some actors set themselves on the surface automatically
@@ -50,35 +99,95 @@ struct FVector2D {
// Sets integer X Z coordinates
typedef struct IVector2D {
- int32_t X, Z;
+ int32_t X, Y;
#ifdef __cplusplus
- IVector2D() : X(0), Z(0) {} // Default constructor
+ IVector2D() : X(0), Y(0) {} // Default constructor
- IVector2D(int32_t x, int32_t z) : X(x), Z(z) {} // Constructor to initialize with values
+ IVector2D(int32_t x, int32_t y) : X(x), Y(y) {} // Constructor to initialize with values
IVector2D& operator=(const IVector2D& other) {
X = other.X;
- Z = other.Z;
+ Y = other.Y;
return *this;
}
#endif // __cplusplus
} IVector2D;
-struct FRotation {
+/**
+ * This struct immediately converts float pitch/yaw/roll in degrees to n64 int16_t binary angles 0-0xFFFF == 0-360 degrees
+ * ToDegrees() Receive an FRotator of float degrees back.
+ * Set() Set an n64 int16_t binary angles 0-0xFFFF
+ */
+struct IRotator {
+ uint16_t pitch, yaw, roll;
+
+#ifdef __cplusplus
+ IRotator& operator=(const IRotator& other) {
+ pitch = other.pitch;
+ yaw = other.yaw;
+ roll = other.roll;
+ return *this;
+ }
+
+ [[nodiscard]] void Set(uint16_t p, uint16_t y, uint16_t r) {
+ pitch = p;
+ yaw = y;
+ roll = r;
+ }
+
+ IRotator() : pitch(0), yaw(0), roll(0) {}
+ IRotator(float p, float y, float r) {
+ pitch = p * (UINT16_MAX / 360);
+ yaw = y * (UINT16_MAX / 360);
+ roll = r * (UINT16_MAX / 360);
+ }
+
+ // Convert to radians as FVector
+ [[nodiscard]] FVector ToRadians() const {
+ float scale = 2.0f * M_PI / 65536.0f;
+ return FVector(
+ pitch * scale,
+ yaw * scale,
+ roll * scale
+ );
+ }
+#endif // __cplusplus
+};
+
+/**
+ * Use IRotator unless you want to do some math in degrees.
+ * Always use ToBinary() or Rotator when sending into matrices or apply translation functions
+ * Convert from IRotator to FRotator float degrees by doing FRotator(myIRotator);
+ */
+struct FRotator {
float pitch, yaw, roll;
#ifdef __cplusplus
- FRotation& operator=(const FRotation& other) {
+ FRotator& operator=(const FRotator& other) {
pitch = other.pitch;
- yaw = other.yaw;
- roll = other.roll;
+ yaw = other.yaw;
+ roll = other.roll;
return *this;
}
- FRotation() : pitch(0), yaw(0), roll(0) {}
- FRotation(float p, float y, float r) : pitch(p), yaw(y), roll(r) {}
+ // Convert to binary rotator 0 --> INT16_MAX
+ [[nodiscard]] IRotator ToBinary() const {
+ return IRotator(
+ static_cast<uint16_t>(pitch * (UINT16_MAX / 360)),
+ static_cast<uint16_t>(yaw * (UINT16_MAX / 360)),
+ static_cast<uint16_t>(roll * (UINT16_MAX / 360))
+ );
+ }
+
+ FRotator() : pitch(0), yaw(0), roll(0) {}
+ FRotator(float p, float y, float r) : pitch(p), yaw(y), roll(r) {}
+ FRotator(IRotator rot) {
+ pitch = static_cast<float>(rot.pitch * (360 / UINT16_MAX));
+ yaw = static_cast<float>(rot.yaw * (360 / UINT16_MAX));
+ roll = static_cast<float>(rot.roll * (360 / UINT16_MAX));
+ }
#endif // __cplusplus
};
@@ -118,4 +227,4 @@ struct IPathSpan {
#endif // __cplusplus
};
-#endif // CORE_MATH_H \ No newline at end of file
+#endif // CORE_MATH_H
diff --git a/src/engine/Cup.cpp b/src/engine/Cup.cpp
index 85d7fed44..ec9e6c913 100644
--- a/src/engine/Cup.cpp
+++ b/src/engine/Cup.cpp
@@ -1,7 +1,7 @@
#include "Cup.h"
#include "courses/Course.h"
-Cup::Cup(const char* id, const char* name, std::vector<Course*> courses) {
+Cup::Cup(std::string id, const char* name, std::vector<Course*> courses) {
Id = id;
Name = name;
Courses = courses;
diff --git a/src/engine/Cup.h b/src/engine/Cup.h
index 4266c0126..0b477824f 100644
--- a/src/engine/Cup.h
+++ b/src/engine/Cup.h
@@ -9,13 +9,13 @@ class Course; // <-- Forward declare
class Cup {
public:
- const char* Id;
+ std::string Id;
const char* Name;
u8 *Thumbnail;
size_t CursorPosition = 0; // Course index in cup
std::vector<Course*> Courses;
- explicit Cup(const char* id, const char* name, std::vector<Course*> courses);
+ explicit Cup(std::string id, const char* name, std::vector<Course*> courses);
virtual void ShuffleCourses();
diff --git a/src/engine/GarbageCollector.cpp b/src/engine/GarbageCollector.cpp
index 926620fe1..9832aa29d 100644
--- a/src/engine/GarbageCollector.cpp
+++ b/src/engine/GarbageCollector.cpp
@@ -4,6 +4,7 @@
void RunGarbageCollector() {
//CleanActors();
CleanObjects();
+ CleanStaticMeshActors();
}
void CleanActors() {
@@ -18,14 +19,27 @@ void CleanActors() {
// }
}
+void CleanStaticMeshActors() {
+ for (auto actor = gWorldInstance.StaticMeshActors.begin(); actor != gWorldInstance.StaticMeshActors.end();) {
+ StaticMeshActor* act = *actor; // Get a mutable copy
+ if (act->bPendingDestroy) {
+ delete act;
+ actor = gWorldInstance.StaticMeshActors.erase(actor); // Remove from container
+ continue;
+ } else {
+ actor++;
+ }
+ }
+}
+
void CleanObjects() {
for (auto object = gWorldInstance.Objects.begin(); object != gWorldInstance.Objects.end();) {
OObject* obj = *object; // Get a mutable copy
- if (obj->PendingDestroy) {
+ if (obj->bPendingDestroy) {
delete obj;
object = gWorldInstance.Objects.erase(object); // Remove from container
continue;
}
object++;
}
-} \ No newline at end of file
+}
diff --git a/src/engine/GarbageCollector.h b/src/engine/GarbageCollector.h
index 337d90e4a..c96f1c36a 100644
--- a/src/engine/GarbageCollector.h
+++ b/src/engine/GarbageCollector.h
@@ -8,4 +8,5 @@
void RunGarbageCollector();
void CleanActors();
+void CleanStaticMeshActors();
void CleanObjects();
diff --git a/src/engine/HM_Intro.cpp b/src/engine/HM_Intro.cpp
new file mode 100644
index 000000000..e27d5db0c
--- /dev/null
+++ b/src/engine/HM_Intro.cpp
@@ -0,0 +1,183 @@
+#include <libultra/gbi.h>
+#include <libultra/gu.h>
+#include "HM_Intro.h"
+
+#include "port/Game.h"
+
+extern "C" {
+#include "main.h"
+#include "memory.h"
+#include "math_util.h"
+#include "courses/harbour/track.h"
+#include "courses/harbour/powered.h"
+#include "courses/harbour/ship2_model.h"
+#include "courses/harbour/ship3_model.h"
+#include "collision.h"
+#include "menu_items.h"
+#include "external.h"
+#include "menus.h"
+extern Gfx ship1_spag1_mesh[];
+}
+
+HarbourMastersIntro::HarbourMastersIntro() {
+}
+
+void HarbourMastersIntro::HM_InitIntro() {
+ _camera.Pos.x = 0;
+ _camera.Pos.y = 0;
+ _camera.Pos.z = 0;
+
+ // The camera setup was broken when this was first made. And then it was fixed.
+ // That's why this file has weird coordinates as the objects were positioned in-front of the camera view
+ // Instead of moving the camera to the right spot in the scene.
+ _camera.LookAt.x = 0;
+ _camera.LookAt.y = 0;
+ _camera.LookAt.z = -2500;
+
+ _cameraSpeed = 0.0f;
+ _cameraMaxSpeed = 16.0f;
+ _cameraAcceleration = 1.0f;
+
+ _pos = FVector(-1000, -205, -800); // -1000, -210, -800
+ _rot = IRotator(-5, 100, 0);
+ _scale = {0.7f, 0.7f, 0.7f};
+
+ _ship2Pos = FVector(300, -210, -1960);
+ _ship2Rot = IRotator(0, 45, 0);
+
+ _shipPos = FVector(20, -210, -1650);
+ _shipRot = IRotator(0, 45, 0);
+
+ _posHM64 = FVector(0, -500, -1000);
+ _rotHM64 = IRotator(0, -90, -4); // -0x2100
+
+ _hPos = FVector(-2000, 100, -4900);
+ _hRot = IRotator(0, -45.0f, 0);
+ _hScale = {2.0f, 2.0f, 2.0f};
+
+ lusPos = FVector(0, -400, -614); // 12, 190, -1000
+ lusRot = IRotator(0, 0, 0);
+ lusScale = FVector(1, 1, 1);
+
+ ground_f3d_material_013_lights = gdSPDefLights1(
+ 0x7F, 0x30, 0x80,
+ 0x60, 20, 10, 0x49, 0x49, 0x49
+ );
+
+ gEditor.AddObject("lus", &lusPos, &lusRot, &lusScale, nullptr, 1, Editor::GameObject::CollisionType::BOUNDING_BOX, 10, &DespawnValue, -1);
+}
+
+void HarbourMastersIntro::HM_TickIntro() {
+ _water += 1;
+ if (_water > 255) {
+ _water = 0;
+ }
+
+ HarbourMastersIntro::SpagBob(_pos, _rot, 2.5f, 0.18f, 1.5f, 0.05f, 1.7f, 0.06f);
+ HarbourMastersIntro::Bob(_shipPos, _shipRot, 1.2f, 0.06f, 1.6f, -0.04f, 1.1f, -0.04f);
+ HarbourMastersIntro::Bob(_ship2Pos, _ship2Rot, 1.2f, 0.06f, 1.6f, -0.04f, 1.1f, -0.04f);
+
+ _pos.x += 9;
+ if (lusPos.y < -60) {
+ lusPos.y += 3;
+ }
+ //_camera.Pos.x -= 1;
+
+ // SWITCH TO NEXT MENU LOGO_INTRO_MENU
+ if (_pos.x >= 1100) {
+ gMenuFadeType = 0;
+ gMenuSelection = LOGO_INTRO_MENU;
+ gFadeModeSelection = FADE_MODE_LOGO;
+ }
+
+ find_and_set_tile_size((uintptr_t) ((void*)mat_water_water1), 0, _water);
+ find_and_set_tile_size((uintptr_t) ((void*)mat_water_water2), _water, 0);;
+}
+
+void HarbourMastersIntro::Bob(FVector& pos, IRotator& rot, f32 bobAmp, f32 bobSpeed, f32 tiltAmp, f32 tiltSpeed, f32 rollAmp, f32 rollSpeed) {
+ float time = (float)gGlobalTimer;
+
+ pos.y = -210 + bobAmp * sin(time * bobSpeed);
+
+ rot.pitch = (tiltAmp * sin(time * tiltSpeed)) * (UINT16_MAX / 360);
+
+ rot.roll = (rollAmp * sin(time * rollSpeed)) * (UINT16_MAX / 360);
+}
+
+void HarbourMastersIntro::SpagBob(FVector& pos, IRotator& rot, f32 bobAmp, f32 bobSpeed, f32 tiltAmp, f32 tiltSpeed, f32 rollAmp, f32 rollSpeed) {
+ float time = (float)gGlobalTimer;
+
+ pos.y = -205 + bobAmp * sin(time * bobSpeed);
+
+ rot.pitch = (-5 + tiltAmp * sin(time * tiltSpeed)) * (UINT16_MAX / 360);
+
+ rot.roll = (rollAmp * sin(time * rollSpeed)) * (UINT16_MAX / 360);
+}
+
+void HarbourMastersIntro::HM_DrawIntro() {
+ HarbourMastersIntro::Setup();
+
+ gSPMatrix(gDisplayListHead++, &gGfxPool->mtxScreen, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
+ gSPMatrix(gDisplayListHead++, &gGfxPool->mtxLookAt[0], G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION);
+ gDPSetRenderMode(gDisplayListHead++, G_RM_AA_ZB_OPA_SURF, G_RM_AA_ZB_OPA_SURF2);
+ gDPSetEnvColor(gDisplayListHead++, 0x00, 0x00, 0x00, 0x00);
+
+ Mat4 mtx_spaghettiShip;
+ ApplyMatrixTransformations(mtx_spaghettiShip, _pos, _rot, _scale);
+ render_set_position(mtx_spaghettiShip, 0);
+ gSPDisplayList(gDisplayListHead++, ship1_spag1_mesh);
+
+ Mat4 mtx_ship2;
+ ApplyMatrixTransformations(mtx_ship2, _ship2Pos, _ship2Rot, _scale);
+ render_set_position(mtx_ship2, 0);
+ gSPDisplayList(gDisplayListHead++, ship2_SoH_mesh);
+
+ Mat4 mtx_ship3;
+ ApplyMatrixTransformations(mtx_ship3, _shipPos, _shipRot, _scale);
+ render_set_position(mtx_ship3, 0);
+ gSPDisplayList(gDisplayListHead++, ship3_2Ship_mesh);
+
+ Mat4 mtx_geo;
+ ApplyMatrixTransformations(mtx_geo, _hPos, _hRot, _hScale);
+ render_set_position(mtx_geo, 0);
+
+ gSPDisplayList(gDisplayListHead++, ground_map_mesh);
+ //gSPDisplayList(gDisplayListHead++, powered_Text_mesh); // Replaced by poweredbylus
+ gSPDisplayList(gDisplayListHead++, castle_map_002_mesh);
+ gSPDisplayList(gDisplayListHead++, road_map_001_mesh);
+ gSPDisplayList(gDisplayListHead++, water_water1_mesh);
+
+ Mat4 lusMtx;
+ ApplyMatrixTransformations(lusMtx, lusPos, lusRot, lusScale);
+ render_set_position(lusMtx, 0);
+ gSPDisplayList(gDisplayListHead++, (Gfx*)"__OTR__hmintro/poweredbylus");
+
+ HarbourMastersIntro::Sync();
+}
+
+void HarbourMastersIntro::Setup() {
+ u16 perspNorm;
+ move_segment_table_to_dmem();
+ gDPSetTexturePersp(gDisplayListHead++, G_TP_PERSP);
+ guPerspective(&gGfxPool->mtxScreen, &perspNorm, 45.0f, 1.3333334f, 100.0f, 12800.0f, 1.0f);
+ gSPPerspNormalize(gDisplayListHead++, perspNorm);
+ guLookAt(&gGfxPool->mtxLookAt[0], _camera.Pos.x, _camera.Pos.y, _camera.Pos.z, _camera.LookAt.x, _camera.LookAt.y, _camera.LookAt.z, 0.0f, 1.0f, 0.0f);
+
+ gDPSetCycleType(gDisplayListHead++, G_CYC_FILL);
+ gDPSetRenderMode(gDisplayListHead++, G_RM_OPA_SURF, G_RM_OPA_SURF2);
+ gSPClearGeometryMode(gDisplayListHead++, G_ZBUFFER | G_CULL_BACK | G_LIGHTING);
+ gDPSetFillColor(gDisplayListHead++, 0x00010001);
+ gDPFillRectangle(gDisplayListHead++, 0, 0, 319, 239);
+ gSPSetGeometryMode(gDisplayListHead++, G_ZBUFFER | G_CULL_BACK | G_LIGHTING);
+ gDPSetRenderMode(gDisplayListHead++, G_RM_AA_ZB_OPA_SURF, G_RM_AA_ZB_OPA_SURF2);
+ gDPSetCycleType(gDisplayListHead++, G_CYC_1CYCLE);
+ gDPSetCombineMode(gDisplayListHead++, G_CC_SHADE, G_CC_SHADE);
+ gSPSetGeometryMode(gDisplayListHead++, G_SHADE | G_CULL_BACK | G_LIGHTING | G_SHADING_SMOOTH);
+ gDPPipeSync(gDisplayListHead++);
+}
+
+void HarbourMastersIntro::Sync() {
+ gDPPipeSync(gDisplayListHead++);
+ gDPSetTexturePersp(gDisplayListHead++, G_TP_NONE);
+ gDPSetTextureFilter(gDisplayListHead++, G_TF_BILERP);
+}
diff --git a/src/engine/HM_Intro.h b/src/engine/HM_Intro.h
new file mode 100644
index 000000000..24fe08e35
--- /dev/null
+++ b/src/engine/HM_Intro.h
@@ -0,0 +1,78 @@
+#ifndef _HM_INTRO_H
+#define _HM_INTRO_H
+
+#include <libultraship.h>
+#include <libultra/gbi.h>
+#include "CoreMath.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "common_structs.h"
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef __cplusplus
+class HarbourMastersIntro {
+public:
+ HarbourMastersIntro();
+
+ void HM_InitIntro();
+ void HM_TickIntro();
+ void HM_DrawIntro();
+private:
+ void Setup();
+ void Sync();
+ void Bob(FVector& pos, IRotator& rot, f32 bobAmp, f32 bobSpeed, f32 tiltAmp, f32 tiltSpeed, f32 rollAmp, f32 rollSpeed);
+ void SpagBob(FVector& pos, IRotator& rot, f32 bobAmp, f32 bobSpeed, f32 tiltAmp, f32 tiltSpeed, f32 rollAmp, f32 rollSpeed);
+ void MoveCloserToCamera(float moveSpeed);
+
+ struct HMCamera {
+ FVector Pos;
+ FVector LookAt;
+ };
+
+ HMCamera _camera;
+
+ f32 _cameraSpeed;
+ f32 _cameraMaxSpeed;
+ f32 _cameraAcceleration;
+
+ FVector _pos;
+ IRotator _rot;
+ FVector _scale;
+
+ FVector _shipPos;
+ IRotator _shipRot;
+
+ FVector _ship2Pos;
+ IRotator _ship2Rot;
+
+ s32 _water = 0;
+
+ FVector _posHM64;
+ IRotator _rotHM64;
+
+ FVector _hPos;
+ IRotator _hRot;
+ FVector _hScale;
+
+ FVector lusPos;
+ IRotator lusRot;
+ FVector lusScale;
+ int32_t DespawnValue = 0;
+};
+
+extern "C" {
+#endif
+
+void HM_InitIntro(void);
+void HM_TickIntro(void);
+void HM_DrawIntro(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _HM_INTRO_H \ No newline at end of file
diff --git a/src/engine/Matrix.cpp b/src/engine/Matrix.cpp
index 354389db9..1f2301258 100644
--- a/src/engine/Matrix.cpp
+++ b/src/engine/Matrix.cpp
@@ -4,6 +4,8 @@
extern "C" {
#include "common_structs.h"
+#include "math_util.h"
+#include "math_util_2.h"
}
void AddMatrix(std::vector<Mtx>& stack, Mat4 mtx, s32 flags) {
@@ -26,7 +28,7 @@ Mtx* GetMatrix(std::vector<Mtx>& stack) {
}
/**
- * Use GetMatrix first
+ * Use GetMatrix() first
*/
void AddMatrixFixed(std::vector<Mtx>& stack, s32 flags) {
// Load the matrix
@@ -58,6 +60,76 @@ Mtx* SetTextMatrix(f32 arg1, f32 arg2, f32 arg3, f32 arg4) {
return mtx;
}
+void ApplyMatrixTransformations(Mat4 mtx, FVector pos, IRotator rot, FVector scale) {
+ f32 sine1, cosine1;
+ f32 sine2, cosine2;
+ f32 sine3, cosine3;
+
+ // Compute the sine and cosine of the orientation (Euler angles)
+ sine1 = sins(rot.pitch);
+ cosine1 = coss(rot.pitch);
+ sine2 = sins(rot.yaw);
+ cosine2 = coss(rot.yaw);
+ sine3 = sins(rot.roll);
+ cosine3 = coss(rot.roll);
+
+ // Compute the rotation matrix
+ mtx[0][0] = (cosine2 * cosine3) + ((sine1 * sine2) * sine3);
+ mtx[1][0] = (-cosine2 * sine3) + ((sine1 * sine2) * cosine3);
+ mtx[2][0] = cosine1 * sine2;
+ mtx[3][0] = pos.x;
+
+ mtx[0][1] = cosine1 * sine3;
+ mtx[1][1] = cosine1 * cosine3;
+ mtx[2][1] = -sine1;
+ mtx[3][1] = pos.y;
+
+ mtx[0][2] = (-sine2 * cosine3) + ((sine1 * cosine2) * sine3);
+ mtx[1][2] = (sine2 * sine3) + ((sine1 * cosine2) * cosine3);
+ mtx[2][2] = cosine1 * cosine2;
+ mtx[3][2] = pos.z;
+
+ // Apply scaling
+ mtx[0][0] *= scale.x;
+ mtx[1][0] *= scale.x;
+ mtx[2][0] *= scale.x;
+ mtx[0][1] *= scale.y;
+ mtx[1][1] *= scale.y;
+ mtx[2][1] *= scale.y;
+ mtx[0][2] *= scale.z;
+ mtx[1][2] *= scale.z;
+ mtx[2][2] *= scale.z;
+
+ // Set the last row and column for the homogeneous coordinate system
+ mtx[0][3] = 0.0f;
+ mtx[1][3] = 0.0f;
+ mtx[2][3] = 0.0f;
+ mtx[3][3] = 1.0f;
+}
+
+void AddLocalRotation(Mat4 mat, IRotator rot) {
+ f32 sin_pitch = sins(rot.pitch);
+ f32 cos_pitch = coss(rot.pitch);
+ f32 sin_yaw = sins(rot.yaw);
+ f32 cos_yaw = coss(rot.yaw);
+ f32 sin_roll = sins(rot.roll);
+ f32 cos_roll = coss(rot.roll);
+
+ // Modify only the rotation part (keep translation intact)
+ mat[0][0] = (cos_yaw * cos_roll) + (sin_pitch * sin_yaw * sin_roll);
+ mat[0][1] = (cos_pitch * sin_roll);
+ mat[0][2] = (-sin_yaw * cos_roll) + (sin_pitch * cos_yaw * sin_roll);
+
+ mat[1][0] = (-cos_yaw * sin_roll) + (sin_pitch * sin_yaw * cos_roll);
+ mat[1][1] = (cos_pitch * cos_roll);
+ mat[1][2] = (sin_yaw * sin_roll) + (sin_pitch * cos_yaw * cos_roll);
+
+ mat[2][0] = (cos_pitch * sin_yaw);
+ mat[2][1] = -sin_pitch;
+ mat[2][2] = (cos_pitch * cos_yaw);
+}
+
+
// API
extern "C" {
@@ -122,3 +194,4 @@ extern "C" {
gWorldInstance.Mtx.Objects.clear();
}
}
+
diff --git a/src/engine/Matrix.h b/src/engine/Matrix.h
index f72af76c4..180ebfb16 100644
--- a/src/engine/Matrix.h
+++ b/src/engine/Matrix.h
@@ -4,9 +4,12 @@
#include <libultraship.h>
#include "common_structs.h"
+#include "CoreMath.h"
#ifdef __cplusplus
extern "C" {
+void ApplyMatrixTransformations(Mat4 mtx, FVector pos, IRotator rot, FVector scale);
+void AddLocalRotation(Mat4 mat, IRotator rot);
#endif
void ClearMatrixPools(void);
void AddHudMatrix(Mat4 mtx, s32 flags);
diff --git a/src/engine/Registry.cpp b/src/engine/Registry.cpp
new file mode 100644
index 000000000..0ea05c9d5
--- /dev/null
+++ b/src/engine/Registry.cpp
@@ -0,0 +1,59 @@
+// #include <vector>
+// #include <functional>
+// #include <iostream>
+// #include <map>
+
+// #include "Registry.h"
+// #include "Course.h"
+// #include "port/Game.h"
+
+// template <class T> Registry<T>::Registry() {
+// }
+
+// template <class T> void Registry<T>::Add(std::string id, std::function<T*()> fn) {
+// // need to handle duplicate registration
+// ContentVault[id] = fn;
+// }
+
+// template <class T>
+// void Registry<T>::AddArgs(std::string id) {
+// ArgsVault[id] = [](Args&&... args) -> T* {
+// return new T(std::forward<Args>(args)...);
+// };
+// }
+
+// template <class T>
+// T* Registry<T>::Get(std::string id) {
+// auto it = ContentVault.find(id);
+// if (it != ContentVault.end()) {
+// return it->second();
+// }
+// return nullptr;
+// }
+
+// // Available Registries
+// Registry<Course> Courses;
+// Registry<Cup> Cups;
+// Registry<AActor> Actors;
+
+// void AddCourse(std::string id, Course* course) {
+// Courses.Add(id, [course]() { return course; });
+// course->Id = id;
+// }
+
+// void AddCup(std::string id, Cup* cup) {
+// Cups.Add(id, [cup]() { return cup; });
+// //cup->Id = id;
+// }
+
+// void AddActor(std::string id, AActor* actor) {
+// Actors.Add(id, [actor]() { return actor; });
+// }
+
+// void AddStockContent() {
+// AddActor("mk:banana", new AMarioSign({0, 0, 0}));
+// }
+
+// template class Registry<Course>;
+// template class Registry<Cup>;
+// template class Registry<AActor>;
diff --git a/src/engine/Registry.h b/src/engine/Registry.h
new file mode 100644
index 000000000..f55818dc3
--- /dev/null
+++ b/src/engine/Registry.h
@@ -0,0 +1,33 @@
+// #pragma once
+
+// #include "Course.h"
+// #include "Cup.h"
+// #include <unordered_map>
+// #include "AllActors.h"
+// #include "Actor.h"
+// #include "objects/Object.h"
+
+// class AActor; // <-- Forward delare
+
+// template <class T> class Registry {
+// public:
+// Registry();
+// void Add(std::string name, std::function<T*()>);
+
+// template <typename... Args>
+// void AddArgs(std::string id);
+// T* Get(std::string id);
+// private:
+// std::unordered_map<std::string, std::function<T*()>> ContentVault;
+// std::map<std::string, std::function<T*(Args&&...)>> ArgsVault;
+// };
+
+// void AddCourse(std::string id, Course* course);
+// void AddCup(std::string id, Cup* cup);
+// void AddActor(std::string id, AActor* actor);
+
+// void AddStockContent();
+
+// extern Registry<Course> Courses;
+// extern Registry<Cup> Cups;
+// extern Registry<AActor> Actors;
diff --git a/src/engine/StaticMeshActor.cpp b/src/engine/StaticMeshActor.cpp
new file mode 100644
index 000000000..2e5fa1119
--- /dev/null
+++ b/src/engine/StaticMeshActor.cpp
@@ -0,0 +1,29 @@
+#include "StaticMeshActor.h"
+#include <libultra/gbi.h>
+#include "Matrix.h"
+
+extern "C" {
+#include "main.h"
+#include "math_util.h"
+#include "math_util_2.h"
+}
+
+StaticMeshActor::StaticMeshActor(std::string name, FVector pos, IRotator rot, FVector scale, std::string model, int32_t* collision) : Name(name), Pos(pos), Rot(rot), Scale(scale), Model(""), Collision(collision) {
+
+}
+
+void StaticMeshActor::Draw() {
+ Mat4 mtx;
+ gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
+ gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
+ if (!Model.empty()) {
+ ApplyMatrixTransformations(mtx, Pos, Rot, Scale);
+ if (render_set_position(mtx, 0) != 0) {
+ gSPDisplayList(gDisplayListHead++, (Gfx*)Model.c_str());
+ }
+ }
+}
+
+void StaticMeshActor::Destroy() {
+ bPendingDestroy = true;
+}
diff --git a/src/engine/StaticMeshActor.h b/src/engine/StaticMeshActor.h
new file mode 100644
index 000000000..4007aa2c1
--- /dev/null
+++ b/src/engine/StaticMeshActor.h
@@ -0,0 +1,61 @@
+#pragma once
+
+#include <libultraship.h>
+#include <libultra/gbi.h>
+#include "CoreMath.h"
+#include <nlohmann/json.hpp>
+
+// todo: Make this class AStaticMeshActor : public AActor
+class StaticMeshActor {
+public:
+ std::string Name;
+ FVector Pos;
+ IRotator Rot;
+ FVector Scale;
+ std::string Model;
+ int32_t* Collision;
+ bool bPendingDestroy = false;
+ StaticMeshActor(std::string name, FVector pos, IRotator rot, FVector scale, std::string model, int32_t* collision);
+
+ nlohmann::json to_json() const {
+ nlohmann::json j;
+
+ // Serialize each field of the class
+ j["Name"] = Name;
+ j["Position"] = {Pos.x, Pos.y, Pos.z}; // Assuming FVector has x, y, z fields
+ j["Rotation"] = {Rot.pitch, Rot.yaw, Rot.roll}; // Assuming IRotator has pitch, yaw, roll fields
+ j["Scale"] = {Scale.x, Scale.y, Scale.z}; // Assuming FVector has x, y, z fields
+ j["Model"] = Model;
+
+ // If Collision is not null, serialize it
+ if (Collision != nullptr) {
+ j["Collision"] = *Collision; // Serialize the value that Collision points to
+ } else {
+ j["Collision"] = nullptr; // Handle the case where Collision is nullptr
+ }
+
+ return j;
+ }
+
+ void from_json(const nlohmann::json& j) {
+ Name = j.at("Name").get<std::string>();
+ Pos = FVector(j.at("Position")[0].get<float>(), j.at("Position")[1].get<float>(), j.at("Position")[2].get<float>());
+ Rot.Set(j.at("Rotation")[0].get<uint16_t>(), j.at("Rotation")[1].get<uint16_t>(), j.at("Rotation")[2].get<uint16_t>());
+ Scale = FVector(j.at("Scale")[0].get<float>(), j.at("Scale")[1].get<float>(), j.at("Scale")[2].get<float>());
+
+ // Deserialize the Model string
+ Model = j.at("Model").get<std::string>();
+
+ // Check if Collision is present in the JSON and deserialize it
+ //if (j.contains("Collision") && !j["Collision"].is_null()) {
+ // If Collision is a valid value, allocate memory for it and assign the value
+ // Collision = new int32_t(j.at("Collision").get<int32_t>());
+ //} else {
+ // If Collision is not present or is null, set it to nullptr
+ Collision = nullptr;
+ //}
+ }
+
+ virtual void Draw();
+ virtual void Destroy();
+};
diff --git a/src/engine/World.cpp b/src/engine/World.cpp
index a63c22b10..8e20806ff 100644
--- a/src/engine/World.cpp
+++ b/src/engine/World.cpp
@@ -6,14 +6,19 @@
#include "TrainCrossing.h"
#include <memory>
#include "objects/Object.h"
+#include "port/Game.h"
+
+#include "editor/GameObject.h"
extern "C" {
- #include "camera.h"
- #include "objects.h"
- #include "main.h"
- #include "defines.h"
- #include "audio/external.h"
- #include "menus.h"
+#include "camera.h"
+#include "objects.h"
+#include "main.h"
+#include "defines.h"
+#include "audio/external.h"
+#include "menus.h"
+#include "common_data.h"
+#include "mario_raceway_data.h"
}
World::World() {}
@@ -112,15 +117,34 @@ void World::PreviousCourse() {
AActor* World::AddActor(AActor* actor) {
Actors.push_back(actor);
+
+ if (actor->Model != NULL) {
+ gEditor.AddObject(actor->Name, (FVector*) &actor->Pos, (IRotator*)&actor->Rot, &actor->Scale,
+ (Gfx*) LOAD_ASSET_RAW(actor->Model), 1.0f, Editor::GameObject::CollisionType::VTX_INTERSECT,
+ 0.0f, (int32_t*) &actor->Type, 0);
+ } else {
+ gEditor.AddObject(actor->Name, (FVector*) &actor->Pos, (IRotator*)&actor->Rot, &actor->Scale, nullptr, 1.0f, Editor::GameObject::CollisionType::VTX_INTERSECT, 0.0f, (int32_t*)&actor->Type, 0);
+ }
return Actors.back();
}
struct Actor* World::AddBaseActor() {
Actors.push_back(new AActor());
+
+ AActor* actor = Actors.back();
+
// Skip C++ vtable to access variables in C
return reinterpret_cast<struct Actor*>(reinterpret_cast<char*>(Actors.back()) + sizeof(void*));
}
+void World::AddEditorObject(Actor* actor, const char* name) {
+ if (actor->model != NULL) {
+ gEditor.AddObject(name, (FVector*) &actor->pos, (IRotator*)&actor->rot, nullptr, (Gfx*)LOAD_ASSET_RAW(actor->model), 1.0f, Editor::GameObject::CollisionType::VTX_INTERSECT, 0.0f, (int32_t*)&actor->type, 0);
+ } else {
+ gEditor.AddObject(name, (FVector*) &actor->pos, (IRotator*)&actor->rot, nullptr, nullptr, 1.0f, Editor::GameObject::CollisionType::VTX_INTERSECT, 0.0f, (int32_t*)&actor->type, 0);
+ }
+}
+
/**
* Converts a C struct Actor* to its C++ AActor class
*/
@@ -153,8 +177,44 @@ void World::TickActors() {
}
}
+StaticMeshActor* World::AddStaticMeshActor(std::string name, FVector pos, IRotator rot, FVector scale, std::string model, int32_t* collision) {
+ StaticMeshActors.push_back(new StaticMeshActor(name, pos, rot, scale, model, collision));
+ auto actor = StaticMeshActors.back();
+ auto gameObj = gEditor.AddObject(actor->Name.c_str(), &actor->Pos, &actor->Rot, &actor->Scale, (Gfx*) LOAD_ASSET_RAW(actor->Model.c_str()), 1.0f,
+ Editor::GameObject::CollisionType::VTX_INTERSECT, 0.0f, (int32_t*) &actor->bPendingDestroy, (int32_t) true);
+ return actor;
+}
+
+void World::DrawStaticMeshActors() {
+ for (const auto& actor: StaticMeshActors) {
+ actor->Draw();
+ }
+}
+
+void World::DeleteStaticMeshActors() {
+ for (auto it = StaticMeshActors.begin(); it != StaticMeshActors.end();) {
+ if ((*it)->bPendingDestroy) {
+ delete *it; // Deallocate memory for the actor
+ it = StaticMeshActors.erase(it); // Remove the pointer from the vector
+ } else {
+ ++it; // Only increment the iterator if we didn't erase an element
+ }
+ }
+}
+
OObject* World::AddObject(OObject* object) {
Objects.push_back(object);
+
+ if (object->_objectIndex != -1) {
+ Object* cObj = &gObjectList[object->_objectIndex];
+
+ if (cObj->model != NULL) {
+ gEditor.AddObject(object->Name, (FVector*) &cObj->origin_pos[0], (IRotator*)&cObj->orientation, nullptr, (Gfx*)LOAD_ASSET_RAW(cObj->model), 1.0f, Editor::GameObject::CollisionType::VTX_INTERSECT, 0.0f, &object->_objectIndex, -1);
+ } else {
+ gEditor.AddObject(object->Name, (FVector*) &cObj->origin_pos[0], (IRotator*)&cObj->orientation, nullptr, nullptr, 1.0f, Editor::GameObject::CollisionType::VTX_INTERSECT, 0.0f, &object->_objectIndex, -1);
+ }
+ }
+
return Objects.back();
}
@@ -209,3 +269,15 @@ Object* World::GetObjectByIndex(size_t index) {
//}
return nullptr; // Or handle the error as needed
}
+
+void World::ClearWorld(void) {
+ World::DeleteStaticMeshActors();
+ CM_CleanWorld();
+
+ // for (size_t i = 0; i < ARRAY_COUNT(gCollisionMesh); i++) {
+
+ // }
+
+ // gCollisionMesh
+ // Paths
+}
diff --git a/src/engine/World.h b/src/engine/World.h
index 9490293b7..bb8979090 100644
--- a/src/engine/World.h
+++ b/src/engine/World.h
@@ -18,20 +18,26 @@
#include <memory>
#include <unordered_map>
#include "Actor.h"
+#include "StaticMeshActor.h"
#include "particles/ParticleEmitter.h"
+#include "editor/Editor.h"
+#include "editor/GameObject.h"
+
extern "C" {
#include "camera.h"
#include "objects.h"
};
-class OObject;
class Cup; // <-- Forward declaration
+class OObject;
class Course;
+class StaticMeshActor;
class AVehicle;
class OBombKart;
class TrainCrossing;
class OLakitu;
+class GameObject; // <-- Editor
class World {
typedef struct {
@@ -49,12 +55,17 @@ public:
AActor* AddActor(AActor* actor);
struct Actor* AddBaseActor();
+ void AddEditorObject(Actor* actor, const char* name);
AActor* GetActor(size_t index);
void TickActors();
AActor* ConvertActorToAActor(Actor* actor);
Actor* ConvertAActorToActor(AActor* actor);
+ void DrawStaticMeshActors();
+ StaticMeshActor* AddStaticMeshActor(std::string name, FVector pos, IRotator rot, FVector scale, std::string model, int32_t* collision);
+ void DeleteStaticMeshActors();
+
OObject* AddObject(OObject* object);
void TickObjects();
@@ -76,6 +87,7 @@ public:
void SetCourseFromCup();
World* GetWorld(void);
+ void ClearWorld(void);
// These are only for browsing through the course list
@@ -85,7 +97,6 @@ public:
Matrix Mtx;
- // Holds all available courses
Course* CurrentCourse;
Cup* CurrentCup;
@@ -93,6 +104,7 @@ public:
std::vector<Cup*> Cups;
size_t CupIndex = 1;
+ std::vector<StaticMeshActor*> StaticMeshActors;
std::vector<AActor*> Actors;
std::vector<OObject*> Objects;
std::vector<ParticleEmitter*> Emitters;
@@ -105,6 +117,7 @@ public:
TrainCrossing* AddCrossing(Vec3f position, u32 waypointMin, u32 waypointMax, f32 approachRadius, f32 exitRadius);
std::vector<std::shared_ptr<TrainCrossing>> Crossings;
+ // Holds all available courses
std::vector<Course*> Courses;
size_t CourseIndex = 0; // For browsing courses.
private:
diff --git a/src/engine/actors/ABanana.cpp b/src/engine/actors/Banana.cpp
index d484ab983..6c7f837d1 100644
--- a/src/engine/actors/ABanana.cpp
+++ b/src/engine/actors/Banana.cpp
@@ -1,6 +1,6 @@
#include <libultraship.h>
-#include "ABanana.h"
+#include "Banana.h"
#include "engine/Actor.h"
extern "C" {
@@ -11,6 +11,7 @@ void render_actor_banana(Camera*, float[4][4], struct BananaActor*);
}
ABanana::ABanana(uint16_t playerId, const float pos[3], const s16 rot[3], const float velocity[3]) {
+ Name = "Banana";
// Initialize the BananaActor's position, rotation, and velocity
std::copy(pos, pos + 3, Pos);
//std::copy(rot, rot + 3, this->a.rot);
diff --git a/src/engine/actors/ABanana.h b/src/engine/actors/Banana.h
index 0da9eb98f..d8c55e9cb 100644
--- a/src/engine/actors/ABanana.h
+++ b/src/engine/actors/Banana.h
@@ -10,7 +10,6 @@ public:
// Constructor
ABanana(uint16_t playerId, const float pos[3], const s16 rot[3], const float velocity[3]);
-
virtual ~ABanana() override = default;
// Virtual functions to be overridden by derived classes
diff --git a/src/engine/actors/BowserStatue.cpp b/src/engine/actors/BowserStatue.cpp
index de448de5e..c680c4c25 100644
--- a/src/engine/actors/BowserStatue.cpp
+++ b/src/engine/actors/BowserStatue.cpp
@@ -13,6 +13,7 @@ Vtx gBowserStatueVtx[717];
Gfx gBowserStatueGfx[162];
ABowserStatue::ABowserStatue(FVector pos, ABowserStatue::Behaviour behaviour) {
+ Name = "Bowser Statue";
Pos = pos;
ABowserStatue::Behaviour _behaviour = behaviour;
}
diff --git a/src/engine/actors/ACloud.cpp b/src/engine/actors/Cloud.cpp
index d3eaad32d..cae55e342 100644
--- a/src/engine/actors/ACloud.cpp
+++ b/src/engine/actors/Cloud.cpp
@@ -1,6 +1,6 @@
#include <libultraship.h>
-#include "ACloud.h"
+#include "Cloud.h"
#include "engine/Actor.h"
#include "World.h"
@@ -14,10 +14,11 @@ extern f32 gKartHopInitialVelocityTable[];
extern f32 gKartGravityTable[];
}
-ACloud::ACloud(Vec3f pos) {
- Pos[0] = pos[0];
- Pos[1] = pos[1];
- Pos[2] = pos[2];
+ACloud::ACloud(FVector pos) {
+ Name = "Cloud";
+ Pos[0] = pos.x;
+ Pos[1] = pos.y;
+ Pos[2] = pos.z;
Rot[0] = 0;
Rot[1] = 0;
Rot[2] = 0;
diff --git a/src/engine/actors/ACloud.h b/src/engine/actors/Cloud.h
index 3d266243c..4805c08b9 100644
--- a/src/engine/actors/ACloud.h
+++ b/src/engine/actors/Cloud.h
@@ -2,6 +2,7 @@
#include <libultraship.h>
#include "engine/Actor.h"
+#include "CoreMath.h"
extern "C" {
#include "macros.h"
@@ -15,7 +16,7 @@ public:
// Constructor
- ACloud(Vec3f pos);
+ ACloud(FVector pos);
virtual ~ACloud() override = default;
diff --git a/src/engine/actors/AFinishline.cpp b/src/engine/actors/Finishline.cpp
index 77dd37ede..0680e60bd 100644
--- a/src/engine/actors/AFinishline.cpp
+++ b/src/engine/actors/Finishline.cpp
@@ -2,7 +2,7 @@
#include <libultra/gbi.h>
#include "CoreMath.h"
-#include "AFinishline.h"
+#include "Finishline.h"
#include "engine/Actor.h"
#include "World.h"
#include "assets/common_data.h"
@@ -18,6 +18,7 @@ extern f32 gKartGravityTable[];
}
AFinishline::AFinishline(std::optional<FVector> pos) {
+ Name = "Finishline";
if (pos.has_value()) {
// Set spawn point to the provided position
diff --git a/src/engine/actors/AFinishline.h b/src/engine/actors/Finishline.h
index 61b561a5e..61b561a5e 100644
--- a/src/engine/actors/AFinishline.h
+++ b/src/engine/actors/Finishline.h
diff --git a/src/engine/actors/MarioSign.cpp b/src/engine/actors/MarioSign.cpp
new file mode 100644
index 000000000..f39e4f69b
--- /dev/null
+++ b/src/engine/actors/MarioSign.cpp
@@ -0,0 +1,56 @@
+#include "MarioSign.h"
+
+#include <libultra/gbi.h>
+#include <assets/mario_raceway_data.h>
+
+extern "C" {
+#include "common_structs.h"
+#include "math_util.h"
+#include "main.h"
+#include "actor_types.h"
+}
+
+AMarioSign::AMarioSign(FVector pos) {
+ Type = ACTOR_MARIO_SIGN;
+ Name = "Mario Sign";
+ Pos[0] = pos.x;
+ Pos[1] = pos.y;
+ Pos[2] = pos.z;
+ Flags |= 0x4000;
+}
+
+void AMarioSign::Tick() {
+ if ((Flags & 0x800) == 0) {
+ if ((Flags & 0x400) != 0) {
+ Pos[1] += 4.0f;
+ if (Pos[1] > 800.0f) {
+ Flags |= 0x800;
+ Rot[1] += 1820;
+ }
+ } else {
+ Rot[1] += 182;
+ }
+ }
+}
+
+void AMarioSign::Draw(Camera *camera) {
+ Mat4 sp40;
+ f32 unk;
+
+ if (Flags & 0x800) {
+ return;
+ }
+
+ unk = is_within_render_distance(camera->pos, Pos, camera->rot[1], 0, gCameraZoom[camera - camera1], 16000000.0f);
+ if (CVarGetInteger("gNoCulling", 0) == 1) {
+ unk = MAX(unk, 0.0f);
+ }
+ if (!(unk < 0.0f)) {
+ gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
+ gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
+ mtxf_pos_rotation_xyz(sp40, Pos, Rot);
+ if (render_set_position(sp40, 0) != 0) {
+ gSPDisplayList(gDisplayListHead++, (Gfx*)d_course_mario_raceway_dl_sign);
+ }
+ }
+}
diff --git a/src/engine/actors/MarioSign.h b/src/engine/actors/MarioSign.h
new file mode 100644
index 000000000..099894dc1
--- /dev/null
+++ b/src/engine/actors/MarioSign.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include <libultraship.h>
+#include "engine/Actor.h"
+#include "CoreMath.h"
+
+extern "C" {
+#include "common_structs.h"
+}
+
+class AMarioSign : public AActor {
+public:
+
+ virtual ~AMarioSign() = default;
+ explicit AMarioSign(FVector pos);
+
+ virtual void Tick() override;
+ virtual void Draw(Camera*) override;
+};
diff --git a/src/engine/actors/Ship.cpp b/src/engine/actors/Ship.cpp
index 148b883eb..5af3553e2 100644
--- a/src/engine/actors/Ship.cpp
+++ b/src/engine/actors/Ship.cpp
@@ -1,6 +1,8 @@
#include "Ship.h"
#include <libultra/gbi.h>
+#include "CoreMath.h"
+#include "Matrix.h"
extern "C" {
#include "common_structs.h"
@@ -14,48 +16,41 @@ extern "C" {
AShip::AShip(FVector pos, AShip::Skin skin) {
Spawn = pos;
Spawn.y += 10;
-
+ Pos[0] = pos.x;
+ Pos[1] = pos.y;
+ Pos[2] = pos.z;
+ Scale = FVector(0.4, 0.4, 0.4);
+
switch(skin) {
case GHOSTSHIP:
+ Name = "Ghostship";
_skin = ghostship_Plane_mesh;
break;
case SHIP2:
+ Name = "Ship_1";
_skin = ship2_SoH_mesh;
break;
case SHIP3:
+ Name = "Ship_2";
_skin = ship3_2Ship_mesh;
break;
}
+ Model = _skin;
}
void AShip::Tick() {
- static float angle = 0.0f; // Keeps track of the ship's rotation around the circle
- float radius = 150.0f; // The radius of the circular path
- float speed = 0.01f; // Speed of rotation
-
- angle += speed; // Increment the angle to move in a circle
-
- // Update the position based on a circular path
- Pos.x = Spawn.x + radius * cosf(angle);
- Pos.z = Spawn.z + radius * sinf(angle);
+ // static float angle = 0.0f; // Keeps track of the ship's rotation around the circle
+ // float radius = 150.0f; // The radius of the circular path
+ // float speed = 0.01f; // Speed of rotation
- // Rotate to face forward along the circle
- Rot.yaw = -static_cast<int16_t>(angle * (32768.0f / M_PI / 2.0f));
-}
-
-void AShip::Draw(Camera *camera) {
- Mat4 shipMtx;
- Vec3f hullPos = {Pos.x, Pos.y, Pos.z};
- Vec3s hullRot = {Rot.pitch, Rot.yaw, Rot.roll};
+ // angle += speed; // Increment the angle to move in a circle
- gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
- gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
+ // // Update the position based on a circular path
+ // Pos.x = Spawn.x + radius * cosf(angle);
+ // Pos.z = Spawn.z + radius * sinf(angle);
- mtxf_pos_rotation_xyz(shipMtx, hullPos, hullRot);
- mtxf_scale(shipMtx, 0.4);
- if (render_set_position(shipMtx, 0) != 0) {
- gSPDisplayList(gDisplayListHead++, _skin);
- }
+ // // Rotate to face forward along the circle
+ // Rot.yaw = -static_cast<int16_t>(angle * (32768.0f / M_PI / 2.0f));
}
bool AShip::IsMod() { return true; }
diff --git a/src/engine/actors/Ship.h b/src/engine/actors/Ship.h
index 59ceb68a8..fe5743922 100644
--- a/src/engine/actors/Ship.h
+++ b/src/engine/actors/Ship.h
@@ -23,12 +23,12 @@ public:
virtual ~AShip() = default;
virtual void Tick() override;
- virtual void Draw(Camera*) override;
virtual bool IsMod() override;
FVector Spawn;
- FVector Pos;
- FRotation Rot = {0, 0, 0};
+ //FVector Pos;
+ ///IRotator Rot = {0, 0, 0};
+ //FVector Scale = {0.4, 0.4, 0.4};
private:
Gfx* _skin;
};
diff --git a/src/engine/actors/SpaghettiShip.cpp b/src/engine/actors/SpaghettiShip.cpp
index d53b90f07..b09ada319 100644
--- a/src/engine/actors/SpaghettiShip.cpp
+++ b/src/engine/actors/SpaghettiShip.cpp
@@ -1,6 +1,7 @@
#include "SpaghettiShip.h"
#include <libultra/gbi.h>
+#include "Matrix.h"
extern "C" {
#include "common_structs.h"
@@ -10,8 +11,13 @@ extern "C" {
}
ASpaghettiShip::ASpaghettiShip(FVector pos) {
+ Name = "Spaghetti Ship";
+ Pos[0] = pos.x;
+ Pos[1] = pos.y;
+ Pos[2] = pos.z;
Spawn = pos;
Spawn.y += 10;
+ Scale = {0.4, 0.4, 0.4};
}
void ASpaghettiShip::Tick() {
@@ -22,12 +28,11 @@ void ASpaghettiShip::Tick() {
angle += speed; // Increment the angle to move in a circle
// Update the position based on a circular path
- Pos.x = Spawn.x + radius * cosf(angle);
- Pos.z = Spawn.z + radius * sinf(angle);
+ Pos[0] = Spawn.x + radius * cosf(angle);
+ Pos[2] = Spawn.z + radius * sinf(angle);
// Rotate to face forward along the circle
- Rot.yaw = -static_cast<int16_t>(angle * (32768.0f / M_PI / 2.0f));
-
+ Rot[1] = -static_cast<int16_t>(angle * (32768.0f / M_PI / 2.0f));
WheelRot.pitch += 500;
}
@@ -36,30 +41,27 @@ void ASpaghettiShip::Draw(Camera *camera) {
Mat4 shipMtx;
Mat4 objectMtx;
Mat4 resultMtx;
- Vec3f hullPos = {Pos.x, Pos.y, Pos.z};
- Vec3s hullRot = {Rot.pitch, Rot.yaw, Rot.roll};
+ Vec3f hullPos = {Pos[0], Pos[1], Pos[2]};
+ Vec3s hullRot = {Rot[0], Rot[1], Rot[2]};
Vec3s rot = {WheelRot.pitch, WheelRot.yaw, WheelRot.roll};
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
- // empty/null mtx as a base
- mtxf_pos_rotation_xyz(shipMtx, hullPos, hullRot);
- mtxf_scale(shipMtx, 0.4);
+ ApplyMatrixTransformations(shipMtx, *(FVector*)Pos, *(IRotator*)Rot, Scale);
if (render_set_position(shipMtx, 0) != 0) {}
// Render the ships hull
- Vec3f hullPos2 = {0, 0, 0};
- mtxf_translate(objectMtx, hullPos2);
+ ApplyMatrixTransformations(objectMtx, {0, 0, 0}, {0, 0, 0}, {1, 1, 1});
mtxf_multiplication(resultMtx, shipMtx, objectMtx);
if (render_set_position(resultMtx, 3) != 0) {
- gSPDisplayList(gDisplayListHead++, ship1_Spaghetti_mesh);
+ gSPDisplayList(gDisplayListHead++, ship1_spag1_mesh);
}
// Front tyre
- Vec3f pos = {0, 0, 110};
- mtxf_rotate_x(shipMtx, WheelRot.pitch);
- mtxf_translate(objectMtx, pos);
+ ApplyMatrixTransformations(objectMtx, FVector(0, 0, 110), IRotator(0, 0, 0), FVector(1, 1, 1));
+ mtxf_identity(shipMtx);
+ AddLocalRotation(shipMtx, WheelRot);
mtxf_multiplication(resultMtx, shipMtx, objectMtx);
if (render_set_position(resultMtx, 3) != 0) {
gSPDisplayList(gDisplayListHead++, wheels_Spaghetti_002_mesh);
@@ -67,9 +69,8 @@ void ASpaghettiShip::Draw(Camera *camera) {
}
// Back tyre
- Vec3f pos2 = {0, 0, -165};
- mtxf_rotate_x(shipMtx, WheelRot.pitch);
- mtxf_translate(objectMtx, pos2);
+ AddLocalRotation(shipMtx, WheelRot);
+ ApplyMatrixTransformations(objectMtx, FVector(0, 0, -165), {0, 0, 0}, {1, 1, 1});
mtxf_multiplication(resultMtx, shipMtx, objectMtx);
if (render_set_position(resultMtx, 3) != 0) {
gSPDisplayList(gDisplayListHead++, wheels_Spaghetti_002_mesh);
diff --git a/src/engine/actors/SpaghettiShip.h b/src/engine/actors/SpaghettiShip.h
index 1d0d656c5..70bd047d7 100644
--- a/src/engine/actors/SpaghettiShip.h
+++ b/src/engine/actors/SpaghettiShip.h
@@ -20,9 +20,5 @@ public:
virtual bool IsMod() override;
FVector Spawn;
- FVector Pos;
- FRotation Rot = {0, 0, 0};
- FRotation WheelRot = {0, 0, 0};
-private:
- f32 scale;
+ IRotator WheelRot = {0, 0, 0};
};
diff --git a/src/engine/actors/Starship.cpp b/src/engine/actors/Starship.cpp
index bc201b84a..e104d0eb6 100644
--- a/src/engine/actors/Starship.cpp
+++ b/src/engine/actors/Starship.cpp
@@ -1,6 +1,7 @@
#include "Starship.h"
#include <libultra/gbi.h>
+#include "Matrix.h"
extern "C" {
#include "common_structs.h"
@@ -10,7 +11,11 @@ extern "C" {
}
AStarship::AStarship(FVector pos) {
+ Name = "Starship";
Spawn = pos;
+ SetLocation(pos);
+ Scale = FVector(1.5, 1.5, 1.5);
+ Model = starship_Cube_mesh;
}
void AStarship::Tick() {
@@ -21,29 +26,17 @@ void AStarship::Tick() {
angle += speed;
// Move relative to the initial position
- Pos.x = Spawn.x + radius * cosf(angle);
- Pos.z = Spawn.z + radius * sinf(angle);
+
+ FVector pos = GetLocation();
+ pos.x = Spawn.x + radius * cosf(angle);
+ pos.z = Spawn.z + radius * sinf(angle);
+ SetLocation(pos);
// Keep y from changing (or adjust it if necessary)
- Pos.y = Spawn.y;
+ //Pos.y = Spawn.y;
// Rotate to face forward along the circle
- Rot.yaw = angle * (180.0f / M_PI) + 90.0f;
-}
-
-void AStarship::Draw(Camera *camera) {
- Mat4 shipMtx;
- Vec3f hullPos = {Pos.x, Pos.y, Pos.z};
- Vec3s hullRot = {Rot.pitch, Rot.yaw, Rot.roll};
-
- gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
- gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
-
- mtxf_pos_rotation_xyz(shipMtx, hullPos, hullRot);
- mtxf_scale(shipMtx, 1.5);
- if (render_set_position(shipMtx, 0) != 0) {
- gSPDisplayList(gDisplayListHead++, starship_Cube_mesh);
- }
+ Rot[1] = angle * (180.0f / M_PI) + 90.0f;
}
bool AStarship::IsMod() { return true; }
diff --git a/src/engine/actors/Starship.h b/src/engine/actors/Starship.h
index 390aed2ea..71b898358 100644
--- a/src/engine/actors/Starship.h
+++ b/src/engine/actors/Starship.h
@@ -16,10 +16,7 @@ public:
virtual ~AStarship() = default;
virtual void Tick() override;
- virtual void Draw(Camera*) override;
virtual bool IsMod() override;
FVector Spawn;
- FVector Pos;
- FRotation Rot = {0, 0, 0};
};
diff --git a/src/engine/actors/ATree.cpp b/src/engine/actors/Tree.cpp
index fa1c7f580..faffd0798 100644
--- a/src/engine/actors/ATree.cpp
+++ b/src/engine/actors/Tree.cpp
@@ -1,4 +1,4 @@
-#include "ATree.h"
+#include "Tree.h"
#include <libultra/gbi.h>
@@ -10,6 +10,7 @@ extern "C" {
}
ATree::ATree(Vec3f pos, Gfx* displaylist, f32 drawDistance, f32 minDrawDistance, const char* tlut = nullptr) {
+ Name = "Tree";
Pos[0] = pos[0];
Pos[1] = pos[1];
Pos[2] = pos[2];
diff --git a/src/engine/actors/ATree.h b/src/engine/actors/Tree.h
index eb51f6e7e..eb51f6e7e 100644
--- a/src/engine/actors/ATree.h
+++ b/src/engine/actors/Tree.h
diff --git a/src/engine/actors/AWarioSign.cpp b/src/engine/actors/WarioSign.cpp
index 8e73a94f3..0e83e114f 100644
--- a/src/engine/actors/AWarioSign.cpp
+++ b/src/engine/actors/WarioSign.cpp
@@ -1,4 +1,4 @@
-#include "AWarioSign.h"
+#include "WarioSign.h"
#include <libultra/gbi.h>
#include <assets/wario_stadium_data.h>
@@ -7,12 +7,15 @@ extern "C" {
#include "common_structs.h"
#include "math_util.h"
#include "main.h"
+#include "actor_types.h"
}
-AWarioSign::AWarioSign(Vec3f pos) {
- Pos[0] = pos[0];
- Pos[1] = pos[1];
- Pos[2] = pos[2];
+AWarioSign::AWarioSign(FVector pos) {
+ Type = ACTOR_WARIO_SIGN;
+ Name = "Wario Sign";
+ Pos[0] = pos.x;
+ Pos[1] = pos.y;
+ Pos[2] = pos.z;
}
void AWarioSign::Tick() {
@@ -27,7 +30,6 @@ void AWarioSign::Draw(Camera *camera) {
if (CVarGetInteger("gNoCulling", 0) == 1) {
unk = MAX(unk, 0.0f);
}
-
if (!(unk < 0.0f)) {
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
diff --git a/src/engine/actors/AWarioSign.h b/src/engine/actors/WarioSign.h
index 31d9b9434..634b2132e 100644
--- a/src/engine/actors/AWarioSign.h
+++ b/src/engine/actors/WarioSign.h
@@ -2,6 +2,7 @@
#include <libultraship.h>
#include "engine/Actor.h"
+#include "CoreMath.h"
extern "C" {
#include "common_structs.h"
@@ -10,9 +11,8 @@ extern "C" {
class AWarioSign : public AActor {
public:
-
virtual ~AWarioSign() = default;
- explicit AWarioSign(Vec3f pos);
+ explicit AWarioSign(FVector pos);
virtual void Tick() override;
virtual void Draw(Camera*) override;
diff --git a/src/engine/courses/BansheeBoardwalk.cpp b/src/engine/courses/BansheeBoardwalk.cpp
index 5ebaf2bc1..51049fb8d 100644
--- a/src/engine/courses/BansheeBoardwalk.cpp
+++ b/src/engine/courses/BansheeBoardwalk.cpp
@@ -5,7 +5,7 @@
#include "BansheeBoardwalk.h"
#include "World.h"
-#include "engine/actors/AFinishline.h"
+#include "engine/actors/Finishline.h"
#include "engine/objects/BombKart.h"
#include "engine/objects/CheepCheep.h"
#include "engine/objects/TrashBin.h"
@@ -35,6 +35,7 @@ extern "C" {
#include "collision.h"
#include "memory.h"
#include "course_offsets.h"
+ #include "course.h"
extern const char *banshee_boardwalk_dls[];
}
@@ -69,17 +70,26 @@ BansheeBoardwalk::BansheeBoardwalk() {
this->gfx = d_course_banshee_boardwalk_packed_dls;
this->gfxSize = 3689;
Props.textures = banshee_boardwalk_textures;
- Props.MinimapTexture = gTextureCourseOutlineBansheeBoardwalk;
- Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
+ Props.Minimap.Texture = gTextureCourseOutlineBansheeBoardwalk;
+ Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
+ Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
+ Props.Minimap.Pos[0].X = 262;
+ Props.Minimap.Pos[0].Y = 170;
+ Props.Minimap.PlayerX = 55;
+ Props.Minimap.PlayerY = 39;
+ Props.Minimap.PlayerScaleFactor = 0.016f;
+ Props.Minimap.FinishlineX = 0;
+ Props.Minimap.FinishlineY = 0;
+
+ Id = "mk:banshee_boardwalk";
+
+ Props.SetText(Props.Name, "banshee boardwalk", sizeof(Props.Name));
+ Props.SetText(Props.DebugName, "ghost", sizeof(Props.DebugName));
+ Props.SetText(Props.CourseLength, "747m", sizeof(Props.CourseLength));
- Props.Id = "mk:banshee_boardwalk";
- Props.Name = "banshee boardwalk";
- Props.DebugName = "ghost";
- Props.CourseLength = "747m";
Props.AIBehaviour = D_0D009058;
Props.AIMaximumSeparation = 40.0f;
Props.AIMinimumSeparation = 0.4f;
- Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
Props.NearPersp = 2.0f;
@@ -119,8 +129,6 @@ BansheeBoardwalk::BansheeBoardwalk() {
Props.Clouds = NULL; // no clouds
Props.CloudList = NULL;
- Props.MinimapFinishlineX = 0;
- Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {0, 0, 0};
Props.Skybox.BottomRight = {0, 0, 0};
@@ -131,6 +139,8 @@ BansheeBoardwalk::BansheeBoardwalk() {
Props.Skybox.FloorBottomLeft = {0, 0, 0};
Props.Skybox.FloorTopLeft = {0, 0, 0};
Props.Sequence = MusicSeq::MUSIC_SEQ_BANSHEE_BOARDWALK;
+
+ Props.WaterLevel = -80.0f;
}
void BansheeBoardwalk::Load() {
@@ -140,10 +150,9 @@ void BansheeBoardwalk::Load() {
D_801625EC = 0;
D_801625F4 = 0;
D_801625F0 = 0;
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_banshee_boardwalk_track_sections));
+ parse_course_displaylists((TrackSections*)LOAD_ASSET_RAW(d_course_banshee_boardwalk_track_sections));
func_80295C6C();
find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07000878), 128, 0, 0, 0);
- D_8015F8E4 = -80.0f;
}
void BansheeBoardwalk::LoadTextures() {
@@ -163,19 +172,19 @@ void BansheeBoardwalk::BeginPlay() {
}
if (gIsMirrorMode) {
- gWorldInstance.AddObject(new OTrashBin(FVector(1765.0f, 45.0f, 195.0f), FRotation(0, 180.0f, 0), 1.0f, bhv));
+ gWorldInstance.AddObject(new OTrashBin(FVector(1765.0f, 45.0f, 195.0f), IRotator(0, 180, 0), 1.0f, bhv));
} else {
- gWorldInstance.AddObject(new OTrashBin(FVector(-1765.0f, 45.0f, 70.0f), FRotation(0, 0, 0), 1.0f, bhv));
+ gWorldInstance.AddObject(new OTrashBin(FVector(-1765.0f, 45.0f, 70.0f), IRotator(0, 0, 0), 1.0f, bhv));
}
if ((gGamestate != CREDITS_SEQUENCE) && (gModeSelection != TIME_TRIALS)) {
- gWorldInstance.AddObject(new OBat(FVector(0,0,0), FRotation(0, 0, 90.0f)));
+ gWorldInstance.AddObject(new OBat(FVector(0,0,0), IRotator(0, 0, 90)));
gWorldInstance.AddObject(new OBoos(5, IPathSpan(180, 190), IPathSpan(200, 210), IPathSpan(280, 290)));
gWorldInstance.AddObject(new OBoos(5, IPathSpan(490, 500), IPathSpan(510, 520), IPathSpan(620, 630)));
}
if (gModeSelection == VERSUS) {
- Vec3f pos = {0, 0, 0};
+ FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][110], 110, 3, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][190], 190, 1, 0.8333333f));
@@ -187,15 +196,6 @@ void BansheeBoardwalk::BeginPlay() {
}
}
-// Likely sets minimap boundaries
-void BansheeBoardwalk::MinimapSettings() {
- D_80165880 = dma_textures((const char*)gTextureGhosts, 0x4CC2, 0xD980);
- D_8018D2A0 = 0.016f;
- D_8018D2C0[0] = 0x0106;
- D_8018D2E0 = 55;
- D_8018D2E8 = 39;
-}
-
void BansheeBoardwalk::InitCourseObjects() {
size_t objectId = 0;
if (gGamestate != CREDITS_SEQUENCE) {
@@ -253,12 +253,6 @@ void BansheeBoardwalk::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
-// Positions the finishline on the minimap
-void BansheeBoardwalk::MinimapFinishlinePosition() {
- //! todo: Place hard-coded values here.
- draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
-}
-
void BansheeBoardwalk::Render(struct UnkStruct_800DC5EC* arg0) {
Camera* camera = arg0->camera;
Mat4 spCC;
@@ -322,8 +316,6 @@ void BansheeBoardwalk::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_banshee_boardwalk_dl_B308));
}
-void BansheeBoardwalk::Collision() {}
-
void BansheeBoardwalk::ScrollingTextures() {
D_802B87BC++;
diff --git a/src/engine/courses/BansheeBoardwalk.h b/src/engine/courses/BansheeBoardwalk.h
index f1b98538d..cc5b72213 100644
--- a/src/engine/courses/BansheeBoardwalk.h
+++ b/src/engine/courses/BansheeBoardwalk.h
@@ -28,17 +28,14 @@ public:
virtual void LoadTextures() override;
virtual void BeginPlay() override;
//virtual void InitClouds() override;
- virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void UpdateCourseObjects() override;
virtual void RenderCourseObjects(s32 cameraId) override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
- virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
- virtual void Collision() override;
virtual void ScrollingTextures() override;
virtual void Waypoints(Player*, int8_t) override;
virtual void DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) override;
diff --git a/src/engine/courses/BigDonut.cpp b/src/engine/courses/BigDonut.cpp
index 5bdf76a23..4e99828eb 100644
--- a/src/engine/courses/BigDonut.cpp
+++ b/src/engine/courses/BigDonut.cpp
@@ -43,16 +43,24 @@ BigDonut::BigDonut() {
this->gfx = d_course_big_donut_packed_dls;
this->gfxSize = 528;
Props.textures = big_donut_textures;
- Props.MinimapTexture = gTextureCourseOutlineBigDonut;
- Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
+ Props.Minimap.Texture = gTextureCourseOutlineBigDonut;
+ Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
+ Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
+ Props.Minimap.Pos[0].X = 257;
+ Props.Minimap.Pos[0].Y = 170;
+ Props.Minimap.PlayerX = 32;
+ Props.Minimap.PlayerY = 31;
+ Props.Minimap.PlayerScaleFactor = 0.0257f;
+ Props.Minimap.FinishlineX = 0;
+ Props.Minimap.FinishlineY = 0;
+
+ Props.SetText(Props.Name, "big donut", sizeof(Props.Name));
+ Props.SetText(Props.DebugName, "doughnut", sizeof(Props.DebugName));
+ Props.SetText(Props.CourseLength, "", sizeof(Props.CourseLength));
- Props.Name = "big donut";
- Props.DebugName = "doughnut";
- Props.CourseLength = "";
Props.AIBehaviour = D_0D008F18;
Props.AIMaximumSeparation = -1.0f;
Props.AIMinimumSeparation = 0.5f;
- Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 40;
Props.PathSizes = {1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0};
@@ -89,8 +97,6 @@ BigDonut::BigDonut() {
Props.Clouds = NULL; // no clouds
Props.CloudList = NULL;
- Props.MinimapFinishlineX = 0;
- Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {0, 0, 0};
Props.Skybox.BottomRight = {0, 0, 0};
@@ -101,6 +107,8 @@ BigDonut::BigDonut() {
Props.Skybox.FloorBottomLeft = {0, 0, 0};
Props.Skybox.FloorTopLeft = {0, 0, 0};
Props.Sequence = MusicSeq::MUSIC_SEQ_BATTLE_ARENAS;
+
+ Props.WaterLevel = 100.0f;
}
void BigDonut::Load() {
@@ -117,17 +125,13 @@ void BigDonut::Load() {
// d_course_big_donut_packed_dl_230
generate_collision_mesh_with_default_section_id((Gfx*) segmented_gfx_to_virtual((void*)0x07000230), 6);
func_80295C6C();
- D_8015F8E4 = 100.0f;
-}
-
-void BigDonut::LoadTextures() {
}
void BigDonut::BeginPlay() {
spawn_all_item_boxes((ActorSpawnData*)LOAD_ASSET_RAW(d_course_big_donut_item_box_spawns));
if (gModeSelection == VERSUS) {
- Vec3f pos = {0, 0, 0};
+ FVector pos = {0, 0, 0};
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][20], 20, 0, 1.0f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][40], 40, 0, 1.0f));
@@ -139,31 +143,10 @@ void BigDonut::BeginPlay() {
}
}
-// Likely sets minimap boundaries
-void BigDonut::MinimapSettings() {
- D_8018D2A0 = 0.0257f;
- D_8018D2E0 = 32;
- D_8018D2E8 = 31;
-}
-
-void BigDonut::InitCourseObjects() {}
-
-void BigDonut::SomeSounds() {}
-
-void BigDonut::WhatDoesThisDo(Player* player, int8_t playerId) {}
-
-void BigDonut::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
-
-// Positions the finishline on the minimap
-void BigDonut::MinimapFinishlinePosition() {
- //! todo: Place hard-coded values here.
- draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
-}
-
void BigDonut::Render(struct UnkStruct_800DC5EC* arg0) {
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
- func_802B5D64(D_800DC610, D_802B87D4, 0, 1);
+ set_track_light_direction(D_800DC610, D_802B87D4, 0, 1);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
@@ -185,8 +168,6 @@ void BigDonut::Render(struct UnkStruct_800DC5EC* arg0) {
void BigDonut::RenderCredits() {}
-void BigDonut::Collision() {}
-
void BigDonut::Waypoints(Player* player, int8_t playerId) {
player->nearestWaypointId = 0;
}
diff --git a/src/engine/courses/BigDonut.h b/src/engine/courses/BigDonut.h
index bc076ecf2..bc10105e1 100644
--- a/src/engine/courses/BigDonut.h
+++ b/src/engine/courses/BigDonut.h
@@ -17,26 +17,14 @@ extern "C" {
class BigDonut : public Course {
public:
- virtual ~BigDonut() = default; // Virtual destructor for proper cleanup in derived classes
+ virtual ~BigDonut() = default;
- // Constructor
explicit BigDonut();
-// virtual void Load(const char* courseVtx,
-// course_texture* textures, const char* displaylists, size_t dlSize);
virtual void Load() override;
- virtual void LoadTextures() override;
virtual void BeginPlay() override;
- //virtual void InitClouds() override;
- virtual void MinimapSettings() override;
- virtual void InitCourseObjects() override;
- virtual void SomeSounds() override;
- virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
- virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
- virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
- virtual void Collision() override;
virtual void Waypoints(Player* player, int8_t playerId) override;
virtual void Destroy() override;
};
diff --git a/src/engine/courses/BlockFort.cpp b/src/engine/courses/BlockFort.cpp
index 136ffeef5..cf246220e 100644
--- a/src/engine/courses/BlockFort.cpp
+++ b/src/engine/courses/BlockFort.cpp
@@ -45,17 +45,24 @@ BlockFort::BlockFort() {
this->gfx = d_course_block_fort_packed_dls;
this->gfxSize = 699;
Props.textures = block_fort_textures;
- Props.MinimapTexture = gTextureCourseOutlineBlockFort;
- Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
+ Props.Minimap.Texture = gTextureCourseOutlineBlockFort;
+ Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
+ Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
+ Props.Minimap.Pos[0].X = 257;
+ Props.Minimap.Pos[0].Y = 170;
+ Props.Minimap.PlayerX = 32;
+ Props.Minimap.PlayerY = 32;
+ Props.Minimap.PlayerScaleFactor = 0.0335f;
+ Props.Minimap.FinishlineX = 0;
+ Props.Minimap.FinishlineY = 0;
+
+ Props.SetText(Props.Name, "block fort", sizeof(Props.Name));
+ Props.SetText(Props.DebugName, "block", sizeof(Props.DebugName));
+ Props.SetText(Props.CourseLength, "", sizeof(Props.CourseLength));
-
- Props.Name = "block fort";
- Props.DebugName = "block";
- Props.CourseLength = "";
Props.AIBehaviour = D_0D008F18;
Props.AIMaximumSeparation = -1.0f;
Props.AIMinimumSeparation = 0.1f;
- Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
Props.NearPersp = 2.0f;
@@ -95,8 +102,6 @@ BlockFort::BlockFort() {
Props.Clouds = NULL; // no clouds
Props.CloudList = NULL;
- Props.MinimapFinishlineX = 0;
- Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {128, 184, 248};
Props.Skybox.BottomRight = {216, 232, 248};
@@ -114,17 +119,14 @@ void BlockFort::Load() {
generate_collision_mesh_with_default_section_id((Gfx*) segmented_gfx_to_virtual((void*)0x070015C0), 1);
func_80295C6C();
- D_8015F8E4 = gCourseMinY - 10.0f;
-}
-
-void BlockFort::LoadTextures() {
+ Props.WaterLevel = gCourseMinY - 10.0f;
}
void BlockFort::BeginPlay() {
spawn_all_item_boxes((ActorSpawnData*)LOAD_ASSET_RAW(d_course_block_fort_item_box_spawns));
if (gModeSelection == VERSUS) {
- Vec3f pos = {0, 0, 0};
+ FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][20], 20, 0, 1.0f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][40], 40, 0, 1.0f));
@@ -136,29 +138,8 @@ void BlockFort::BeginPlay() {
}
}
-// Likely sets minimap boundaries
-void BlockFort::MinimapSettings() {
- D_8018D2A0 = 0.0335f;
- D_8018D2E0 = 32;
- D_8018D2E8 = 32;
-}
-
-void BlockFort::InitCourseObjects() {}
-
-void BlockFort::SomeSounds() {}
-
-void BlockFort::WhatDoesThisDo(Player* player, int8_t playerId) {}
-
-void BlockFort::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
-
-// Positions the finishline on the minimap
-void BlockFort::MinimapFinishlinePosition() {
- //! todo: Place hard-coded values here.
- draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
-}
-
void BlockFort::Render(struct UnkStruct_800DC5EC* arg0) {
- func_802B5D64(D_800DC610, D_802B87D4, 0, 1);
+ set_track_light_direction(D_800DC610, D_802B87D4, 0, 1);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
@@ -166,12 +147,6 @@ void BlockFort::Render(struct UnkStruct_800DC5EC* arg0) {
gSPDisplayList(gDisplayListHead++, (segmented_gfx_to_virtual((void*)0x070015C0)));
}
-void BlockFort::RenderCredits() {}
-
-void BlockFort::Collision() {}
-
void BlockFort::Waypoints(Player* player, int8_t playerId) {
player->nearestWaypointId = 0;
}
-
-void BlockFort::Destroy() { }
diff --git a/src/engine/courses/BlockFort.h b/src/engine/courses/BlockFort.h
index c985b9546..f0e4c6aa6 100644
--- a/src/engine/courses/BlockFort.h
+++ b/src/engine/courses/BlockFort.h
@@ -25,18 +25,7 @@ public:
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
virtual void Load() override;
- virtual void LoadTextures() override;
virtual void BeginPlay() override;
- //virtual void InitClouds() override;
- virtual void MinimapSettings() override;
- virtual void InitCourseObjects() override;
- virtual void SomeSounds() override;
- virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
- virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
- virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
- virtual void RenderCredits() override;
- virtual void Collision() override;
virtual void Waypoints(Player*, int8_t) override;
- virtual void Destroy() override;
};
diff --git a/src/engine/courses/BowsersCastle.cpp b/src/engine/courses/BowsersCastle.cpp
index cac1dde92..22b6cbe78 100644
--- a/src/engine/courses/BowsersCastle.cpp
+++ b/src/engine/courses/BowsersCastle.cpp
@@ -5,7 +5,7 @@
#include "BowsersCastle.h"
#include "World.h"
-#include "engine/actors/AFinishline.h"
+#include "engine/actors/Finishline.h"
#include "engine/objects/BombKart.h"
#include "engine/objects/Thwomp.h"
#include "bowsers_castle_data.h"
@@ -31,6 +31,7 @@ extern "C" {
#include "collision.h"
#include "code_8003DC40.h"
#include "memory.h"
+ #include "course.h"
extern const char *bowsers_castle_dls[];
}
@@ -71,17 +72,26 @@ BowsersCastle::BowsersCastle() {
this->gfx = d_course_bowsers_castle_packed_dls;
this->gfxSize = 4900;
Props.textures = bowsers_castle_textures;
- Props.MinimapTexture = gTextureCourseOutlineBowsersCastle;
- Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
+ Props.Minimap.Texture = gTextureCourseOutlineBowsersCastle;
+ Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
+ Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
+ Props.Minimap.Pos[0].X = 265;
+ Props.Minimap.Pos[0].Y = 170;
+ Props.Minimap.PlayerX = 12;
+ Props.Minimap.PlayerY = 48;
+ Props.Minimap.PlayerScaleFactor = 0.0174f;
+ Props.Minimap.FinishlineX = 0;
+ Props.Minimap.FinishlineY = 0;
+
+ Id = "mk:bowsers_castle";
+
+ Props.SetText(Props.Name, "bowser's castle", sizeof(Props.Name));
+ Props.SetText(Props.DebugName, "castle", sizeof(Props.DebugName));
+ Props.SetText(Props.CourseLength, "777m", sizeof(Props.CourseLength));
- Props.Id = "mk:bowsers_castle";
- Props.Name = "bowser's castle";
- Props.DebugName = "castle";
- Props.CourseLength = "777m";
Props.AIBehaviour = D_0D008FB8;
Props.AIMaximumSeparation = 35.0f;
Props.AIMinimumSeparation = 0.2f;
- Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
Props.NearPersp = 2.0f;
@@ -121,8 +131,6 @@ BowsersCastle::BowsersCastle() {
Props.Clouds = NULL; // no clouds
Props.CloudList = NULL;
- Props.MinimapFinishlineX = 0;
- Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {48, 8, 120};
Props.Skybox.BottomRight = {0, 0, 0};
@@ -133,21 +141,40 @@ BowsersCastle::BowsersCastle() {
Props.Skybox.FloorBottomLeft = {0, 0, 0};
Props.Skybox.FloorTopLeft = {0, 0, 0};
Props.Sequence = MusicSeq::MUSIC_SEQ_BOWSERS_CASTLE;
+
+ Props.WaterLevel = -50.0f;
+ WaterVolumes.push_back({20.0f, 1549.0f, 1859.0f, -1402.0f, -1102.0f});
}
void BowsersCastle::Load() {
Course::Load();
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_bowsers_castle_addr));
+ parse_course_displaylists((TrackSections*)LOAD_ASSET_RAW(d_course_bowsers_castle_addr));
func_80295C6C();
find_vtx_and_set_colours(segmented_gfx_to_virtual(reinterpret_cast<void*>(0x07001350)), 0x32, 0, 0, 0);
- D_8015F8E4 = -50.0f;
}
void BowsersCastle::LoadTextures() {
dma_textures(gTextureShrub, 0x000003FFU, 0x00000800U);
}
+// Required for the 2 thwomps that go far
+void BowsersCastle::SpawnStockThwomp() {
+ s32 objectId = indexObjectList1[0];
+ init_object(objectId, 0);
+ gObjectList[objectId].origin_pos[0] = 0x04b0 * xOrientation;
+ gObjectList[objectId].origin_pos[2] = 0xf5ba;
+ gObjectList[objectId].unk_0D5 = 3;
+ gObjectList[objectId].primAlpha = 0;
+
+ objectId = indexObjectList1[1];
+ init_object(objectId, 0);
+ gObjectList[objectId].origin_pos[0] = 0x04b0 * xOrientation;
+ gObjectList[objectId].origin_pos[2] = 0xf592;
+ gObjectList[objectId].unk_0D5 = 3;
+ gObjectList[objectId].primAlpha = 1;
+}
+
void BowsersCastle::BeginPlay() {
spawn_foliage((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_bowsers_castle_tree_spawn));
spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_bowsers_castle_item_box_spawns));
@@ -159,6 +186,7 @@ void BowsersCastle::BeginPlay() {
gWorldInstance.AddObject(new OThwomp(0x044c, 0xf92a, 0xC000, 1.0f, 1, 1));
gWorldInstance.AddObject(new OThwomp(0x02bc, 0xf95c, 0xC000, 1.0f, 2, 0));
gWorldInstance.AddObject(new OThwomp(0x04b0, 0xf8f8, 0xC000, 1.0f, 2, 1));
+ BowsersCastle::SpawnStockThwomp();
gWorldInstance.AddObject(new OThwomp(0x04b0, 0xf5ba, 0xC000, 1.0f, 3, 0));
gWorldInstance.AddObject(new OThwomp(0x04b0, 0xf592, 0xC000, 1.0f, 3, 1));
gWorldInstance.AddObject(new OThwomp(0x091a, 0xf5bf, 0xC000, 1.0f, 4, 0));
@@ -170,6 +198,7 @@ void BowsersCastle::BeginPlay() {
case CC_50:
gWorldInstance.AddObject(new OThwomp(0x3B6, 0xF92A, 0xC000, 1.0f, 1, 0));
gWorldInstance.AddObject(new OThwomp(0x0352, 0xf95c, 0xC000, 1.0f, 2, 0));
+ BowsersCastle::SpawnStockThwomp();
gWorldInstance.AddObject(new OThwomp(0x04b0, 0xf5ba, 0xC000, 1.0f, 3, 0));
gWorldInstance.AddObject(new OThwomp(0x04b0, 0xf592, 0xC000, 1.0f, 3, 1));
gWorldInstance.AddObject(new OThwomp(0x091a, 0xf5b0, 0xC000, 1.0f, 4, 0));
@@ -182,6 +211,7 @@ void BowsersCastle::BeginPlay() {
gWorldInstance.AddObject(new OThwomp(0x044c, 0xf92a, 0xC000, 1.0f, 1, 1));
gWorldInstance.AddObject(new OThwomp(0x02bc, 0xf95c, 0xC000, 1.0f, 2, 0));
gWorldInstance.AddObject(new OThwomp(0x04b0, 0xf8f8, 0xC000, 1.0f, 2, 1));
+ BowsersCastle::SpawnStockThwomp();
gWorldInstance.AddObject(new OThwomp(0x04b0, 0xf5ba, 0xC000, 1.0f, 3, 0));
gWorldInstance.AddObject(new OThwomp(0x04b0, 0xf592, 0xC000, 1.0f, 3, 1));
gWorldInstance.AddObject(new OThwomp(0x091a, 0xf5c9, 0xC000, 1.0f, 4, 0));
@@ -194,7 +224,7 @@ void BowsersCastle::BeginPlay() {
}
if (gModeSelection == VERSUS) {
- Vec3f pos = {0, 0, 0};
+ FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][50], 50, 3, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][150], 150, 1, 0.8333333f));
@@ -206,14 +236,6 @@ void BowsersCastle::BeginPlay() {
}
}
-// Likely sets minimap boundaries
-void BowsersCastle::MinimapSettings() {
- D_8018D2C0[0] = 265;
- D_8018D2A0 = 0.0174f;
- D_8018D2E0 = 12;
- D_8018D2E8 = 48;
-}
-
void BowsersCastle::InitCourseObjects() {
size_t objectId;
size_t i;
@@ -283,12 +305,6 @@ void BowsersCastle::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
-// Positions the finishline on the minimap
-void BowsersCastle::MinimapFinishlinePosition() {
- //! todo: Place hard-coded values here.
- draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
-}
-
void BowsersCastle::Render(struct UnkStruct_800DC5EC* arg0) {
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
@@ -320,8 +336,6 @@ void BowsersCastle::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_bowsers_castle_dl_9148));
}
-void BowsersCastle::Collision() {}
-
void BowsersCastle::SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) {
func_8003E6EC(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
}
diff --git a/src/engine/courses/BowsersCastle.h b/src/engine/courses/BowsersCastle.h
index 767bbdb8c..b52af2a26 100644
--- a/src/engine/courses/BowsersCastle.h
+++ b/src/engine/courses/BowsersCastle.h
@@ -26,19 +26,17 @@ public:
// course_texture* textures, const char* displaylists, size_t dlSize);
virtual void Load() override;
virtual void LoadTextures() override;
+ void SpawnStockThwomp();
virtual void BeginPlay() override;
//virtual void InitClouds() override;
- virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void UpdateCourseObjects() override;
virtual void RenderCourseObjects(s32 cameraId) override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
- virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
- virtual void Collision() override;
virtual void SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) override;
virtual void Waypoints(Player*, int8_t) override;
virtual void DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection);
diff --git a/src/engine/courses/ChocoMountain.cpp b/src/engine/courses/ChocoMountain.cpp
index 632f31981..be5dcb0b1 100644
--- a/src/engine/courses/ChocoMountain.cpp
+++ b/src/engine/courses/ChocoMountain.cpp
@@ -7,7 +7,7 @@
#include "World.h"
#include "engine/objects/BombKart.h"
#include "choco_mountain_data.h"
-#include "engine/actors/AFinishline.h"
+#include "engine/actors/Finishline.h"
extern "C" {
#include "main.h"
@@ -31,6 +31,7 @@ extern "C" {
#include "code_8003DC40.h"
#include "memory.h"
#include "course_offsets.h"
+ #include "course.h"
extern const char *choco_mountain_dls[];
}
@@ -63,17 +64,25 @@ ChocoMountain::ChocoMountain() {
this->gfx = d_course_choco_mountain_packed_dls;
this->gfxSize = 2910;
Props.textures = choco_mountain_textures;
- Props.MinimapTexture = gTextureCourseOutlineChocoMountain;
- Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
+ Props.Minimap.Texture = gTextureCourseOutlineChocoMountain;
+ Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
+ Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
+ Props.Minimap.Pos[0].X = 265;
+ Props.Minimap.Pos[0].Y = 170;
+ Props.Minimap.PlayerX = 19;
+ Props.Minimap.PlayerY = 37;
+ Props.Minimap.PlayerScaleFactor = 0.022f;
+ Props.Minimap.FinishlineX = 0;
+ Props.Minimap.FinishlineY = -16.0;
+
+ Id = "mk:choco_mountain";
+ Props.SetText(Props.Name, "choco mountain", sizeof(Props.Name));
+ Props.SetText(Props.DebugName, "mountain", sizeof(Props.DebugName));
+ Props.SetText(Props.CourseLength, "687m", sizeof(Props.CourseLength));
- Props.Id = "mk:choco_mountain";
- Props.Name = "choco mountain";
- Props.DebugName = "mountain";
- Props.CourseLength = "687m";
Props.AIBehaviour = D_0D008F80;
Props.AIMaximumSeparation = 35.0f;
Props.AIMinimumSeparation = 0.3f;
- Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
Props.NearPersp = 2.0f;
@@ -113,8 +122,6 @@ ChocoMountain::ChocoMountain() {
Props.Clouds = NULL; // no clouds
Props.CloudList = NULL;
- Props.MinimapFinishlineX = 0;
- Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {255, 255, 255};
Props.Skybox.BottomRight = {255, 255, 255};
@@ -125,6 +132,8 @@ ChocoMountain::ChocoMountain() {
Props.Skybox.FloorBottomLeft = {255, 255, 255};
Props.Skybox.FloorTopLeft = {255, 255, 255};
Props.Sequence = MusicSeq::MUSIC_SEQ_CHOCO_MOUNTAIN;
+
+ Props.WaterLevel = -80.0f;
}
void ChocoMountain::Load() {
@@ -154,10 +163,9 @@ void ChocoMountain::Load() {
nullify_displaylist((uintptr_t) segmented_gfx_to_virtual(reinterpret_cast<void*>(0x070003C8)));
}
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_choco_mountain_addr));
+ parse_course_displaylists((TrackSections*)LOAD_ASSET_RAW(d_course_choco_mountain_addr));
func_802B5CAC(0x238E, 0x31C7, D_8015F590);
func_80295C6C();
- D_8015F8E4 = -80.0f;
}
void ChocoMountain::LoadTextures() {
@@ -168,7 +176,7 @@ void ChocoMountain::BeginPlay() {
spawn_falling_rocks((struct ActorSpawnData*)LOAD_ASSET_RAW((const char*)d_course_choco_mountain_falling_rock_spawns));
if (gModeSelection == VERSUS) {
- Vec3f pos = {0, 0, 0};
+ FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][140], 140, 3, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][165], 165, 1, 0.8333333f));
@@ -180,14 +188,6 @@ void ChocoMountain::BeginPlay() {
}
}
-// Likely sets minimap boundaries
-void ChocoMountain::MinimapSettings() {
- D_8018D2A0 = 0.022f;
- D_8018D2C0[0] = 265;
- D_8018D2E0 = 19;
- D_8018D2E8 = 37;
-}
-
void ChocoMountain::InitCourseObjects() {
if (gGamestate != CREDITS_SEQUENCE) {
if (gModeSelection == GRAND_PRIX) {
@@ -235,12 +235,6 @@ void ChocoMountain::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
-// Positions the finishline on the minimap
-void ChocoMountain::MinimapFinishlinePosition() {
- //! todo: Place hard-coded values here.
- draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
-}
-
void ChocoMountain::Render(struct UnkStruct_800DC5EC* arg0) {
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
@@ -292,8 +286,6 @@ void ChocoMountain::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_choco_mountain_dl_71B8));
}
-void ChocoMountain::Collision() {}
-
void ChocoMountain::SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) {
func_8003E37C(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
}
diff --git a/src/engine/courses/ChocoMountain.h b/src/engine/courses/ChocoMountain.h
index 45926ed61..b592ba9df 100644
--- a/src/engine/courses/ChocoMountain.h
+++ b/src/engine/courses/ChocoMountain.h
@@ -27,15 +27,12 @@ public:
virtual void Load() override;
virtual void LoadTextures() override;
virtual void BeginPlay() override;
- virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
- virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
- virtual void Collision() override;
virtual void SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) override;
virtual void Destroy() override;
};
diff --git a/src/engine/courses/Course.cpp b/src/engine/courses/Course.cpp
index 3e5c0b2ab..bbc9455fe 100644
--- a/src/engine/courses/Course.cpp
+++ b/src/engine/courses/Course.cpp
@@ -3,6 +3,9 @@
#include "Course.h"
#include "MarioRaceway.h"
#include "ChocoMountain.h"
+#include "port/Game.h"
+#include "port/resource/type/TrackWaypoint.h"
+#include "port/resource/type/TrackSections.h"
extern "C" {
#include "main.h"
@@ -18,20 +21,36 @@ extern "C" {
#include "staff_ghosts.h"
#include "code_800029B0.h"
#include "render_courses.h"
+#include "collision.h"
+#include "actors.h"
extern StaffGhost* d_mario_raceway_staff_ghost;
}
Course::Course() {
// Props.Name = "Course Name";
// Props.DebugName = "CName";
- // Props.CourseLength = "567m";
+ Props.SetText(Props.CourseLength, "100m", sizeof(Props.CourseLength));
// Props.Cup = FLOWER_CUP;
// Props.CupIndex = 3;
+ Id = "";
+ Props.Minimap.Texture = gTextureCourseOutlineMarioRaceway;
+ Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
+ Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
+ Props.Minimap.Pos[0].X = 257;
+ Props.Minimap.Pos[0].Y = 170;
+ Props.Minimap.PlayerX = 0;
+ Props.Minimap.PlayerY = 0;
+ Props.Minimap.PlayerScaleFactor = 0.22f;
+ Props.Minimap.FinishlineX = 0;
+ Props.Minimap.FinishlineY = 0;
+ Props.Minimap.Colour = {255, 255, 255};
+ Props.WaterLevel = -10.0f;
+
Props.LakituTowType = (s32) OLakitu::LakituTowType::NORMAL;
Props.AIBehaviour = D_0D008F28;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.3f;
- Props.SomePtr = D_800DCB34;
+ Props.AIDistance = gMarioRacewayAIDistances;
Props.AISteeringSensitivity = 48;
Props.NearPersp = 3.0f;
@@ -71,11 +90,10 @@ Course::Course() {
Props.Clouds = NULL;
Props.CloudList = NULL;
- Props.MinimapFinishlineX = 0;
- Props.MinimapFinishlineY = 0;
Props.Sequence = MusicSeq::MUSIC_SEQ_UNKNOWN;
}
+// Load custom track from code
void Course::Load(Vtx* vtx, Gfx* gfx) {
gSegmentTable[4] = reinterpret_cast<uintptr_t>(&vtx[0]);
gSegmentTable[7] = reinterpret_cast<uintptr_t>(&gfx[0]);
@@ -83,8 +101,60 @@ void Course::Load(Vtx* vtx, Gfx* gfx) {
Course::Init();
}
+void Course::LoadO2R(std::string trackPath) {
+ if (!trackPath.empty()) {
+ TrackSectionsPtr = (trackPath + "/data_track_sections");
+
+ std::string path_file = (trackPath + "/data_paths").c_str();
+
+ auto res = std::dynamic_pointer_cast<MK64::Paths>(ResourceLoad(path_file.c_str()));
+
+ if (res != nullptr) {
+ auto& paths = res->PathList;
+
+ size_t i = 0;
+ for (auto& path : paths) {
+ if (i == 0) {
+ Props.PathTable[0] = (TrackWaypoint*)path.data();
+ Props.PathTable[1] = NULL;
+ Props.PathTable[2] = NULL;
+ Props.PathTable[3] = NULL;
+ Props.PathTable2[0] = (TrackWaypoint*)path.data();
+ Props.PathTable2[1] = NULL;
+ Props.PathTable2[2] = NULL;
+ Props.PathTable2[3] = NULL;
+ }
+
+ i += 1;
+ }
+ }
+
+ } else {
+ printf("Course.cpp: LoadO2R: trackPath str is empty\n");
+ }
+}
+
+// Load stock track
void Course::Load() {
+ // Load from O2R
+ if (!TrackSectionsPtr.empty()) {
+ bIsMod = true;
+ //auto res = std::dynamic_pointer_cast<MK64::TrackSectionsO2RClass>(ResourceLoad(TrackSectionsPtr.c_str()));
+
+ TrackSectionsO2R* sections = (TrackSectionsO2R*) LOAD_ASSET_RAW(TrackSectionsPtr.c_str());
+ size_t size = ResourceGetSizeByName(TrackSectionsPtr.c_str());
+
+ if (sections != nullptr) {
+ Course::Init();
+ ParseCourseSections(sections, size);
+ func_80295C6C();
+ Props.WaterLevel = gCourseMinY - 10.0f;
+ }
+ return;
+ }
+
+ // Stock
size_t vtxSize = (ResourceGetSizeByName(this->vtx) / sizeof(CourseVtx)) * sizeof(Vtx);
size_t texSegSize;
@@ -129,6 +199,53 @@ void Course::Load() {
Course::Init();
}
+// C++ version of parse_course_displaylists()
+void Course::ParseCourseSections(TrackSectionsO2R* sections, size_t size) {
+ for (size_t i = 0; i < (size / sizeof(TrackSectionsO2R)); i++) {
+ if (sections[i].flags & 0x8000) {
+ D_8015F59C = 1;
+ } else {
+ D_8015F59C = 0;
+ }
+ if (sections[i].flags & 0x2000) {
+ D_8015F5A0 = 1;
+ } else {
+ D_8015F5A0 = 0;
+ }
+ if (sections[i].flags & 0x4000) {
+ D_8015F5A4 = 1;
+ } else {
+ D_8015F5A4 = 0;
+ }
+ printf("LOADING DL %s\n", sections[i].addr.c_str());
+ generate_collision_mesh((Gfx*)LOAD_ASSET_RAW(sections[i].addr.c_str()), sections[i].surfaceType, sections[i].sectionId);
+ }
+}
+
+void Course::TestPath() {
+ // DEBUG ONLY TO VISUALIZE PATH
+ return;
+ s16 x;
+ s16 y;
+ s16 z;
+ Vec3s rot = {0, 0, 0};
+ Vec3f vel = {0, 0, 0};
+
+ for (size_t i = 0; i < gWaypointCountByPathIndex[0]; i++) {
+ x = D_80164550[0][i].posX;
+ y = D_80164550[0][i].posY;
+ z = D_80164550[0][i].posZ;
+
+ if (((x & 0xFFFF) == 0x8000) && ((y & 0xFFFF) == 0x8000) && ((z & 0xFFFF) == 0x8000)) {
+ break;
+ }
+
+ f32 height = spawn_actor_on_surface(x, 2000.0f, z);
+ Vec3f itemPos = {x, height, z};
+ add_actor_to_empty_slot(itemPos, rot, vel, ACTOR_ITEM_BOX);
+ }
+}
+
void Course::Init() {
gNumActors = 0;
gCourseMinX = 0;
@@ -153,6 +270,7 @@ void Course::LoadTextures() {
}
void Course::BeginPlay() {
+ TestPath();
}
void Course::InitClouds() {
@@ -181,9 +299,6 @@ void Course::SomeCollisionThing(Player* player, Vec3f arg1, Vec3f arg2, Vec3f ar
func_8003E048(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
}
-void Course::MinimapSettings() {
-}
-
void Course::InitCourseObjects() {
}
@@ -206,13 +321,6 @@ void Course::WhatDoesThisDo(Player* player, int8_t playerId) {
void Course::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
-// Positions the finishline on the minimap
-void Course::MinimapFinishlinePosition() {
- //! todo: Place hard-coded values here.
- draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY,
- (u8*) common_texture_minimap_finish_line);
-}
-
void Course::SetStaffGhost() {
D_80162DD6 = 1;
D_80162DF4 = 1;
@@ -226,11 +334,49 @@ void Course::Waypoints(Player* player, int8_t playerId) {
}
void Course::Render(struct UnkStruct_800DC5EC* arg0) {
+ if (!TrackSectionsPtr.empty()) {
+ gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
+ gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
+ // set_track_light_direction(D_800DC610, D_802B87D4, 0, 1);
+ gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
+ gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
+
+ if (func_80290C20(arg0->camera) == 1) {
+ gDPSetCombineMode(gDisplayListHead++, G_CC_SHADE, G_CC_SHADE);
+ gDPSetRenderMode(gDisplayListHead++, G_RM_AA_ZB_OPA_SURF, G_RM_AA_ZB_OPA_SURF2);
+ // d_course_big_donut_packed_dl_DE8
+ }
+
+ TrackSectionsO2R* sections = (TrackSectionsO2R*)LOAD_ASSET_RAW(TrackSectionsPtr.c_str());
+ size_t size = ResourceGetSizeByName(TrackSectionsPtr.c_str());
+ for (size_t i = 0; i < (size / sizeof(TrackSectionsO2R)); i++) {
+ gSPDisplayList(gDisplayListHead++, (Gfx*)LOAD_ASSET_RAW(sections[i].addr.c_str()));
+ }
+ }
}
+
void Course::RenderCredits() {
}
-void Course::Collision() {
+
+f32 Course::GetWaterLevel(FVector pos, Collision* collision) {
+ float highestWater = -FLT_MAX;
+ bool found = false;
+
+ for (const auto& volume : gWorldInstance.CurrentCourse->WaterVolumes) {
+ if (pos.x >= volume.MinX && pos.x <= volume.MaxX &&
+ pos.z >= volume.MinZ && pos.z <= volume.MaxZ) {
+ // Choose the highest water volume the player is over
+ if (!found || volume.Height > highestWater) {
+ highestWater = volume.Height;
+ found = true;
+ }
+ }
+ }
+
+ // If player is not over-top of a water volume then return the courses default water level
+ return found ? highestWater : gWorldInstance.CurrentCourse->Props.WaterLevel;
}
+
void Course::ScrollingTextures() {
}
void Course::DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot,
@@ -241,7 +387,7 @@ void Course::Destroy() {
}
bool Course::IsMod() {
- return false;
+ return bIsMod;
}
Course* currentCourse = nullptr;
diff --git a/src/engine/courses/Course.h b/src/engine/courses/Course.h
index 889012a12..0a0eff823 100644
--- a/src/engine/courses/Course.h
+++ b/src/engine/courses/Course.h
@@ -6,6 +6,7 @@
#ifdef __cplusplus
#include "engine/objects/Lakitu.h"
+#include "port/resource/type/TrackSections.h"
extern "C" {
#endif
@@ -34,20 +35,44 @@ typedef struct SkyboxColours {
RGB8 FloorTopLeft;
} SkyboxColours;
+// Extends infinitely in the Y direction
+// If a player is overtop of a water volume then it should use its height
+// Recommend using the new water surface type. This is here to support the stock tracks.
+// Albeit, there's no reason you cannot use this so long as you input a square.
+// How to use: WaterVolumes.push_back({0, -100, 100, -100, 100});
+struct WaterVolume {
+ float Height; // Y coordinate of the Water level
+ float MinX;
+ float MaxX;
+ float MinZ;
+ float MaxZ;
+};
+
+typedef struct MinimapProps {
+ const char* Texture;
+ int16_t Width;
+ int16_t Height;
+ IVector2D Pos[2]; // Minimap position for players 1 and 2. 3/4 player mode is hard-coded to the center.
+ int32_t PlayerX; // The offset to place the player markers
+ int32_t PlayerY;
+ float PlayerScaleFactor; // Scale factor of the player markers
+ float FinishlineX; // The offset to place the finishline texture on the minimap
+ float FinishlineY;
+ RGB8 Colour; // Colour of the visible pixels (the track path)
+} MinimapProps;
+
typedef struct Properties {
- const char* Id;
- const char* Name;
- const char* DebugName;
- const char* CourseLength;
+ char Name[128];
+ char DebugName[128];
+ char CourseLength[128];
+ int32_t LakituTowType;
+ MinimapProps Minimap;
const char* AIBehaviour;
- const char* MinimapTexture;
- s32 LakituTowType;
- IVector2D MinimapDimensions;
float AIMaximumSeparation;
float AIMinimumSeparation;
float NearPersp;
float FarPersp;
- int16_t *SomePtr;
+ int16_t* AIDistance;
uint32_t AISteeringSensitivity;
_struct_gCoursePathSizes_0x10 PathSizes;
Vec4f D_0D009418;
@@ -56,13 +81,160 @@ typedef struct Properties {
Vec4f D_0D009808;
TrackWaypoint* PathTable[4];
TrackWaypoint* PathTable2[4];
+ uint8_t* CloudTexture;
CloudData *Clouds;
CloudData *CloudList;
- int32_t MinimapFinishlineX;
- int32_t MinimapFinishlineY;
SkyboxColours Skybox;
const course_texture *textures;
enum MusicSeq Sequence;
+ float WaterLevel; // Used for effects, and Lakitu pick up height. Not necessarily the visual water model height.
+
+#ifdef __cplusplus
+ nlohmann::json to_json() const {
+ nlohmann::json j;
+ // j["Id"] = Id ? Id : "";
+ j["Name"] = Name ? Name : "";
+ j["DebugName"] = DebugName ? DebugName : "";
+ j["CourseLength"] = CourseLength ? CourseLength : "";
+ j["AIBehaviour"] = AIBehaviour ? AIBehaviour : "";
+ j["LakituTowType"] = LakituTowType;
+ j["AIMaximumSeparation"] = AIMaximumSeparation;
+ j["AIMinimumSeparation"] = AIMinimumSeparation;
+ j["NearPersp"] = NearPersp;
+ j["FarPersp"] = FarPersp;
+
+ // AIDistance as a JSON array
+ j["AIDistance"] = std::vector<int16_t>(AIDistance, AIDistance + 32); // gAIDistances array size of 32
+
+ j["AISteeringSensitivity"] = AISteeringSensitivity;
+
+ // PathSizes - Assuming _struct_gCoursePathSizes_0x10 can be serialized similarly
+ // j["PathSizes"] = PathSizes; // Implement your serialization logic here
+
+ j["D_0D009418"] = { D_0D009418[0], D_0D009418[1], D_0D009418[2], D_0D009418[3] };
+ j["D_0D009568"] = { D_0D009568[0], D_0D009568[1], D_0D009568[2], D_0D009568[3] };
+ j["D_0D0096B8"] = { D_0D0096B8[0], D_0D0096B8[1], D_0D0096B8[2], D_0D0096B8[3] };
+ j["D_0D009808"] = { D_0D009808[0], D_0D009808[1], D_0D009808[2], D_0D009808[3] };
+
+ // Serialize arrays PathTable and PathTable2 (convert pointers into a JSON array if possible)
+ //j["PathTable"] = {{}};
+ //j["PathTable2"] = {{}};
+ // Populate PathTable and PathTable2
+
+ //j["Clouds"] = Clouds ? nlohmann::json{{"x", Clouds->x, "y", Clouds->y, "z", Clouds->z}} : nullptr;
+ //j["CloudList"] = CloudList ? nlohmann::json{{"x", CloudList->x, "y", CloudList->y, "z", CloudList->z}} : nullptr;
+
+ j["MinimapPosition"] = {Minimap.Pos[0].X, Minimap.Pos[0].Y};
+ j["MinimapPosition2P"] = {Minimap.Pos[1].X, Minimap.Pos[1].Y};
+ j["MinimapPlayerX"] = Minimap.PlayerX;
+ j["MinimapPlayerY"] = Minimap.PlayerY;
+ j["MinimapPlayerScaleFactor"] = Minimap.PlayerScaleFactor;
+ j["MinimapFinishlineX"] = Minimap.FinishlineX;
+ j["MinimapFinishlineY"] = Minimap.FinishlineY;
+ j["MinimapColour"] = {static_cast<int>(Minimap.Colour.r), static_cast<int>(Minimap.Colour.g), static_cast<int>(Minimap.Colour.b)};
+ // SkyboxColors - assuming SkyboxColors can be serialized similarly
+ // j["Skybox"] = Skybox; // Implement your serialization logic here
+ j["Sequence"] = static_cast<int>(Sequence);
+
+ j["WaterLevel"] = static_cast<float>(WaterLevel);
+
+ return j;
+ }
+
+ // Function to load struct from JSON
+ void from_json(const nlohmann::json& j) {
+ //Id = j.at("Id").get<std::string>().c_str();
+// Name = j.at("Name").get<std::string>().c_str();
+ strncpy(Name, j.at("Name").get<std::string>().c_str(), sizeof(Name) - 1);
+ Name[sizeof(Name) - 1] = '\0'; // Ensure null termination
+
+// DebugName = j.at("DebugName").get<std::string>().c_str();
+ strncpy(DebugName, j.at("DebugName").get<std::string>().c_str(), sizeof(DebugName) - 1);
+ DebugName[sizeof(DebugName) - 1] = '\0'; // Ensure null termination
+
+ // CourseLength = j.at("CourseLength").get<std::string>().c_str();
+ strncpy(CourseLength, j.at("CourseLength").get<std::string>().c_str(), sizeof(CourseLength) - 1);
+ CourseLength[sizeof(CourseLength) - 1] = '\0'; // Ensure null termination
+
+ AIBehaviour = j.at("AIBehaviour").get<std::string>().c_str();
+ LakituTowType = j.at("LakituTowType").get<int>();
+
+ AIMaximumSeparation = j.at("AIMaximumSeparation").get<float>();
+ AIMinimumSeparation = j.at("AIMinimumSeparation").get<float>();
+ NearPersp = j.at("NearPersp").get<float>();
+ FarPersp = j.at("FarPersp").get<float>();
+
+ const auto temp = j.at("AIDistance").get<std::vector<int16_t>>();
+
+ // Ensure the vector has 32 entries
+ if (temp.size() == 32) {
+ // Copy the data into the existing AIDistances array
+ std::copy(temp.begin(), temp.end(), AIDistance);
+ } else {
+ printf("Course::from_json() AIDistance array not size of 32\n");
+ }
+
+ AISteeringSensitivity = j.at("AISteeringSensitivity").get<uint32_t>();
+
+ // Deserialize PathSizes and other custom structs if needed
+
+ D_0D009418[0] = j.at("D_0D009418")[0].get<float>();
+ D_0D009418[1] = j.at("D_0D009418")[1].get<float>();
+ D_0D009418[2] = j.at("D_0D009418")[2].get<float>();
+ D_0D009418[3] = j.at("D_0D009418")[3].get<float>();
+
+ D_0D009568[0] = j.at("D_0D009568")[0].get<float>();
+ D_0D009568[1] = j.at("D_0D009568")[1].get<float>();
+ D_0D009568[2] = j.at("D_0D009568")[2].get<float>();
+ D_0D009568[3] = j.at("D_0D009568")[3].get<float>();
+
+ D_0D0096B8[0] = j.at("D_0D0096B8")[0].get<float>();
+ D_0D0096B8[1] = j.at("D_0D0096B8")[1].get<float>();
+ D_0D0096B8[2] = j.at("D_0D0096B8")[2].get<float>();
+ D_0D0096B8[3] = j.at("D_0D0096B8")[3].get<float>();
+
+ D_0D009808[0] = j.at("D_0D009808")[0].get<float>();
+ D_0D009808[1] = j.at("D_0D009808")[1].get<float>();
+ D_0D009808[2] = j.at("D_0D009808")[2].get<float>();
+ D_0D009808[3] = j.at("D_0D009808")[3].get<float>();
+
+ // Deserialize arrays PathTable and PathTable2 similarly
+
+ //Clouds = nullptr; // Deserialize if data is present
+ //CloudList = nullptr; // Deserialize if data is present
+ Minimap.Pos[0].X = j.at("MinimapPosition")[0].get<int32_t>();
+ Minimap.Pos[0].Y = j.at("MinimapPosition")[1].get<int32_t>();
+ Minimap.Pos[1].X = j.at("MinimapPosition2P")[0].get<int32_t>();
+ Minimap.Pos[1].Y = j.at("MinimapPosition2P")[1].get<int32_t>();
+ Minimap.PlayerX = j.at("MinimapPlayerX").get<int32_t>();
+ Minimap.PlayerY = j.at("MinimapPlayerY").get<int32_t>();
+ Minimap.PlayerScaleFactor = j.at("MinimapPlayerScaleFactor").get<float>();
+ Minimap.FinishlineX = j.at("MinimapFinishlineX").get<float>();
+ Minimap.FinishlineY = j.at("MinimapFinishlineY").get<float>();
+ Minimap.Colour.r = j.at("MinimapColour")[0].get<uint8_t>();
+ Minimap.Colour.g = j.at("MinimapColour")[1].get<uint8_t>();
+ Minimap.Colour.b = j.at("MinimapColour")[2].get<uint8_t>();
+ //textures = nullptr; // Deserialize textures if present
+ Sequence = static_cast<MusicSeq>(j.at("Sequence").get<int>());
+ WaterLevel = j.at("WaterLevel").get<float>();
+ }
+ void SetText(char* name, const char* title, size_t bufferSize) {
+ // Copy the title into the name buffer, ensuring it's null-terminated and within bounds
+ std::strncpy(name, title, bufferSize - 1);
+ name[bufferSize - 1] = '\0'; // Ensure the string is null-terminated
+ }
+
+ const char* GetName() {
+ return Name;
+ }
+
+ void New() {
+ SetText(Name, "", sizeof(Name));
+ SetText(DebugName, "", sizeof(DebugName));
+ SetText(CourseLength, "", sizeof(CourseLength));
+ }
+#endif
+
} Properties;
#ifdef __cplusplus
@@ -72,32 +244,41 @@ class World; // <-- Forward declare
class Course {
public:
+ std::string Id;
Properties Props;
+ // This allows multiple water levels in a map.
+ // Ex. DK Jungle where there's a waterfall and you can drive above and below it.
+ std::vector<WaterVolume> WaterVolumes;
+
const char* vtx = nullptr;
const char* gfx = nullptr;
size_t gfxSize = 0;
const course_texture* textures = nullptr;
bool bSpawnFinishline = true;
std::optional<FVector> FinishlineSpawnPoint;
+ std::string TrackSectionsPtr;
+ bool bIsMod = false;
virtual ~Course() = default;
explicit Course();
- virtual void Load(); // Decompress and load stock courses. Must be overridden for custom courses
- virtual void Load(Vtx* vtx, Gfx *gfx); // Load custom course
+ virtual void LoadO2R(std::string trackPath); // Load custom track from o2r
+ virtual void Load(); // Decompress and load stock courses or from o2r but TrackSectionsPtr must be set.
+ virtual void Load(Vtx* vtx, Gfx *gfx); // Load custom track from code. Load must be overridden and then call to this base class method impl.
virtual void LoadTextures();
+ virtual void ParseCourseSections(TrackSectionsO2R* sections, size_t size);
/**
* @brief BeginPlay This function is called once at the start of gameplay.
* Actor spawning should go here.
*/
virtual void BeginPlay();
+ virtual void TestPath();
virtual void InitClouds();
virtual void UpdateClouds(s32, Camera*);
virtual void SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7);
- virtual void MinimapSettings();
virtual void InitCourseObjects();
virtual void UpdateCourseObjects();
virtual void RenderCourseObjects(s32 cameraId);
@@ -105,12 +286,11 @@ public:
virtual void CreditsSpawnActors();
virtual void WhatDoesThisDo(Player*, int8_t);
virtual void WhatDoesThisDoAI(Player*, int8_t);
- virtual void MinimapFinishlinePosition();
virtual void SetStaffGhost();
virtual void Render(struct UnkStruct_800DC5EC*);
virtual void RenderCredits();
virtual void Waypoints(Player* player, int8_t playerId);
- virtual void Collision();
+ virtual f32 GetWaterLevel(FVector pos, Collision* collision);
virtual void ScrollingTextures();
virtual void DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection);
virtual void Destroy();
diff --git a/src/engine/courses/DKJungle.cpp b/src/engine/courses/DKJungle.cpp
index bb9c951bc..bbb602584 100644
--- a/src/engine/courses/DKJungle.cpp
+++ b/src/engine/courses/DKJungle.cpp
@@ -5,7 +5,7 @@
#include "DKJungle.h"
#include "World.h"
-#include "engine/actors/AFinishline.h"
+#include "engine/actors/Finishline.h"
#include "engine/objects/BombKart.h"
#include "assets/dks_jungle_parkway_data.h"
@@ -14,6 +14,7 @@
extern "C" {
#include "main.h"
+ #include "common_structs.h"
#include "camera.h"
#include "course_offsets.h"
#include "code_800029B0.h"
@@ -34,6 +35,7 @@ extern "C" {
#include "code_8003DC40.h"
#include "memory.h"
#include "sounds.h"
+ #include "course.h"
extern const char *d_course_dks_jungle_parkway_unknown_dl_list[];
extern s16 currentScreenSection;
}
@@ -71,16 +73,24 @@ DKJungle::DKJungle() {
this->gfx = d_course_dks_jungle_parkway_packed_dls;
this->gfxSize = 4997;
Props.textures = dks_jungle_parkway_textures;
- Props.MinimapTexture = gTextureCourseOutlineDksJungleParkway;
- Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
+ Props.Minimap.Texture = gTextureCourseOutlineDksJungleParkway;
+ Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
+ Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
+ Props.Minimap.Pos[0].X = 255;
+ Props.Minimap.Pos[0].Y = 170;
+ Props.Minimap.PlayerX = 29;
+ Props.Minimap.PlayerY = 47;
+ Props.Minimap.PlayerScaleFactor = 0.0155f;
+ Props.Minimap.FinishlineX = 0;
+ Props.Minimap.FinishlineY = 0;
+
+ Props.SetText(Props.Name, "d.k.'s jungle parkway", sizeof(Props.Name));
+ Props.SetText(Props.DebugName, "jungle", sizeof(Props.DebugName));
+ Props.SetText(Props.CourseLength, "893m", sizeof(Props.CourseLength));
- Props.Name = "d.k.'s jungle parkway";
- Props.DebugName = "jungle";
- Props.CourseLength = "893m";
Props.AIBehaviour = D_0D0093C0;
Props.AIMaximumSeparation = 40.0f;
Props.AIMinimumSeparation = 0.1f;
- Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
Props.NearPersp = 9.0f;
@@ -120,8 +130,6 @@ DKJungle::DKJungle() {
Props.Clouds = NULL; // no clouds
Props.CloudList = NULL;
- Props.MinimapFinishlineX = 0;
- Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {255, 174, 0};
Props.Skybox.BottomRight = {255, 229, 124};
@@ -132,18 +140,50 @@ DKJungle::DKJungle() {
Props.Skybox.FloorBottomLeft = {0, 0, 0};
Props.Skybox.FloorTopLeft = {22, 145, 22};
Props.Sequence = MusicSeq::MUSIC_SEQ_DK_JUNGLE;
+
+ Props.WaterLevel = -475.0f;
}
void DKJungle::Load() {
Course::Load();
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_dks_jungle_parkway_addr));
+ parse_course_displaylists((TrackSections*)LOAD_ASSET_RAW(d_course_dks_jungle_parkway_addr));
func_80295C6C();
- D_8015F8E4 = -475.0f;
// d_course_dks_jungle_parkway_packed_dl_3FA8
find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07003FA8), 120, 255, 255, 255);
}
+f32 DKJungle::GetWaterLevel(FVector pos, Collision* collision) {
+ int32_t temp_v1 = get_track_section_id(collision->meshIndexZX) & 0xFF;
+
+ if (temp_v1 == 0xFF) {
+ if ((get_surface_type(collision->meshIndexZX) & 0xFF) == CAVE) {
+ return -475.0f;
+ }
+ if (pos.x > -478.0f) {
+ return -33.9f;
+ }
+ if (pos.x < -838.0f) {
+ return -475.0f;
+ }
+ if (pos.z > -436.0f) {
+ return -475.0f;
+ }
+ if (pos.z < -993.0f) {
+ return -33.9f;
+ }
+ if (pos.z < pos.x) {
+ return -475.0f;
+ }
+
+ return -33.9f;
+ }
+ if (temp_v1 >= 0x14) {
+ return -475.0f;
+ }
+ return -33.9f;
+}
+
void DKJungle::LoadTextures() {
dma_textures(gTextureDksJungleParkwayKiwanoFruit1, 0x0000032FU, 0x00000400U);
dma_textures(gTextureDksJungleParkwayKiwanoFruit2, 0x00000369U, 0x00000400U);
@@ -164,7 +204,7 @@ void DKJungle::BeginPlay() {
gWorldInstance.AddActor(new ABoat((0.6666666f)/4, 0));
if (gModeSelection == VERSUS) {
- Vec3f pos = {0, 0, 0};
+ FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][50], 50, 3, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][100], 100, 1, 0.8333333f));
@@ -177,14 +217,6 @@ void DKJungle::BeginPlay() {
}
}
-// Likely sets minimap boundaries
-void DKJungle::MinimapSettings() {
- D_8018D2A0 = 0.0155f;
- D_8018D2C0[0] = 255;
- D_8018D2E0 = 29;
- D_8018D2E8 = 47;
-}
-
void DKJungle::InitCourseObjects() {
for (size_t i = 0; i < NUM_TORCHES; i++) {
init_smoke_particles(i);
@@ -253,15 +285,9 @@ void DKJungle::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
-// Positions the finishline on the minimap
-void DKJungle::MinimapFinishlinePosition() {
- //! todo: Place hard-coded values here.
- draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
-}
-
void DKJungle::Render(struct UnkStruct_800DC5EC* arg0) {
- func_802B5D64(D_800DC610, D_802B87D4, 0, 1);
- func_802B5D64(&D_800DC610[1], D_802B87D4, D_802B87D0, 1);
+ set_track_light_direction(D_800DC610, D_802B87D4, 0, 1);
+ set_track_light_direction(&D_800DC610[1], D_802B87D4, D_802B87D0, 1);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_CULL_BACK | G_LIGHTING);
@@ -286,8 +312,6 @@ void DKJungle::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_dks_jungle_parkway_dl_13C30));
}
-void DKJungle::Collision() {}
-
void DKJungle::SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) {
func_8003F138(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
}
diff --git a/src/engine/courses/DKJungle.h b/src/engine/courses/DKJungle.h
index 71cc1e582..84767a94a 100644
--- a/src/engine/courses/DKJungle.h
+++ b/src/engine/courses/DKJungle.h
@@ -26,19 +26,17 @@ public:
// course_texture* textures, const char* displaylists, size_t dlSize);
virtual void Load() override;
virtual void LoadTextures() override;
+ virtual f32 GetWaterLevel(FVector pos, Collision* collision) override;
virtual void BeginPlay() override;
//virtual void InitClouds() override;
- virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void UpdateCourseObjects() override;
virtual void RenderCourseObjects(s32 cameraId) override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
- virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
- virtual void Collision() override;
virtual void SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) override;
virtual void Waypoints(Player* player, int8_t playerId) override;
virtual void ScrollingTextures() override;
diff --git a/src/engine/courses/DoubleDeck.cpp b/src/engine/courses/DoubleDeck.cpp
index fea83005d..ecadf9d48 100644
--- a/src/engine/courses/DoubleDeck.cpp
+++ b/src/engine/courses/DoubleDeck.cpp
@@ -43,16 +43,25 @@ DoubleDeck::DoubleDeck() {
this->gfx = d_course_double_deck_packed_dls;
this->gfxSize = 699;
Props.textures = double_deck_textures;
- Props.MinimapTexture = gTextureCourseOutlineDoubleDeck;
- Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
+ Props.Minimap.Texture = gTextureCourseOutlineDoubleDeck;
+ Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
+ Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
+ Props.Minimap.Pos[0].X = 257;
+ Props.Minimap.Pos[0].Y = 170;
+ Props.Minimap.PlayerX = 32;
+ Props.Minimap.PlayerY = 32;
+ Props.Minimap.PlayerScaleFactor = 0.0285f;
+ Props.Minimap.FinishlineX = 0;
+ Props.Minimap.FinishlineY = 0;
+
+ Props.SetText(Props.Name, "double deck", sizeof(Props.Name));
+ Props.SetText(Props.DebugName, "deck", sizeof(Props.DebugName));
+ Props.SetText(Props.CourseLength, "", sizeof(Props.CourseLength));
+
- Props.Name = "double deck";
- Props.DebugName = "deck";
- Props.CourseLength = "";
Props.AIBehaviour = D_0D008F18;
Props.AIMaximumSeparation = -1.0f;
Props.AIMinimumSeparation = 0.5f;
- Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
Props.NearPersp = 2.0f;
@@ -92,8 +101,6 @@ DoubleDeck::DoubleDeck() {
Props.Clouds = NULL; // no clouds
Props.CloudList = NULL;
- Props.MinimapFinishlineX = 0;
- Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {113, 70, 255};
Props.Skybox.BottomRight = {255, 184, 99};
@@ -111,7 +118,7 @@ void DoubleDeck::Load() {
generate_collision_mesh_with_default_section_id((Gfx*) segmented_gfx_to_virtual((void*)0x07000738), 1);
func_80295C6C();
- D_8015F8E4 = gCourseMinY - 10.0f;
+ Props.WaterLevel = gCourseMinY - 10.0f;
}
void DoubleDeck::LoadTextures() {
@@ -121,7 +128,7 @@ void DoubleDeck::BeginPlay() {
spawn_all_item_boxes((ActorSpawnData*)LOAD_ASSET_RAW(d_course_double_deck_item_box_spawns));
if (gModeSelection == VERSUS) {
- Vec3f pos = {0, 0, 0};
+ FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][20], 20, 0, 1.0f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][40], 40, 0, 1.0f));
@@ -133,13 +140,6 @@ void DoubleDeck::BeginPlay() {
}
}
-// Likely sets minimap boundaries
-void DoubleDeck::MinimapSettings() {
- D_8018D2A0 = 0.0285f;
- D_8018D2E0 = 32;
- D_8018D2E8 = 32;
-}
-
void DoubleDeck::InitCourseObjects() {}
void DoubleDeck::SomeSounds() {}
@@ -148,14 +148,8 @@ void DoubleDeck::WhatDoesThisDo(Player* player, int8_t playerId) {}
void DoubleDeck::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
-// Positions the finishline on the minimap
-void DoubleDeck::MinimapFinishlinePosition() {
- //! todo: Place hard-coded values here.
- draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
-}
-
void DoubleDeck::Render(struct UnkStruct_800DC5EC* arg0) {
- func_802B5D64(D_800DC610, D_802B87D4, 0, 1);
+ set_track_light_direction(D_800DC610, D_802B87D4, 0, 1);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
@@ -167,8 +161,6 @@ void DoubleDeck::Render(struct UnkStruct_800DC5EC* arg0) {
void DoubleDeck::RenderCredits() {}
-void DoubleDeck::Collision() {}
-
void DoubleDeck::Waypoints(Player* player, int8_t playerId) {
player->nearestWaypointId = 0;
}
diff --git a/src/engine/courses/DoubleDeck.h b/src/engine/courses/DoubleDeck.h
index d821187c8..2ebb5d9c3 100644
--- a/src/engine/courses/DoubleDeck.h
+++ b/src/engine/courses/DoubleDeck.h
@@ -27,16 +27,12 @@ public:
virtual void Load() override;
virtual void LoadTextures() override;
virtual void BeginPlay() override;
- //virtual void InitClouds() override;
- virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
- virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
- virtual void Collision() override;
virtual void Waypoints(Player* player, int8_t playerId) override;
virtual void Destroy() override;
};
diff --git a/src/engine/courses/FrappeSnowland.cpp b/src/engine/courses/FrappeSnowland.cpp
index 7383946d1..16b9b7380 100644
--- a/src/engine/courses/FrappeSnowland.cpp
+++ b/src/engine/courses/FrappeSnowland.cpp
@@ -6,7 +6,7 @@
#include "FrappeSnowland.h"
#include "World.h"
#include "CoreMath.h"
-#include "engine/actors/AFinishline.h"
+#include "engine/actors/Finishline.h"
#include "engine/objects/BombKart.h"
#include "engine/objects/Snowman.h"
#include "assets/frappe_snowland_data.h"
@@ -34,6 +34,7 @@ extern "C" {
#include "memory.h"
#include "update_objects.h"
#include "course_offsets.h"
+ #include "course.h"
extern const char *d_course_frappe_snowland_dl_list[];
extern s8 gPlayerCount;
}
@@ -51,16 +52,25 @@ FrappeSnowland::FrappeSnowland() {
this->gfx = d_course_frappe_snowland_packed_dls;
this->gfxSize = 4140;
Props.textures = frappe_snowland_textures;
- Props.MinimapTexture = gTextureCourseOutlineFrappeSnowland;
- Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
+ Props.Minimap.Texture = gTextureCourseOutlineFrappeSnowland;
+ Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
+ Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
+ Props.Minimap.Pos[0].X = 262;
+ Props.Minimap.Pos[0].Y = 170;
+ Props.Minimap.PlayerX = 36;
+ Props.Minimap.PlayerY = 40;
+ Props.Minimap.PlayerScaleFactor = 0.016f;
+ Props.Minimap.FinishlineX = 0;
+ Props.Minimap.FinishlineY = 0;
+ Props.Minimap.Colour = {72, 100, 255};
+
+ Props.SetText(Props.Name, "frappe snowland", sizeof(Props.Name));
+ Props.SetText(Props.DebugName, "snow", sizeof(Props.DebugName));
+ Props.SetText(Props.CourseLength, "734m", sizeof(Props.CourseLength));
- Props.Name = "frappe snowland";
- Props.DebugName = "snow";
- Props.CourseLength = "734m";
Props.AIBehaviour = D_0D0090F8;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.3f;
- Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
Props.NearPersp = 9.0f;
@@ -100,8 +110,6 @@ FrappeSnowland::FrappeSnowland() {
Props.Clouds = NULL; // not used for frappe
Props.CloudList = NULL;
- Props.MinimapFinishlineX = 0;
- Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {28, 11, 90};
Props.Skybox.BottomRight = {0, 99, 164};
@@ -112,14 +120,15 @@ FrappeSnowland::FrappeSnowland() {
Props.Skybox.FloorBottomLeft = {0, 0, 0};
Props.Skybox.FloorTopLeft = {0, 99, 164};
Props.Sequence = MusicSeq::MUSIC_SEQ_FRAPPE_SNOWLAND;
+
+ Props.WaterLevel = -50.0f;
}
void FrappeSnowland::Load() {
Course::Load();
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_frappe_snowland_addr));
+ parse_course_displaylists((TrackSections*)LOAD_ASSET_RAW(d_course_frappe_snowland_addr));
func_80295C6C();
- D_8015F8E4 = -50.0f;
}
void FrappeSnowland::LoadTextures() {
@@ -130,7 +139,7 @@ void FrappeSnowland::LoadTextures() {
void FrappeSnowland::BeginPlay() {
spawn_foliage((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_frappe_snowland_tree_spawns));
spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_frappe_snowland_item_box_spawns));
-
+
if (gGamestate != CREDITS_SEQUENCE) {
gWorldInstance.AddObject(new OSnowman(FVector(697, 0, -1684)));
gWorldInstance.AddObject(new OSnowman(FVector(82, 0, -2245)));
@@ -154,7 +163,7 @@ void FrappeSnowland::BeginPlay() {
}
if (gModeSelection == VERSUS) {
- Vec3f pos = {0, 0, 0};
+ FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][50], 50, 3, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][100], 100, 1, 0.8333333f));
@@ -186,17 +195,6 @@ void FrappeSnowland::UpdateClouds(s32 sp1C, Camera* camera) {
func_80078170(sp1C, camera);
}
-// Likely sets minimap boundaries
-void FrappeSnowland::MinimapSettings() {
- D_8018D2C0[0] = 262;
- D_8018D2A0 = 0.016f;
- D_8018D2E0 = 36;
- D_8018D2E8 = 40;
- D_8018D300 = 72;
- D_8018D308 = 100;
- D_8018D310 = 255;
-}
-
void FrappeSnowland::InitCourseObjects() {
size_t objectId;
size_t i;
@@ -209,22 +207,6 @@ void FrappeSnowland::UpdateCourseObjects() {
update_snowflakes();
}
-void FrappeSnowland::RenderCourseObjects(s32 cameraId) {
-}
-
-void FrappeSnowland::SomeSounds() {
-}
-
-void FrappeSnowland::WhatDoesThisDo(Player* player, int8_t playerId) {}
-
-void FrappeSnowland::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
-
-// Positions the finishline on the minimap
-void FrappeSnowland::MinimapFinishlinePosition() {
- //! todo: Place hard-coded values here.
- draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
-}
-
void FrappeSnowland::Render(struct UnkStruct_800DC5EC* arg0) {
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
@@ -246,8 +228,6 @@ void FrappeSnowland::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_frappe_snowland_dl_76A0));
}
-void FrappeSnowland::Collision() {}
-
void FrappeSnowland::Waypoints(Player* player, int8_t playerId) {
s16 waypoint = gNearestWaypointByPlayerId[playerId];
@@ -260,7 +240,3 @@ void FrappeSnowland::Waypoints(Player* player, int8_t playerId) {
}
}
}
-
-void FrappeSnowland::ScrollingTextures() {}
-
-void FrappeSnowland::Destroy() {}
diff --git a/src/engine/courses/FrappeSnowland.h b/src/engine/courses/FrappeSnowland.h
index 8ecbdbf46..8f01559a9 100644
--- a/src/engine/courses/FrappeSnowland.h
+++ b/src/engine/courses/FrappeSnowland.h
@@ -17,30 +17,18 @@ extern "C" {
class FrappeSnowland : public Course {
public:
- virtual ~FrappeSnowland() = default; // Virtual destructor for proper cleanup in derived classes
+ virtual ~FrappeSnowland() = default;
- // Constructor
explicit FrappeSnowland();
-// virtual void Load(const char* courseVtx,
-// course_texture* textures, const char* displaylists, size_t dlSize);
virtual void Load() override;
virtual void LoadTextures() override;
virtual void BeginPlay() override;
virtual void InitClouds() override;
virtual void UpdateClouds(s32 sp1C, Camera* camera) override;
- virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void UpdateCourseObjects() override;
- virtual void RenderCourseObjects(s32 cameraId) override;
- virtual void SomeSounds() override;
- virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
- virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
- virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
- virtual void Collision() override;
- virtual void ScrollingTextures() override;
virtual void Waypoints(Player* player, int8_t playerId) override;
- virtual void Destroy() override;
};
diff --git a/src/engine/courses/Harbour.cpp b/src/engine/courses/Harbour.cpp
index a33f9f3b6..bd037754c 100644
--- a/src/engine/courses/Harbour.cpp
+++ b/src/engine/courses/Harbour.cpp
@@ -6,7 +6,7 @@
#include "Harbour.h"
#include "World.h"
-#include "engine/actors/AFinishline.h"
+#include "engine/actors/Finishline.h"
#include "engine/actors/BowserStatue.h"
#include "engine/actors/Ship.h"
#include "engine/actors/SpaghettiShip.h"
@@ -16,8 +16,8 @@
#include "assets/mario_raceway_data.h"
#include "assets/bowsers_castle_data.h"
#include "assets/bowsers_castle_displaylists.h"
-#include "engine/actors/ATree.h"
-#include "engine/actors/ACloud.h"
+#include "engine/actors/Tree.h"
+#include "engine/actors/Cloud.h"
#include "engine/vehicles/Train.h"
#include "engine/objects/Trophy.h"
#include "engine/objects/CheepCheep.h"
@@ -28,6 +28,7 @@
#include "engine/objects/HotAirBalloon.h"
#include "engine/objects/Crab.h"
#include "engine/objects/Boos.h"
+#include "engine/objects/GrandPrixBalloons.h"
extern "C" {
#include "main.h"
@@ -50,12 +51,7 @@ extern "C" {
#include "collision.h"
#include "memory.h"
#include "courses/harbour/track.h"
- typedef struct {
- Gfx* addr;
- u8 surfaceType;
- u8 sectionId;
- u16 flags;
- } TrackSections;
+ #include "course.h"
}
TrackWaypoint harbour_path[] = {
@@ -518,27 +514,28 @@ TrackWaypoint harbour_path[] = {
{13,-121,0,0},
{15,-121,-14,0},
{-32768, -32768, -32768, 0}
-
-
-
-
};
Harbour::Harbour() {
this->gfxSize = 100;
this->textures = NULL;
- Props.MinimapTexture = gTextureCourseOutlineMarioRaceway;
- Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
-
- Props.Id = "mk:harbour";
- Props.Name = "Harbour";
- Props.DebugName = "harbour";
- Props.CourseLength = "99m";
+ Props.Minimap.Texture = gTextureCourseOutlineMarioRaceway;
+ Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
+ Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
+ Props.Minimap.Pos[0].X = 260;
+ Props.Minimap.Pos[0].Y = 170;
+ Props.Minimap.PlayerX = 6;
+ Props.Minimap.PlayerY = 28;
+ Props.Minimap.PlayerScaleFactor = 0.022f;
+
+ Id = "mk:harbour";
+ Props.SetText(Props.Name, "Harbour", sizeof(Props.Name));
+ Props.SetText(Props.DebugName, "harbour", sizeof(Props.DebugName));
+ Props.SetText(Props.CourseLength, "99m", sizeof(Props.CourseLength));
Props.AIBehaviour = D_0D008F28;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.3f;
- Props.SomePtr = D_800DCB34;
Props.AISteeringSensitivity = 48;
Props.NearPersp = 9.0f;
@@ -576,10 +573,11 @@ Harbour::Harbour() {
Props.PathTable2[2] = NULL;
Props.PathTable2[3] = NULL;
+ Props.CloudTexture = (u8*) LOAD_ASSET_RAW(gTextureExhaust5);
Props.Clouds = gKalimariDesertClouds;
Props.CloudList = gLuigiRacewayClouds;
- Props.MinimapFinishlineX = 0;
- Props.MinimapFinishlineY = 0;
+ Props.Minimap.FinishlineX = 0;
+ Props.Minimap.FinishlineY = 0;
Props.Skybox.TopRight = {120, 140, 188};
Props.Skybox.BottomRight = {216, 232, 248};
@@ -601,6 +599,12 @@ TrackSections harbour_surfaces[] = {
void Harbour::Load() {
Course::Load(road_map_001_mesh_vtx_0, NULL);
+ // The light gets overridden in hm_intro, reset to normal
+ ground_f3d_material_013_lights = gdSPDefLights1(
+ 0x7F, 0x7F, 0x7F,
+ 0xFF, 0xFF, 0xFF, 0x49, 0x49, 0x49
+ );
+
generate_collision_mesh_with_default_section_id(ground_map_mesh, 8);
generate_collision_mesh_with_default_section_id(road_map_001_mesh, 1);
generate_collision_mesh_with_defaults(castle_map_002_mesh);
@@ -608,9 +612,9 @@ void Harbour::Load() {
generate_collision_mesh_with_defaults(bush_map_004_mesh);
generate_collision_mesh_with_defaults(statue_map_005_mesh);
- parse_course_displaylists((TrackSectionsI*)harbour_surfaces);
+ parse_course_displaylists((TrackSections*)harbour_surfaces);
func_80295C6C();
- D_8015F8E4 = gCourseMinY - 10.0f;
+ Props.WaterLevel = gCourseMinY - 10.0f;
}
void Harbour::LoadTextures() {
@@ -726,7 +730,7 @@ void Harbour::BeginPlay() {
// gWorldInstance.AddObject(new OCheepCheep(FVector(0, 40, 0), OCheepCheep::CheepType::RACE, IPathSpan(0, 10)));
// gWorldInstance.AddObject(new OTrophy(FVector(0,0,0), OTrophy::TrophyType::GOLD, OTrophy::Behaviour::GO_FISH));
//gWorldInstance.AddObject(new OSnowman(FVector(0, 0, 0)));
- //gWorldInstance.AddObject(new OTrashBin(FVector(0.0f, 0.0f, 0.0f), FRotation(0, 90, 0), 1.0f, OTrashBin::Behaviour::MUNCHING));
+ //gWorldInstance.AddObject(new OTrashBin(FVector(0.0f, 0.0f, 0.0f), IRotator(0, 90, 0), 1.0f, OTrashBin::Behaviour::MUNCHING));
//gWorldInstance.AddObject(new OHedgehog(FVector(0, 0, 0), FVector2D(0, -200), 9));
//gWorldInstance.AddObject(new OFlagpole(FVector(0, 0, -200), 0x400));
@@ -750,34 +754,11 @@ void Harbour::BeginPlay() {
// add_actor_to_empty_slot(itemPos, rot, vel, ACTOR_ITEM_BOX);
// }
// }
- gWorldInstance.AddActor(new AShip(FVector(-1694, -111, 1451), AShip::Skin::GHOSTSHIP));
- gWorldInstance.AddActor(new AShip(FVector(2811, -83, 966), AShip::Skin::SHIP2));
- gWorldInstance.AddActor(new AShip(FVector(1526, -36, -2228), AShip::Skin::SHIP3));
-
-
- gWorldInstance.AddActor(new ASpaghettiShip(FVector(582, -70, -650)));
- //gWorldInstance.AddActor(new ASpaghettiShip(FVector(2811, -83, 966 )));
- gWorldInstance.AddActor(new AStarship(FVector(1019, 160, 1987)));
-
+ //gWorldInstance.AddActor(new AShip(FVector(-1694, -111, 1451), AShip::Skin::GHOSTSHIP));
+ //gWorldInstance.AddActor(new AShip(FVector(2811, -83, 966), AShip::Skin::SHIP2));
+ //gWorldInstance.AddObject(new OGrandPrixBalloons(FVector(16, -136, -34)));
}
-// Likely sets minimap boundaries
-void Harbour::MinimapSettings() {
- D_8018D220 = reinterpret_cast<uint8_t (*)[1024]>(dma_textures(gTextureExhaust5, 0x443, 0x1000));
- D_8018D2A0 = 0.022f;
- D_8018D2E0 = 6;
- D_8018D2E8 = 28;
- D_8018D2C0[0] = 260;
- D_8018D2D8[0] = 170;
- D_80165718 = 0;
- D_80165720 = 5;
- D_80165728 = -240;
-}
-
-void Harbour::InitCourseObjects() {}
-
-void Harbour::SomeSounds() {}
-
void Harbour::WhatDoesThisDo(Player* player, int8_t playerId) {
if (((s16) gNearestWaypointByPlayerId[playerId] >= 0x19B) &&
((s16) gNearestWaypointByPlayerId[playerId] < 0x1B9)) {
@@ -808,16 +789,10 @@ void Harbour::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
-// Positions the finishline on the minimap
-void Harbour::MinimapFinishlinePosition() {
- //! todo: Place hard-coded values here.
- draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
-}
-
void Harbour::Render(struct UnkStruct_800DC5EC* arg0) {
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
- func_802B5D64(D_800DC610, D_802B87D4, 0, 1);
+ set_track_light_direction(D_800DC610, D_802B87D4, 0, 1);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
@@ -836,13 +811,6 @@ void Harbour::Render(struct UnkStruct_800DC5EC* arg0) {
gSPDisplayList(gDisplayListHead++, moon_moon_mesh);
}
-void Harbour::RenderCredits() {
-}
-
-void Harbour::Collision() {}
-
-void Harbour::Destroy() { }
-
bool Harbour::IsMod() {
return true;
} \ No newline at end of file
diff --git a/src/engine/courses/Harbour.h b/src/engine/courses/Harbour.h
index dadb78f5a..834154f84 100644
--- a/src/engine/courses/Harbour.h
+++ b/src/engine/courses/Harbour.h
@@ -27,15 +27,8 @@ public:
virtual void Load() override;
virtual void LoadTextures() override;
virtual void BeginPlay() override;
- virtual void MinimapSettings() override;
- virtual void InitCourseObjects() override;
- virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
- virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
- virtual void RenderCredits() override;
- virtual void Collision() override;
- virtual void Destroy() override;
virtual bool IsMod() override;
};
diff --git a/src/engine/courses/KalimariDesert.cpp b/src/engine/courses/KalimariDesert.cpp
index 133a38e08..8f4c3e893 100644
--- a/src/engine/courses/KalimariDesert.cpp
+++ b/src/engine/courses/KalimariDesert.cpp
@@ -5,7 +5,7 @@
#include "KalimariDesert.h"
#include "World.h"
-#include "engine/actors/AFinishline.h"
+#include "engine/actors/Finishline.h"
#include "engine/objects/BombKart.h"
#include "kalimari_desert_data.h"
#include "engine/vehicles/Utils.h"
@@ -32,6 +32,7 @@ extern "C" {
#include "actors.h"
#include "collision.h"
#include "memory.h"
+ #include "course.h"
extern const char *kalimari_desert_dls[];
}
@@ -56,16 +57,24 @@ KalimariDesert::KalimariDesert() {
this->gfx = d_course_kalimari_desert_packed_dls;
this->gfxSize = 5328;
Props.textures = kalimari_desert_textures;
- Props.MinimapTexture = gTextureCourseOutlineKalimariDesert;
- Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
+ Props.Minimap.Texture = gTextureCourseOutlineKalimariDesert;
+ Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
+ Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
+ Props.Minimap.Pos[0].X = 263;
+ Props.Minimap.Pos[0].Y = 165;
+ Props.Minimap.PlayerX = 55;
+ Props.Minimap.PlayerY = 27;
+ Props.Minimap.PlayerScaleFactor = 0.015f;
+ Props.Minimap.FinishlineX = 0;
+ Props.Minimap.FinishlineY = 4.0;
+
+ Props.SetText(Props.Name, "kalimari desert", sizeof(Props.Name));
+ Props.SetText(Props.DebugName, "desert", sizeof(Props.DebugName));
+ Props.SetText(Props.CourseLength, "753m", sizeof(Props.CourseLength));
- Props.Name = "kalimari desert";
- Props.DebugName = "desert";
- Props.CourseLength = "753m";
Props.AIBehaviour = D_0D009260;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.3f;
- Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
Props.NearPersp = 10.0f;
@@ -103,10 +112,9 @@ KalimariDesert::KalimariDesert() {
Props.PathTable2[2] = NULL;
Props.PathTable2[3] = NULL;
+ Props.CloudTexture = (u8*) LOAD_ASSET_RAW(gTextureExhaust5);
Props.Clouds = gKalimariDesertClouds;
Props.CloudList = gKalimariDesertClouds;
- Props.MinimapFinishlineX = 0;
- Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {195, 231, 255};
Props.Skybox.BottomRight = {255, 192, 0};
@@ -122,9 +130,9 @@ KalimariDesert::KalimariDesert() {
void KalimariDesert::Load() {
Course::Load();
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_kalimari_desert_addr));
+ parse_course_displaylists((TrackSections*)LOAD_ASSET_RAW(d_course_kalimari_desert_addr));
func_80295C6C();
- D_8015F8E4 = gCourseMinY - 10.0f;
+ Props.WaterLevel = gCourseMinY - 10.0f;
}
void KalimariDesert::LoadTextures() {
@@ -202,7 +210,7 @@ void KalimariDesert::BeginPlay() {
}
if (gModeSelection == VERSUS) {
- Vec3f pos = {0, 0, 0};
+ FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][50], 50, 3, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][138], 138, 1, 0.8333333f));
@@ -215,16 +223,6 @@ void KalimariDesert::BeginPlay() {
}
}
-// Likely sets minimap boundaries
-void KalimariDesert::MinimapSettings() {
- D_8018D2C0[0] = 263;
- D_8018D2D8[0] = 165;
- D_8018D220 = reinterpret_cast<uint8_t (*)[1024]>(dma_textures(gTextureExhaust5, 0x443, 0x1000));
- D_8018D2A0 = 0.015f;
- D_8018D2E0 = 55;
- D_8018D2E8 = 27;
-}
-
void KalimariDesert::InitCourseObjects() {
size_t i;
if (gGamestate != CREDITS_SEQUENCE) {
@@ -248,14 +246,8 @@ void KalimariDesert::WhatDoesThisDo(Player* player, int8_t playerId) {}
void KalimariDesert::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
-// Positions the finishline on the minimap
-void KalimariDesert::MinimapFinishlinePosition() {
- //! todo: Place hard-coded values here.
- draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
-}
-
void KalimariDesert::Render(struct UnkStruct_800DC5EC* arg0) {
- func_802B5D64(D_800DC610, D_802B87D4, 0, 1);
+ set_track_light_direction(D_800DC610, D_802B87D4, 0, 1);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
@@ -291,6 +283,4 @@ void KalimariDesert::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_kalimari_desert_dl_22E00));
}
-void KalimariDesert::Collision() {}
-
void KalimariDesert::Destroy() { }
diff --git a/src/engine/courses/KalimariDesert.h b/src/engine/courses/KalimariDesert.h
index 0a07fcbb3..fe8b21f23 100644
--- a/src/engine/courses/KalimariDesert.h
+++ b/src/engine/courses/KalimariDesert.h
@@ -29,15 +29,12 @@ public:
virtual void Load() override;
virtual void LoadTextures() override;
virtual void BeginPlay() override;
- virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
- virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
- virtual void Collision() override;
virtual void Destroy() override;
private:
diff --git a/src/engine/courses/KoopaTroopaBeach.cpp b/src/engine/courses/KoopaTroopaBeach.cpp
index 3fd22598a..fff1b7b55 100644
--- a/src/engine/courses/KoopaTroopaBeach.cpp
+++ b/src/engine/courses/KoopaTroopaBeach.cpp
@@ -6,7 +6,7 @@
#include "KoopaTroopaBeach.h"
#include "World.h"
-#include "engine/actors/AFinishline.h"
+#include "engine/actors/Finishline.h"
#include "engine/objects/BombKart.h"
#include "engine/objects/Crab.h"
#include "assets/koopa_troopa_beach_data.h"
@@ -32,6 +32,7 @@ extern "C" {
#include "collision.h"
#include "code_8003DC40.h"
#include "memory.h"
+ #include "course.h"
extern const char *koopa_troopa_beach_dls[];
extern s8 gPlayerCount;
}
@@ -61,17 +62,25 @@ KoopaTroopaBeach::KoopaTroopaBeach() {
this->gfx = d_course_koopa_troopa_beach_packed_dls;
this->gfxSize = 5720;
Props.textures = koopa_troopa_beach_textures;
- Props.MinimapTexture = gTextureCourseOutlineKoopaTroopaBeach;
- Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
+ Props.Minimap.Texture = gTextureCourseOutlineKoopaTroopaBeach;
+ Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
+ Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
+ Props.Minimap.Pos[0].X = 268;
+ Props.Minimap.Pos[0].Y = 170;
+ Props.Minimap.PlayerX = 40;
+ Props.Minimap.PlayerY = 21;
+ Props.Minimap.PlayerScaleFactor = 0.014f;
+ Props.Minimap.FinishlineX = 0;
+ Props.Minimap.FinishlineY = 0;
+
+ Id = "mk:koopa_beach";
+ Props.SetText(Props.Name, "koopa troopa beach", sizeof(Props.Name));
+ Props.SetText(Props.DebugName, "beach", sizeof(Props.DebugName));
+ Props.SetText(Props.CourseLength, "691m", sizeof(Props.CourseLength));
- Props.Id = "mk:koopa_beach";
- Props.Name = "koopa troopa beach";
- Props.DebugName = "beach";
- Props.CourseLength = "691m";
Props.AIBehaviour = D_0D009158;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.5f;
- Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
Props.NearPersp = 1.0f;
@@ -109,10 +118,9 @@ KoopaTroopaBeach::KoopaTroopaBeach() {
Props.PathTable2[2] = NULL;
Props.PathTable2[3] = NULL;
+ Props.CloudTexture = (u8*) LOAD_ASSET_RAW(gTextureExhaust3);
Props.Clouds = gKoopaTroopaBeachClouds;
Props.CloudList = gKoopaTroopaBeachClouds;
- Props.MinimapFinishlineX = 0;
- Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {48, 152, 120};
Props.Skybox.BottomRight = {216, 232, 248};
@@ -123,12 +131,16 @@ KoopaTroopaBeach::KoopaTroopaBeach() {
Props.Skybox.FloorBottomLeft = {0, 0, 0};
Props.Skybox.FloorTopLeft = {48, 152, 120};
Props.Sequence = MusicSeq::MUSIC_SEQ_KOOPA_TROOPA_BEACH;
+
+ Props.WaterLevel = 0.0f;
+ gWaterVelocity = -0.1f;
+ WaterVolumes.push_back({0.8f, 67.0f, 239.0f, 2233.0f, 2405.0f});
}
void KoopaTroopaBeach::Load() {
Course::Load();
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_koopa_troopa_beach_addr));
+ parse_course_displaylists((TrackSections*)LOAD_ASSET_RAW(d_course_koopa_troopa_beach_addr));
func_80295C6C();
find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x0700ADE0), -0x6A, 255, 255, 255);
find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x0700A540), -0x6A, 255, 255, 255);
@@ -172,7 +184,7 @@ void KoopaTroopaBeach::BeginPlay() {
}
if (gModeSelection == VERSUS) {
- Vec3f pos = {0, 0, 0};
+ FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][60], 60, 1, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][120], 120, 1, 0.8333333f));
@@ -184,15 +196,6 @@ void KoopaTroopaBeach::BeginPlay() {
}
}
-// Likely sets minimap boundaries
-void KoopaTroopaBeach::MinimapSettings() {
- D_8018D220 = reinterpret_cast<uint8_t (*)[1024]>(dma_textures(gTextureExhaust3, 0x3C8U, 0x1000));
- D_8018D2A0 = 0.014f;
- D_8018D2C0[0] = 268;
- D_8018D2E0 = 40;
- D_8018D2E8 = 21;
-}
-
void KoopaTroopaBeach::InitCourseObjects() {
}
@@ -228,12 +231,6 @@ void KoopaTroopaBeach::WhatDoesThisDo(Player* player, int8_t playerId) {}
void KoopaTroopaBeach::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
-// Positions the finishline on the minimap
-void KoopaTroopaBeach::MinimapFinishlinePosition() {
- //! todo: Place hard-coded values here.
- draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
-}
-
void KoopaTroopaBeach::Render(struct UnkStruct_800DC5EC* arg0) {
gDPPipeSync(gDisplayListHead++);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
@@ -264,21 +261,20 @@ void KoopaTroopaBeach::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_koopa_troopa_beach_dl_18D68));
}
-void KoopaTroopaBeach::Collision() {}
-
void KoopaTroopaBeach::SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) {
func_8003E37C(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
}
void KoopaTroopaBeach::ScrollingTextures() {
// clang-format off
- if (D_8015F8E8 < 0.0f) {
- if (D_8015F8E4 < -20.0f) { D_8015F8E8 *= -1.0f; }
+ // This flips the velocity from 0.1f to -0.1f
+ if (gWaterVelocity < 0.0f) {
+ if (Props.WaterLevel < -20.0f) { gWaterVelocity *= -1.0f; }
} else {
- if (D_8015F8E4 > 0.0f) { D_8015F8E8 *= -1.0f; }
+ if (Props.WaterLevel > 0.0f) { gWaterVelocity *= -1.0f; }
}
// clang-format on
- D_8015F8E4 += D_8015F8E8;
+ Props.WaterLevel += gWaterVelocity;
D_802B87BC += 9;
if (D_802B87BC > 255) {
@@ -330,7 +326,7 @@ void KoopaTroopaBeach::DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pat
break;
}
vector[0] = 0.0f;
- vector[1] = D_8015F8E4;
+ vector[1] = Props.WaterLevel;
vector[2] = 0.0f;
mtxf_translate(matrix, vector);
render_set_position(matrix, 0);
diff --git a/src/engine/courses/KoopaTroopaBeach.h b/src/engine/courses/KoopaTroopaBeach.h
index 490dfe8ab..7ebd8bac8 100644
--- a/src/engine/courses/KoopaTroopaBeach.h
+++ b/src/engine/courses/KoopaTroopaBeach.h
@@ -30,17 +30,14 @@ public:
virtual void Load() override;
virtual void LoadTextures() override;
virtual void BeginPlay() override;
- virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void UpdateCourseObjects() override;
virtual void RenderCourseObjects(s32 cameraId) override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
- virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
- virtual void Collision() override;
virtual void SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) override;
virtual void ScrollingTextures() override;
virtual void DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) override;
diff --git a/src/engine/courses/LuigiRaceway.cpp b/src/engine/courses/LuigiRaceway.cpp
index 555af3212..e4ee857a3 100644
--- a/src/engine/courses/LuigiRaceway.cpp
+++ b/src/engine/courses/LuigiRaceway.cpp
@@ -8,7 +8,8 @@
#include "engine/objects/BombKart.h"
#include "assets/luigi_raceway_data.h"
#include "engine/objects/HotAirBalloon.h"
-#include "engine/actors/AFinishline.h"
+#include "engine/actors/Finishline.h"
+#include "engine/objects/GrandPrixBalloons.h"
extern "C" {
#include "main.h"
@@ -34,6 +35,7 @@ extern "C" {
#include "courses/staff_ghost_data.h"
#include "framebuffer_effects.h"
#include "skybox_and_splitscreen.h"
+#include "course.h"
extern const char* luigi_raceway_dls[];
extern s16 currentScreenSection;
}
@@ -87,17 +89,25 @@ LuigiRaceway::LuigiRaceway() {
this->gfx = d_course_luigi_raceway_packed_dls;
this->gfxSize = 6377;
Props.textures = luigi_raceway_textures;
- Props.MinimapTexture = gTextureCourseOutlineLuigiRaceway;
- Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
+ Props.Minimap.Texture = gTextureCourseOutlineLuigiRaceway;
+ Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
+ Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
+ Props.Minimap.Pos[0].X = 271;
+ Props.Minimap.Pos[0].Y = 170;
+ Props.Minimap.PlayerX = 45;
+ Props.Minimap.PlayerY = 60;
+ Props.Minimap.PlayerScaleFactor = 0.0155f;
+ Props.Minimap.FinishlineX = 0;
+ Props.Minimap.FinishlineY = 0;
+
+ Id = "mk:luigi_raceway";
+ Props.SetText(Props.Name, "luigi raceway", sizeof(Props.Name));
+ Props.SetText(Props.DebugName, "l circuit", sizeof(Props.DebugName));
+ Props.SetText(Props.CourseLength, "717m", sizeof(Props.CourseLength));
- Props.Id = "mk:luigi_raceway";
- Props.Name = "luigi raceway";
- Props.DebugName = "l circuit";
- Props.CourseLength = "717m";
Props.AIBehaviour = D_0D0091E8;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.7f;
- Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 48;
Props.NearPersp = 9.0f;
@@ -135,10 +145,9 @@ LuigiRaceway::LuigiRaceway() {
Props.PathTable2[2] = NULL;
Props.PathTable2[3] = NULL;
+ Props.CloudTexture = (u8*)LOAD_ASSET_RAW(gTextureExhaust2);
Props.Clouds = gLuigiRacewayClouds;
Props.CloudList = gLuigiRacewayClouds;
- Props.MinimapFinishlineX = 0;
- Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = { 128, 184, 248 };
Props.Skybox.BottomRight = { 216, 232, 248 };
@@ -154,9 +163,9 @@ LuigiRaceway::LuigiRaceway() {
void LuigiRaceway::Load() {
Course::Load();
- parse_course_displaylists((TrackSectionsI*) LOAD_ASSET_RAW(d_course_luigi_raceway_addr));
+ parse_course_displaylists((TrackSections*) LOAD_ASSET_RAW(d_course_luigi_raceway_addr));
func_80295C6C();
- D_8015F8E4 = gCourseMinY - 10.0f;
+ Props.WaterLevel = gCourseMinY - 10.0f;
}
void LuigiRaceway::LoadTextures() {
@@ -172,10 +181,11 @@ void LuigiRaceway::BeginPlay() {
gWorldInstance.AddObject(new OHotAirBalloon(FVector(-1250.0f, 0.0f, 1110.0f)));
} else { // Normal gameplay
gWorldInstance.AddObject(new OHotAirBalloon(FVector(-176.0, 0.0f, -2323.0f)));
+ gWorldInstance.AddObject(new OGrandPrixBalloons(FVector(-140, -44, -215)));
}
if (gModeSelection == VERSUS) {
- Vec3f pos = { 0, 0, 0 };
+ FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][50], 50, 1, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][200], 200, 3, 0.8333333f));
@@ -187,38 +197,15 @@ void LuigiRaceway::BeginPlay() {
}
}
-// Likely sets minimap boundaries
-void LuigiRaceway::MinimapSettings() {
- D_8018D220 = reinterpret_cast<uint8_t(*)[1024]>(dma_textures(gTextureExhaust2, 0x4F4U, 0xC00));
- D_8018D2A0 = 0.0155f;
- D_8018D2C0[0] = 271;
- D_8018D2E0 = 45;
- D_8018D2E8 = 60;
- D_80165718 = -140;
- D_80165720 = -44;
- D_80165728 = -215;
-}
-
void LuigiRaceway::InitCourseObjects() {
size_t i;
if (gGamestate != CREDITS_SEQUENCE) {
if (gModeSelection == GRAND_PRIX) {
func_80070714();
}
-
- for (i = 0; i < D_80165738; i++) {
- find_unused_obj_index(&gObjectParticle3[i]);
- init_object(gObjectParticle3[i], 0);
- }
}
}
-void LuigiRaceway::UpdateCourseObjects() {
-}
-
-void LuigiRaceway::RenderCourseObjects(s32 cameraId) {
-}
-
void LuigiRaceway::SomeSounds() {
vec3f_set(D_8015F748, 85.0f, 21.0f, -219.0f);
func_800C9D80(D_8015F748, D_802B91C8, 0x5103700B);
@@ -252,13 +239,6 @@ void LuigiRaceway::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
-// Positions the finishline on the minimap
-void LuigiRaceway::MinimapFinishlinePosition() {
- //! todo: Place hard-coded values here.
- draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY,
- (u8*) common_texture_minimap_finish_line);
-}
-
void LuigiRaceway::SetStaffGhost() {
u32 temp_v0 = func_800B4E24(0) & 0xfffff;
if (temp_v0 <= 11200) {
@@ -444,13 +424,7 @@ void LuigiRaceway::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*) (d_course_luigi_raceway_dl_FD40));
}
-void LuigiRaceway::Collision() {
-}
-
void LuigiRaceway::SomeCollisionThing(Player* player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5,
f32* arg6, f32* arg7) {
func_8003E9EC(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
}
-
-void LuigiRaceway::Destroy() {
-}
diff --git a/src/engine/courses/LuigiRaceway.h b/src/engine/courses/LuigiRaceway.h
index c5e089d81..48a7d8c08 100644
--- a/src/engine/courses/LuigiRaceway.h
+++ b/src/engine/courses/LuigiRaceway.h
@@ -29,19 +29,13 @@ class LuigiRaceway : public Course {
virtual void Load() override;
virtual void LoadTextures() override;
virtual void BeginPlay() override;
- virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
- virtual void UpdateCourseObjects() override;
- virtual void RenderCourseObjects(s32 cameraId) override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
- virtual void MinimapFinishlinePosition() override;
virtual void SetStaffGhost() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
- virtual void Collision() override;
virtual void SomeCollisionThing(Player* player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6,
f32* arg7) override;
- virtual void Destroy() override;
};
diff --git a/src/engine/courses/MarioRaceway.cpp b/src/engine/courses/MarioRaceway.cpp
index e3b9bba21..50af0d890 100644
--- a/src/engine/courses/MarioRaceway.cpp
+++ b/src/engine/courses/MarioRaceway.cpp
@@ -5,9 +5,10 @@
#include "MarioRaceway.h"
#include "World.h"
-#include "engine/actors/AFinishline.h"
+#include "engine/actors/Finishline.h"
#include "engine/objects/Object.h"
#include "engine/objects/BombKart.h"
+#include "engine/objects/GrandPrixBalloons.h"
extern "C" {
#include "main.h"
@@ -31,6 +32,7 @@ extern "C" {
#include "collision.h"
#include "memory.h"
#include "courses/staff_ghost_data.h"
+ #include "course.h"
extern const char *mario_raceway_dls[];
}
@@ -72,19 +74,28 @@ MarioRaceway::MarioRaceway() {
this->vtx = d_course_mario_raceway_vertex;
this->gfx = d_course_mario_raceway_packed_dls;
this->gfxSize = 3367;
- Props.textures = mario_raceway_textures;
- Props.MinimapTexture = gTextureCourseOutlineMarioRaceway;
- Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
- Props.Id = "mk:mario_raceway";
- Props.Name = "Mario Raceway";
- Props.DebugName = "m circuit";
- Props.CourseLength = "567m";
+ Props.textures = mario_raceway_textures;
+ Props.Minimap.Texture = gTextureCourseOutlineMarioRaceway;
+ Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
+ Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
+ Props.Minimap.Pos[0].X = 260;
+ Props.Minimap.Pos[0].Y = 170;
+ Props.Minimap.PlayerX = 6;
+ Props.Minimap.PlayerY = 28;
+ Props.Minimap.PlayerScaleFactor = 0.022f;
+ Props.Minimap.FinishlineX = 0;
+ Props.Minimap.FinishlineY = -2.0;
+
+ Id = "mk:mario_raceway";
+ Props.SetText(Props.Name, "mario raceway", sizeof(Props.Name));
+ Props.SetText(Props.DebugName, "m circuit", sizeof(Props.DebugName));
+ Props.SetText(Props.CourseLength, "567m", sizeof(Props.CourseLength));
Props.AIBehaviour = D_0D008F28;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.3f;
- Props.SomePtr = D_800DCB34;
+ Props.AIDistance = gMarioRacewayAIDistances;
Props.AISteeringSensitivity = 48;
Props.NearPersp = 9.0f;
@@ -122,10 +133,9 @@ MarioRaceway::MarioRaceway() {
Props.PathTable2[2] = NULL;
Props.PathTable2[3] = NULL;
+ Props.CloudTexture = (uint8_t*) LOAD_ASSET_RAW(gTextureExhaust5);
Props.Clouds = gKalimariDesertClouds;
Props.CloudList = gLuigiRacewayClouds;
- Props.MinimapFinishlineX = 0;
- Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {0, 184, 248};
Props.Skybox.BottomRight = {216, 232, 248};
@@ -156,9 +166,9 @@ void MarioRaceway::Load() {
}
}
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_mario_raceway_addr));
+ parse_course_displaylists((TrackSections*)LOAD_ASSET_RAW(d_course_mario_raceway_addr));
func_80295C6C();
- D_8015F8E4 = gCourseMinY - 10.0f;
+ Props.WaterLevel = gCourseMinY - 10.0f;
}
void MarioRaceway::LoadTextures() {
@@ -191,7 +201,7 @@ void MarioRaceway::BeginPlay() {
add_actor_to_empty_slot(position, rotation, velocity, ACTOR_MARIO_SIGN);
if (gModeSelection == VERSUS) {
- Vec3f pos = {0, 0, 0};
+ FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][40], 40, 3, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][100], 100, 3, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][265], 265, 3, 0.8333333f));
@@ -200,19 +210,10 @@ void MarioRaceway::BeginPlay() {
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][0], 0, 0, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][0], 0, 0, 0.8333333f));
}
-}
-// Likely sets minimap boundaries
-void MarioRaceway::MinimapSettings() {
- D_8018D220 = reinterpret_cast<uint8_t (*)[1024]>(dma_textures(gTextureExhaust5, 0x443, 0x1000));
- D_8018D2A0 = 0.022f;
- D_8018D2E0 = 6;
- D_8018D2E8 = 28;
- D_8018D2C0[0] = 260;
- D_8018D2D8[0] = 170;
- D_80165718 = 0;
- D_80165720 = 5;
- D_80165728 = -240;
+ if (gGamestate != CREDITS_SEQUENCE) {
+ gWorldInstance.AddObject(new OGrandPrixBalloons(FVector(0, 5, -240)));
+ }
}
void MarioRaceway::InitCourseObjects() {
@@ -220,10 +221,6 @@ void MarioRaceway::InitCourseObjects() {
if (gModeSelection == GRAND_PRIX) {
func_80070714();
}
- for (size_t i = 0; i < D_80165738; i++) {
- find_unused_obj_index(&gObjectParticle3[i]);
- init_object(gObjectParticle3[i], 0);
- }
}
}
@@ -262,12 +259,6 @@ void MarioRaceway::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
-// Positions the finishline on the minimap
-void MarioRaceway::MinimapFinishlinePosition() {
- //! todo: Place hard-coded values here.
- draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
-}
-
void MarioRaceway::SetStaffGhost() {
u32 temp_v0 = func_800B4E24(0) & 0xfffff;
if (temp_v0 <= 9000) {
@@ -390,8 +381,6 @@ void MarioRaceway::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_mario_raceway_dl_9348));
}
-void MarioRaceway::Collision() {}
-
void MarioRaceway::CreditsSpawnActors() {
dma_textures(gTextureTrees1, 0x35B, 0x800);
spawn_foliage((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_mario_raceway_tree_spawns));
diff --git a/src/engine/courses/MarioRaceway.h b/src/engine/courses/MarioRaceway.h
index a91226dbe..e237f1538 100644
--- a/src/engine/courses/MarioRaceway.h
+++ b/src/engine/courses/MarioRaceway.h
@@ -27,16 +27,13 @@ public:
virtual void Load() override;
virtual void LoadTextures() override;
virtual void BeginPlay() override;
- virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
- virtual void MinimapFinishlinePosition() override;
virtual void SetStaffGhost() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
- virtual void Collision() override;
virtual void CreditsSpawnActors() override;
virtual void Destroy() override;
};
diff --git a/src/engine/courses/MooMooFarm.cpp b/src/engine/courses/MooMooFarm.cpp
index cf83a920d..304ad2210 100644
--- a/src/engine/courses/MooMooFarm.cpp
+++ b/src/engine/courses/MooMooFarm.cpp
@@ -5,7 +5,7 @@
#include "MooMooFarm.h"
#include "World.h"
-#include "engine/actors/AFinishline.h"
+#include "engine/actors/Finishline.h"
#include "engine/objects/BombKart.h"
#include "assets/moo_moo_farm_data.h"
#include "engine/objects/MoleGroup.h"
@@ -32,6 +32,7 @@ extern "C" {
#include "collision.h"
#include "memory.h"
#include "code_80086E70.h"
+ #include "course.h"
extern const char *moo_moo_farm_dls[];
extern s16 currentScreenSection;
extern s8 gPlayerCount;
@@ -74,16 +75,24 @@ MooMooFarm::MooMooFarm() {
this->gfx = d_course_moo_moo_farm_packed_dls;
this->gfxSize = 3304;
Props.textures = moo_moo_farm_textures;
- Props.MinimapTexture = gTextureCourseOutlineMooMooFarm;
- Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
+ Props.Minimap.Texture = gTextureCourseOutlineMooMooFarm;
+ Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
+ Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
+ Props.Minimap.Pos[0].X = 271;
+ Props.Minimap.Pos[0].Y = 170;
+ Props.Minimap.PlayerX = 18;
+ Props.Minimap.PlayerY = 36;
+ Props.Minimap.PlayerScaleFactor = 0.0155f;
+ Props.Minimap.FinishlineX = 0;
+ Props.Minimap.FinishlineY = 0;
+
+ Props.SetText(Props.Name, "moo moo farm", sizeof(Props.Name));
+ Props.SetText(Props.DebugName, "farm", sizeof(Props.DebugName));
+ Props.SetText(Props.CourseLength, "527m", sizeof(Props.CourseLength));
- Props.Name = "moo moo farm";
- Props.DebugName = "farm";
- Props.CourseLength = "527m";
Props.AIBehaviour = D_0D009210;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.5f;
- Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 48;
Props.NearPersp = 9.0f;
@@ -121,10 +130,9 @@ MooMooFarm::MooMooFarm() {
Props.PathTable2[2] = NULL;
Props.PathTable2[3] = NULL;
+ Props.CloudTexture = (u8*) LOAD_ASSET_RAW(gTextureExhaust0);
Props.Clouds = gYoshiValleyMooMooFarmClouds;
Props.CloudList = gYoshiValleyMooMooFarmClouds;
- Props.MinimapFinishlineX = 0;
- Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {0, 18, 255};
Props.Skybox.BottomRight = {197, 211, 255};
@@ -140,9 +148,9 @@ MooMooFarm::MooMooFarm() {
void MooMooFarm::Load() {
Course::Load();
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_moo_moo_farm_addr));
+ parse_course_displaylists((TrackSections*)LOAD_ASSET_RAW(d_course_moo_moo_farm_addr));
func_80295C6C();
- D_8015F8E4 = gCourseMinY - 10.0f;
+ Props.WaterLevel = gCourseMinY - 10.0f;
}
void MooMooFarm::LoadTextures() {
@@ -311,7 +319,7 @@ void MooMooFarm::BeginPlay() {
}
if (gModeSelection == VERSUS) {
- Vec3f pos = {0, 0, 0};
+ FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][50], 50, 3, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][140], 140, 3, 0.8333333f));
@@ -323,15 +331,6 @@ void MooMooFarm::BeginPlay() {
}
}
-// Likely sets minimap boundaries
-void MooMooFarm::MinimapSettings() {
- D_8018D220 = reinterpret_cast<uint8_t (*)[1024]>(dma_textures(gTextureExhaust0, 0x479, 0xC00));
- D_8018D2A0 = 0.0155f;
- D_8018D2C0[0] = 271;
- D_8018D2E0 = 18;
- D_8018D2E8 = 36;
-}
-
void MooMooFarm::WhatDoesThisDo(Player* player, int8_t playerId) {
if (((s16) gNearestWaypointByPlayerId[playerId] >= 0x145) &&
((s16) gNearestWaypointByPlayerId[playerId] < 0x18B)) {
@@ -362,17 +361,11 @@ void MooMooFarm::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
-// Positions the finishline on the minimap
-void MooMooFarm::MinimapFinishlinePosition() {
- //! todo: Place hard-coded values here.
- draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
-}
-
void MooMooFarm::Render(struct UnkStruct_800DC5EC* arg0) {
s16 temp_s0 = arg0->pathCounter;
s16 temp_s1 = arg0->playerDirection;
- func_802B5D64(D_800DC610, D_802B87D4, 0, 1);
+ set_track_light_direction(D_800DC610, D_802B87D4, 0, 1);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
@@ -445,8 +438,6 @@ void MooMooFarm::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_moo_moo_farm_dl_14088));
}
-void MooMooFarm::Collision() {}
-
void MooMooFarm::CreditsSpawnActors() {
dma_textures(gTextureTrees4Left, 0x3E8, 0x800);
dma_textures(gTextureTrees4Right, 0x3E8, 0x800);
diff --git a/src/engine/courses/MooMooFarm.h b/src/engine/courses/MooMooFarm.h
index 8b8b1b811..3c18e5024 100644
--- a/src/engine/courses/MooMooFarm.h
+++ b/src/engine/courses/MooMooFarm.h
@@ -30,13 +30,10 @@ public:
virtual void Load() override;
virtual void LoadTextures() override;
virtual void BeginPlay() override;
- virtual void MinimapSettings() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
- virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
- virtual void Collision() override;
virtual void CreditsSpawnActors() override;
virtual void Destroy() override;
};
diff --git a/src/engine/courses/PodiumCeremony.cpp b/src/engine/courses/PodiumCeremony.cpp
index 637dbc5d3..a4c01f588 100644
--- a/src/engine/courses/PodiumCeremony.cpp
+++ b/src/engine/courses/PodiumCeremony.cpp
@@ -12,6 +12,7 @@
#include "engine/objects/Podium.h"
#include "engine/objects/CheepCheep.h"
#include "engine/particles/StarEmitter.h"
+#include "engine/objects/GrandPrixBalloons.h"
extern "C" {
#include "main.h"
@@ -35,6 +36,7 @@ extern "C" {
#include "memory.h"
#include "courses/staff_ghost_data.h"
#include "podium_ceremony_actors.h"
+ #include "course.h"
extern const char *royal_raceway_dls[];
}
@@ -90,15 +92,23 @@ PodiumCeremony::PodiumCeremony() {
this->gfx = d_course_royal_raceway_packed_dls;
this->gfxSize = 5670;
Props.textures = podium_ceremony_textures;
- Props.MinimapDimensions = IVector2D(0, 0);
+ Props.Minimap.Width = 0;
+ Props.Minimap.Height = 0;
+ Props.Minimap.Pos[0].X = 262;
+ Props.Minimap.Pos[0].Y = 170;
+ Props.Minimap.PlayerX = 37;
+ Props.Minimap.PlayerY = 50;
+ Props.Minimap.PlayerScaleFactor = 0.014f;
+ Props.Minimap.FinishlineX = 0;
+ Props.Minimap.FinishlineY = 0;
+
+ Props.SetText(Props.Name, "royal raceway", sizeof(Props.Name));
+ Props.SetText(Props.DebugName, "p circuit", sizeof(Props.DebugName));
+ Props.SetText(Props.CourseLength, "1025m", sizeof(Props.CourseLength));
- Props.Name = "royal raceway";
- Props.DebugName = "p circuit";
- Props.CourseLength = "1025m";
Props.AIBehaviour = D_0D009188;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.4f;
- Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
Props.PathSizes = {500, 500, 500, 500, 1, 0, 0, 0, 0, 0, 0};
@@ -133,10 +143,9 @@ PodiumCeremony::PodiumCeremony() {
Props.PathTable2[2] = NULL;
Props.PathTable2[3] = NULL;
+ Props.CloudTexture = (u8*) LOAD_ASSET_RAW(gTextureExhaust4);
Props.Clouds = NULL; // no clouds
Props.CloudList = NULL;
- Props.MinimapFinishlineX = 0;
- Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {238, 144, 255};
Props.Skybox.BottomRight = {255, 224, 240};
@@ -147,14 +156,15 @@ PodiumCeremony::PodiumCeremony() {
Props.Skybox.FloorBottomLeft = {0, 0, 0};
Props.Skybox.FloorTopLeft = {255, 224, 240};
Props.Sequence = MusicSeq::MUSIC_SEQ_UNKNOWN;
+
+ Props.WaterLevel = -60.0f;
}
void PodiumCeremony::Load() {
Course::Load();
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_royal_raceway_addr));
+ parse_course_displaylists((TrackSections*)LOAD_ASSET_RAW(d_course_royal_raceway_addr));
func_80295C6C();
- D_8015F8E4 = -60.0f;
}
void PodiumCeremony::LoadTextures() {
@@ -189,7 +199,7 @@ void PodiumCeremony::BeginPlay() {
OTrophy* trophy = reinterpret_cast<OTrophy*>(gWorldInstance.AddObject(new OTrophy(pos, type, OTrophy::Behaviour::PODIUM_CEREMONY)));
- Vec3f kart = {0, 0, 0};
+ FVector kart = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(kart, &D_80164550[3][3], 3, 5, 1.25f));
gWorldInstance.AddObject(new OBombKart(kart, &D_80164550[3][40], 40, 0, 1.0f));
gWorldInstance.AddObject(new OBombKart(kart, &D_80164550[3][60], 60, 0, 1.0f));
@@ -197,18 +207,10 @@ void PodiumCeremony::BeginPlay() {
gWorldInstance.AddObject(new OBombKart(kart, &D_80164550[3][100], 100, 0, 1.0f));
gWorldInstance.AddObject(new OBombKart(kart, &D_80164550[3][120], 120, 0, 1.0f));
gWorldInstance.AddObject(new OBombKart(kart, &D_80164550[3][140], 140, 0, 1.0f));
-}
-// Likely sets minimap boundaries
-void PodiumCeremony::MinimapSettings() {
- D_8018D220 = reinterpret_cast<uint8_t (*)[1024]>(dma_textures(gTextureExhaust4, 0x3F8, 0x1000));
- D_8018D2C0[0] = 262;
- D_8018D2A0 = 0.014f;
- D_8018D2E0 = 37;
- D_8018D2E8 = 50;
- D_80165718 = -64;
- D_80165720 = 5;
- D_80165728 = -330;
+ if (gGamestate != CREDITS_SEQUENCE) {
+ gWorldInstance.AddObject(new OGrandPrixBalloons(FVector(-64, 5, -330)));
+ }
}
void PodiumCeremony::InitCourseObjects() {
@@ -217,10 +219,6 @@ void PodiumCeremony::InitCourseObjects() {
if (gModeSelection == GRAND_PRIX) {
func_80070714();
}
- for (i = 0; i < D_80165738; i++) {
- find_unused_obj_index(&gObjectParticle3[i]);
- init_object(gObjectParticle3[i], 0);
- }
}
}
@@ -257,12 +255,6 @@ void PodiumCeremony::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
-// Positions the finishline on the minimap
-void PodiumCeremony::MinimapFinishlinePosition() {
- //! todo: Place hard-coded values here.
- draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
-}
-
void PodiumCeremony::Render(struct UnkStruct_800DC5EC* arg0) {
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
@@ -296,6 +288,4 @@ void PodiumCeremony::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_royal_raceway_dl_D8E8));
}
-void PodiumCeremony::Collision() {}
-
void PodiumCeremony::Destroy() { }
diff --git a/src/engine/courses/PodiumCeremony.h b/src/engine/courses/PodiumCeremony.h
index 140d95889..6026d7f9f 100644
--- a/src/engine/courses/PodiumCeremony.h
+++ b/src/engine/courses/PodiumCeremony.h
@@ -29,14 +29,11 @@ public:
virtual void LoadTextures() override;
virtual void BeginPlay() override;
//virtual void InitClouds() override;
- virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
- virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
- virtual void Collision() override;
virtual void Destroy() override;
};
diff --git a/src/engine/courses/RainbowRoad.cpp b/src/engine/courses/RainbowRoad.cpp
index 11ca643b8..7c60d3af3 100644
--- a/src/engine/courses/RainbowRoad.cpp
+++ b/src/engine/courses/RainbowRoad.cpp
@@ -5,7 +5,7 @@
#include "RainbowRoad.h"
#include "World.h"
-#include "engine/actors/AFinishline.h"
+#include "engine/actors/Finishline.h"
#include "engine/objects/ChainChomp.h"
#include "engine/objects/BombKart.h"
#include "assets/rainbow_road_data.h"
@@ -30,6 +30,7 @@ extern "C" {
#include "actors.h"
#include "collision.h"
#include "memory.h"
+ #include "course.h"
extern const char *rainbow_road_dls[];
}
@@ -48,16 +49,24 @@ RainbowRoad::RainbowRoad() {
this->gfx = d_course_rainbow_road_packed_dls;
this->gfxSize = 5670;
Props.textures = rainbow_road_textures;
- Props.MinimapTexture = gTextureCourseOutlineRainbowRoad;
- Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
+ Props.Minimap.Texture = gTextureCourseOutlineRainbowRoad;
+ Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
+ Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
+ Props.Minimap.Pos[0].X = 261;
+ Props.Minimap.Pos[0].Y = 166;
+ Props.Minimap.PlayerX = 39;
+ Props.Minimap.PlayerY = 55;
+ Props.Minimap.PlayerScaleFactor = 0.0103f;
+ Props.Minimap.FinishlineX = 0;
+ Props.Minimap.FinishlineY = 0;
+
+ Props.SetText(Props.Name, "rainbow road", sizeof(Props.Name));
+ Props.SetText(Props.DebugName, "rainbow", sizeof(Props.DebugName));
+ Props.SetText(Props.CourseLength, "2000m", sizeof(Props.CourseLength));
- Props.Name = "rainbow road";
- Props.DebugName = "rainbow";
- Props.CourseLength = "2000m";
Props.AIBehaviour = D_0D0092C8;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.4f;
- Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 38;
Props.NearPersp = 2.0f;
@@ -97,8 +106,6 @@ RainbowRoad::RainbowRoad() {
Props.Clouds = gToadsTurnpikeRainbowRoadStars;
Props.CloudList = gToadsTurnpikeRainbowRoadStars;
- Props.MinimapFinishlineX = 0;
- Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {0, 0, 0};
Props.Skybox.BottomRight = {0, 0, 0};
@@ -109,15 +116,16 @@ RainbowRoad::RainbowRoad() {
Props.Skybox.FloorBottomLeft = {0, 0, 0};
Props.Skybox.FloorTopLeft = {0, 0, 0};
Props.Sequence = MusicSeq::MUSIC_SEQ_RAINBOW_ROAD;
+
+ Props.WaterLevel = 0.0f;
}
void RainbowRoad::Load() {
Course::Load();
D_800DC5C8 = 1;
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_rainbow_road_addr));
+ parse_course_displaylists((TrackSections*)LOAD_ASSET_RAW(d_course_rainbow_road_addr));
func_80295C6C();
- D_8015F8E4 = 0.0f;
// d_course_rainbow_road_packed_dl_2068
find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07002068), -0x6A, 255, 255, 255);
// d_course_rainbow_road_packed_dl_1E18
@@ -147,7 +155,7 @@ void RainbowRoad::BeginPlay() {
}
if (gModeSelection == VERSUS) {
- Vec3f pos = {0, 0, 0};
+ FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][50], 50, 3, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][100], 100, 1, 0.8333333f));
@@ -167,15 +175,6 @@ void RainbowRoad::UpdateClouds(s32 sp1C, Camera* camera) {
update_stars(sp1C, camera, this->Props.CloudList);
}
-// Likely sets minimap boundaries
-void RainbowRoad::MinimapSettings() {
- D_8018D2A0 = 0.0103f;
- D_8018D2C0[0] = 261;
- D_8018D2D8[0] = 166;
- D_8018D2E0 = 39;
- D_8018D2E8 = 55;
-}
-
void RainbowRoad::InitCourseObjects() {
if (gGamestate != CREDITS_SEQUENCE) {
size_t i;
@@ -206,12 +205,6 @@ void RainbowRoad::WhatDoesThisDo(Player* player, int8_t playerId) {}
void RainbowRoad::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
-// Positions the finishline on the minimap
-void RainbowRoad::MinimapFinishlinePosition() {
- //! todo: Place hard-coded values here.
- draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
-}
-
void RainbowRoad::Render(struct UnkStruct_800DC5EC* arg0) {
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
@@ -224,8 +217,6 @@ void RainbowRoad::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_rainbow_road_dl_16220));
}
-void RainbowRoad::Collision() {}
-
void RainbowRoad::Waypoints(Player* player, int8_t playerId) {
player->nearestWaypointId = gCopyNearestWaypointByPlayerId[playerId];
}
diff --git a/src/engine/courses/RainbowRoad.h b/src/engine/courses/RainbowRoad.h
index e5262f170..282655ace 100644
--- a/src/engine/courses/RainbowRoad.h
+++ b/src/engine/courses/RainbowRoad.h
@@ -29,17 +29,14 @@ public:
virtual void BeginPlay() override;
virtual void InitClouds() override;
virtual void UpdateClouds(s32, Camera*) override;
- virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void UpdateCourseObjects() override;
virtual void RenderCourseObjects(s32 cameraId) override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
- virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
- virtual void Collision() override;
virtual void Waypoints(Player* player, int8_t playerId) override;
virtual void DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) override;
virtual void CreditsSpawnActors() override;
diff --git a/src/engine/courses/RoyalRaceway.cpp b/src/engine/courses/RoyalRaceway.cpp
index 7ff7579ff..849087c3f 100644
--- a/src/engine/courses/RoyalRaceway.cpp
+++ b/src/engine/courses/RoyalRaceway.cpp
@@ -5,9 +5,10 @@
#include "RoyalRaceway.h"
#include "World.h"
-#include "engine/actors/AFinishline.h"
+#include "engine/actors/Finishline.h"
#include "engine/objects/BombKart.h"
#include "assets/royal_raceway_data.h"
+#include "engine/objects/GrandPrixBalloons.h"
extern "C" {
#include "main.h"
@@ -30,6 +31,7 @@ extern "C" {
#include "collision.h"
#include "memory.h"
#include "courses/staff_ghost_data.h"
+ #include "course.h"
extern const char *royal_raceway_dls[];
}
@@ -85,16 +87,24 @@ RoyalRaceway::RoyalRaceway() {
this->gfx = d_course_royal_raceway_packed_dls;
this->gfxSize = 5670;
Props.textures = royal_raceway_textures;
- Props.MinimapTexture = gTextureCourseOutlineRoyalRaceway;
- Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
+ Props.Minimap.Texture = gTextureCourseOutlineRoyalRaceway;
+ Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
+ Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
+ Props.Minimap.Pos[0].X = 262;
+ Props.Minimap.Pos[0].Y = 170;
+ Props.Minimap.PlayerX = 37;
+ Props.Minimap.PlayerY = 50;
+ Props.Minimap.PlayerScaleFactor = 0.014f;
+ Props.Minimap.FinishlineX = 0;
+ Props.Minimap.FinishlineY = 0;
+
+ Props.SetText(Props.Name, "royal raceway", sizeof(Props.Name));
+ Props.SetText(Props.DebugName, "p circuit", sizeof(Props.DebugName));
+ Props.SetText(Props.CourseLength, "1025m", sizeof(Props.CourseLength));
- Props.Name = "royal raceway";
- Props.DebugName = "p circuit";
- Props.CourseLength = "1025m";
Props.AIBehaviour = D_0D009188;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.4f;
- Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
Props.NearPersp = 9.0f;
@@ -132,10 +142,9 @@ RoyalRaceway::RoyalRaceway() {
Props.PathTable2[2] = NULL;
Props.PathTable2[3] = NULL;
+ Props.CloudTexture = (u8*) LOAD_ASSET_RAW(gTextureExhaust4);
Props.Clouds = gRoyalRacewayClouds;
Props.CloudList = gRoyalRacewayClouds;
- Props.MinimapFinishlineX = 0;
- Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {238, 144, 255};
Props.Skybox.BottomRight = {255, 224, 240};
@@ -146,14 +155,15 @@ RoyalRaceway::RoyalRaceway() {
Props.Skybox.FloorBottomLeft = {0, 0, 0};
Props.Skybox.FloorTopLeft = {255, 224, 240};
Props.Sequence = MusicSeq::MUSIC_SEQ_RACEWAYS_WARIO_STADIUM;
+
+ Props.WaterLevel = -60.0f;
}
void RoyalRaceway::Load() {
Course::Load();
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_royal_raceway_addr));
+ parse_course_displaylists((TrackSections*)LOAD_ASSET_RAW(d_course_royal_raceway_addr));
func_80295C6C();
- D_8015F8E4 = -60.0f;
}
void RoyalRaceway::LoadTextures() {
@@ -176,7 +186,7 @@ void RoyalRaceway::BeginPlay() {
spawn_piranha_plants((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_royal_raceway_piranha_plant_spawn));
if (gModeSelection == VERSUS) {
- Vec3f pos = {0, 0, 0};
+ FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][50], 50, 3, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][100], 100, 3, 0.8333333f));
@@ -186,18 +196,9 @@ void RoyalRaceway::BeginPlay() {
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][0], 0, 0, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][0], 0, 0, 0.8333333f));
}
-}
-
-// Likely sets minimap boundaries
-void RoyalRaceway::MinimapSettings() {
- D_8018D220 = reinterpret_cast<uint8_t (*)[1024]>(dma_textures(gTextureExhaust4, 0x3F8, 0x1000));
- D_8018D2C0[0] = 262;
- D_8018D2A0 = 0.014f;
- D_8018D2E0 = 37;
- D_8018D2E8 = 50;
- D_80165718 = -64;
- D_80165720 = 5;
- D_80165728 = -330;
+ if (gGamestate != CREDITS_SEQUENCE) {
+ gWorldInstance.AddObject(new OGrandPrixBalloons(FVector(-64, 5, -330)));
+ }
}
void RoyalRaceway::InitCourseObjects() {
@@ -206,16 +207,9 @@ void RoyalRaceway::InitCourseObjects() {
if (gModeSelection == GRAND_PRIX) {
func_80070714();
}
- for (i = 0; i < D_80165738; i++) {
- find_unused_obj_index(&gObjectParticle3[i]);
- init_object(gObjectParticle3[i], 0);
- }
}
}
-void RoyalRaceway::SomeSounds() {
-}
-
void RoyalRaceway::WhatDoesThisDo(Player* player, int8_t playerId) {
if (((s16) gNearestWaypointByPlayerId[playerId] >= 0x180) &&
((s16) gNearestWaypointByPlayerId[playerId] < 0x1E1)) {
@@ -246,12 +240,6 @@ void RoyalRaceway::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
-// Positions the finishline on the minimap
-void RoyalRaceway::MinimapFinishlinePosition() {
- //! todo: Place hard-coded values here.
- draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
-}
-
void RoyalRaceway::SetStaffGhost() {
u32 temp_v0 = func_800B4E24(0) & 0xfffff;
if (temp_v0 <= 16000) {
@@ -298,8 +286,6 @@ void RoyalRaceway::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_royal_raceway_dl_D8E8));
}
-void RoyalRaceway::Collision() {}
-
void RoyalRaceway::Waypoints(Player* player, int8_t playerId) {
s16 waypoint = gNearestWaypointByPlayerId[playerId];
if ((waypoint >= 0x258) && (waypoint < 0x2A4)) {
@@ -322,5 +308,3 @@ void RoyalRaceway::ScrollingTextures() {
// d_course_royal_raceway_packed_dl_A648
find_and_set_tile_size((uintptr_t) segmented_gfx_to_virtual((void*)0x0700A648), 0, D_802B87BC);
}
-
-void RoyalRaceway::Destroy() { }
diff --git a/src/engine/courses/RoyalRaceway.h b/src/engine/courses/RoyalRaceway.h
index 2a3095bc8..7fe973edd 100644
--- a/src/engine/courses/RoyalRaceway.h
+++ b/src/engine/courses/RoyalRaceway.h
@@ -27,17 +27,12 @@ public:
virtual void Load() override;
virtual void LoadTextures() override;
virtual void BeginPlay() override;
- virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
- virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
- virtual void MinimapFinishlinePosition() override;
virtual void SetStaffGhost() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
- virtual void Collision() override;
virtual void ScrollingTextures() override;
virtual void Waypoints(Player* player, int8_t playerId) override;
- virtual void Destroy() override;
};
diff --git a/src/engine/courses/SherbetLand.cpp b/src/engine/courses/SherbetLand.cpp
index a452d2c03..7eb7e958c 100644
--- a/src/engine/courses/SherbetLand.cpp
+++ b/src/engine/courses/SherbetLand.cpp
@@ -5,7 +5,7 @@
#include "SherbetLand.h"
#include "World.h"
-#include "engine/actors/AFinishline.h"
+#include "engine/actors/Finishline.h"
#include "engine/objects/BombKart.h"
#include "assets/sherbet_land_data.h"
#include "engine/objects/Penguin.h"
@@ -30,6 +30,7 @@ extern "C" {
#include "actors.h"
#include "collision.h"
#include "memory.h"
+ #include "course.h"
extern const char *sherbet_land_dls[];
extern const char *sherbet_land_dls_2[];
}
@@ -48,19 +49,27 @@ SherbetLand::SherbetLand() {
this->gfx = d_course_sherbet_land_packed_dls;
this->gfxSize = 1803;
Props.textures = sherbet_land_textures;
- Props.MinimapTexture = gTextureCourseOutlineSherbetLand;
- Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
-
- Props.Name = "sherbet land";
- Props.DebugName = "sherbet";
- Props.CourseLength = "756m";
+ Props.Minimap.Texture = gTextureCourseOutlineSherbetLand;
+ Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
+ Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
+ Props.Minimap.Pos[0].X = 262;
+ Props.Minimap.Pos[0].Y = 170;
+ Props.Minimap.PlayerX = 52;
+ Props.Minimap.PlayerY = 33;
+ Props.Minimap.PlayerScaleFactor = 0.015f;
+ Props.Minimap.FinishlineX = 0;
+ Props.Minimap.FinishlineY = 0;
+ Props.Minimap.Colour = {72, 100, 255};
+
+ Props.SetText(Props.Name, "sherbet land", sizeof(Props.Name));
+ Props.SetText(Props.DebugName, "sherbet", sizeof(Props.DebugName));
+ Props.SetText(Props.CourseLength, "756m", sizeof(Props.CourseLength));
Props.LakituTowType = (s32)OLakitu::LakituTowType::ICE;
Props.AIBehaviour = D_0D009280;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.3f;
- Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
Props.NearPersp = 9.0f;
@@ -98,10 +107,9 @@ SherbetLand::SherbetLand() {
Props.PathTable2[2] = NULL;
Props.PathTable2[3] = NULL;
+ Props.CloudTexture = (u8*) LOAD_ASSET_RAW(gTextureExhaust1);
Props.Clouds = gSherbetLandClouds;
Props.CloudList = gSherbetLandClouds;
- Props.MinimapFinishlineX = 0;
- Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {128, 184, 248};
Props.Skybox.BottomRight = {216, 232, 248};
@@ -112,21 +120,26 @@ SherbetLand::SherbetLand() {
Props.Skybox.FloorBottomLeft = {128, 184, 248};
Props.Skybox.FloorTopLeft = {216, 232, 248};
Props.Sequence = MusicSeq::MUSIC_SEQ_FRAPPE_SNOWLAND;
+
+ Props.WaterLevel = -18.0f;
}
void SherbetLand::Load() {
Course::Load();
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_sherbet_land_addr));
+ parse_course_displaylists((TrackSections*)LOAD_ASSET_RAW(d_course_sherbet_land_addr));
func_80295C6C();
- D_8015F8E4 = -18.0f;
// d_course_sherbet_land_packed_dl_1EB8
find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07001EB8), -0x4C, 255, 255, 255);
// d_course_sherbet_land_packed_dl_2308
find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07002308), -0x6A, 255, 255, 255);
}
-void SherbetLand::LoadTextures() {
+f32 SherbetLand::GetWaterLevel(FVector pos, Collision* collision) {
+ if ((get_surface_type(collision->meshIndexZX) & 0xFF) == SNOW) {
+ return (f32) (gCourseMinY - 0xA);
+ }
+ return Props.WaterLevel;
}
void SherbetLand::BeginPlay() {
@@ -134,65 +147,65 @@ void SherbetLand::BeginPlay() {
// Multiplayer does not spawn the big penguin
// if (gPlayerCountSelection1 == 1) {
- Vec3f pos = {-383.0f, 2.0f, -690.0f};
+ FVector pos = {-383.0f, 2.0f, -690.0f};
gWorldInstance.AddObject(new OPenguin(pos, 0, OPenguin::PenguinType::EMPEROR, OPenguin::Behaviour::STRUT));
// }
- Vec3f pos2 = {-2960.0f, -80.0f, 1521.0f};
+ FVector pos2 = { -2960.0f, -80.0f, 1521.0f };
auto penguin = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos2, 0x150, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE)));
auto penguin2 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos2, 0x150, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE)));
penguin->Diameter = penguin2->Diameter = 100.0f;
- Vec3f pos3 = {-2490.0f, -80.0f, 1612.0f};
+ FVector pos3 = { -2490.0f, -80.0f, 1612.0f };
auto penguin3 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos3, 0x100, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE)));
auto penguin4 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos3, 0x100, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE)));
penguin3->Diameter = penguin4->Diameter = 80.0f;
- Vec3f pos4 = {-2098.0f, -80.0f, 1624.0f};
+ FVector pos4 = { -2098.0f, -80.0f, 1624.0f };
auto penguin5 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos4, 0xFF00, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE)));
auto penguin6 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos4, 0xFF00, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE)));
penguin5->Diameter = penguin6->Diameter = 80.0f;
- Vec3f pos5 = {-2080.0f, -80.0f, 1171.0f};
+ FVector pos5 = { -2080.0f, -80.0f, 1171.0f };
auto penguin7 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos5, 0x150, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE)));
auto penguin8 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos5, 0x150, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE)));
penguin7->Diameter = penguin8->Diameter = 80.0f;
if (gGamestate == CREDITS_SEQUENCE) {
- Vec3f pos6 = {380.0, 0.0f, -535.0f};
+ FVector pos6 = { 380.0, 0.0f, -535.0f };
auto penguin9 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos6, 0x9000, OPenguin::PenguinType::CREDITS, OPenguin::Behaviour::SLIDE3)));
penguin9->MirrorModeAngleOffset = -0x4000;
} else {
- Vec3f pos6 = {146.0f, 0.0f, -380.0f};
+ FVector pos6 = { 146.0f, 0.0f, -380.0f };
auto penguin9 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos6, 0x9000, OPenguin::PenguinType::CHICK, OPenguin::Behaviour::SLIDE3)));
penguin9->MirrorModeAngleOffset = -0x4000;
}
- Vec3f pos7 = {380.0f, 0.0f, -766.0f};
+ FVector pos7 = { 380.0f, 0.0f, -766.0f };
auto penguin10 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos7, 0x5000, OPenguin::PenguinType::CHICK, OPenguin::Behaviour::SLIDE4)));
penguin10->MirrorModeAngleOffset = 0x8000;
- Vec3f pos8 = {-2300.0f, 0.0f, -210.0f};
+ FVector pos8 = { -2300.0f, 0.0f, -210.0f };
auto penguin11 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos8, 0xC000, OPenguin::PenguinType::CHICK, OPenguin::Behaviour::SLIDE6)));
penguin11->MirrorModeAngleOffset = 0x8000;
- Vec3f pos9 = {-2500.0f, 0.0f, -250.0f};
+ FVector pos9 = { -2500.0f, 0.0f, -250.0f };
auto penguin12 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos9, 0x4000, OPenguin::PenguinType::CHICK, OPenguin::Behaviour::SLIDE6)));
penguin12->MirrorModeAngleOffset = 0x8000;
- Vec3f pos10 = {-535.0f, 0.0f, 875.0f};
+ FVector pos10 = { -535.0f, 0.0f, 875.0f };
auto penguin13 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos10, 0x8000, OPenguin::PenguinType::CHICK, OPenguin::Behaviour::SLIDE6)));
penguin13->MirrorModeAngleOffset = -0x4000;
- Vec3f pos11 = {-250.0f, 0.0f, 953.0f};
+ FVector pos11 = { -250.0f, 0.0f, 953.0f };
auto penguin14 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos11, 0x9000, OPenguin::PenguinType::CHICK, OPenguin::Behaviour::SLIDE6)));
penguin14->MirrorModeAngleOffset = -0x4000;
if (gGamestate != CREDITS_SEQUENCE) {
if (gModeSelection == VERSUS) {
- Vec3f kart = {0, 0, 0};
+ FVector kart = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(kart, &D_80164550[0][50], 50, 3, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(kart, &D_80164550[0][100], 100, 1, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(kart, &D_80164550[0][150], 150, 3, 0.8333333f));
@@ -204,21 +217,6 @@ void SherbetLand::BeginPlay() {
}
}
-// Likely sets minimap boundaries
-void SherbetLand::MinimapSettings() {
- D_8018D220 = reinterpret_cast<uint8_t (*)[1024]>(dma_textures(gTextureExhaust1, 0x485, 0xC00));
- D_8018D2A0 = 0.015f;
- D_8018D2C0[0] = 262;
- D_8018D2E0 = 52;
- D_8018D2E8 = 33;
- D_8018D300 = 72;
- D_8018D308 = 100;
- D_8018D310 = 255;
-}
-
-void SherbetLand::InitCourseObjects() {
-}
-
void SherbetLand::UpdateCourseObjects() {
if (gGamestate != CREDITS_SEQUENCE) {
func_800842C8();
@@ -231,19 +229,6 @@ void SherbetLand::RenderCourseObjects(s32 cameraId) {
}
}
-void SherbetLand::SomeSounds() {
-}
-
-void SherbetLand::WhatDoesThisDo(Player* player, int8_t playerId) {}
-
-void SherbetLand::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
-
-// Positions the finishline on the minimap
-void SherbetLand::MinimapFinishlinePosition() {
- //! todo: Place hard-coded values here.
- draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
-}
-
void SherbetLand::Render(struct UnkStruct_800DC5EC* arg0) {
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
@@ -257,8 +242,6 @@ void SherbetLand::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_sherbet_land_dl_9AE8));
}
-void SherbetLand::Collision() {}
-
void SherbetLand::DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) {
Mat4 matrix;
@@ -275,7 +258,7 @@ void SherbetLand::DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCoun
render_course_segments(sherbet_land_dls_2, screen);
gDPSetAlphaCompare(gDisplayListHead++, G_AC_NONE);
- if ((func_80290C20(screen->camera) == 1) && (func_802AAB4C(screen->player) < screen->player->pos[1])) {
+ if ((func_80290C20(screen->camera) == 1) && (get_water_level(screen->player) < screen->player->pos[1])) {
gSPSetGeometryMode(gDisplayListHead++, G_ZBUFFER);
gDPSetCombineMode(gDisplayListHead++, G_CC_SHADE, G_CC_SHADE);
gDPSetRenderMode(gDisplayListHead++, G_RM_AA_ZB_OPA_SURF, G_RM_AA_ZB_OPA_SURF2);
@@ -291,5 +274,3 @@ void SherbetLand::CreditsSpawnActors() {
// d_course_sherbet_land_packed_dl_2308
find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07002308), -0x6A, 0xFF, 0xFF, 0xFF);
}
-
-void SherbetLand::Destroy() { }
diff --git a/src/engine/courses/SherbetLand.h b/src/engine/courses/SherbetLand.h
index 13e41e592..eb62e2807 100644
--- a/src/engine/courses/SherbetLand.h
+++ b/src/engine/courses/SherbetLand.h
@@ -25,20 +25,12 @@ public:
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
virtual void Load() override;
- virtual void LoadTextures() override;
+ virtual f32 GetWaterLevel(FVector pos, Collision* collision) override;
virtual void BeginPlay() override;
- virtual void MinimapSettings() override;
- virtual void InitCourseObjects() override;
virtual void UpdateCourseObjects() override;
virtual void RenderCourseObjects(s32 cameraId) override;
- virtual void SomeSounds() override;
- virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
- virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
- virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
- virtual void Collision() override;
virtual void DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) override;
virtual void CreditsSpawnActors() override;
- virtual void Destroy() override;
};
diff --git a/src/engine/courses/Skyscraper.cpp b/src/engine/courses/Skyscraper.cpp
index abf622ae2..4c165a787 100644
--- a/src/engine/courses/Skyscraper.cpp
+++ b/src/engine/courses/Skyscraper.cpp
@@ -64,16 +64,24 @@ Skyscraper::Skyscraper() {
this->gfx = d_course_skyscraper_packed_dls;
this->gfxSize = 548;
Props.textures = skyscraper_textures;
- Props.MinimapTexture = gTextureCourseOutlineSkyscraper;
- Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
+ Props.Minimap.Texture = gTextureCourseOutlineSkyscraper;
+ Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
+ Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
+ Props.Minimap.Pos[0].X = 257;
+ Props.Minimap.Pos[0].Y = 170;
+ Props.Minimap.PlayerX = 32;
+ Props.Minimap.PlayerY = 32;
+ Props.Minimap.PlayerScaleFactor = 0.0445f;
+ Props.Minimap.FinishlineX = 0;
+ Props.Minimap.FinishlineY = 0;
+
+ Props.SetText(Props.Name, "skyscraper", sizeof(Props.Name));
+ Props.SetText(Props.DebugName, "skyscraper", sizeof(Props.DebugName));
+ Props.SetText(Props.CourseLength, "", sizeof(Props.CourseLength));
- Props.Name = "skyscraper";
- Props.DebugName = "skyscraper";
- Props.CourseLength = "";
Props.AIBehaviour = D_0D008F18;
Props.AIMaximumSeparation = -1.0f;
Props.AIMinimumSeparation = 0.5f;
- Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
Props.NearPersp = 2.0f;
@@ -113,8 +121,6 @@ Skyscraper::Skyscraper() {
Props.Clouds = NULL; // no clouds
Props.CloudList = NULL;
- Props.MinimapFinishlineX = 0;
- Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {0, 0, 0};
Props.Skybox.BottomRight = {0, 0, 0};
@@ -125,6 +131,8 @@ Skyscraper::Skyscraper() {
Props.Skybox.FloorBottomLeft = {0, 0, 0};
Props.Skybox.FloorTopLeft = {0, 0, 0};
Props.Sequence = MusicSeq::MUSIC_SEQ_BATTLE_ARENAS;
+
+ Props.WaterLevel = -480.0f;
}
void Skyscraper::Load() {
@@ -135,8 +143,6 @@ void Skyscraper::Load() {
// d_course_skyscraper_packed_dl_258
generate_collision_mesh_with_default_section_id((Gfx*) segmented_gfx_to_virtual((void*)0x07000258), 1);
func_80295C6C();
-
- D_8015F8E4 = -480.0f;
}
void Skyscraper::LoadTextures() {
@@ -146,7 +152,7 @@ void Skyscraper::BeginPlay() {
spawn_all_item_boxes((ActorSpawnData*)LOAD_ASSET_RAW(d_course_skyscraper_item_box_spawns));
if (gModeSelection == VERSUS) {
- Vec3f pos = {0, 0, 0};
+ FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][20], 20, 0, 1.0f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][40], 40, 0, 1.0f));
@@ -158,13 +164,6 @@ void Skyscraper::BeginPlay() {
}
}
-// Likely sets minimap boundaries
-void Skyscraper::MinimapSettings() {
- D_8018D2A0 = 0.0445f;
- D_8018D2E0 = 32;
- D_8018D2E8 = 32;
-}
-
void Skyscraper::InitCourseObjects() {}
void Skyscraper::SomeSounds() {}
@@ -173,14 +172,8 @@ void Skyscraper::WhatDoesThisDo(Player* player, int8_t playerId) {}
void Skyscraper::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
-// Positions the finishline on the minimap
-void Skyscraper::MinimapFinishlinePosition() {
- //! todo: Place hard-coded values here.
- draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
-}
-
void Skyscraper::Render(struct UnkStruct_800DC5EC* arg0) {
- func_802B5D64(D_800DC610, D_802B87D4, 0, 1);
+ set_track_light_direction(D_800DC610, D_802B87D4, 0, 1);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
@@ -204,8 +197,6 @@ void Skyscraper::Render(struct UnkStruct_800DC5EC* arg0) {
void Skyscraper::RenderCredits() {}
-void Skyscraper::Collision() {}
-
void Skyscraper::Waypoints(Player* player, int8_t playerId) {
player->nearestWaypointId = 0;
}
diff --git a/src/engine/courses/Skyscraper.h b/src/engine/courses/Skyscraper.h
index b9b998f73..ed6592121 100644
--- a/src/engine/courses/Skyscraper.h
+++ b/src/engine/courses/Skyscraper.h
@@ -28,15 +28,12 @@ public:
virtual void LoadTextures() override;
virtual void BeginPlay() override;
//virtual void InitClouds() override;
- virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
- virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
- virtual void Collision() override;
virtual void Waypoints(Player* player, int8_t playerId) override;
virtual void Destroy() override;
};
diff --git a/src/engine/courses/TestCourse.cpp b/src/engine/courses/TestCourse.cpp
index 3217f8f4a..eebaee17a 100644
--- a/src/engine/courses/TestCourse.cpp
+++ b/src/engine/courses/TestCourse.cpp
@@ -6,7 +6,7 @@
#include "TestCourse.h"
#include "World.h"
-#include "engine/actors/AFinishline.h"
+#include "engine/actors/Finishline.h"
#include "engine/actors/BowserStatue.h"
#include "engine/actors/Ship.h"
#include "engine/actors/SpaghettiShip.h"
@@ -16,8 +16,8 @@
#include "assets/mario_raceway_data.h"
#include "assets/bowsers_castle_data.h"
#include "assets/bowsers_castle_displaylists.h"
-#include "engine/actors/ATree.h"
-#include "engine/actors/ACloud.h"
+#include "engine/actors/Tree.h"
+#include "engine/actors/Cloud.h"
#include "engine/vehicles/Train.h"
#include "engine/objects/Trophy.h"
#include "engine/objects/CheepCheep.h"
@@ -28,6 +28,7 @@
#include "engine/objects/HotAirBalloon.h"
#include "engine/objects/Crab.h"
#include "engine/objects/Boos.h"
+#include "engine/objects/GrandPrixBalloons.h"
extern "C" {
#include "main.h"
@@ -49,12 +50,7 @@ extern "C" {
#include "actors.h"
#include "collision.h"
#include "memory.h"
- typedef struct {
- Gfx* addr;
- u8 surfaceType;
- u8 sectionId;
- u16 flags;
- } TrackSections;
+ #include "course.h"
extern Gfx test_course_dls[];
extern Vtx mario_Plane_001_mesh_vtx_1[];
extern Gfx mario_Plane_001_mesh[];
@@ -65,18 +61,27 @@ extern "C" {
TestCourse::TestCourse() {
this->gfxSize = 100;
this->textures = NULL;
- Props.MinimapTexture = gTextureCourseOutlineMarioRaceway;
- Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
-
- Props.Id = "mk:test_course";
- Props.Name = "Test Course";
- Props.DebugName = "test track";
- Props.CourseLength = "100m";
+ Props.Minimap.Texture = gTextureCourseOutlineMarioRaceway;
+ Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
+ Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
+ Props.Minimap.Pos[0].X = 260;
+ Props.Minimap.Pos[0].Y = 170;
+ Props.Minimap.PlayerX = 6;
+ Props.Minimap.PlayerY = 28;
+ Props.Minimap.PlayerScaleFactor = 0.022f;
+ Props.Minimap.FinishlineX = 0;
+ Props.Minimap.FinishlineY = 0;
+ Props.Minimap.Colour = {255, 255, 255};
+
+ Id = "mk:test_course";
+
+ Props.SetText(Props.Name, "Test Course", sizeof(Props.Name));
+ Props.SetText(Props.DebugName, "test track", sizeof(Props.DebugName));
+ Props.SetText(Props.CourseLength, "100m", sizeof(Props.CourseLength));
Props.AIBehaviour = D_0D008F28;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.3f;
- Props.SomePtr = D_800DCB34;
Props.AISteeringSensitivity = 48;
Props.NearPersp = 9.0f;
@@ -114,10 +119,9 @@ TestCourse::TestCourse() {
Props.PathTable2[2] = NULL;
Props.PathTable2[3] = NULL;
+ Props.CloudTexture = (u8*) LOAD_ASSET_RAW(gTextureExhaust5);
Props.Clouds = gKalimariDesertClouds;
Props.CloudList = gLuigiRacewayClouds;
- Props.MinimapFinishlineX = 0;
- Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {120, 140, 188};
Props.Skybox.BottomRight = {216, 232, 248};
@@ -135,9 +139,9 @@ void TestCourse::Load() {
generate_collision_mesh_with_defaults(mario_Plane_001_mesh);
- parse_course_displaylists((TrackSectionsI*)test_course_addr);
+ parse_course_displaylists((TrackSections*)test_course_addr);
func_80295C6C();
- D_8015F8E4 = gCourseMinY - 10.0f;
+ Props.WaterLevel = gCourseMinY - 10.0f;
}
void TestCourse::LoadTextures() {
@@ -267,7 +271,7 @@ void TestCourse::BeginPlay() {
// gWorldInstance.AddObject(new OCheepCheep(FVector(0, 40, 0), OCheepCheep::CheepType::RACE, IPathSpan(0, 10)));
// gWorldInstance.AddObject(new OTrophy(FVector(0,0,0), OTrophy::TrophyType::GOLD, OTrophy::Behaviour::GO_FISH));
//gWorldInstance.AddObject(new OSnowman(FVector(0, 0, 0)));
- //gWorldInstance.AddObject(new OTrashBin(FVector(0.0f, 0.0f, 0.0f), FRotation(0, 90, 0), 1.0f, OTrashBin::Behaviour::MUNCHING));
+ //gWorldInstance.AddObject(new OTrashBin(FVector(0.0f, 0.0f, 0.0f), IRotator(0, 90, 0), 1.0f, OTrashBin::Behaviour::MUNCHING));
//gWorldInstance.AddObject(new OHedgehog(FVector(0, 0, 0), FVector2D(0, -200), 9));
//gWorldInstance.AddObject(new OFlagpole(FVector(0, 0, -200), 0x400));
@@ -285,32 +289,16 @@ void TestCourse::BeginPlay() {
//gWorldInstance.AddTrain(ATrain::TenderStatus::HAS_TENDER, 5, 2.5f, 0);
//gWorldInstance.AddTrain(ATrain::TenderStatus::HAS_TENDER, 5, 2.5f, 8);
- Vec3f pos2 = {0, 0, 0};
+ FVector pos2 = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos2, &D_80164550[0][25], 25, 4, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos2, &D_80164550[0][45], 45, 4, 0.8333333f));
gWorldInstance.AddActor(new AShip(FVector(0, 0, 0), AShip::Skin::SHIP3));
+ gWorldInstance.AddObject(new OGrandPrixBalloons(FVector(0, 0, 0)));
}
-// Likely sets minimap boundaries
-void TestCourse::MinimapSettings() {
- D_8018D220 = reinterpret_cast<uint8_t (*)[1024]>(dma_textures(gTextureExhaust5, 0x443, 0x1000));
- D_8018D2A0 = 0.022f;
- D_8018D2E0 = 6;
- D_8018D2E8 = 28;
- D_8018D2C0[0] = 260;
- D_8018D2D8[0] = 170;
- D_80165718 = 0;
- D_80165720 = 5;
- D_80165728 = -240;
-}
-
-void TestCourse::InitCourseObjects() {}
-
-void TestCourse::SomeSounds() {}
-
void TestCourse::WhatDoesThisDo(Player* player, int8_t playerId) {
if (((s16) gNearestWaypointByPlayerId[playerId] >= 0x19B) &&
((s16) gNearestWaypointByPlayerId[playerId] < 0x1B9)) {
@@ -341,16 +329,10 @@ void TestCourse::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
-// Positions the finishline on the minimap
-void TestCourse::MinimapFinishlinePosition() {
- //! todo: Place hard-coded values here.
- draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
-}
-
void TestCourse::Render(struct UnkStruct_800DC5EC* arg0) {
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
- func_802B5D64(D_800DC610, D_802B87D4, 0, 1);
+ set_track_light_direction(D_800DC610, D_802B87D4, 0, 1);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
@@ -362,13 +344,6 @@ void TestCourse::Render(struct UnkStruct_800DC5EC* arg0) {
gSPDisplayList(gDisplayListHead++, mario_Plane_001_mesh);
}
-void TestCourse::RenderCredits() {
-}
-
-void TestCourse::Collision() {}
-
-void TestCourse::Destroy() { }
-
bool TestCourse::IsMod() {
return true;
} \ No newline at end of file
diff --git a/src/engine/courses/TestCourse.h b/src/engine/courses/TestCourse.h
index 3421304e2..d44e0a266 100644
--- a/src/engine/courses/TestCourse.h
+++ b/src/engine/courses/TestCourse.h
@@ -27,15 +27,8 @@ public:
virtual void Load() override;
virtual void LoadTextures() override;
virtual void BeginPlay() override;
- virtual void MinimapSettings() override;
- virtual void InitCourseObjects() override;
- virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
- virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
- virtual void RenderCredits() override;
- virtual void Collision() override;
- virtual void Destroy() override;
virtual bool IsMod() override;
};
diff --git a/src/engine/courses/ToadsTurnpike.cpp b/src/engine/courses/ToadsTurnpike.cpp
index a9507acad..867fedf25 100644
--- a/src/engine/courses/ToadsTurnpike.cpp
+++ b/src/engine/courses/ToadsTurnpike.cpp
@@ -7,7 +7,7 @@
#include "World.h"
#include "engine/objects/BombKart.h"
#include "assets/toads_turnpike_data.h"
-#include "engine/actors/AFinishline.h"
+#include "engine/actors/Finishline.h"
#include "engine/vehicles/Bus.h"
#include "engine/vehicles/Car.h"
#include "engine/vehicles/Truck.h"
@@ -36,6 +36,7 @@ extern "C" {
#include "collision.h"
#include "memory.h"
#include "code_80086E70.h"
+ #include "course.h"
extern const char *d_course_toads_turnpike_dl_list[];
extern s16 currentScreenSection;
extern s8 gPlayerCount;
@@ -69,16 +70,24 @@ ToadsTurnpike::ToadsTurnpike() {
this->gfx = d_course_toads_turnpike_packed_dls;
this->gfxSize = 3427;
Props.textures = toads_turnpike_textures;
- Props.MinimapTexture = gTextureCourseOutlineToadsTurnpike;
- Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
+ Props.Minimap.Texture = gTextureCourseOutlineToadsTurnpike;
+ Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
+ Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
+ Props.Minimap.Pos[0].X = 252;
+ Props.Minimap.Pos[0].Y = 170;
+ Props.Minimap.PlayerX = 57;
+ Props.Minimap.PlayerY = 44;
+ Props.Minimap.PlayerScaleFactor = 0.013f;
+ Props.Minimap.FinishlineX = 0;
+ Props.Minimap.FinishlineY = 0;
+
+ Props.SetText(Props.Name, "toad's turnpike", sizeof(Props.Name));
+ Props.SetText(Props.DebugName, "highway", sizeof(Props.DebugName));
+ Props.SetText(Props.CourseLength, "1036m", sizeof(Props.CourseLength));
- Props.Name = "toad's turnpike";
- Props.DebugName = "highway";
- Props.CourseLength = "1036m";
Props.AIBehaviour = D_0D009238;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.5f;
- Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 40;
Props.NearPersp = 9.0f;
@@ -126,9 +135,6 @@ ToadsTurnpike::ToadsTurnpike() {
this->FinishlineSpawnPoint = finish;
- Props.MinimapFinishlineX = 0;
- Props.MinimapFinishlineY = 0;
-
Props.Skybox.TopRight = {0, 2, 94};
Props.Skybox.BottomRight = {209, 65, 23};
Props.Skybox.BottomLeft = {209, 65, 23};
@@ -148,9 +154,9 @@ void ToadsTurnpike::Load() {
D_801625F0 = 4;
D_802B87B0 = 993;
D_802B87B4 = 1000;
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_toads_turnpike_addr));
+ parse_course_displaylists((TrackSections*)LOAD_ASSET_RAW(d_course_toads_turnpike_addr));
func_80295C6C();
- D_8015F8E4 = gCourseMinY - 10.0f;
+ Props.WaterLevel = gCourseMinY - 10.0f;
}
void ToadsTurnpike::LoadTextures() {
@@ -195,7 +201,7 @@ void ToadsTurnpike::BeginPlay() {
}
if (gModeSelection == VERSUS) {
- Vec3f pos = {0, 0, 0};
+ FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][50], 50, 3, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][100], 100, 1, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][150], 150, 3, 0.8333333f));
@@ -215,14 +221,6 @@ void ToadsTurnpike::UpdateClouds(s32 sp1C, Camera* camera) {
update_stars(sp1C, camera, this->Props.CloudList);
}
-// Likely sets minimap boundaries
-void ToadsTurnpike::MinimapSettings() {
- D_8018D2A0 = 0.013f;
- D_8018D2C0[0] = 252;
- D_8018D2E0 = 57;
- D_8018D2E8 = 44;
-}
-
void ToadsTurnpike::SomeSounds() {}
void ToadsTurnpike::WhatDoesThisDo(Player* player, int8_t playerId) {
@@ -253,14 +251,8 @@ void ToadsTurnpike::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
-// Positions the finishline on the minimap
-void ToadsTurnpike::MinimapFinishlinePosition() {
- //! todo: Place hard-coded values here.
- draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
-}
-
void ToadsTurnpike::Render(struct UnkStruct_800DC5EC* arg0) {
- func_802B5D64(D_800DC610, D_802B87D4, 0, 1);
+ set_track_light_direction(D_800DC610, D_802B87D4, 0, 1);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
@@ -289,6 +281,4 @@ void ToadsTurnpike::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_toads_turnpike_dl_23930));
}
-void ToadsTurnpike::Collision() {}
-
void ToadsTurnpike::Destroy() { }
diff --git a/src/engine/courses/ToadsTurnpike.h b/src/engine/courses/ToadsTurnpike.h
index a73e3829f..de145849d 100644
--- a/src/engine/courses/ToadsTurnpike.h
+++ b/src/engine/courses/ToadsTurnpike.h
@@ -29,14 +29,11 @@ public:
virtual void BeginPlay() override;
virtual void InitClouds() override;
virtual void UpdateClouds(s32, Camera*) override;
- virtual void MinimapSettings() override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
- virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
- virtual void Collision() override;
virtual void Destroy() override;
private:
size_t _numTrucks = 7;
diff --git a/src/engine/courses/WarioStadium.cpp b/src/engine/courses/WarioStadium.cpp
index d60d754c0..b703323f4 100644
--- a/src/engine/courses/WarioStadium.cpp
+++ b/src/engine/courses/WarioStadium.cpp
@@ -7,8 +7,8 @@
#include "World.h"
#include "engine/objects/BombKart.h"
#include "assets/wario_stadium_data.h"
-#include "engine/actors/AWarioSign.h"
-#include "engine/actors/AFinishline.h"
+#include "engine/actors/WarioSign.h"
+#include "engine/actors/Finishline.h"
extern "C" {
#include "main.h"
@@ -32,6 +32,7 @@ extern "C" {
#include "code_8003DC40.h"
#include "memory.h"
#include "skybox_and_splitscreen.h"
+#include "course.h"
extern const char* wario_stadium_dls[];
extern s16 currentScreenSection;
}
@@ -65,16 +66,24 @@ WarioStadium::WarioStadium() {
this->gfx = d_course_wario_stadium_packed_dls;
this->gfxSize = 5272;
Props.textures = wario_stadium_textures;
- Props.MinimapTexture = gTextureCourseOutlineWarioStadium;
- Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
+ Props.Minimap.Texture = gTextureCourseOutlineWarioStadium;
+ Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
+ Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
+ Props.Minimap.Pos[0].X = 262;
+ Props.Minimap.Pos[0].Y = 170;
+ Props.Minimap.PlayerX = 53;
+ Props.Minimap.PlayerY = 35;
+ Props.Minimap.PlayerScaleFactor = 0.0155f;
+ Props.Minimap.FinishlineX = 0;
+ Props.Minimap.FinishlineY = 0;
+
+ Props.SetText(Props.Name, "wario stadium", sizeof(Props.Name));
+ Props.SetText(Props.DebugName, "stadium", sizeof(Props.DebugName));
+ Props.SetText(Props.CourseLength, "1591m", sizeof(Props.CourseLength));
- Props.Name = "wario stadium";
- Props.DebugName = "stadium";
- Props.CourseLength = "1591m";
Props.AIBehaviour = D_0D009310;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.6f;
- Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
Props.NearPersp = 10.0f;
@@ -122,9 +131,6 @@ WarioStadium::WarioStadium() {
this->FinishlineSpawnPoint = finish;
- Props.MinimapFinishlineX = 0;
- Props.MinimapFinishlineY = 0;
-
Props.Skybox.TopRight = { 20, 30, 56 };
Props.Skybox.BottomRight = { 40, 60, 110 };
Props.Skybox.BottomLeft = { 40, 60, 110 };
@@ -139,9 +145,9 @@ WarioStadium::WarioStadium() {
void WarioStadium::Load() {
Course::Load();
- parse_course_displaylists((TrackSectionsI*) LOAD_ASSET_RAW(d_course_wario_stadium_addr));
+ parse_course_displaylists((TrackSections*) LOAD_ASSET_RAW(d_course_wario_stadium_addr));
func_80295C6C();
- D_8015F8E4 = gCourseMinY - 10.0f;
+ Props.WaterLevel = gCourseMinY - 10.0f;
// d_course_wario_stadium_packed_dl_C50
find_vtx_and_set_colours(segmented_gfx_to_virtual((void*) 0x07000C50), 100, 255, 255, 255);
// d_course_wario_stadium_packed_dl_BD8
@@ -166,20 +172,20 @@ void WarioStadium::LoadTextures() {
void WarioStadium::BeginPlay() {
spawn_all_item_boxes((struct ActorSpawnData*) LOAD_ASSET_RAW(d_course_wario_stadium_item_box_spawns));
- Vec3f pos = { -131.0f, 83.0f, 286.0f };
- pos[0] *= gCourseDirection;
+ FVector pos = { -131.0f, 83.0f, 286.0f };
+ pos.x *= gCourseDirection;
gWorldInstance.AddActor(new AWarioSign(pos));
- Vec3f pos2 = { -2353.0f, 72.0f, -1608.0f };
- pos2[0] *= gCourseDirection;
+ FVector pos2 = { -2353.0f, 72.0f, -1608.0f };
+ pos2.x *= gCourseDirection;
gWorldInstance.AddActor(new AWarioSign(pos2));
- Vec3f pos3 = { -2622.0f, 79.0f, 739.0f };
- pos3[0] *= gCourseDirection;
+ FVector pos3 = { -2622.0f, 79.0f, 739.0f };
+ pos3.x *= gCourseDirection;
gWorldInstance.AddActor(new AWarioSign(pos3));
if (gModeSelection == VERSUS) {
- Vec3f pos = { 0, 0, 0 };
+ FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][50], 50, 3, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][100], 100, 1, 0.8333333f));
@@ -199,14 +205,6 @@ void WarioStadium::UpdateClouds(s32 sp1C, Camera* camera) {
update_stars(sp1C, camera, this->Props.CloudList);
}
-// Likely sets minimap boundaries
-void WarioStadium::MinimapSettings() {
- D_8018D2A0 = 0.0155f;
- D_8018D2C0[0] = 0x0106;
- D_8018D2E0 = 53;
- D_8018D2E8 = 35;
-}
-
void WarioStadium::InitCourseObjects() {
}
@@ -227,13 +225,6 @@ void WarioStadium::WhatDoesThisDo(Player* player, int8_t playerId) {
void WarioStadium::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
-// Positions the finishline on the minimap
-void WarioStadium::MinimapFinishlinePosition() {
- //! todo: Place hard-coded values here.
- draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY,
- (u8*) common_texture_minimap_finish_line);
-}
-
void WarioStadium::Jumbotron() {
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gDPTileSync(gDisplayListHead++);
@@ -365,9 +356,6 @@ void WarioStadium::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*) (d_course_wario_stadium_dl_CA78));
}
-void WarioStadium::Collision() {
-}
-
void WarioStadium::SomeCollisionThing(Player* player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5,
f32* arg6, f32* arg7) {
func_8003EE2C(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
diff --git a/src/engine/courses/WarioStadium.h b/src/engine/courses/WarioStadium.h
index 72f796cc7..91f613c1b 100644
--- a/src/engine/courses/WarioStadium.h
+++ b/src/engine/courses/WarioStadium.h
@@ -31,15 +31,12 @@ class WarioStadium : public Course {
virtual void BeginPlay() override;
virtual void InitClouds() override;
virtual void UpdateClouds(s32, Camera*) override;
- virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
- virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
- virtual void Collision() override;
virtual void SomeCollisionThing(Player* player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6,
f32* arg7) override;
virtual void DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot,
diff --git a/src/engine/courses/YoshiValley.cpp b/src/engine/courses/YoshiValley.cpp
index 98d887b03..5fbcbea69 100644
--- a/src/engine/courses/YoshiValley.cpp
+++ b/src/engine/courses/YoshiValley.cpp
@@ -6,7 +6,7 @@
#include "YoshiValley.h"
#include "World.h"
-#include "engine/actors/AFinishline.h"
+#include "engine/actors/Finishline.h"
#include "engine/objects/BombKart.h"
#include "engine/objects/Hedgehog.h"
#include "engine/objects/Flagpole.h"
@@ -33,6 +33,7 @@ extern "C" {
#include "actors.h"
#include "collision.h"
#include "memory.h"
+ #include "course.h"
extern const char *d_course_yoshi_valley_dl_list[];
}
@@ -60,16 +61,22 @@ YoshiValley::YoshiValley() {
this->gfxSize = 4140;
Props.textures = yoshi_valley_textures;
- Props.MinimapTexture = gTextureCourseOutlineYoshiValley;
- Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
+ Props.Minimap.Texture = gTextureCourseOutlineYoshiValley;
+ Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
+ Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
+ Props.Minimap.PlayerX = 61;
+ Props.Minimap.PlayerY = 38;
+ Props.Minimap.PlayerScaleFactor = 0.018f;
+ Props.Minimap.FinishlineX = 0;
+ Props.Minimap.FinishlineY = 0;
+
+ Props.SetText(Props.Name, "yoshi valley", sizeof(Props.Name));
+ Props.SetText(Props.DebugName, "maze", sizeof(Props.DebugName));
+ Props.SetText(Props.CourseLength, "772m", sizeof(Props.CourseLength));
- Props.Name = "yoshi valley";
- Props.DebugName = "maze";
- Props.CourseLength = "772m";
Props.AIBehaviour = D_0D0090B8;
Props.AIMaximumSeparation = 35.0f;
Props.AIMinimumSeparation = 0.0f;
- Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
Props.NearPersp = 9.0f;
@@ -107,10 +114,9 @@ YoshiValley::YoshiValley() {
Props.PathTable2[2] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_yoshi_valley_track_waypoints_3);
Props.PathTable2[3] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_yoshi_valley_track_waypoints_4);
+ Props.CloudTexture = (u8*) LOAD_ASSET_RAW(gTextureExhaust0);
Props.Clouds = gYoshiValleyMooMooFarmClouds;
Props.CloudList = gYoshiValleyMooMooFarmClouds;
- Props.MinimapFinishlineX = 0;
- Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {113, 70, 255};
Props.Skybox.BottomRight = {255, 184, 99};
@@ -127,10 +133,10 @@ void YoshiValley::Load() {
Course::Load();
Lights1 lights4 = gdSPDefLights1(100, 100, 100, 255, 254, 254, 0, 0, 120);
- func_802B5D64(&lights4, -0x38F0, 0x1C70, 1);
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_yoshi_valley_addr));
+ set_track_light_direction(&lights4, -0x38F0, 0x1C70, 1);
+ parse_course_displaylists((TrackSections*)LOAD_ASSET_RAW(d_course_yoshi_valley_addr));
func_80295C6C();
- D_8015F8E4 = gCourseMinY - 10.0f;
+ Props.WaterLevel = gCourseMinY - 10.0f;
}
void YoshiValley::LoadTextures() {
@@ -177,31 +183,23 @@ void YoshiValley::BeginPlay() {
// the original data has values here.
// Note that the Y height is calculated automatically to place the kart on the surface
- Vec3f pos = {-1533, 0, -682};
+ FVector pos = { -1533, 0, -682 };
gWorldInstance.AddObject(new OBombKart(pos, NULL, 0, 0, 0.8333333f));
- Vec3f pos2 = {-1565, 0, -619};
+ FVector pos2 = { -1565, 0, -619 };
gWorldInstance.AddObject(new OBombKart(pos2, NULL, 10, 0, 0.8333333f));
- Vec3f pos3 = {-1529, 0, -579};
+ FVector pos3 = { -1529, 0, -579 };
gWorldInstance.AddObject(new OBombKart(pos3, NULL, 20, 0, 0.8333333f));
- Vec3f pos4 = {-1588, 0, -534};
+ FVector pos4 = { -1588, 0, -534 };
gWorldInstance.AddObject(new OBombKart(pos4, NULL, 30, 0, 0.8333333f));
- Vec3f pos5 = {-1598, 0, -207};
+ FVector pos5 = { -1598, 0, -207 };
gWorldInstance.AddObject(new OBombKart(pos5, NULL, 40, 0, 0.8333333f));
- Vec3f pos6 = {-1646, 0, -147};
+ FVector pos6 = { -1646, 0, -147 };
gWorldInstance.AddObject(new OBombKart(pos6, NULL, 50, 0, 0.8333333f));
- Vec3f pos7 = {-2532, 0, -445};
+ FVector pos7 = { -2532, 0, -445 };
gWorldInstance.AddObject(new OBombKart(pos7, NULL, 60, 0, 0.8333333f));
}
}
-// Likely sets minimap boundaries
-void YoshiValley::MinimapSettings() {
- D_8018D220 = reinterpret_cast<uint8_t (*)[1024]>(dma_textures(gTextureExhaust0, 0x479, 0xC00));
- D_8018D2A0 = 0.018f;
- D_8018D2E0 = 61;
- D_8018D2E8 = 38;
-}
-
void YoshiValley::InitCourseObjects() {
}
@@ -218,12 +216,6 @@ void YoshiValley::WhatDoesThisDo(Player* player, int8_t playerId) {}
void YoshiValley::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
-// Positions the finishline on the minimap
-void YoshiValley::MinimapFinishlinePosition() {
- //! todo: Place hard-coded values here.
- draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
-}
-
void YoshiValley::Render(struct UnkStruct_800DC5EC* arg0) {
gDPPipeSync(gDisplayListHead++);
gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEI, G_CC_MODULATEI);
@@ -237,8 +229,6 @@ void YoshiValley::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_yoshi_valley_dl_18020));
}
-void YoshiValley::Collision() {}
-
void YoshiValley::Waypoints(Player* player, int8_t playerId) {
player->nearestWaypointId = gCopyNearestWaypointByPlayerId[playerId];
}
diff --git a/src/engine/courses/YoshiValley.h b/src/engine/courses/YoshiValley.h
index a986cd902..b4ec8d442 100644
--- a/src/engine/courses/YoshiValley.h
+++ b/src/engine/courses/YoshiValley.h
@@ -27,17 +27,14 @@ public:
virtual void Load() override;
virtual void LoadTextures() override;
virtual void BeginPlay() override;
- virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void UpdateCourseObjects() override;
virtual void RenderCourseObjects(s32 cameraId) override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
- virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
- virtual void Collision() override;
virtual void ScrollingTextures() override;
virtual void Waypoints(Player* player, int8_t playerId) override;
virtual void CreditsSpawnActors() override;
diff --git a/src/engine/editor/Collision.cpp b/src/engine/editor/Collision.cpp
new file mode 100644
index 000000000..bf62d6273
--- /dev/null
+++ b/src/engine/editor/Collision.cpp
@@ -0,0 +1,188 @@
+#include "Collision.h"
+
+#include <libultraship/libultraship.h>
+#include <libultra/gbi.h>
+#include "Matrix.h"
+
+extern "C" {
+#include "main.h"
+#include "other_textures.h"
+}
+
+namespace Editor {
+ void GenerateCollisionMesh(GameObject* object, Gfx* model, float scale) {
+ int8_t opcode;
+ uintptr_t lo;
+ uintptr_t hi;
+
+ Gfx* ptr = model;
+ Vtx* vtx = NULL;
+ size_t i = 0;
+ bool run = true;
+ while (run) {
+ i++;
+ lo = ptr->words.w0;
+ hi = ptr->words.w1;
+
+ opcode = (EDITOR_GFX_GET_OPCODE(lo) >> 24);
+ switch(opcode) {
+ case G_DL:
+ GenerateCollisionMesh(object, (Gfx*)hi, scale);
+ break;
+ case G_DL_OTR_HASH:
+ ptr++;
+ GenerateCollisionMesh(object, (Gfx*)ResourceGetDataByCrc(((uint64_t)(ptr->words.w0 << 32)) + ptr->words.w1), scale);
+ break;
+ case G_DL_OTR_FILEPATH:
+ // printf("otr filepath: %s\n", (const char*)hi);
+ GenerateCollisionMesh(object, (Gfx*)ResourceGetDataByName((const char*)hi), scale);
+ break;
+ case G_VTX:
+ vtx = (Vtx*)ptr->words.w1;
+ break;
+ case G_VTX_OTR_HASH: {
+ ptr++;
+ vtx = (Vtx*)ResourceGetDataByCrc(((uint64_t)(ptr->words.w0 << 32)) + ptr->words.w1);
+ break;
+ }
+ case G_VTX_OTR_FILEPATH: {
+ const char* filePath = (const char*)hi;
+ ptr++;
+ size_t vtxDataOff = ptr->words.w1 & 0xFFFF;
+ vtx = ( (Vtx*)ResourceGetDataByName(filePath) ) + vtxDataOff;
+ break;
+ }
+ case G_TRI1: {
+ if (vtx == NULL) {
+ ptr++;
+ continue;
+ }
+ uint32_t v1 = ((hi & 0x00FF0000) >> 16) / 2;
+ uint32_t v2 = ((hi & 0x0000FF00) >> 8) / 2;
+ uint32_t v3 = (hi & 0x000000FF) / 2;
+
+ FVector p1 = FVector(vtx[v1].v.ob[0], vtx[v1].v.ob[1], vtx[v1].v.ob[2]);
+ FVector p2 = FVector(vtx[v2].v.ob[0], vtx[v2].v.ob[1], vtx[v2].v.ob[2]);
+ FVector p3 = FVector(vtx[v3].v.ob[0], vtx[v3].v.ob[1], vtx[v3].v.ob[2]);
+
+ object->Triangles.push_back({p1, p2, p3});
+ break;
+ }
+ case G_TRI1_OTR: {
+ if (vtx == NULL) {
+ ptr++;
+ continue;
+ }
+
+ // The shift values here are different than the above. No idea why. But it has to be this way.
+ uint32_t v1 = (lo & 0x0000FFFF);
+ uint32_t v2 = (hi >> 16);
+ uint32_t v3 = (hi & 0x0000FFFF);
+
+ FVector p1 = FVector(vtx[v1].v.ob[0], vtx[v1].v.ob[1], vtx[v1].v.ob[2]);
+ FVector p2 = FVector(vtx[v2].v.ob[0], vtx[v2].v.ob[1], vtx[v2].v.ob[2]);
+ FVector p3 = FVector(vtx[v3].v.ob[0], vtx[v3].v.ob[1], vtx[v3].v.ob[2]);
+
+ object->Triangles.push_back({p1, p2, p3});
+
+ break;
+ }
+ case G_TRI2: {
+ if (vtx == NULL) {
+ ptr++;
+ continue;
+ }
+ uint32_t v1 = ((lo & 0x00FF0000) >> 16) / 2;
+ uint32_t v2 = ((lo & 0x0000FF00) >> 8) / 2;
+ uint32_t v3 = (lo & 0x000000FF) / 2;
+
+ // This is actually triangle 2; vert 1,2,3.
+ uint32_t v4 = ((hi & 0x00FF0000) >> 16) / 2;
+ uint32_t v5 = ((hi & 0x0000FF00) >> 8) / 2;
+ uint32_t v6 = (hi & 0x000000FF) / 2;
+
+ FVector p1 = FVector(vtx[v1].v.ob[0], vtx[v1].v.ob[1], vtx[v1].v.ob[2]);
+ FVector p2 = FVector(vtx[v2].v.ob[0], vtx[v2].v.ob[1], vtx[v2].v.ob[2]);
+ FVector p3 = FVector(vtx[v3].v.ob[0], vtx[v3].v.ob[1], vtx[v3].v.ob[2]);
+
+ FVector p4 = FVector(vtx[v4].v.ob[0], vtx[v4].v.ob[1], vtx[v4].v.ob[2]);
+ FVector p5 = FVector(vtx[v5].v.ob[0], vtx[v5].v.ob[1], vtx[v5].v.ob[2]);
+ FVector p6 = FVector(vtx[v6].v.ob[0], vtx[v6].v.ob[1], vtx[v6].v.ob[2]);
+
+ object->Triangles.push_back({p1, p2, p3});
+ object->Triangles.push_back({p4, p5, p6});
+ break;
+ }
+ case G_QUAD: {
+ if (vtx == NULL) {
+ ptr++;
+ continue;
+ }
+ uint32_t v1 = ((hi & 0x00FF0000) >> 16) / 2;
+ uint32_t v2 = ((hi & 0x0000FF00) >> 8) / 2;
+ uint32_t v3 = (hi & 0x000000FF) / 2;
+ uint32_t v4 = ((hi & 0xFF000000) >> 24) / 2;
+
+ FVector p1 = FVector(vtx[v1].v.ob[0], vtx[v1].v.ob[1], vtx[v1].v.ob[2]);
+ FVector p2 = FVector(vtx[v2].v.ob[0], vtx[v2].v.ob[1], vtx[v2].v.ob[2]);
+ FVector p3 = FVector(vtx[v3].v.ob[0], vtx[v3].v.ob[1], vtx[v3].v.ob[2]);
+ FVector p4 = FVector(vtx[v4].v.ob[0], vtx[v4].v.ob[1], vtx[v4].v.ob[2]);
+
+ object->Triangles.push_back({p1, p2, p3});
+ object->Triangles.push_back({p1, p3, p4});
+ break;
+ }
+ case G_ENDDL:
+ run = false;
+ break;
+ }
+
+ ptr++;
+ }
+ }
+
+ std::unordered_map<GameObject*, std::vector<Vtx>> gDebugObjVtxCache;
+
+ // Render a collision model
+ void DebugCollision(GameObject* obj, FVector pos, IRotator rot, FVector scale, const std::vector<Triangle>& triangles) {
+ if (obj == NULL || triangles.empty()) {
+ return;
+ }
+
+ gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_OFF);
+
+ auto& vtxBuffer = gDebugObjVtxCache[obj];
+ if (vtxBuffer.empty()) {
+ for (const auto& tri : triangles) {
+ vtxBuffer.push_back({(s16)tri.v0.x, (s16)tri.v0.y, (s16)tri.v0.z, 0, {0, 0}, {255, 255, 255, 255}});
+ vtxBuffer.push_back({(s16)tri.v1.x, (s16)tri.v1.y, (s16)tri.v1.z, 0, {0, 0}, {255, 255, 255, 255}});
+ vtxBuffer.push_back({(s16)tri.v2.x, (s16)tri.v2.y, (s16)tri.v2.z, 0, {0, 0}, {255, 255, 255, 255}});
+ }
+ }
+
+ // Setup matrix and render state
+ Mat4 mtx;
+ ApplyMatrixTransformations(mtx, pos, rot, scale);
+ Editor_AddMatrix(mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+
+ gSPSetGeometryMode(gDisplayListHead++, G_FOG);
+ gDPPipeSync(gDisplayListHead++);
+ gDPSetCombineMode(gDisplayListHead++, G_CC_PRIMITIVE, G_CC_PRIMITIVE);
+ gSPTexture(gDisplayListHead++, 0, 0, 0, G_TX_RENDERTILE, G_OFF);
+ gDPSetRenderMode(gDisplayListHead++, G_RM_FOG_SHADE_A, G_RM_AA_ZB_OPA_SURF2);
+ uint32_t hash = (uint32_t)((uintptr_t)obj ^ ((uintptr_t)obj >> 16));
+ u8 r = (hash >> 16) & 0xFF;
+ u8 g = (hash >> 8) & 0xFF;
+ u8 b = hash & 0xFF;
+
+ gDPSetPrimColor(gDisplayListHead++, 0, 0, r, g, b, 255);
+
+ // Render triangles in batches of 3
+ for (size_t i = 0; i + 2 < vtxBuffer.size(); i += 3) {
+ gSPVertex(gDisplayListHead++, (uintptr_t)&vtxBuffer[i], 3, 0);
+ gSP1Triangle(gDisplayListHead++, 0, 1, 2, 0);
+ }
+
+ gSPSetGeometryMode(gDisplayListHead++, G_CULL_BACK | G_ZBUFFER);
+ }
+}
diff --git a/src/engine/editor/Collision.h b/src/engine/editor/Collision.h
new file mode 100644
index 000000000..ee8fef4af
--- /dev/null
+++ b/src/engine/editor/Collision.h
@@ -0,0 +1,23 @@
+#pragma once
+
+#include <libultraship/libultraship.h>
+#include <libultra/gbi.h>
+#include "GameObject.h"
+
+#include "EditorMath.h"
+
+/**
+ * @file Editor Collision
+ *
+ * Most actors use cylinder collision.
+ * Proper vtx intersection tests are necessary for object picking
+ *
+ * Therefore, generate a full collision mesh for actors
+ */
+
+#define EDITOR_GFX_GET_OPCODE(var) ((uint32_t) ((var) & 0xFF000000))
+
+namespace Editor {
+ void GenerateCollisionMesh(GameObject* object, Gfx* model, float scale);
+ void DebugCollision(GameObject* obj, FVector pos, IRotator rot, FVector scale, const std::vector<Triangle>& triangles);
+} \ No newline at end of file
diff --git a/src/engine/editor/Editor.cpp b/src/engine/editor/Editor.cpp
new file mode 100644
index 000000000..446da7487
--- /dev/null
+++ b/src/engine/editor/Editor.cpp
@@ -0,0 +1,166 @@
+#include <libultraship/libultraship.h>
+#include <libultra/gbi.h>
+#include "../CoreMath.h"
+#include <libultra/types.h>
+#include "../World.h"
+
+#include "Editor.h"
+#include "Collision.h"
+#include "Light.h"
+
+#include "port/Engine.h"
+#include <controller/controldevice/controller/mapping/keyboard/KeyboardScancodes.h>
+#include <window/Window.h>
+
+#include "engine/actors/Ship.h"
+#include "port/Game.h"
+
+extern "C" {
+#include "common_structs.h"
+#include "main.h"
+#include "defines.h"
+#include "actors.h"
+#include "camera.h"
+}
+
+namespace Editor {
+ int gfx_create_framebuffer(uint32_t width, uint32_t height, uint32_t native_width, uint32_t native_height,
+ uint8_t resize);
+
+ Editor::Editor() {
+ }
+
+ void Editor::Load() {
+ printf("Editor: Loading Editor...\n");
+ eObjectPicker.Load();
+ for (auto& object : eGameObjects) {
+ GenerateCollisionMesh(object, object->Model, 1.0f);
+ object->Load();
+ }
+ printf("Editor: Loading Complete!\n");
+ }
+
+ void Editor::Tick() {
+
+ if (CVarGetInteger("gEditorEnabled", 0) == true) {
+ bEditorEnabled = true;
+ } else {
+ bEditorEnabled = false;
+ return;
+ }
+
+ auto wnd = GameEngine::Instance->context->GetWindow();
+
+ static bool wasMouseDown = false;
+ static bool isDragging = false;
+ static Ship::Coords mouseStartPos;
+
+ Ship::Coords mousePos = wnd->GetMousePos();
+ bool isMouseDown = wnd->GetMouseState(Ship::LUS_MOUSE_BTN_LEFT);
+
+ eGameObjects.erase(
+ std::remove_if(eGameObjects.begin(), eGameObjects.end(),
+ [](const auto& object) { return (*object->DespawnFlag) == object->DespawnValue; }),
+ eGameObjects.end());
+
+ if (isMouseDown && !wasMouseDown) {
+ // Mouse just pressed (Pressed state)
+ mouseStartPos = mousePos;
+ isDragging = false;
+ }
+
+ if (isMouseDown) {
+ // Mouse is being held (Held state)
+ int dx = mousePos.x - mouseStartPos.x;
+ int dy = mousePos.y - mouseStartPos.y;
+ int dragThreshold = 5; // Adjust as needed
+
+ if ((dx * dx + dy * dy) > (dragThreshold * dragThreshold)) {
+ // Squared distance check to avoid unnecessary sqrt()
+ isDragging = true;
+ eObjectPicker.DragHandle(); // Call drag logic
+ }
+ }
+
+ if (!isMouseDown && wasMouseDown) {
+ // Mouse just released (Released state)
+ eObjectPicker.eGizmo.SelectedHandle = Gizmo::GizmoHandle::None;
+ eObjectPicker.eGizmo.ManipulationStart = true;
+ if (!isDragging) {
+ eObjectPicker.SelectObject(eGameObjects);
+ }
+
+ }
+
+ wasMouseDown = isMouseDown; // Update previous state
+
+ eObjectPicker.Tick();
+
+ for (auto& object : eGameObjects) {
+ object->Tick();
+ }
+ }
+
+ void Editor::Draw() {
+ if (!bEditorEnabled) {
+ return;
+ }
+ eObjectPicker.Draw();
+ for (auto& object : eGameObjects) {
+ object->Draw();
+ }
+ }
+
+ GameObject* Editor::AddObject(const char* name, FVector* pos, IRotator* rot, FVector* scale, Gfx* model, float collScale, GameObject::CollisionType collision, float boundingBoxSize, int32_t* despawnFlag, int32_t despawnValue) {
+ //printf("After AddObj: Pos(%f, %f, %f), Name: %s, Model: %s\n",
+ // pos->x, pos->y, pos->z, name, model);
+ if (model != nullptr) {
+ eGameObjects.push_back(new GameObject(name, pos, rot, scale, model, {}, collision, boundingBoxSize, despawnFlag, despawnValue));
+ GenerateCollisionMesh(eGameObjects.back(), model, collScale);
+ } else { // to bounding box or sphere collision
+ eGameObjects.push_back(new GameObject(name, pos, rot, scale, model, {}, GameObject::CollisionType::BOUNDING_BOX,
+ 10.0f, despawnFlag, despawnValue));
+ }
+ return eGameObjects.back();
+ }
+
+ void Editor::AddLight(const char* name, FVector* pos, s8* rot) {
+ eGameObjects.push_back(new LightObject(name, pos, rot));
+ }
+
+ void Editor::ClearObjects() {
+ for (auto& obj : eGameObjects) {
+ delete obj;
+ }
+ eGameObjects.clear();
+ }
+
+ void Editor::DeleteObject() {
+ GameObject* obj = eObjectPicker.eGizmo._selected;
+
+ if (obj) {
+ *obj->DespawnFlag = obj->DespawnValue;
+ obj = nullptr;
+ eObjectPicker._selected = nullptr;
+ }
+ }
+
+ void Editor::ClearMatrixPool() {
+ EditorMatrix.clear();
+ }
+
+ void Editor::SelectObjectFromSceneExplorer(GameObject* object) {
+ eObjectPicker._selected = object;
+ eObjectPicker.eGizmo.Enabled = true;
+ eObjectPicker.eGizmo.SetGizmoNoCursor(object);
+ }
+
+ void Editor::SetLevelDimensions(s16 minX, s16 maxX, s16 minZ, s16 maxZ, s16 minY, s16 maxY) {
+ eObjectPicker.eGizmo.dimensions.MinX = minX + -1000;
+ eObjectPicker.eGizmo.dimensions.MaxX = maxX + 1000;
+ eObjectPicker.eGizmo.dimensions.MinY = minY + -100;
+ eObjectPicker.eGizmo.dimensions.MaxY = maxY + 500;
+ eObjectPicker.eGizmo.dimensions.MinZ = minZ + -1000;
+ eObjectPicker.eGizmo.dimensions.MaxZ = maxZ + 1000;
+ }
+}
diff --git a/src/engine/editor/Editor.h b/src/engine/editor/Editor.h
new file mode 100644
index 000000000..759c59355
--- /dev/null
+++ b/src/engine/editor/Editor.h
@@ -0,0 +1,47 @@
+#ifndef __EDITOR_H__
+#define __EDITOR_H__
+
+#include <libultraship/libultraship.h>
+#include <libultra/gbi.h>
+#include "GameObject.h"
+
+#ifdef __cplusplus
+
+#include "ObjectPicker.h"
+namespace Editor {
+ class ObjectPicker;
+
+ class Editor {
+public:
+ Editor();
+
+ ObjectPicker eObjectPicker;
+ std::vector<GameObject*> eGameObjects;
+
+ void Tick();
+ void Draw();
+ void Load();
+ GameObject* AddObject(const char* name, FVector* pos, IRotator* rot, FVector* scale, Gfx* model, float collScale, GameObject::CollisionType collision, float boundingBoxSize, int32_t* despawnFlag, int32_t despawnValue);
+ void AddLight(const char* name, FVector* pos, s8* rot);
+ void ClearObjects();
+ void RemoveObject();
+ void SelectObjectFromSceneExplorer(GameObject* object);
+ void SetLevelDimensions(s16 minX, s16 maxX, s16 minZ, s16 maxZ, s16 minY, s16 maxY);
+ void ClearMatrixPool();
+ void DeleteObject();
+ bool bEditorEnabled = false;
+
+private:
+ bool _draw = false;
+ Vec3f _ray;
+
+ s32 Inverse(MtxF* src, MtxF* dest);
+ void Copy(MtxF* src, MtxF* dest);
+ void Clear(MtxF* mf);
+};
+}
+#endif
+
+void SetLevelDimensions(s16 minX, s16 maxX, s16 minZ, s16 maxZ, s16 minY, s16 maxY);
+
+#endif // __EDITOR_H__
diff --git a/src/engine/editor/EditorMath.cpp b/src/engine/editor/EditorMath.cpp
new file mode 100644
index 000000000..533c0c2b5
--- /dev/null
+++ b/src/engine/editor/EditorMath.cpp
@@ -0,0 +1,427 @@
+#include "EditorMath.h"
+
+#include <libultraship/libultraship.h>
+#include "port/Game.h"
+#include "port/Engine.h"
+#include <libultra/types.h>
+#include "GameObject.h"
+
+#include <vector>
+#include <limits>
+#include <cmath>
+
+extern "C" {
+#include "common_structs.h"
+#include "main.h"
+#include "defines.h"
+#include "actors.h"
+#include "math_util.h"
+#include "math_util_2.h"
+#include "camera.h"
+}
+
+std::vector<Mtx> EditorMatrix;
+
+bool IsInGameScreen() {
+ auto wnd = GameEngine::Instance->context->GetWindow();
+ Ship::Coords mouse = wnd->GetMousePos();
+
+ // Define viewport boundaries
+ int left = gfx_current_game_window_viewport.x;
+ int right = left + OTRGetGameRenderWidth();
+ int top = gfx_current_game_window_viewport.y;
+ int bottom = top + OTRGetGameRenderHeight();
+
+ // Check if the mouse is within the game render area
+ return (mouse.x >= left && mouse.x < right) && (mouse.y >= top && mouse.y < bottom);
+}
+
+FVector ScreenRayTrace() {
+ auto wnd = GameEngine::Instance->context->GetWindow();
+ Camera* camera = &cameras[0];
+
+ Ship::Coords mouse = wnd->GetMousePos();
+ mouse.x -= gfx_current_game_window_viewport.x;
+ mouse.y -= gfx_current_game_window_viewport.y;
+ // Get screen dimensions
+ uint32_t width = OTRGetGameViewportWidth();
+ uint32_t height = OTRGetGameViewportHeight();
+
+ // Convert mouse to NDS screen coordinates
+ float x = (2.0f * mouse.x) / width - 1.0f; // Normalized X: -1 to 1
+ float y = 1.0f - (2.0f * mouse.y) / height; // Normalized Y: -1 to 1
+ float z = 1.0f; // z is typically 1.0 for the near plane
+
+ FVector4 rayClip = {x, y, z, 1.0f};
+
+ Mat4 perspMtx;
+ u16 perspNorm;
+ guPerspectiveF(perspMtx, &perspNorm, gCameraZoom[0], OTRGetAspectRatio(), CM_GetProps()->NearPersp, CM_GetProps()->FarPersp, 1.0f);
+
+ Mat4 inversePerspMtx;
+ if (InverseMatrix((float*)&perspMtx, (float*)&inversePerspMtx) != 2) {
+ FVector4 rayEye = MultiplyMatrixVector(inversePerspMtx, (float*)&rayClip.x);
+
+ Mat4 lookAtMtx;
+ guLookAtF(lookAtMtx, camera->pos[0], camera->pos[1], camera->pos[2], camera->lookAt[0], camera->lookAt[1], camera->lookAt[2], camera->up[0], camera->up[1], camera->up[2]);
+ Mat4 inverseViewMtx;
+ if (InverseMatrix((float*)&lookAtMtx, (float*)&inverseViewMtx[0][0]) != 2) {
+ rayEye.w = 0;
+ FVector4 invRayWor = MultiplyMatrixVector(inverseViewMtx, (float*)&rayEye.x);
+
+ FVector direction;
+ direction = FVector(invRayWor.x, invRayWor.y, invRayWor.z);
+
+ return direction;
+ }
+ }
+ return FVector(0, 0, 0);
+}
+
+bool QueryCollisionRayActor(Vec3f rayOrigin, Vec3f rayDir, Vec3f actorMin, Vec3f actorMax, float* t) {
+ float tmin = -FLT_MAX, tmax = FLT_MAX;
+
+ for (int i = 0; i < 3; i++) {
+ if (fabs(rayDir[i]) > 1e-6f) { // Avoid division by zero
+ float t1 = (actorMin[i] - rayOrigin[i]) / rayDir[i];
+ float t2 = (actorMax[i] - rayOrigin[i]) / rayDir[i];
+
+ if (t1 > t2) { float temp = t1; t1 = t2; t2 = temp; }
+
+ tmin = fmax(tmin, t1);
+ tmax = fmin(tmax, t2);
+
+ if (tmax < tmin) return false; // No intersection
+ } else if (rayOrigin[i] < actorMin[i] || rayOrigin[i] > actorMax[i]) {
+ return false; // Ray is outside the slab
+ }
+ }
+
+ *t = tmin; // Distance to first intersection
+ return true;
+}
+
+FVector4 MultiplyMatrixVector(float matrix[4][4], float vector[4]) {
+ FVector4 result;
+ float* resultPtr = &result.x;
+ for (int i = 0; i < 4; i++) {
+ resultPtr[i] = 0;
+ for (int j = 0; j < 4; j++) {
+ resultPtr[i] += matrix[j][i] * vector[j]; // Swap [i][j] → [j][i] for column order
+ }
+ }
+ return result;
+}
+
+// https://stackoverflow.com/questions/1148309/inverting-a-4x4-matrix
+static bool InverseMatrix(const float m[16], float invOut[16]) {
+ float inv[16], det;
+ int i;
+
+ inv[0] = m[5] * m[10] * m[15] - m[5] * m[11] * m[14] - m[9] * m[6] * m[15] + m[9] * m[7] * m[14] +
+ m[13] * m[6] * m[11] - m[13] * m[7] * m[10];
+
+ inv[4] = -m[4] * m[10] * m[15] + m[4] * m[11] * m[14] + m[8] * m[6] * m[15] - m[8] * m[7] * m[14] -
+ m[12] * m[6] * m[11] + m[12] * m[7] * m[10];
+
+ inv[8] = m[4] * m[9] * m[15] - m[4] * m[11] * m[13] - m[8] * m[5] * m[15] + m[8] * m[7] * m[13] +
+ m[12] * m[5] * m[11] - m[12] * m[7] * m[9];
+
+ inv[12] = -m[4] * m[9] * m[14] + m[4] * m[10] * m[13] + m[8] * m[5] * m[14] - m[8] * m[6] * m[13] -
+ m[12] * m[5] * m[10] + m[12] * m[6] * m[9];
+
+ inv[1] = -m[1] * m[10] * m[15] + m[1] * m[11] * m[14] + m[9] * m[2] * m[15] - m[9] * m[3] * m[14] -
+ m[13] * m[2] * m[11] + m[13] * m[3] * m[10];
+
+ inv[5] = m[0] * m[10] * m[15] - m[0] * m[11] * m[14] - m[8] * m[2] * m[15] + m[8] * m[3] * m[14] +
+ m[12] * m[2] * m[11] - m[12] * m[3] * m[10];
+
+ inv[9] = -m[0] * m[9] * m[15] + m[0] * m[11] * m[13] + m[8] * m[1] * m[15] - m[8] * m[3] * m[13] -
+ m[12] * m[1] * m[11] + m[12] * m[3] * m[9];
+
+ inv[13] = m[0] * m[9] * m[14] - m[0] * m[10] * m[13] - m[8] * m[1] * m[14] + m[8] * m[2] * m[13] +
+ m[12] * m[1] * m[10] - m[12] * m[2] * m[9];
+
+ inv[2] = m[1] * m[6] * m[15] - m[1] * m[7] * m[14] - m[5] * m[2] * m[15] + m[5] * m[3] * m[14] +
+ m[13] * m[2] * m[7] - m[13] * m[3] * m[6];
+
+ inv[6] = -m[0] * m[6] * m[15] + m[0] * m[7] * m[14] + m[4] * m[2] * m[15] - m[4] * m[3] * m[14] -
+ m[12] * m[2] * m[7] + m[12] * m[3] * m[6];
+
+ inv[10] = m[0] * m[5] * m[15] - m[0] * m[7] * m[13] - m[4] * m[1] * m[15] + m[4] * m[3] * m[13] +
+ m[12] * m[1] * m[7] - m[12] * m[3] * m[5];
+
+ inv[14] = -m[0] * m[5] * m[14] + m[0] * m[6] * m[13] + m[4] * m[1] * m[14] - m[4] * m[2] * m[13] -
+ m[12] * m[1] * m[6] + m[12] * m[2] * m[5];
+
+ inv[3] = -m[1] * m[6] * m[11] + m[1] * m[7] * m[10] + m[5] * m[2] * m[11] - m[5] * m[3] * m[10] -
+ m[9] * m[2] * m[7] + m[9] * m[3] * m[6];
+
+ inv[7] = m[0] * m[6] * m[11] - m[0] * m[7] * m[10] - m[4] * m[2] * m[11] + m[4] * m[3] * m[10] +
+ m[8] * m[2] * m[7] - m[8] * m[3] * m[6];
+
+ inv[11] = -m[0] * m[5] * m[11] + m[0] * m[7] * m[9] + m[4] * m[1] * m[11] - m[4] * m[3] * m[9] -
+ m[8] * m[1] * m[7] + m[8] * m[3] * m[5];
+
+ inv[15] = m[0] * m[5] * m[10] - m[0] * m[6] * m[9] - m[4] * m[1] * m[10] + m[4] * m[2] * m[9] + m[8] * m[1] * m[6] -
+ m[8] * m[2] * m[5];
+
+ det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12];
+
+ if (det == 0) {
+ return false;
+ }
+
+ det = 1.0 / det;
+
+ for (i = 0; i < 16; i++) {
+ invOut[i] = inv[i] * det;
+ }
+
+ return true;
+}
+
+FVector TransformVecByMatrix(const FVector& vec, const float mtx[4][4]) {
+ FVector result;
+ result.x = vec.x * mtx[0][0] + vec.y * mtx[1][0] + vec.z * mtx[2][0] + mtx[3][0];
+ result.y = vec.x * mtx[0][1] + vec.y * mtx[1][1] + vec.z * mtx[2][1] + mtx[3][1];
+ result.z = vec.x * mtx[0][2] + vec.y * mtx[1][2] + vec.z * mtx[2][2] + mtx[3][2];
+ return result;
+}
+
+FVector TransformVecDirection(const FVector& dir, const float mtx[4][4]) {
+ FVector result;
+ result.x = dir.x * mtx[0][0] + dir.y * mtx[1][0] + dir.z * mtx[2][0];
+ result.y = dir.x * mtx[0][1] + dir.y * mtx[1][1] + dir.z * mtx[2][1];
+ result.z = dir.x * mtx[0][2] + dir.y * mtx[1][2] + dir.z * mtx[2][2];
+ return result;
+}
+
+Ray RayToLocalSpace(MtxF mtx, const Ray& ray) {
+ MtxF inverse;
+
+ if (InverseMatrix((float*)&mtx, (float*)&inverse) != 2) {
+ FVector localRayOrigin = TransformVecByMatrix(ray.Origin, (float(*)[4])&inverse);
+ FVector localRayDir = TransformVecDirection(ray.Direction, (float(*)[4])&inverse);
+ return Ray{localRayOrigin, localRayDir.Normalize()};
+ }
+ return Ray{}; // Fail. Return empty ray
+}
+
+bool IntersectRayTriangle(const Ray& ray, const Triangle& tri, float& t) {
+ constexpr float EPSILON = 1e-6f;
+
+ // Adjust the triangle vertices by the object's position
+ FVector v0 = tri.v0;
+ FVector v1 = tri.v1;
+ FVector v2 = tri.v2;
+
+ FVector edge1 = v1 - v0;
+ FVector edge2 = v2 - v0;
+ FVector h = ray.Direction.Cross(edge2);
+ float a = edge1.Dot(h);
+
+ if (std::abs(a) < EPSILON)
+ return false; // Ray is parallel to triangle
+
+ float f = 1.0f / a;
+ FVector s = ray.Origin - v0;
+ float u = f * s.Dot(h);
+
+ if (u < 0.0f || u > 1.0f)
+ return false;
+
+ FVector q = s.Cross(edge1);
+ float v = f * ray.Direction.Dot(q);
+
+ if (v < 0.0f || u + v > 1.0f)
+ return false;
+
+ t = f * edge2.Dot(q);
+ return t > EPSILON;
+}
+
+bool IntersectRayTriangleAndTransform(const Ray& ray, FVector pos, const Triangle& tri, float& t) {
+ constexpr float EPSILON = 1e-6f;
+
+ // Adjust the triangle vertices by the object's position
+ FVector v0 = tri.v0 + pos;
+ FVector v1 = tri.v1 + pos;
+ FVector v2 = tri.v2 + pos;
+
+ FVector edge1 = v1 - v0;
+ FVector edge2 = v2 - v0;
+ FVector h = ray.Direction.Cross(edge2);
+ float a = edge1.Dot(h);
+
+ if (std::abs(a) < EPSILON)
+ return false; // Ray is parallel to triangle
+
+ float f = 1.0f / a;
+ FVector s = ray.Origin - v0;
+ float u = f * s.Dot(h);
+
+ if (u < 0.0f || u > 1.0f)
+ return false;
+
+ FVector q = s.Cross(edge1);
+ float v = f * ray.Direction.Dot(q);
+
+ if (v < 0.0f || u + v > 1.0f)
+ return false;
+
+ t = f * edge2.Dot(q);
+ return t > EPSILON;
+}
+
+std::optional<FVector> QueryHandleIntersection(MtxF mtx, Ray ray, const Triangle& tri) {
+ float t;
+ Ray localRay = RayToLocalSpace(mtx, ray);
+ if (IntersectRayTriangle(localRay, tri, t)) {
+ FVector localClickPosition = localRay.Origin + localRay.Direction * t;
+ FVector worldClickPosition = TransformVecByMatrix(localClickPosition, (float(*)[4])&mtx);
+
+ return worldClickPosition; // Stop checking objects if we selected a Gizmo handle
+ }
+ return std::nullopt;
+}
+
+bool IntersectRaySphere(const Ray& ray, const FVector& sphereCenter, float radius, float& t) {
+ const float EPSILON = 1e-6f;
+
+ // Vector from ray origin to sphere center
+ FVector oc = ray.Origin - sphereCenter;
+
+ // Quadratic equation coefficients
+ float a = ray.Direction.Dot(ray.Direction);
+ float b = 2.0f * oc.Dot(ray.Direction);
+ float c = oc.Dot(oc) - (radius * radius);
+
+ // Compute discriminant
+ float discriminant = (b * b) - (4 * a * c);
+
+ // No intersection if discriminant is negative
+ if (discriminant < 0) {
+ return false;
+ }
+
+ // Compute nearest intersection point
+ float sqrtD = sqrtf(discriminant);
+ float t0 = (-b - sqrtD) / (2.0f * a);
+ float t1 = (-b + sqrtD) / (2.0f * a);
+
+ // Select the closest valid intersection
+ if (t0 > EPSILON) {
+ t = t0;
+ return true;
+ } else if (t1 > EPSILON) {
+ t = t1;
+ return true;
+ }
+
+ return false; // Sphere is behind the ray origin
+}
+
+// bool FindClosestObject(const Ray& ray, const std::vector<GameObject*>& objects, GameObject* outObject, float& outDistance) {
+// float closestDist = std::numeric_limits<float>::max();
+// bool found = false;
+
+// for (const auto& obj : objects) {
+// for (const auto& tri : obj.Triangles) {
+// float t;
+// if (IntersectRayTriangle(ray, tri, *obj.Pos, t) && t < closestDist) {
+// closestDist = t;
+// outObject = obj;
+// found = true;
+// }
+// }
+// }
+
+// if (found) {
+// outDistance = closestDist;
+// return true;
+// }
+
+// return false;
+// }
+
+// Transform a matrix to a matrix identity
+void Editor_MatrixIdentity(Mat4 mtx) {
+ register s32 i;
+ register s32 k;
+
+ for (i = 0; i < 4; i++) {
+ for (k = 0; k < 4; k++) {
+ mtx[i][k] = (i == k) ? 1.0f : 0.0f;
+ }
+ }
+}
+
+void Editor_AddMatrix(Mat4 mtx, int32_t flags) {
+ EditorMatrix.emplace_back();
+ guMtxF2L(mtx, &EditorMatrix.back());
+ gSPMatrix(gDisplayListHead++, &EditorMatrix.back(), flags);
+}
+
+float CalculateAngle(const FVector& start, const FVector& end) {
+ float dot = start.Dot(end);
+
+ float magStart = start.Magnitude();
+ float magEnd = end.Magnitude();
+
+ float cosAngle = dot / (magStart * magEnd);
+ cosAngle = std::min(1.0f, std::max(-1.0f, cosAngle));
+
+ return acos(cosAngle);
+}
+
+void SetDirectionFromRotator(IRotator rot, s8 direction[3]) {
+ float yaw = (rot.yaw) * (M_PI / 32768.0f); // Convert from n64 binary angles 0-0xFFFF 0-360 degrees to radians
+ float pitch = rot.pitch * (M_PI / 32768.0f);
+
+ // Compute unit direction vector
+ float x = cosf(yaw) * cosf(pitch);
+ float y = -sinf(pitch);
+ float z = -sinf(yaw) * cosf(pitch);
+
+ // Scale into -127 to 127 range (not 128 to avoid overflow)
+ direction[0] = static_cast<s8>(x * 127.0f);
+ direction[1] = static_cast<s8>(y * 127.0f);
+ direction[2] = static_cast<s8>(z * 127.0f);
+
+ //printf("Light dir %d %d %d (from rot 0x%X 0x%X 0x%X)\n", direction[0], direction[1], direction[2], rotator[0], rotator[1], rotator[2]);
+}
+
+void SetRotatorFromDirection(FVector direction, IRotator* rot) {
+ // Compute pitch (inverse of -sinf(pitch))
+ float pitch = -asinf(direction.y);
+
+ // Compute yaw (inverse of cosf(yaw) * cosf(pitch))
+ float yaw = atan2f(-direction.z, direction.x);
+
+ // Convert back to N64 angles (0-0xFFFF range)
+ rot->pitch = (s16)(pitch * (32768.0f / M_PI));
+ rot->yaw = (s16)(yaw * (32768.0f / M_PI));
+ rot->roll = 0; // Assume no roll, since it's undefined from direction alone
+}
+
+FVector GetPositionAheadOfCamera(f32 dist) {
+ FVector pos = FVector(cameras[0].pos[0], cameras[0].pos[1], cameras[0].pos[2]);
+
+ f32 pitch = (cameras[0].rot[2] / 65535.0f) * 360.0f;
+ f32 yaw = (cameras[0].rot[1] / 65535.0f) * 360.0f;
+
+ // Convert degrees to radians
+ pitch = pitch * M_PI / 180.0f;
+ yaw = yaw * M_PI / 180.0f;
+
+ // Compute forward vector
+ FVector forward(
+ -sinf(yaw), // X
+ -sinf(pitch), // Y
+ cosf(yaw) // Z (vertical component)
+ );
+
+ // Move 1000 units forward from the camera position
+ return pos + (forward * dist);
+}
diff --git a/src/engine/editor/EditorMath.h b/src/engine/editor/EditorMath.h
new file mode 100644
index 000000000..abc694976
--- /dev/null
+++ b/src/engine/editor/EditorMath.h
@@ -0,0 +1,58 @@
+#pragma once
+
+#include <libultraship/libultraship.h>
+#include <libultra/gbi.h>
+#include <libultra/types.h>
+#include "../CoreMath.h"
+#include <vector>
+#include "GameObject.h"
+
+extern "C" {
+#include "common_structs.h"
+}
+
+extern std::vector<Mtx> EditorMatrix;
+
+struct Ray {
+ FVector Origin;
+ FVector Direction;
+};
+
+struct Triangle {
+ FVector v0, v1, v2;
+};
+
+/**
+ * Projects 2D cursor into the game world
+ *
+ * @return FVector ray direction
+ *
+ * ray.x = camera->pos[0] + direction.x * length;
+ * ray.y = camera->pos[1] + direction.y * length;
+ * ray.z = camera->pos[2] + direction.z * length;
+ */
+bool IsInGameScreen();
+FVector ScreenRayTrace();
+bool QueryCollisionRayActor(Vec3f rayOrigin, Vec3f rayDir, Vec3f actorMin, Vec3f actorMax, float* t);
+FVector4 MultiplyMatrixVector(float matrix[4][4], float vector[4]);
+static bool InverseMatrix(const float m[16], float invOut[16]);
+void Copy(MtxF* src, MtxF* dest);
+void Clear(MtxF* mf);
+
+FVector TransformVecByMatrix(const FVector& vec, const float mtx[4][4]);
+FVector TransformVecDirection(const FVector& dir, const float mtx[4][4]);
+Ray RayToLocalSpace(MtxF mtx, const Ray& ray);
+bool IntersectRayTriangle(const Ray& ray, const Triangle& tri, float& t); // Uses local space not global space.
+bool IntersectRayTriangleAndTransform(const Ray& ray, FVector pos, const Triangle& tri, float& t); // Uses global space because no access to mtx
+bool IntersectRaySphere(const Ray& ray, const FVector& sphereCenter, float radius, float& t);
+/**
+ * optional used here so we can check for successful query and return the click position
+ */
+std::optional<FVector> QueryHandleIntersection(MtxF mtx, Ray ray, const Triangle& tri);
+
+void Editor_MatrixIdentity(Mat4 mtx);
+void Editor_AddMatrix(Mat4 mtx, int32_t flags);
+float CalculateAngle(const FVector& start, const FVector& end);
+void SetDirectionFromRotator(IRotator rot, s8 direction[3]);
+void SetRotatorFromDirection(FVector direction, IRotator* rot);
+FVector GetPositionAheadOfCamera(f32 dist);
diff --git a/src/engine/editor/GameObject.cpp b/src/engine/editor/GameObject.cpp
new file mode 100644
index 000000000..6f52c8ac8
--- /dev/null
+++ b/src/engine/editor/GameObject.cpp
@@ -0,0 +1,30 @@
+#include <libultraship/libultraship.h>
+#include "GameObject.h"
+
+namespace Editor {
+
+ GameObject::GameObject(const char* name, FVector* pos, IRotator* rot, FVector* scale, Gfx* model, std::vector<Triangle> triangles, CollisionType collision, float boundingBoxSize, int32_t* despawnFlag, int32_t despawnValue) {
+ Name = name;
+ Pos = pos;
+ Rot = rot;
+ Scale = scale;
+ Model = model;
+ Triangles = triangles;
+ Collision = collision;
+ BoundingBoxSize = boundingBoxSize;
+ DespawnFlag = despawnFlag;
+ DespawnValue = despawnValue;
+ }
+
+ GameObject::GameObject(FVector* pos, Vec3s* rot) {
+ //Pos = pos;
+ //Rot = rot;
+ }
+
+ GameObject::GameObject() {};
+
+ void GameObject::Draw(){};
+
+ void GameObject::Tick(){};
+
+} // namespace Editor
diff --git a/src/engine/editor/GameObject.h b/src/engine/editor/GameObject.h
new file mode 100644
index 000000000..ca08d8ba9
--- /dev/null
+++ b/src/engine/editor/GameObject.h
@@ -0,0 +1,44 @@
+#pragma once
+
+#include <libultraship/libultraship.h>
+#include <libultra/gbi.h>
+#include <libultra/types.h>
+#include "../CoreMath.h"
+#include "EditorMath.h"
+#include <vector>
+
+extern "C" {
+#include "common_structs.h"
+}
+
+struct Triangle;
+
+namespace Editor {
+ class GameObject {
+public:
+ enum class CollisionType {
+ VTX_INTERSECT,
+ BOUNDING_BOX,
+ BOUNDING_SPHERE
+ };
+
+ GameObject(const char* name, FVector* pos, IRotator* rot, FVector* scale, Gfx* model, std::vector<Triangle> triangles, CollisionType collision, float boundingBoxSize, int32_t* despawnFlag, int32_t despawnValue);
+ GameObject(FVector* pos, Vec3s* rot);
+ GameObject();
+ virtual void Tick();
+ virtual void Draw();
+ virtual void Load() {};
+
+ const char* Name;
+ FVector* Pos;
+ IRotator* Rot;
+ FVector* Scale;
+ Gfx* Model;
+ std::vector<Triangle> Triangles;
+ CollisionType Collision;
+ float BoundingBoxSize;
+ int32_t* DespawnFlag;
+ int32_t DespawnValue;
+
+ };
+}
diff --git a/src/engine/editor/Gizmo.cpp b/src/engine/editor/Gizmo.cpp
new file mode 100644
index 000000000..4987242f0
--- /dev/null
+++ b/src/engine/editor/Gizmo.cpp
@@ -0,0 +1,348 @@
+#include <libultraship/libultraship.h>
+#include <libultra/gbi.h>
+#include "../CoreMath.h"
+#include <libultra/types.h>
+#include "../World.h"
+
+#include "EditorMath.h"
+#include "Gizmo.h"
+#include "Collision.h"
+#include "port/Engine.h"
+#include <controller/controldevice/controller/mapping/keyboard/KeyboardScancodes.h>
+#include <window/Window.h>
+
+
+#include "engine/actors/Ship.h"
+#include "port/Game.h"
+#include "Handles.h"
+
+extern "C" {
+#include "common_structs.h"
+#include "main.h"
+#include "actors.h"
+#include "camera.h"
+#include "src/racing/collision.h"
+#include "math_util.h"
+}
+
+namespace Editor {
+
+void Gizmo::Load() {
+ /* Translate handle collision */
+ RedCollision.Pos = &Pos;
+ RedCollision.Model = (Gfx*)"__OTR__editor/gizmo/translate_handle_red";
+
+ GreenCollision.Pos = &Pos;
+ GreenCollision.Model = (Gfx*)"__OTR__editor/gizmo/translate_handle_green";
+
+ BlueCollision.Pos = &Pos;
+ BlueCollision.Model = (Gfx*)"__OTR__editor/gizmo/translate_handle_blue";
+
+ /* Rotate handle collision */
+ RedRotateCollision.Pos = &Pos;
+ RedRotateCollision.Model = (Gfx*)"__OTR__editor/gizmo/rot_handle_red";
+
+ GreenRotateCollision.Pos = &Pos;
+ GreenRotateCollision.Model = (Gfx*)"__OTR__editor/gizmo/rot_handle_green";
+
+ BlueRotateCollision.Pos = &Pos;
+ BlueRotateCollision.Model = (Gfx*)"__OTR__editor/gizmo/rot_handle_blue";
+
+ /* Scale handle collision */
+ RedScaleCollision.Pos = &Pos;
+ RedScaleCollision.Model = (Gfx*)"__OTR__editor/gizmo/scale_handle_red";
+
+ GreenScaleCollision.Pos = &Pos;
+ GreenScaleCollision.Model = (Gfx*)"__OTR__editor/gizmo/scale_handle_green";
+
+ BlueScaleCollision.Pos = &Pos;
+ BlueScaleCollision.Model = (Gfx*)"__OTR__editor/gizmo/scale_handle_blue";
+
+ GenerateCollisionMesh(&RedCollision, (Gfx*)LOAD_ASSET_RAW(RedCollision.Model), 1.0f);
+ GenerateCollisionMesh(&GreenCollision, (Gfx*)LOAD_ASSET_RAW(GreenCollision.Model), 1.0f);
+ GenerateCollisionMesh(&BlueCollision, (Gfx*)LOAD_ASSET_RAW(BlueCollision.Model), 1.0f);
+
+ GenerateCollisionMesh(&RedRotateCollision, (Gfx*)LOAD_ASSET_RAW(RedRotateCollision.Model), 1.0f);
+ GenerateCollisionMesh(&GreenRotateCollision, (Gfx*)LOAD_ASSET_RAW(GreenRotateCollision.Model), 1.0f);
+ GenerateCollisionMesh(&BlueRotateCollision, (Gfx*)LOAD_ASSET_RAW(BlueRotateCollision.Model), 1.0f);
+
+ GenerateCollisionMesh(&RedScaleCollision, (Gfx*)LOAD_ASSET_RAW(RedScaleCollision.Model), 1.0f);
+ GenerateCollisionMesh(&GreenScaleCollision, (Gfx*)LOAD_ASSET_RAW(GreenScaleCollision.Model), 1.0f);
+ GenerateCollisionMesh(&BlueScaleCollision, (Gfx*)LOAD_ASSET_RAW(BlueScaleCollision.Model), 1.0f);
+}
+
+void Gizmo::Tick() {
+ if (Enabled) {
+ TranslationMode mode = static_cast<TranslationMode>(CVarGetInteger("eGizmoMode", 0));
+ switch(mode) {
+ case TranslationMode::Move:
+ Gizmo::Translate();
+ break;
+ case TranslationMode::Rotate:
+ Gizmo::Rotate();
+ break;
+ case TranslationMode::Scale:
+ Gizmo::Scale();
+ break;
+ }
+ }
+}
+
+// Makes the gizmo visible
+void Gizmo::SetGizmo(GameObject* object, Ray ray) {
+ _selected = object;
+ _ray = ray.Direction;
+ Pos = FVector(
+ object->Pos->x,
+ object->Pos->y,
+ object->Pos->z
+ );
+}
+
+void Gizmo::SetGizmoNoCursor(GameObject* object) {
+ _selected = object;
+ Pos = FVector(
+ object->Pos->x,
+ object->Pos->y,
+ object->Pos->z
+ );
+}
+
+void Gizmo::Translate() {
+ static float length = 180.0f; // Default value
+
+ // Prevent nullptr exceptions
+ if (_selected == NULL || _selected->Pos == NULL) {
+ return;
+ }
+
+ if (Enabled) {
+ length = sqrt(
+ pow(_selected->Pos->x - cameras[0].pos[0], 2) +
+ pow(_selected->Pos->y - cameras[0].pos[1], 2) +
+ pow(_selected->Pos->z - cameras[0].pos[2], 2)
+ );
+
+ switch(SelectedHandle) {
+ case GizmoHandle::All_Axis:
+ _selected->Pos->x = (cameras[0].pos[0] + _ray.x * PickDistance) + _cursorOffset.x;
+ _selected->Pos->y = (cameras[0].pos[1] + _ray.y * PickDistance) + _cursorOffset.y;
+ _selected->Pos->z = (cameras[0].pos[2] + _ray.z * PickDistance) + _cursorOffset.z;
+ if (CVarGetInteger("gEditorSnapToGround", 0) == true) {
+ _selected->Pos->y = SnapToSurface(_selected->Pos);
+ }
+ break;
+ case GizmoHandle::X_Axis:
+ _selected->Pos->x = (cameras[0].pos[0] + _ray.x * length) + _cursorOffset.x;
+ if (CVarGetInteger("gEditorSnapToGround", 0) == true) {
+ _selected->Pos->y = SnapToSurface(_selected->Pos);
+ }
+ break;
+ case GizmoHandle::Y_Axis:
+ _selected->Pos->y = (cameras[0].pos[1] + _ray.y * length) + _cursorOffset.y;
+ break;
+ case GizmoHandle::Z_Axis:
+ _selected->Pos->z = (cameras[0].pos[2] + _ray.z * length) + _cursorOffset.z;
+ if (CVarGetInteger("gEditorSnapToGround", 0) == true) {
+ _selected->Pos->y = SnapToSurface(_selected->Pos);
+ }
+ break;
+ }
+
+ if (CVarGetInteger("gEditorBoundary", 0) == true) {
+ _selected->Pos->x = MAX(_selected->Pos->x, dimensions.MinX);
+ _selected->Pos->x = MIN(_selected->Pos->x, dimensions.MaxX);
+
+ _selected->Pos->y = MAX(_selected->Pos->y, dimensions.MinY);
+ _selected->Pos->y = MIN(_selected->Pos->y, dimensions.MaxY);
+
+ _selected->Pos->z = MAX(_selected->Pos->z, dimensions.MinZ);
+ _selected->Pos->z = MIN(_selected->Pos->z, dimensions.MaxZ);
+ }
+
+ Pos = FVector(
+ _selected->Pos->x,
+ _selected->Pos->y,
+ _selected->Pos->z
+ );
+ }
+}
+
+f32 Gizmo::SnapToSurface(FVector* pos) {
+ float y;
+ y = spawn_actor_on_surface(pos->x, 2000.0f, pos->z);
+
+ if (y == 3000.0f || y == -3000.0f) {
+ y = pos->y;
+ }
+
+ return y;
+}
+
+void Gizmo::Rotate() {
+ FVector cam = FVector(cameras[0].pos[0], cameras[0].pos[1], cameras[0].pos[2]);
+
+ if (_selected == nullptr || _selected->Rot == nullptr) {
+ return;
+ }
+
+ // Store initial scale at the beginning of the drag
+ if (ManipulationStart) {
+ ManipulationStart = false;
+ InitialRotation = *_selected->Rot; // Store initial rotation
+ }
+
+ // Initial click position
+ FVector clickPos = *_selected->Pos - _cursorOffset;
+
+ // Calculate difference
+ FVector diff = (cam + _ray * PickDistance) - clickPos;
+
+ // Set rotation sensitivity
+ diff = diff * 100.0f;
+ switch (SelectedHandle) {
+ case GizmoHandle::X_Axis:
+ _selected->Rot->pitch = (uint16_t)InitialRotation.pitch + diff.x;
+ break;
+ case GizmoHandle::Y_Axis:
+ _selected->Rot->yaw = (uint16_t)InitialRotation.yaw + diff.y;
+ break;
+ case GizmoHandle::Z_Axis:
+ _selected->Rot->roll = (uint16_t)InitialRotation.roll + diff.z;
+ break;
+ }
+}
+
+void Gizmo::Scale() {
+ FVector cam = FVector(cameras[0].pos[0], cameras[0].pos[1], cameras[0].pos[2]);
+ if (_selected == nullptr || _selected->Scale == nullptr) {
+ return;
+ }
+
+ // Store initial scale at the beginning of the drag
+ if (ManipulationStart) {
+ ManipulationStart = false;
+ InitialScale = *_selected->Scale;
+ }
+
+ // Initial click position
+ FVector clickPos = *_selected->Pos - _cursorOffset;
+
+ // Calculate difference
+ FVector diff = (cam + _ray * PickDistance) - clickPos;
+
+ // Lower scaling sensitivity
+ diff = diff * 0.01f;
+
+ switch (SelectedHandle) {
+ case GizmoHandle::X_Axis:
+ _selected->Scale->x = InitialScale.x + -diff.x;
+ break;
+ case GizmoHandle::Y_Axis:
+ _selected->Scale->y = InitialScale.y + diff.y;
+ break;
+ case GizmoHandle::Z_Axis:
+ _selected->Scale->z = InitialScale.z + -diff.z;
+ break;
+ case GizmoHandle::All_Axis:
+ float uniformScale = (diff.x - diff.y - diff.z) / 3.0f;
+ uniformScale *= 1.8; // Increased sensitivity
+ _selected->Scale->x = uniformScale;
+ _selected->Scale->y = uniformScale;
+ _selected->Scale->z = uniformScale;
+ break;
+ }
+}
+
+void Gizmo::Draw() {
+ if (Enabled) {
+ DrawHandles();
+ //DebugCollision(&RedCollision, Pos, {0, 0, 0}, {0.05f, 0.05f, 0.05f}, RedCollision.Triangles);
+ //DebugCollision(&BlueCollision, Pos, {90, 0, 0}, {0.05f, 0.05f, 0.05f}, BlueCollision.Triangles);
+ //DebugCollision(&GreenCollision, Pos, {0, 90, 0}, {0.05f, 0.05f, 0.05f}, GreenCollision.Triangles);
+ //DebugCollision(&RedRotateCollision, Pos, {0, 0, 0}, {0.15f, 0.15f, 0.15f}, RedRotateCollision.Triangles);
+ //DebugCollision((uintptr_t)_selected, Pos, BlueRotateCollision.Triangles);
+ //DebugCollision((uintptr_t)_selected, Pos, GreenRotateCollision.Triangles);
+ }
+}
+
+void Gizmo::DrawHandles() {
+ Mat4 mainMtx;
+ Editor_MatrixIdentity((float(*)[4])&Mtx_RedX);
+ Editor_MatrixIdentity((float(*)[4])&Mtx_GreenY);
+ Editor_MatrixIdentity((float(*)[4])&Mtx_BlueZ);
+
+ const char* blueHandle;
+ const char* greenHandle;
+ const char* redHandle;
+ const char* center = nullptr;
+ IRotator blueRot;
+ IRotator greenRot;
+ IRotator redRot;
+ FVector scale = {0.05f, 0.05f, 0.05f};
+
+ switch(static_cast<TranslationMode>(CVarGetInteger("eGizmoMode", 0))) {
+ case TranslationMode::Move:
+ center = "__OTR__editor/gizmo/center_handle";
+ blueHandle = "__OTR__editor/gizmo/translate_handle_blue";
+ greenHandle = "__OTR__editor/gizmo/translate_handle_green";
+ redHandle = "__OTR__editor/gizmo/translate_handle_red";
+ _gizmoOffset = 8.0f;
+ greenRot = {0, 90, 0};
+ blueRot = {90, 0, 0};
+ scale = {0.3, 0.3, 0.3};
+ break;
+ case TranslationMode::Rotate:
+ center = nullptr; // No All_Axis drag button for Rotation
+ blueHandle = "__OTR__editor/gizmo/rot_handle_blue";
+ greenHandle = "__OTR__editor/gizmo/rot_handle_green";
+ redHandle = "__OTR__editor/gizmo/rot_handle_red";
+ _gizmoOffset = 0.0f;
+ scale = {0.15f, 0.15f, 0.15f};
+ break;
+ case TranslationMode::Scale:
+ center = "__OTR__editor/gizmo/center_handle";
+ blueHandle = "__OTR__editor/gizmo/scale_handle_blue";
+ greenHandle = "__OTR__editor/gizmo/scale_handle_green";
+ redHandle = "__OTR__editor/gizmo/scale_handle_red";
+ _gizmoOffset = 8.0f;
+ greenRot = {0, 90, 0};
+ blueRot = {90, 0, 0};
+ scale = {0.05f, 0.05f, 0.05f};
+ break;
+ }
+
+ ApplyMatrixTransformations(mainMtx, Pos, Rot, {1, 1, 1});
+ Editor_AddMatrix(mainMtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+
+ if (center) {
+ Mat4 CenterMtx;
+ Editor_MatrixIdentity(CenterMtx);
+
+ // Calculate camera-to-object distance
+ FVector cameraDir = FVector(Pos.x - cameras[0].pos[0], Pos.y - cameras[0].pos[1], Pos.z - cameras[0].pos[2]);
+ cameraDir = cameraDir.Normalize();
+
+ IRotator centerRot;
+ SetRotatorFromDirection(cameraDir, &centerRot);
+ centerRot.pitch += 0x4000; // Align mesh to face camera since it was not exported facing the correct direction
+ centerRot.yaw += 0x4000;
+
+ ApplyMatrixTransformations(CenterMtx, Pos, centerRot, FVector(0.06f, 0.06f, 0.06f));
+ Editor_AddMatrix(CenterMtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(gDisplayListHead++, (Gfx*)center);
+ }
+
+ ApplyMatrixTransformations((float(*)[4])&Mtx_RedX, FVector(Pos.x, Pos.y, Pos.z - _gizmoOffset), Rot, scale);
+ Editor_AddMatrix((float(*)[4])&Mtx_RedX, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(gDisplayListHead++, (Gfx*)redHandle);
+
+ ApplyMatrixTransformations((float(*)[4])&Mtx_GreenY, FVector(Pos.x - _gizmoOffset, Pos.y, Pos.z), greenRot, scale);
+ Editor_AddMatrix((float(*)[4])&Mtx_GreenY, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(gDisplayListHead++, (Gfx*)greenHandle);
+
+ ApplyMatrixTransformations((float(*)[4])&Mtx_BlueZ, FVector(Pos.x, Pos.y + _gizmoOffset, Pos.z), blueRot, scale);
+ Editor_AddMatrix((float(*)[4])&Mtx_BlueZ, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(gDisplayListHead++, (Gfx*)blueHandle);
+}
+}
diff --git a/src/engine/editor/Gizmo.h b/src/engine/editor/Gizmo.h
new file mode 100644
index 000000000..47ef99549
--- /dev/null
+++ b/src/engine/editor/Gizmo.h
@@ -0,0 +1,85 @@
+#pragma once
+
+#include <libultraship/libultraship.h>
+#include <libultra/gbi.h>
+#include "Collision.h"
+#include "GameObject.h"
+
+namespace Editor {
+
+class Gizmo {
+public:
+
+ enum class GizmoHandle {
+ None,
+ All_Axis,
+ X_Axis,
+ Y_Axis,
+ Z_Axis
+ };
+
+ enum class TranslationMode {
+ Move,
+ Rotate,
+ Scale
+ };
+
+ void Tick();
+ void Draw();
+ void Load();
+
+ void SetGizmo(GameObject* object, Ray ray);
+ void SetGizmoNoCursor(GameObject* object); // Used for scene explorer selection
+ void Translate();
+ void Rotate();
+ void Scale();
+ void DrawHandles();
+ f32 SnapToSurface(FVector* pos);
+
+ struct TrackDimensions {
+ s16 MinX = -10000;
+ s16 MaxX = 10000;
+ s16 MinY = -3000;
+ s16 MaxY = 3000;
+ s16 MinZ = -10000;
+ s16 MaxZ = 10000;
+ };
+ TrackDimensions dimensions;
+
+ bool Enabled;
+ bool ManipulationStart = true;
+ FVector InitialScale = {1, 1, 1};
+ IRotator InitialRotation = {0, 0, 0};
+ GizmoHandle SelectedHandle;
+
+ GameObject RedCollision;
+ GameObject GreenCollision;
+ GameObject BlueCollision;
+
+ GameObject RedRotateCollision;
+ GameObject GreenRotateCollision;
+ GameObject BlueRotateCollision;
+
+ GameObject RedScaleCollision;
+ GameObject GreenScaleCollision;
+ GameObject BlueScaleCollision;
+
+ MtxF Mtx_RedX;
+ MtxF Mtx_GreenY;
+ MtxF Mtx_BlueZ;
+
+ FVector Pos; // Global scene view
+ IRotator Rot = {0, 0, 0};
+ float AllAxisRadius = 3.0f; // Free move selection radius
+ float PickDistance;
+ FVector _cursorOffset;
+ float _gizmoOffset = 8.0f;
+
+ float HandleSize = 2.0f;
+
+ FVector _ray;
+ GameObject* _selected = nullptr;
+ private:
+ bool _draw = false;
+};
+}
diff --git a/src/engine/editor/Handles.cpp b/src/engine/editor/Handles.cpp
new file mode 100644
index 000000000..9074a2b45
--- /dev/null
+++ b/src/engine/editor/Handles.cpp
@@ -0,0 +1,23 @@
+#include <libultraship/libultraship.h>
+#include <libultra/gbi.h>
+
+#include "Handles.h"
+
+namespace Editor {
+ Handles::Handles() {
+ Pos = &pos;
+ Rot = &rot;
+ }
+
+ void Handles::Load() {
+
+ }
+
+ void Handles::Tick() {
+
+ }
+
+ void Handles::Draw() {
+
+ }
+} \ No newline at end of file
diff --git a/src/engine/editor/Handles.h b/src/engine/editor/Handles.h
new file mode 100644
index 000000000..1faa4b59e
--- /dev/null
+++ b/src/engine/editor/Handles.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include <libultraship/libultraship.h>
+#include <libultra/gbi.h>
+#include "GameObject.h"
+
+namespace Editor {
+ class Handles : public GameObject {
+
+ Handles();
+
+ virtual void Tick() override;
+ virtual void Draw() override;
+ virtual void Load() override;
+
+ FVector pos;
+ IRotator rot;
+ };
+}
diff --git a/src/engine/editor/Light.cpp b/src/engine/editor/Light.cpp
new file mode 100644
index 000000000..594383bd3
--- /dev/null
+++ b/src/engine/editor/Light.cpp
@@ -0,0 +1,84 @@
+#include <iostream>
+#include <libultraship/libultraship.h>
+#include <libultra/gbi.h>
+#include "../CoreMath.h"
+#include <libultra/types.h>
+#include "../World.h"
+
+#include "Light.h"
+#include "port/Engine.h"
+#include <controller/controldevice/controller/mapping/keyboard/KeyboardScancodes.h>
+#include <window/Window.h>
+
+#include "engine/actors/Ship.h"
+#include "port/Game.h"
+#include "Gizmo.h"
+
+#include "EditorMath.h"
+
+extern "C" {
+#include "common_structs.h"
+#include "main.h"
+#include "defines.h"
+#include "actors.h"
+#include "camera.h"
+#include "math_util.h"
+#include "math_util_2.h"
+}
+
+namespace Editor {
+
+size_t LightObject::NumLights = 0;
+
+ LightObject::LightObject(const char* name, FVector* pos, s8* direction) : GameObject(nullptr, nullptr) {
+ Name = name;
+ Pos = &LightPos;
+ Rot = &LightRot;
+ Scale = &LightScale;
+
+ DespawnFlag = &_despawnFlag;
+ DespawnValue = -1;
+
+ Direction = direction;
+
+ Collision = CollisionType::BOUNDING_BOX;
+ BoundingBoxSize = 4.0f;
+
+ NumLights += 1;
+ }
+
+ void LightObject::Load() {
+ }
+
+ void LightObject::Tick() {
+ SetDirectionFromRotator(*Rot, Direction);
+ }
+ void LightObject::Draw() {
+ Mat4 mtx_sun;
+ Editor_MatrixIdentity(mtx_sun);
+ gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
+ gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
+
+
+ // Calculate camera-to-object distance
+ FVector cameraDir = FVector(LightPos.x - cameras[0].pos[0], LightPos.y - cameras[0].pos[1], LightPos.z - cameras[0].pos[2]);
+ cameraDir = cameraDir.Normalize();
+
+ IRotator centerRot;
+ SetRotatorFromDirection(cameraDir, &centerRot);
+
+ // Account for object not facing the correct direction when exported
+ centerRot.yaw += 0x4000;
+ ApplyMatrixTransformations(mtx_sun, LightPos, centerRot, LightScale);
+ Editor_AddMatrix(mtx_sun, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(gDisplayListHead++, sun_LightModel_mesh);
+
+ // Draw Arrow
+ Mat4 mtx_arrow;
+ IRotator rot = LightRot;
+ rot.yaw += 0x4000;
+ ApplyMatrixTransformations(mtx_arrow, LightPos, rot, LightScale);
+ Editor_AddMatrix(mtx_arrow, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(gDisplayListHead++, (Gfx*)"__OTR__editor/light/sun_arrow");
+ }
+}
diff --git a/src/engine/editor/Light.h b/src/engine/editor/Light.h
new file mode 100644
index 000000000..972942663
--- /dev/null
+++ b/src/engine/editor/Light.h
@@ -0,0 +1,2143 @@
+#pragma once
+
+#include <libultraship/libultraship.h>
+#include <libultra/gbi.h>
+#include "Collision.h"
+#include "Gizmo.h"
+#include "GameObject.h"
+
+namespace Editor {
+
+class LightObject : public GameObject {
+public:
+ LightObject(const char* name, FVector* pos, s8* direction);
+
+ virtual void Draw() override;
+ virtual void Tick() override;
+ virtual void Load() override;
+
+ static size_t NumLights;
+ FVector LightPos = FVector(0, 100, 0);
+ IRotator LightRot = IRotator(0, 0, 0);
+ FVector LightScale = FVector(0.1, 0.1, 0.1);
+ s8* Direction;
+ s32 _despawnFlag = 0;
+
+u8 sun_sun_rgba32[16384] = {
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0xed, 0x8e, 0x00, 0xff,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0xe4, 0x85, 0x00, 0xff, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xfb, 0x9d, 0x01, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0xdb, 0x7d, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xac, 0x01, 0xff,
+ 0xe5, 0x87, 0x01, 0xff, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xae, 0x01, 0xff,
+ 0xd1, 0x72, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0xff, 0xba, 0x00, 0xff,
+ 0xff, 0xaa, 0x00, 0xff, 0xbc, 0x5d, 0x01, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xc4, 0x01, 0xff, 0xfe, 0xba, 0x00, 0xff,
+ 0xc6, 0x67, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xc9, 0x00, 0xff,
+ 0xff, 0xc8, 0x01, 0xff, 0xda, 0x7c, 0x01, 0xff,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xd9, 0x00, 0xff,
+ 0xff, 0xd1, 0x01, 0xff, 0xff, 0xc0, 0x01, 0xff,
+ 0xbb, 0x5d, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0xff, 0xd8, 0x00, 0xff,
+ 0xff, 0xd8, 0x01, 0xff, 0xfe, 0xa2, 0x00, 0xff,
+ 0xbc, 0x5d, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xe5, 0x00, 0xff,
+ 0xff, 0xde, 0x00, 0xff, 0xff, 0xb8, 0x01, 0xff,
+ 0xbc, 0x5d, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xe8, 0x01, 0xff,
+ 0xff, 0xe9, 0x01, 0xff, 0xff, 0xcc, 0x01, 0xff,
+ 0xcd, 0x6f, 0x01, 0xff, 0xbc, 0x5d, 0x01, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xf9, 0x00, 0xff, 0xff, 0xf3, 0x00, 0xff,
+ 0xff, 0xec, 0x00, 0xff, 0xff, 0xae, 0x00, 0xff,
+ 0xbc, 0x5d, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xfe, 0xf5, 0x00, 0xff,
+ 0xff, 0xf8, 0x00, 0xff, 0xff, 0xf2, 0x00, 0xff,
+ 0xf8, 0x99, 0x00, 0xff, 0xbc, 0x5d, 0x01, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xfa, 0x01, 0xff, 0xff, 0xa5, 0x01, 0xff,
+ 0xbb, 0x5d, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xca, 0x00, 0xff, 0xc1, 0x63, 0x01, 0xff,
+ 0xbb, 0x5d, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xfd, 0x01, 0xff, 0xf6, 0x98, 0x00, 0xff,
+ 0xbb, 0x5d, 0x00, 0xff, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xef, 0x91, 0x00, 0xff,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xf6, 0x01, 0xff, 0xef, 0x91, 0x00, 0xff,
+ 0xbc, 0x5e, 0x01, 0xff, 0xbb, 0x5d, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xf9, 0x01, 0xff, 0xeb, 0x8c, 0x01, 0xff,
+ 0xbb, 0x5d, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0xfe, 0xa0, 0x01, 0xff,
+ 0xef, 0x91, 0x01, 0xff, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xfd, 0x9e, 0x00, 0xff,
+ 0xff, 0xa4, 0x00, 0xff, 0xcf, 0x70, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xc6, 0x01, 0xff,
+ 0xbb, 0x5d, 0x00, 0xff, 0xbc, 0x5d, 0x01, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xf3, 0x01, 0xff, 0xdc, 0x7e, 0x00, 0xff,
+ 0xbc, 0x5d, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0xff, 0xc2, 0x01, 0xff,
+ 0xff, 0xb3, 0x00, 0xff, 0xff, 0xa4, 0x00, 0xff,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xb3, 0x01, 0xff, 0xff, 0xb9, 0x01, 0xff,
+ 0xe2, 0x84, 0x01, 0xff, 0xbb, 0x5c, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xf7, 0x01, 0xff,
+ 0xe1, 0x82, 0x00, 0xff, 0xbc, 0x5d, 0x01, 0xff,
+ 0xbc, 0x5e, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xec, 0x00, 0xff, 0xcd, 0x6e, 0x00, 0xff,
+ 0xbc, 0x5d, 0x00, 0xff, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0xff, 0xe4, 0x00, 0xff,
+ 0xff, 0xd7, 0x01, 0xff, 0xff, 0xc9, 0x01, 0xff,
+ 0xff, 0xb9, 0x00, 0xff, 0xcf, 0x70, 0x01, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xc0, 0x00, 0xff, 0xff, 0xc7, 0x00, 0xff,
+ 0xff, 0xcf, 0x01, 0xff, 0xf8, 0x99, 0x01, 0xff,
+ 0xbc, 0x5e, 0x01, 0xff, 0xbb, 0x5d, 0x00, 0xff,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xbe, 0x00, 0xff, 0xbc, 0x5d, 0x01, 0xff,
+ 0xbc, 0x5d, 0x01, 0xff, 0xbc, 0x5d, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xe5, 0x00, 0xff, 0xbb, 0x5d, 0x00, 0xff,
+ 0xbb, 0x5d, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xf8, 0x00, 0xff, 0xff, 0xeb, 0x00, 0xff,
+ 0xff, 0xde, 0x00, 0xff, 0xff, 0xcf, 0x00, 0xff,
+ 0xe1, 0x82, 0x01, 0xff, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xd5, 0x00, 0xff,
+ 0xfe, 0xdc, 0x00, 0xff, 0xff, 0xe7, 0x01, 0xff,
+ 0xff, 0xb2, 0x00, 0xff, 0xd0, 0x72, 0x01, 0xff,
+ 0xbb, 0x5d, 0x00, 0xff, 0xbb, 0x5d, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xf7, 0x00, 0xff, 0xea, 0x8b, 0x00, 0xff,
+ 0xfc, 0x9e, 0x00, 0xff, 0xff, 0xb0, 0x01, 0xff,
+ 0xff, 0xb1, 0x00, 0xff, 0xff, 0xa2, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xdc, 0x00, 0xff, 0xbc, 0x5d, 0x01, 0xff,
+ 0xbb, 0x5c, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xf4, 0x00, 0xff,
+ 0xff, 0xe7, 0x01, 0xff, 0xf6, 0x98, 0x00, 0xff,
+ 0xbb, 0x5c, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0xff, 0xe1, 0x00, 0xff,
+ 0xff, 0xea, 0x00, 0xff, 0xff, 0xf3, 0x01, 0xff,
+ 0xfe, 0xfc, 0x00, 0xff, 0xfe, 0xcb, 0x00, 0xff,
+ 0xe2, 0x84, 0x00, 0xff, 0xbc, 0x5d, 0x01, 0xff,
+ 0xbc, 0x5e, 0x01, 0xff, 0xbc, 0x5d, 0x01, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xa2, 0x00, 0xff, 0xfe, 0xb5, 0x00, 0xff,
+ 0xff, 0xc9, 0x01, 0xff, 0xff, 0xda, 0x01, 0xff,
+ 0xff, 0xe1, 0x01, 0xff, 0xff, 0xe6, 0x01, 0xff,
+ 0xff, 0xe7, 0x01, 0xff, 0xff, 0xe2, 0x01, 0xff,
+ 0xff, 0xda, 0x01, 0xff, 0xfe, 0xcb, 0x00, 0xff,
+ 0xff, 0xbd, 0x00, 0xff, 0xff, 0xaa, 0x01, 0xff,
+ 0xf1, 0x93, 0x00, 0xff, 0xda, 0x7c, 0x00, 0xff,
+ 0xbc, 0x5d, 0x01, 0xff, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xfd, 0x00, 0xff,
+ 0xff, 0xb0, 0x00, 0xff, 0xbb, 0x5c, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0xff, 0xf5, 0x01, 0xff, 0xff, 0xfe, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xe3, 0x00, 0xff, 0xff, 0xa0, 0x00, 0xff,
+ 0xbb, 0x5d, 0x00, 0xff, 0xbb, 0x5d, 0x00, 0xff,
+ 0xbb, 0x5d, 0x00, 0xff, 0xbc, 0x5d, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xb7, 0x00, 0xff,
+ 0xff, 0xd4, 0x00, 0xff, 0xff, 0xdc, 0x01, 0xff,
+ 0xff, 0xe2, 0x01, 0xff, 0xff, 0xe8, 0x01, 0xff,
+ 0xff, 0xee, 0x00, 0xff, 0xfe, 0xf3, 0x00, 0xff,
+ 0xfe, 0xf7, 0x00, 0xff, 0xff, 0xfd, 0x00, 0xff,
+ 0xfe, 0xfc, 0x00, 0xff, 0xfe, 0xf9, 0x00, 0xff,
+ 0xff, 0xf5, 0x01, 0xff, 0xff, 0xf0, 0x01, 0xff,
+ 0xff, 0xe9, 0x00, 0xff, 0xff, 0xe3, 0x01, 0xff,
+ 0xff, 0xdc, 0x00, 0xff, 0xff, 0xd4, 0x00, 0xff,
+ 0xff, 0xb9, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xcb, 0x01, 0xff,
+ 0xce, 0x6f, 0x01, 0xff, 0xbb, 0x5d, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xca, 0x00, 0xff, 0xd5, 0x76, 0x01, 0xff,
+ 0xbc, 0x5e, 0x01, 0xff, 0xfa, 0x9b, 0x01, 0xff,
+ 0xfe, 0xd2, 0x00, 0xff, 0xfe, 0xe2, 0x00, 0xff,
+ 0xff, 0xf0, 0x00, 0xff, 0xfe, 0xf5, 0x00, 0xff,
+ 0xff, 0xfc, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xfe, 0x01, 0xff,
+ 0xff, 0xf7, 0x00, 0xff, 0xfe, 0xf0, 0x00, 0xff,
+ 0xff, 0xe4, 0x01, 0xff, 0xff, 0xd4, 0x01, 0xff,
+ 0xff, 0xa7, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xe2, 0x01, 0xff, 0xe0, 0x82, 0x01, 0xff,
+ 0xbc, 0x5d, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xd4, 0x75, 0x00, 0xff,
+ 0xff, 0xbb, 0x00, 0xff, 0xfe, 0xd7, 0x00, 0xff,
+ 0xff, 0xe8, 0x01, 0xff, 0xff, 0xf7, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xf8, 0x00, 0xff, 0xff, 0xeb, 0x00, 0xff,
+ 0xff, 0xda, 0x00, 0xff, 0xff, 0xc1, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xfb, 0x9d, 0x00, 0xff, 0xbb, 0x5d, 0x00, 0xff,
+ 0xbc, 0x5d, 0x00, 0xff, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xf6, 0x98, 0x01, 0xff, 0xff, 0xcb, 0x01, 0xff,
+ 0xff, 0xdc, 0x01, 0xff, 0xff, 0xed, 0x01, 0xff,
+ 0xff, 0xfb, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xf1, 0x01, 0xff, 0xff, 0xdf, 0x00, 0xff,
+ 0xff, 0xcc, 0x00, 0xff, 0xf6, 0x97, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xc6, 0x00, 0xff,
+ 0xbb, 0x5d, 0x00, 0xff, 0xbc, 0x5d, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xca, 0x00, 0xff, 0xfe, 0xe3, 0x00, 0xff,
+ 0xfe, 0xf3, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xf5, 0x00, 0xff,
+ 0xff, 0xe3, 0x00, 0xff, 0xff, 0xca, 0x01, 0xff,
+ 0xd1, 0x73, 0x01, 0xff, 0xcf, 0x71, 0x01, 0xff,
+ 0xbc, 0x5d, 0x01, 0xff, 0xbc, 0x5d, 0x01, 0xff,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xbc, 0x01, 0xff,
+ 0xff, 0xdb, 0x00, 0xff, 0xff, 0xf4, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xf3, 0x01, 0xff, 0xff, 0xd9, 0x01, 0xff,
+ 0xff, 0xb6, 0x00, 0xff, 0xbc, 0x5d, 0x01, 0xff,
+ 0xbc, 0x5d, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff,
+ 0xfd, 0x9f, 0x00, 0xff, 0xff, 0xd3, 0x00, 0xff,
+ 0xff, 0xec, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xe7, 0x00, 0xff,
+ 0xff, 0xd1, 0x01, 0xff, 0xf1, 0x92, 0x00, 0xff,
+ 0xbc, 0x5d, 0x01, 0xff, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xc9, 0x01, 0xff, 0xff, 0xe3, 0x01, 0xff,
+ 0xfe, 0xf8, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xf5, 0x01, 0xff,
+ 0xff, 0xe0, 0x01, 0xff, 0xff, 0xc8, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xcf, 0x71, 0x00, 0xff, 0xc7, 0x68, 0x01, 0xff,
+ 0xbd, 0x5e, 0x01, 0xff, 0xbb, 0x5d, 0x00, 0xff,
+ 0xbc, 0x5e, 0x01, 0xff, 0xbc, 0x5d, 0x00, 0xff,
+ 0xbc, 0x5e, 0x01, 0xff, 0xbc, 0x5d, 0x01, 0xff,
+ 0xbb, 0x5d, 0x00, 0xff, 0xbc, 0x5d, 0x01, 0xff,
+ 0xbc, 0x5d, 0x01, 0xff, 0xbc, 0x5d, 0x01, 0xff,
+ 0xbc, 0x5d, 0x01, 0xff, 0xbc, 0x5d, 0x01, 0xff,
+ 0xbc, 0x5d, 0x00, 0xff, 0xff, 0xaa, 0x00, 0xff,
+ 0xff, 0xd8, 0x01, 0xff, 0xff, 0xef, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xed, 0x00, 0xff, 0xff, 0xd7, 0x01, 0xff,
+ 0xff, 0xa9, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xfe, 0xf6, 0x00, 0xff,
+ 0xff, 0xe7, 0x01, 0xff, 0xff, 0xd7, 0x01, 0xff,
+ 0xff, 0xc7, 0x01, 0xff, 0xff, 0xb8, 0x01, 0xff,
+ 0xff, 0xa7, 0x00, 0xff, 0xf6, 0x98, 0x00, 0xff,
+ 0xe7, 0x89, 0x01, 0xff, 0xd9, 0x7b, 0x01, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xf8, 0x99, 0x00, 0xff, 0xff, 0xa6, 0x00, 0xff,
+ 0xff, 0xac, 0x00, 0xff, 0xff, 0xa4, 0x00, 0xff,
+ 0xfa, 0x9b, 0x01, 0xff, 0xf0, 0x91, 0x00, 0xff,
+ 0xe4, 0x85, 0x00, 0xff, 0xd9, 0x7a, 0x01, 0xff,
+ 0xcb, 0x6c, 0x00, 0xff, 0xbc, 0x5d, 0x00, 0xff,
+ 0xbb, 0x5c, 0x00, 0xff, 0xbb, 0x5d, 0x00, 0xff,
+ 0xca, 0x6b, 0x01, 0xff, 0xff, 0xc5, 0x00, 0xff,
+ 0xff, 0xe4, 0x01, 0xff, 0xfe, 0xfa, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xfb, 0x01, 0xff, 0xff, 0xe3, 0x01, 0xff,
+ 0xff, 0xc5, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xf8, 0x00, 0xff,
+ 0xff, 0xe7, 0x00, 0xff, 0xff, 0xd7, 0x00, 0xff,
+ 0xff, 0xc5, 0x00, 0xff, 0xff, 0xb4, 0x00, 0xff,
+ 0xf4, 0x95, 0x00, 0xff, 0xd0, 0x71, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0xff, 0xaf, 0x00, 0xff,
+ 0xff, 0xbc, 0x01, 0xff, 0xff, 0xca, 0x01, 0xff,
+ 0xff, 0xd9, 0x00, 0xff, 0xff, 0xe9, 0x01, 0xff,
+ 0xff, 0xec, 0x00, 0xff, 0xff, 0xe8, 0x01, 0xff,
+ 0xff, 0xe2, 0x01, 0xff, 0xff, 0xdc, 0x00, 0xff,
+ 0xff, 0xd5, 0x00, 0xff, 0xff, 0xcd, 0x01, 0xff,
+ 0xdf, 0x80, 0x00, 0xff, 0xfe, 0xcb, 0x00, 0xff,
+ 0xff, 0xe9, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xe8, 0x01, 0xff,
+ 0xff, 0xcc, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xfa, 0x00, 0xff,
+ 0xff, 0xe0, 0x00, 0xff, 0xff, 0xb8, 0x00, 0xff,
+ 0xec, 0x8e, 0x01, 0xff, 0xc4, 0x65, 0x00, 0xff,
+ 0xbc, 0x5d, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xc4, 0x00, 0xff, 0xff, 0xd1, 0x00, 0xff,
+ 0xff, 0xdf, 0x01, 0xff, 0xfe, 0xed, 0x00, 0xff,
+ 0xff, 0xfe, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xf4, 0x96, 0x01, 0xff, 0xff, 0xd1, 0x00, 0xff,
+ 0xff, 0xee, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xec, 0x01, 0xff,
+ 0xff, 0xd0, 0x00, 0xff, 0xec, 0x8d, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xe4, 0x01, 0xff, 0xfe, 0xb5, 0x00, 0xff,
+ 0xe2, 0x83, 0x01, 0xff, 0xbc, 0x5d, 0x00, 0xff,
+ 0xbb, 0x5c, 0x00, 0xff, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0xfe, 0xe4, 0x00, 0xff, 0xff, 0xf2, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xa8, 0x00, 0xff, 0xff, 0xd6, 0x00, 0xff,
+ 0xff, 0xf3, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xef, 0x00, 0xff,
+ 0xff, 0xd5, 0x01, 0xff, 0xff, 0xa0, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xfe, 0xe3, 0x00, 0xff, 0xff, 0xaf, 0x00, 0xff,
+ 0xd8, 0x79, 0x00, 0xff, 0xbb, 0x5d, 0x00, 0xff,
+ 0xbc, 0x5d, 0x01, 0xff, 0xbb, 0x5d, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0xff, 0xf7, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xfe, 0xb5, 0x00, 0xff, 0xff, 0xdb, 0x01, 0xff,
+ 0xff, 0xf6, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xf4, 0x01, 0xff,
+ 0xff, 0xd9, 0x00, 0xff, 0xfe, 0xb1, 0x00, 0xff,
+ 0xff, 0xe2, 0x00, 0xff, 0xff, 0xa6, 0x00, 0xff,
+ 0xc9, 0x6a, 0x01, 0xff, 0xbb, 0x5d, 0x00, 0xff,
+ 0xbb, 0x5d, 0x00, 0xff, 0xbb, 0x5c, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xc3, 0x00, 0xff, 0xff, 0xe0, 0x01, 0xff,
+ 0xff, 0xf9, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xf7, 0x00, 0xff,
+ 0xff, 0xde, 0x01, 0xff, 0xfe, 0xc2, 0x00, 0xff,
+ 0xd0, 0x72, 0x01, 0xff, 0xbb, 0x5d, 0x00, 0xff,
+ 0xbb, 0x5d, 0x00, 0xff, 0xbc, 0x5d, 0x00, 0xff,
+ 0xbc, 0x5d, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xe5, 0x87, 0x01, 0xff,
+ 0xff, 0xc9, 0x01, 0xff, 0xfe, 0xe2, 0x00, 0xff,
+ 0xff, 0xfb, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xfe, 0xfa, 0x00, 0xff,
+ 0xff, 0xe2, 0x01, 0xff, 0xff, 0xc9, 0x01, 0xff,
+ 0xe1, 0x83, 0x00, 0xff, 0xbb, 0x5d, 0x00, 0xff,
+ 0xbc, 0x5d, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0xfe, 0xff, 0x00, 0xff, 0xf4, 0x95, 0x01, 0xff,
+ 0xff, 0xcd, 0x01, 0xff, 0xff, 0xe5, 0x00, 0xff,
+ 0xff, 0xfe, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xfd, 0x01, 0xff,
+ 0xff, 0xe4, 0x00, 0xff, 0xff, 0xcc, 0x00, 0xff,
+ 0xf2, 0x93, 0x00, 0xff, 0xbb, 0x5d, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0xbb, 0x5d, 0x00, 0xff, 0xf1, 0x92, 0x01, 0xff,
+ 0xff, 0xca, 0x00, 0xff, 0xff, 0xe3, 0x01, 0xff,
+ 0xff, 0xfc, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xfb, 0x00, 0xff,
+ 0xff, 0xe3, 0x00, 0xff, 0xff, 0xcb, 0x00, 0xff,
+ 0xf2, 0x93, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0xbb, 0x5d, 0x00, 0xff,
+ 0xbb, 0x5d, 0x00, 0xff, 0xdd, 0x7f, 0x00, 0xff,
+ 0xff, 0xc4, 0x00, 0xff, 0xff, 0xdd, 0x00, 0xff,
+ 0xff, 0xf6, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xf7, 0x00, 0xff,
+ 0xff, 0xde, 0x01, 0xff, 0xfe, 0xc4, 0x00, 0xff,
+ 0xe1, 0x82, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0xbb, 0x5d, 0x00, 0xff,
+ 0xbc, 0x5d, 0x01, 0xff, 0xbc, 0x5d, 0x01, 0xff,
+ 0xbc, 0x5d, 0x01, 0xff, 0xca, 0x6b, 0x01, 0xff,
+ 0xff, 0xbb, 0x00, 0xff, 0xff, 0xd7, 0x00, 0xff,
+ 0xff, 0xf1, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xf2, 0x01, 0xff,
+ 0xff, 0xd9, 0x01, 0xff, 0xff, 0xbc, 0x01, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xbb, 0x5d, 0x00, 0xff, 0xbb, 0x5d, 0x00, 0xff,
+ 0xbc, 0x5d, 0x00, 0xff, 0xbf, 0x60, 0x00, 0xff,
+ 0xfc, 0x9e, 0x00, 0xff, 0xff, 0xdb, 0x00, 0xff,
+ 0xfe, 0xa8, 0x00, 0xff, 0xfe, 0xcf, 0x00, 0xff,
+ 0xff, 0xea, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xed, 0x01, 0xff,
+ 0xff, 0xd1, 0x00, 0xff, 0xff, 0xac, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xfe, 0x01, 0xff,
+ 0xff, 0xf0, 0x01, 0xff, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xbc, 0x5d, 0x01, 0xff, 0xbc, 0x5d, 0x01, 0xff,
+ 0xbb, 0x5c, 0x00, 0xff, 0xcd, 0x6f, 0x00, 0xff,
+ 0xff, 0xa5, 0x01, 0xff, 0xff, 0xd9, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xf2, 0x94, 0x00, 0xff, 0xff, 0xc9, 0x01, 0xff,
+ 0xff, 0xe3, 0x00, 0xff, 0xff, 0xfb, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xfc, 0x01, 0xff, 0xff, 0xe6, 0x01, 0xff,
+ 0xff, 0xc9, 0x00, 0xff, 0xf9, 0x9b, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xf9, 0x01, 0xff,
+ 0xff, 0xea, 0x01, 0xff, 0xff, 0xdd, 0x01, 0xff,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0xbc, 0x5d, 0x01, 0xff,
+ 0xbb, 0x5d, 0x00, 0xff, 0xd6, 0x77, 0x01, 0xff,
+ 0xff, 0xa9, 0x00, 0xff, 0xff, 0xd7, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xdc, 0x7e, 0x00, 0xff, 0xfe, 0xc1, 0x00, 0xff,
+ 0xff, 0xdd, 0x01, 0xff, 0xfe, 0xf4, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xf6, 0x01, 0xff, 0xff, 0xdf, 0x01, 0xff,
+ 0xff, 0xc2, 0x00, 0xff, 0xe4, 0x86, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xf3, 0x00, 0xff,
+ 0xff, 0xe3, 0x00, 0xff, 0xff, 0xd5, 0x01, 0xff,
+ 0xff, 0xc7, 0x01, 0xff, 0xff, 0xb9, 0x00, 0xff,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xbc, 0x5d, 0x01, 0xff,
+ 0xbc, 0x5e, 0x01, 0xff, 0xde, 0x80, 0x00, 0xff,
+ 0xff, 0xaa, 0x01, 0xff, 0xff, 0xd3, 0x00, 0xff,
+ 0xff, 0xed, 0x01, 0xff, 0xff, 0xfd, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xba, 0x00, 0xff,
+ 0xfe, 0xd5, 0x00, 0xff, 0xff, 0xee, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xee, 0x00, 0xff, 0xff, 0xd7, 0x01, 0xff,
+ 0xff, 0xba, 0x01, 0xff, 0xcd, 0x6e, 0x01, 0xff,
+ 0xff, 0xba, 0x01, 0xff, 0xff, 0xc4, 0x01, 0xff,
+ 0xff, 0xcc, 0x00, 0xff, 0xff, 0xd3, 0x01, 0xff,
+ 0xff, 0xd9, 0x00, 0xff, 0xfe, 0xde, 0x00, 0xff,
+ 0xff, 0xdc, 0x00, 0xff, 0xfe, 0xcc, 0x00, 0xff,
+ 0xff, 0xbe, 0x01, 0xff, 0xff, 0xaf, 0x00, 0xff,
+ 0xff, 0xa3, 0x01, 0xff, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0xc2, 0x64, 0x01, 0xff, 0xe6, 0x87, 0x00, 0xff,
+ 0xff, 0xa7, 0x01, 0xff, 0xff, 0xb7, 0x00, 0xff,
+ 0xff, 0xc8, 0x00, 0xff, 0xff, 0xd8, 0x00, 0xff,
+ 0xff, 0xea, 0x01, 0xff, 0xff, 0xf9, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xb1, 0x01, 0xff,
+ 0xff, 0xce, 0x00, 0xff, 0xff, 0xe6, 0x00, 0xff,
+ 0xff, 0xf9, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xf9, 0x00, 0xff,
+ 0xff, 0xe6, 0x01, 0xff, 0xff, 0xcf, 0x01, 0xff,
+ 0xff, 0xb1, 0x00, 0xff, 0xbc, 0x5d, 0x01, 0xff,
+ 0xbb, 0x5d, 0x00, 0xff, 0xbb, 0x5d, 0x00, 0xff,
+ 0xbc, 0x5d, 0x00, 0xff, 0xbb, 0x5d, 0x00, 0xff,
+ 0xc6, 0x67, 0x01, 0xff, 0xd2, 0x73, 0x00, 0xff,
+ 0xdf, 0x80, 0x00, 0xff, 0xe9, 0x8b, 0x00, 0xff,
+ 0xf3, 0x95, 0x00, 0xff, 0xfb, 0x9d, 0x00, 0xff,
+ 0xf6, 0x98, 0x00, 0xff, 0xea, 0x8b, 0x00, 0xff,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0xc9, 0x6a, 0x00, 0xff, 0xd8, 0x79, 0x01, 0xff,
+ 0xe6, 0x88, 0x01, 0xff, 0xf5, 0x97, 0x00, 0xff,
+ 0xfe, 0xa6, 0x00, 0xff, 0xff, 0xb7, 0x01, 0xff,
+ 0xff, 0xc7, 0x01, 0xff, 0xff, 0xd6, 0x00, 0xff,
+ 0xff, 0xe6, 0x00, 0xff, 0xff, 0xf4, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xf0, 0x91, 0x00, 0xff,
+ 0xff, 0xbf, 0x01, 0xff, 0xfe, 0xd4, 0x00, 0xff,
+ 0xff, 0xe9, 0x00, 0xff, 0xff, 0xfb, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xf9, 0x00, 0xff, 0xff, 0xeb, 0x00, 0xff,
+ 0xff, 0xd6, 0x00, 0xff, 0xff, 0xc1, 0x01, 0xff,
+ 0xf1, 0x92, 0x00, 0xff, 0xbc, 0x5e, 0x01, 0xff,
+ 0xbc, 0x5d, 0x01, 0xff, 0xbb, 0x5d, 0x00, 0xff,
+ 0xbc, 0x5d, 0x01, 0xff, 0xbb, 0x5d, 0x00, 0xff,
+ 0xbb, 0x5d, 0x00, 0xff, 0xbc, 0x5d, 0x01, 0xff,
+ 0xbb, 0x5c, 0x00, 0xff, 0xbc, 0x5d, 0x00, 0xff,
+ 0xbc, 0x5d, 0x01, 0xff, 0xbb, 0x5d, 0x00, 0xff,
+ 0xbc, 0x5d, 0x00, 0xff, 0xbc, 0x5d, 0x01, 0xff,
+ 0xbc, 0x5d, 0x01, 0xff, 0xc0, 0x62, 0x00, 0xff,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xae, 0x01, 0xff, 0xfe, 0xc3, 0x00, 0xff,
+ 0xfe, 0xd9, 0x00, 0xff, 0xfe, 0xef, 0x00, 0xff,
+ 0xff, 0xfd, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xf8, 0x00, 0xff,
+ 0xfe, 0xee, 0x00, 0xff, 0xff, 0xdd, 0x01, 0xff,
+ 0xfe, 0xc7, 0x00, 0xff, 0xff, 0xae, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0xbb, 0x5d, 0x00, 0xff,
+ 0xd1, 0x73, 0x00, 0xff, 0xff, 0xb2, 0x00, 0xff,
+ 0xff, 0xc8, 0x01, 0xff, 0xff, 0xe2, 0x01, 0xff,
+ 0xfe, 0xf1, 0x00, 0xff, 0xff, 0xfe, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xf9, 0x01, 0xff, 0xff, 0xee, 0x00, 0xff,
+ 0xff, 0xe2, 0x00, 0xff, 0xff, 0xce, 0x00, 0xff,
+ 0xff, 0xb5, 0x01, 0xff, 0xdf, 0x80, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xbc, 0x5d, 0x00, 0xff,
+ 0xbb, 0x5d, 0x00, 0xff, 0xf3, 0x94, 0x01, 0xff,
+ 0xff, 0xb6, 0x00, 0xff, 0xff, 0xd1, 0x01, 0xff,
+ 0xfe, 0xe4, 0x00, 0xff, 0xff, 0xf0, 0x01, 0xff,
+ 0xff, 0xfa, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xf6, 0x00, 0xff,
+ 0xff, 0xed, 0x00, 0xff, 0xfe, 0xe3, 0x00, 0xff,
+ 0xff, 0xd2, 0x01, 0xff, 0xff, 0xba, 0x01, 0xff,
+ 0xf9, 0x9a, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xbc, 0x5e, 0x01, 0xff, 0xbc, 0x5d, 0x01, 0xff,
+ 0xbb, 0x5d, 0x00, 0xff, 0xbb, 0x5c, 0x00, 0xff,
+ 0xff, 0xa4, 0x00, 0xff, 0xff, 0xbf, 0x01, 0xff,
+ 0xfe, 0xd0, 0x00, 0xff, 0xff, 0xdf, 0x01, 0xff,
+ 0xff, 0xec, 0x01, 0xff, 0xff, 0xf5, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xfe, 0x00, 0xff,
+ 0xfe, 0xf3, 0x00, 0xff, 0xff, 0xeb, 0x01, 0xff,
+ 0xff, 0xde, 0x00, 0xff, 0xff, 0xcf, 0x00, 0xff,
+ 0xff, 0xbf, 0x01, 0xff, 0xff, 0xa6, 0x01, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xbb, 0x5d, 0x00, 0xff, 0xbb, 0x5d, 0x00, 0xff,
+ 0xff, 0xa3, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xcd, 0x6f, 0x01, 0xff, 0xff, 0xa4, 0x00, 0xff,
+ 0xff, 0xb7, 0x01, 0xff, 0xff, 0xc9, 0x01, 0xff,
+ 0xff, 0xd7, 0x01, 0xff, 0xff, 0xe3, 0x01, 0xff,
+ 0xff, 0xf1, 0x01, 0xff, 0xff, 0xf7, 0x00, 0xff,
+ 0xff, 0xfb, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xfe, 0x00, 0xff, 0xff, 0xfb, 0x00, 0xff,
+ 0xff, 0xf7, 0x01, 0xff, 0xff, 0xf0, 0x01, 0xff,
+ 0xff, 0xe2, 0x00, 0xff, 0xff, 0xd3, 0x01, 0xff,
+ 0xff, 0xc4, 0x00, 0xff, 0xff, 0xb3, 0x00, 0xff,
+ 0xfe, 0xa2, 0x00, 0xff, 0xcd, 0x6e, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xbb, 0x5c, 0x00, 0xff,
+ 0xbb, 0x5d, 0x00, 0xff, 0xd7, 0x78, 0x01, 0xff,
+ 0xfe, 0xe3, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xf3, 0x95, 0x01, 0xff, 0xff, 0xae, 0x00, 0xff,
+ 0xfe, 0xbf, 0x00, 0xff, 0xff, 0xcd, 0x01, 0xff,
+ 0xff, 0xdb, 0x01, 0xff, 0xff, 0xe3, 0x01, 0xff,
+ 0xff, 0xe9, 0x01, 0xff, 0xff, 0xee, 0x01, 0xff,
+ 0xff, 0xf1, 0x00, 0xff, 0xff, 0xf5, 0x00, 0xff,
+ 0xfe, 0xf8, 0x00, 0xff, 0xff, 0xfb, 0x00, 0xff,
+ 0xff, 0xfc, 0x01, 0xff, 0xff, 0xf9, 0x01, 0xff,
+ 0xff, 0xf5, 0x01, 0xff, 0xff, 0xf1, 0x00, 0xff,
+ 0xff, 0xec, 0x01, 0xff, 0xff, 0xe8, 0x01, 0xff,
+ 0xff, 0xe2, 0x00, 0xff, 0xff, 0xda, 0x00, 0xff,
+ 0xff, 0xcb, 0x01, 0xff, 0xff, 0xbc, 0x00, 0xff,
+ 0xff, 0xac, 0x01, 0xff, 0xed, 0x8e, 0x00, 0xff,
+ 0xbb, 0x5d, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xf6, 0x00, 0xff, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xbb, 0x5d, 0x00, 0xff,
+ 0xbc, 0x5d, 0x01, 0xff, 0xff, 0xbe, 0x01, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xd6, 0x77, 0x01, 0xff,
+ 0xff, 0xa4, 0x00, 0xff, 0xfe, 0xb4, 0x00, 0xff,
+ 0xff, 0xc1, 0x00, 0xff, 0xff, 0xc8, 0x00, 0xff,
+ 0xff, 0xcf, 0x01, 0xff, 0xff, 0xd5, 0x01, 0xff,
+ 0xff, 0xda, 0x01, 0xff, 0xff, 0xdf, 0x01, 0xff,
+ 0xff, 0xe3, 0x01, 0xff, 0xff, 0xe6, 0x00, 0xff,
+ 0xff, 0xe6, 0x01, 0xff, 0xff, 0xe1, 0x00, 0xff,
+ 0xff, 0xdd, 0x01, 0xff, 0xff, 0xd7, 0x01, 0xff,
+ 0xff, 0xd2, 0x01, 0xff, 0xff, 0xcd, 0x01, 0xff,
+ 0xff, 0xc7, 0x01, 0xff, 0xfe, 0xc1, 0x00, 0xff,
+ 0xfe, 0xb3, 0x00, 0xff, 0xff, 0xa4, 0x00, 0xff,
+ 0xc9, 0x6b, 0x01, 0xff, 0xbc, 0x5d, 0x01, 0xff,
+ 0xbc, 0x5d, 0x01, 0xff, 0xfe, 0x9f, 0x00, 0xff,
+ 0xff, 0xe2, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xf6, 0x01, 0xff,
+ 0xff, 0xec, 0x01, 0xff, 0xff, 0xe3, 0x01, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0xbc, 0x5d, 0x01, 0xff, 0xbb, 0x5c, 0x00, 0xff,
+ 0xff, 0xa5, 0x00, 0xff, 0xff, 0xf4, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xe3, 0x85, 0x00, 0xff,
+ 0xfe, 0xa1, 0x00, 0xff, 0xff, 0xaa, 0x00, 0xff,
+ 0xff, 0xb0, 0x00, 0xff, 0xff, 0xb7, 0x00, 0xff,
+ 0xff, 0xbd, 0x00, 0xff, 0xff, 0xc3, 0x01, 0xff,
+ 0xff, 0xc7, 0x00, 0xff, 0xff, 0xcb, 0x00, 0xff,
+ 0xff, 0xcb, 0x01, 0xff, 0xff, 0xc6, 0x01, 0xff,
+ 0xff, 0xc1, 0x01, 0xff, 0xff, 0xbb, 0x00, 0xff,
+ 0xfe, 0xb5, 0x00, 0xff, 0xff, 0xb0, 0x01, 0xff,
+ 0xff, 0xaa, 0x01, 0xff, 0xff, 0xa2, 0x01, 0xff,
+ 0xe2, 0x84, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xbc, 0x5d, 0x01, 0xff, 0xbc, 0x5d, 0x01, 0xff,
+ 0xbb, 0x5d, 0x00, 0xff, 0xbb, 0x5c, 0x00, 0xff,
+ 0xd3, 0x74, 0x00, 0xff, 0xff, 0xbd, 0x01, 0xff,
+ 0xff, 0xf3, 0x00, 0xff, 0xff, 0xe9, 0x01, 0xff,
+ 0xff, 0xde, 0x00, 0xff, 0xff, 0xd5, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xbc, 0x5d, 0x01, 0xff, 0xe7, 0x89, 0x00, 0xff,
+ 0xff, 0xdb, 0x01, 0xff, 0xff, 0xe8, 0x01, 0xff,
+ 0xff, 0xf4, 0x00, 0xff, 0xff, 0xfe, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0xbb, 0x5d, 0x00, 0xff,
+ 0xbc, 0x5d, 0x01, 0xff, 0xbb, 0x5d, 0x00, 0xff,
+ 0xd1, 0x72, 0x00, 0xff, 0xe4, 0x86, 0x00, 0xff,
+ 0xf4, 0x96, 0x00, 0xff, 0xff, 0xa4, 0x00, 0xff,
+ 0xff, 0xac, 0x00, 0xff, 0xff, 0xb2, 0x01, 0xff,
+ 0xff, 0xb1, 0x00, 0xff, 0xfe, 0xab, 0x00, 0xff,
+ 0xff, 0xa4, 0x00, 0xff, 0xf0, 0x91, 0x00, 0xff,
+ 0xdd, 0x7e, 0x00, 0xff, 0xc9, 0x6a, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xbc, 0x5d, 0x01, 0xff, 0xbc, 0x5d, 0x01, 0xff,
+ 0xbc, 0x5d, 0x01, 0xff, 0xbb, 0x5d, 0x00, 0xff,
+ 0xff, 0xa4, 0x01, 0xff, 0xff, 0xdb, 0x00, 0xff,
+ 0xff, 0xd1, 0x00, 0xff, 0xff, 0xc8, 0x01, 0xff,
+ 0xff, 0xbf, 0x00, 0xff, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xbc, 0x5d, 0x00, 0xff,
+ 0xcf, 0x70, 0x01, 0xff, 0xff, 0xc2, 0x01, 0xff,
+ 0xff, 0xd0, 0x00, 0xff, 0xff, 0xdd, 0x01, 0xff,
+ 0xff, 0xe9, 0x00, 0xff, 0xff, 0xf3, 0x01, 0xff,
+ 0xff, 0xfc, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xbb, 0x5d, 0x00, 0xff,
+ 0xbb, 0x5d, 0x00, 0xff, 0xff, 0xab, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xc6, 0x67, 0x00, 0xff, 0xd6, 0x78, 0x01, 0xff,
+ 0xd5, 0x77, 0x01, 0xff, 0xc2, 0x64, 0x00, 0xff,
+ 0xbb, 0x5d, 0x00, 0xff, 0xff, 0xc6, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0xbc, 0x5d, 0x00, 0xff, 0xbc, 0x5d, 0x01, 0xff,
+ 0xbc, 0x5d, 0x01, 0xff, 0xe7, 0x89, 0x01, 0xff,
+ 0xfe, 0xc1, 0x00, 0xff, 0xff, 0xb9, 0x00, 0xff,
+ 0xff, 0xb0, 0x00, 0xff, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xbc, 0x5d, 0x00, 0xff,
+ 0xff, 0xa9, 0x01, 0xff, 0xff, 0xb7, 0x00, 0xff,
+ 0xff, 0xc6, 0x01, 0xff, 0xff, 0xd2, 0x00, 0xff,
+ 0xff, 0xdf, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xbc, 0x5d, 0x00, 0xff,
+ 0xbc, 0x5d, 0x00, 0xff, 0xff, 0xb3, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xfe, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xbb, 0x5d, 0x00, 0xff, 0xbc, 0x5d, 0x00, 0xff,
+ 0xbb, 0x5c, 0x00, 0xff, 0xe5, 0x87, 0x01, 0xff,
+ 0xff, 0xf5, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0xbc, 0x5d, 0x01, 0xff, 0xbc, 0x5d, 0x01, 0xff,
+ 0xcd, 0x6f, 0x00, 0xff, 0xff, 0xa9, 0x01, 0xff,
+ 0xff, 0xa1, 0x00, 0xff, 0xf9, 0x9a, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xbb, 0x5c, 0x00, 0xff, 0xef, 0x91, 0x00, 0xff,
+ 0xfe, 0xa0, 0x00, 0xff, 0xff, 0xae, 0x00, 0xff,
+ 0xff, 0xbd, 0x01, 0xff, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xbc, 0x5d, 0x01, 0xff,
+ 0xbc, 0x5d, 0x01, 0xff, 0xff, 0xbc, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xbb, 0x5d, 0x00, 0xff,
+ 0xbb, 0x5d, 0x00, 0xff, 0xbb, 0x5c, 0x00, 0xff,
+ 0xff, 0xc6, 0x01, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xbb, 0x5c, 0x00, 0xff, 0xbb, 0x5d, 0x00, 0xff,
+ 0xf0, 0x91, 0x01, 0xff, 0xea, 0x8b, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0xda, 0x7b, 0x00, 0xff, 0xe9, 0x8b, 0x01, 0xff,
+ 0xf7, 0x98, 0x00, 0xff, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xbb, 0x5d, 0x00, 0xff,
+ 0xbc, 0x5d, 0x01, 0xff, 0xff, 0xc3, 0x01, 0xff,
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff,
+ 0xfe, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xbc, 0x5d, 0x00, 0xff, 0xbc, 0x5d, 0x01, 0xff,
+ 0xed, 0x8e, 0x00, 0xff, 0xff, 0xef, 0x01, 0xff,
+ 0xff, 0xfe, 0x01, 0xff, 0xff, 0xfa, 0x00, 0xff,
+ 0xff, 0xf5, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xbc, 0x5d, 0x00, 0xff, 0xda, 0x7c, 0x01, 0xff,
+ 0xd6, 0x77, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xc6, 0x67, 0x00, 0xff,
+ 0xd4, 0x76, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0xbb, 0x5d, 0x00, 0xff,
+ 0xbb, 0x5c, 0x00, 0xff, 0xff, 0xc8, 0x00, 0xff,
+ 0xff, 0xf2, 0x01, 0xff, 0xff, 0xf6, 0x00, 0xff,
+ 0xff, 0xfa, 0x01, 0xff, 0xff, 0xfc, 0x01, 0xff,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xbc, 0x5d, 0x01, 0xff, 0xbb, 0x5d, 0x00, 0xff,
+ 0xbb, 0x5c, 0x00, 0xff, 0xff, 0xc5, 0x01, 0xff,
+ 0xff, 0xee, 0x01, 0xff, 0xff, 0xea, 0x00, 0xff,
+ 0xff, 0xe7, 0x00, 0xff, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0xc6, 0x67, 0x00, 0xff, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0xbb, 0x5d, 0x00, 0xff,
+ 0xc0, 0x61, 0x01, 0xff, 0xff, 0xcd, 0x00, 0xff,
+ 0xff, 0xe2, 0x00, 0xff, 0xff, 0xe7, 0x00, 0xff,
+ 0xff, 0xeb, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xbb, 0x5d, 0x00, 0xff,
+ 0xbb, 0x5d, 0x00, 0xff, 0xf3, 0x94, 0x00, 0xff,
+ 0xff, 0xdd, 0x01, 0xff, 0xff, 0xda, 0x00, 0xff,
+ 0xff, 0xd8, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xbc, 0x5d, 0x01, 0xff,
+ 0xcc, 0x6e, 0x01, 0xff, 0xff, 0xca, 0x00, 0xff,
+ 0xff, 0xd1, 0x00, 0xff, 0xff, 0xd7, 0x00, 0xff,
+ 0xff, 0xdb, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0xbc, 0x5d, 0x00, 0xff, 0xbf, 0x60, 0x00, 0xff,
+ 0xff, 0xc1, 0x00, 0xff, 0xff, 0xc8, 0x00, 0xff,
+ 0xfe, 0xc6, 0x00, 0xff, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0xbb, 0x5d, 0x00, 0xff,
+ 0xd6, 0x77, 0x00, 0xff, 0xff, 0xb9, 0x00, 0xff,
+ 0xff, 0xc1, 0x00, 0xff, 0xff, 0xc8, 0x01, 0xff,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0xbb, 0x5c, 0x00, 0xff, 0xbc, 0x5d, 0x01, 0xff,
+ 0xf4, 0x96, 0x00, 0xff, 0xff, 0xb6, 0x00, 0xff,
+ 0xff, 0xb6, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0xbc, 0x5d, 0x01, 0xff,
+ 0xdf, 0x81, 0x00, 0xff, 0xff, 0xaa, 0x00, 0xff,
+ 0xff, 0xb2, 0x00, 0xff, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0xbb, 0x5d, 0x00, 0xff,
+ 0xc9, 0x6b, 0x01, 0xff, 0xff, 0xa5, 0x01, 0xff,
+ 0xff, 0xa6, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xbb, 0x5d, 0x00, 0xff,
+ 0xe8, 0x89, 0x00, 0xff, 0xf9, 0x9b, 0x00, 0xff,
+ 0xff, 0xa4, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xbb, 0x5c, 0x00, 0xff, 0xf1, 0x92, 0x00, 0xff,
+ 0xf3, 0x94, 0x00, 0xff, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xbc, 0x5d, 0x01, 0xff,
+ 0xe2, 0x83, 0x00, 0xff, 0xec, 0x8e, 0x01, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0xbc, 0x5d, 0x01, 0xff, 0xd1, 0x73, 0x00, 0xff,
+ 0xe2, 0x84, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0xbc, 0x5d, 0x01, 0xff,
+ 0xd6, 0x77, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xbc, 0x5d, 0x01, 0xff,
+ 0xd3, 0x74, 0x01, 0xff, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0xbb, 0x5c, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xc3, 0x64, 0x00, 0xff, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xbb, 0x5d, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xbb, 0x5d, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+};
+
+Vtx sun_LightModel_mesh_vtx_cull[8] = {
+ {{ {-100, -100, 0}, 0, {0, 0}, {0, 0, 0, 0} }},
+ {{ {-100, -100, 0}, 0, {0, 0}, {0, 0, 0, 0} }},
+ {{ {-100, 100, 0}, 0, {0, 0}, {0, 0, 0, 0} }},
+ {{ {-100, 100, 0}, 0, {0, 0}, {0, 0, 0, 0} }},
+ {{ {100, -100, 0}, 0, {0, 0}, {0, 0, 0, 0} }},
+ {{ {100, -100, 0}, 0, {0, 0}, {0, 0, 0, 0} }},
+ {{ {100, 100, 0}, 0, {0, 0}, {0, 0, 0, 0} }},
+ {{ {100, 100, 0}, 0, {0, 0}, {0, 0, 0, 0} }},
+};
+
+Vtx sun_LightModel_mesh_vtx_0[4] = {
+ {{ {-100, -100, 0}, 0, {-16, 2032}, {0, 0, 127, 255} }},
+ {{ {100, -100, 0}, 0, {2032, 2032}, {0, 0, 127, 255} }},
+ {{ {100, 100, 0}, 0, {2032, -16}, {0, 0, 127, 255} }},
+ {{ {-100, 100, 0}, 0, {-16, -16}, {0, 0, 127, 255} }},
+};
+
+Gfx sun_LightModel_mesh_tri_0[3] = {
+ gsSPVertex(sun_LightModel_mesh_vtx_0 + 0, 4, 0),
+ gsSP2Triangles(0, 1, 2, 0, 0, 2, 3, 0),
+ gsSPEndDisplayList(),
+};
+
+Gfx mat_sun_sun[13] = {
+ gsSPSetGeometryMode(G_FOG),
+ gsSPClearGeometryMode(G_CULL_BACK | G_CLIPPING),
+ gsDPPipeSync(),
+ gsDPSetCombineLERP(0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0, COMBINED, 0, PRIMITIVE, 0, COMBINED, 0, PRIMITIVE, 0),
+ gsDPSetRenderMode(G_RM_FOG_SHADE_A, G_RM_AA_ZB_XLU_SURF2),
+ gsSPTexture(65535, 65535, 0, 0, 1),
+ gsDPSetPrimColor(0, 0, 255, 255, 255, 128),
+ gsDPSetTextureImage(G_IM_FMT_RGBA, G_IM_SIZ_32b_LOAD_BLOCK, 1, sun_sun_rgba32),
+ gsDPSetTile(G_IM_FMT_RGBA, G_IM_SIZ_32b_LOAD_BLOCK, 0, 0, 7, 0, G_TX_WRAP | G_TX_NOMIRROR, 0, 0, G_TX_WRAP | G_TX_NOMIRROR, 0, 0),
+ gsDPLoadBlock(7, 0, 0, 4095, 64),
+ gsDPSetTile(G_IM_FMT_RGBA, G_IM_SIZ_32b, 16, 0, 0, 0, G_TX_WRAP | G_TX_NOMIRROR, 6, 0, G_TX_WRAP | G_TX_NOMIRROR, 6, 0),
+ gsDPSetTileSize(0, 0, 0, 252, 252),
+ gsSPEndDisplayList(),
+};
+
+Gfx mat_revert_sun_sun[4] = {
+ gsSPClearGeometryMode(G_FOG),
+ gsSPSetGeometryMode(G_CULL_BACK | G_CLIPPING),
+ gsDPPipeSync(),
+ gsSPEndDisplayList(),
+};
+
+Gfx sun_LightModel_mesh[13] = {
+ gsSPClearGeometryMode(G_LIGHTING),
+ gsSPVertex(sun_LightModel_mesh_vtx_cull + 0, 8, 0),
+ gsSPSetGeometryMode(G_LIGHTING),
+ gsSPCullDisplayList(0, 7),
+ gsSPDisplayList(mat_sun_sun),
+ gsSPDisplayList(sun_LightModel_mesh_tri_0),
+ gsSPDisplayList(mat_revert_sun_sun),
+ gsDPPipeSync(),
+ gsSPSetGeometryMode(G_LIGHTING),
+ gsSPClearGeometryMode(G_TEXTURE_GEN),
+ gsDPSetCombineLERP(0, 0, 0, SHADE, 0, 0, 0, ENVIRONMENT, 0, 0, 0, SHADE, 0, 0, 0, ENVIRONMENT),
+ gsSPTexture(65535, 65535, 0, 0, 0),
+ gsSPEndDisplayList(),
+};
+
+
+};
+}
diff --git a/src/engine/editor/ObjectPicker.cpp b/src/engine/editor/ObjectPicker.cpp
new file mode 100644
index 000000000..9cfeed5f8
--- /dev/null
+++ b/src/engine/editor/ObjectPicker.cpp
@@ -0,0 +1,207 @@
+#include <libultraship/libultraship.h>
+#include <libultra/gbi.h>
+#include "../CoreMath.h"
+#include <libultra/types.h>
+#include "../World.h"
+
+#include "ObjectPicker.h"
+#include "port/Engine.h"
+#include <controller/controldevice/controller/mapping/keyboard/KeyboardScancodes.h>
+#include <window/Window.h>
+
+#include "engine/actors/Ship.h"
+#include "port/Game.h"
+#include "Gizmo.h"
+
+#include "EditorMath.h"
+
+extern "C" {
+#include "common_structs.h"
+#include "main.h"
+#include "defines.h"
+#include "actors.h"
+#include "camera.h"
+}
+
+namespace Editor {
+
+void ObjectPicker::Load() {
+ eGizmo.Load();
+}
+
+void ObjectPicker::Tick() {
+}
+
+void ObjectPicker::SelectObject(std::vector<GameObject*> objects) {
+ Ray ray;
+ ray.Origin = FVector(cameras[0].pos[0], cameras[0].pos[1], cameras[0].pos[2]);
+
+ // This allows selection of objects in the scene explorer.
+ // Otherwise this would still run when selecting buttons in editor windows.
+ if (IsInGameScreen()) {
+ ray.Direction = ScreenRayTrace();
+
+ ObjectPicker::FindObject(ray, objects);
+
+ if (_selected != nullptr) {
+ eGizmo.SetGizmo(_selected, ray);
+ eGizmo.Enabled = true;
+ } else {
+ //eGizmo.Disable();
+ eGizmo.Enabled = false;
+ eGizmo._selected = nullptr;
+ }
+ }
+}
+
+void ObjectPicker::DragHandle() {
+ Ray ray;
+ ray.Origin = FVector(cameras[0].pos[0], cameras[0].pos[1], cameras[0].pos[2]);
+ ray.Direction = ScreenRayTrace();
+
+ // Skip if a drag is already in progress
+ if (eGizmo.SelectedHandle != Gizmo::GizmoHandle::None) {
+ eGizmo._ray = ray.Direction;
+ eGizmo.Tick();
+ return;
+ }
+
+ // Is the gizmo being dragged?
+ if (!eGizmo.Enabled) { return; }
+ float closestDistance = FLT_MAX;
+ std::optional<FVector> closestClickPos;
+ Gizmo::GizmoHandle closestHandle = Gizmo::GizmoHandle::None;
+
+ // All axis grab. Not used in rotate mode rotate
+ if (static_cast<Gizmo::TranslationMode>(CVarGetInteger("eGizmoMode", 0)) != Gizmo::TranslationMode::Rotate) {
+ float t;
+ if (IntersectRaySphere(ray, eGizmo.Pos, eGizmo.AllAxisRadius, t)) {
+ if (t < closestDistance) {
+ closestDistance = t;
+ closestClickPos = ray.Origin + ray.Direction * t;
+ closestHandle = Gizmo::GizmoHandle::All_Axis;
+ }
+ }
+ }
+
+ // Arrow handles
+ auto tryHandle = [&](Gizmo::GizmoHandle handle, MtxF mtx, const std::vector<Triangle>& tris) {
+ for (const auto& tri : tris) {
+ if (auto clickPos = QueryHandleIntersection(mtx, ray, tri)) {
+ float dist = (*clickPos - ray.Origin).Magnitude();
+ if (dist < closestDistance) {
+ closestDistance = dist;
+ closestClickPos = *clickPos;
+ closestHandle = handle;
+ }
+ }
+ }
+ };
+
+ switch(static_cast<Gizmo::TranslationMode>(CVarGetInteger("eGizmoMode", 0))) {
+ case Gizmo::TranslationMode::Move:
+ tryHandle(Gizmo::GizmoHandle::Z_Axis, eGizmo.Mtx_RedX, eGizmo.RedCollision.Triangles);
+ tryHandle(Gizmo::GizmoHandle::X_Axis, eGizmo.Mtx_GreenY, eGizmo.GreenCollision.Triangles);
+ tryHandle(Gizmo::GizmoHandle::Y_Axis, eGizmo.Mtx_BlueZ, eGizmo.BlueCollision.Triangles);
+ break;
+ case Gizmo::TranslationMode::Rotate:
+ tryHandle(Gizmo::GizmoHandle::X_Axis, eGizmo.Mtx_RedX, eGizmo.RedRotateCollision.Triangles);
+ tryHandle(Gizmo::GizmoHandle::Z_Axis, eGizmo.Mtx_GreenY, eGizmo.GreenRotateCollision.Triangles);
+ tryHandle(Gizmo::GizmoHandle::Y_Axis, eGizmo.Mtx_BlueZ, eGizmo.BlueRotateCollision.Triangles);
+ break;
+ case Gizmo::TranslationMode::Scale:
+ tryHandle(Gizmo::GizmoHandle::Z_Axis, eGizmo.Mtx_RedX, eGizmo.RedScaleCollision.Triangles);
+ tryHandle(Gizmo::GizmoHandle::X_Axis, eGizmo.Mtx_GreenY, eGizmo.GreenScaleCollision.Triangles);
+ tryHandle(Gizmo::GizmoHandle::Y_Axis, eGizmo.Mtx_BlueZ, eGizmo.BlueScaleCollision.Triangles);
+ break;
+
+ }
+
+ if (closestHandle != Gizmo::GizmoHandle::None && closestClickPos.has_value()) {
+ eGizmo.SelectedHandle = closestHandle;
+ eGizmo._ray = ray.Direction;
+ eGizmo._cursorOffset = eGizmo.Pos - *closestClickPos;
+ eGizmo.PickDistance = closestDistance;
+ }
+}
+
+void ObjectPicker::Draw() {
+ if (_selected != NULL) {
+ eGizmo.Draw();
+ }
+
+ if (Debug) {
+ Mat4 CursorMtx;
+ IRotator rot = IRotator(0,0,0);
+ FVector scale = FVector(0.1, 0.1, 0.1);
+ FVector ray = ScreenRayTrace();
+
+ float x = (cameras[0].pos[0] + ray.x * 800);
+ float y = (cameras[0].pos[1] + ray.y * 800);
+ float z = (cameras[0].pos[2] + ray.z * 800);
+
+ ApplyMatrixTransformations((float(*)[4])&CursorMtx, FVector(x, y, z), rot, scale);
+ Editor_AddMatrix((float(*)[4])&CursorMtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(gDisplayListHead++, (Gfx*)"__OTR__tracks/sphere");
+ }
+}
+
+void ObjectPicker::FindObject(Ray ray, std::vector<GameObject*> objects) {
+ bool found = false;
+ GameObject* closestObject = nullptr;
+ float closestDistance = FLT_MAX;
+
+ for (auto& object : objects) {
+ float boundingBox = object->BoundingBoxSize;
+ if (boundingBox == 0.0f) {
+ boundingBox = 2.0f;
+ }
+
+ switch(object->Collision) {
+ case GameObject::CollisionType::VTX_INTERSECT:
+ for (const auto& tri : object->Triangles) {
+ float t;
+ if (IntersectRayTriangleAndTransform(ray, *object->Pos, tri, t)) {
+ if (t < closestDistance) {
+ closestDistance = t;
+ closestObject = object;
+ printf("SELECTED OBJECT\n");
+ }
+ }
+ }
+ break;
+ case GameObject::CollisionType::BOUNDING_BOX: {
+ float max = 2.0f;
+ float min = -2.0f;
+ Vec3f boxMin = { object->Pos->x + boundingBox * min,
+ object->Pos->y + boundingBox * min,
+ object->Pos->z + boundingBox * min };
+
+ Vec3f boxMax = { object->Pos->x + boundingBox * max,
+ object->Pos->y + boundingBox * max,
+ object->Pos->z + boundingBox * max };
+ float t;
+ if (QueryCollisionRayActor(&ray.Origin.x, &ray.Direction.x, boxMin, boxMax, &t)) {
+ if (t < closestDistance) {
+ closestDistance = t;
+ closestObject = object;
+ printf("FOUND BOUNDING BOX OBJECT\n");
+ }
+ break;
+ }
+ break;
+ }
+ case GameObject::CollisionType::BOUNDING_SPHERE:
+ printf("Editor::ObjectPicker.cpp Bounding sphere collision type not yet supported\n");
+ break;
+ }
+ }
+ if (closestObject != nullptr) {
+ _selected = closestObject;
+ // printf("FOUND COLLISION %d\n", type);
+ } else {
+ // printf("NO COLLISION\n");
+ _selected = nullptr;
+ }
+}
+}
diff --git a/src/engine/editor/ObjectPicker.h b/src/engine/editor/ObjectPicker.h
new file mode 100644
index 000000000..e96bddcbc
--- /dev/null
+++ b/src/engine/editor/ObjectPicker.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#include <libultraship/libultraship.h>
+#include <libultra/gbi.h>
+#include "Collision.h"
+#include "Gizmo.h"
+#include "GameObject.h"
+
+namespace Editor {
+ class ObjectPicker {
+ public:
+ void SelectObject(std::vector<GameObject*> objects);
+ void DragHandle();
+ void Draw();
+ void FindObject(Ray ray, std::vector<GameObject*> objects);
+ void Load();
+ void Tick();
+ Gizmo eGizmo;
+ GameObject* _selected;
+ private:
+ bool _draw = false;
+ GameObject* _lastSelected;
+ s32 Inverse(MtxF* src, MtxF* dest);
+ void Copy(MtxF* src, MtxF* dest);
+ void Clear(MtxF* mf);
+ bool Debug = false;
+ };
+}
diff --git a/src/engine/editor/SceneManager.cpp b/src/engine/editor/SceneManager.cpp
new file mode 100644
index 000000000..a2de6656c
--- /dev/null
+++ b/src/engine/editor/SceneManager.cpp
@@ -0,0 +1,156 @@
+#include "SceneManager.h"
+#include "port/Game.h"
+#include "CoreMath.h"
+#include "World.h"
+#include "GameObject.h"
+
+#include <iostream>
+#include <fstream>
+#include <nlohmann/json.hpp>
+#include "port/Engine.h"
+#include <libultraship/src/resource/type/Json.h>
+#include "port/resource/type/Minimap.h"
+#include <libultraship/src/resource/File.h>
+#include "port/resource/type/ResourceType.h"
+
+namespace Editor {
+
+ std::shared_ptr<Ship::Archive> CurrentArchive;
+ std::string SceneFile = "";
+
+ void SaveLevel() {
+ auto props = gWorldInstance.CurrentCourse->Props;
+
+ if ((CurrentArchive) && (!SceneFile.empty())) {
+ nlohmann::json data;
+
+ data["Props"] = props.to_json();
+
+ nlohmann::json staticMesh;
+
+ for (const auto& mesh : gWorldInstance.StaticMeshActors) {
+ staticMesh.push_back(mesh->to_json());
+ }
+ data["StaticMeshActors"] = staticMesh;
+
+ // nlohmann::json actors;
+
+ // for (const auto& actor : gWorldInstance.Actors) {
+ // actors.push_back(actor->to_json());
+ // }
+ // data["Actors"] = actors;
+
+ // nlohmann::json objects;
+
+ // for (const auto& object : gWorldInstance.Objects) {
+ // objects.push_back(object->to_json());
+ // }
+ // data["Objects"] = objects;
+
+ try {
+ auto dat = data.dump();
+ std::vector<uint8_t> stringify;
+ stringify.assign(dat.begin(), dat.end());
+
+ bool wrote = GameEngine::Instance->context->GetResourceManager()->GetArchiveManager()->WriteFile(CurrentArchive, SceneFile, stringify);
+ if (wrote) {
+ printf("Successfully wrote scene file!\n Wrote: %s\n", SceneFile.c_str());
+ } else {
+ printf("Failed to write scene file!\n");
+ }
+ } catch (const nlohmann::json::exception& e) {
+ printf("SceneManager::SaveLevel():\n JSON error during dump: %s\n", e.what());
+ }
+ } else {
+ printf("Could not save scene file, SceneFile or CurrentArchive not set\n");
+ }
+ }
+
+ void LoadLevel(std::shared_ptr<Ship::Archive> archive, Course* course, std::string sceneFile) {
+ SceneFile = sceneFile;
+
+ if (archive) {
+ auto initData = std::make_shared<Ship::ResourceInitData>();
+ initData->Parent = archive;
+ initData->Format = RESOURCE_FORMAT_BINARY;
+ initData->ByteOrder = Ship::Endianness::Little;
+ initData->Type = static_cast<uint32_t>(Ship::ResourceType::Json);
+ initData->ResourceVersion = 0;
+
+ nlohmann::json data = std::static_pointer_cast<Ship::Json>(
+ GameEngine::Instance->context->GetResourceManager()->LoadResource(sceneFile, true, initData))->Data;
+
+ if (data.is_null() || data.empty()) {
+ return;
+ }
+
+ // Load the Props (deserialize it)
+ if (data.contains("Props")) {
+ auto& propsJson = data["Props"];
+ try {
+ course->Props.from_json(propsJson);
+ } catch(const std::exception& e) {
+ std::cerr << "SceneManager::LoadLevel() Error parsing track properties: " << e.what() << std::endl;
+ std::cerr << " Is your scene.json file out of date?" << std::endl;
+ }
+ } else {
+ std::cerr << "Props data not found in the JSON file!" << std::endl;
+ }
+
+ // Load the Actors (deserialize them)
+ if (data.contains("StaticMeshActors")) {
+ auto& actorsJson = data["StaticMeshActors"];
+ gWorldInstance.StaticMeshActors.clear(); // Clear existing actors, if any
+
+ for (const auto& actorJson : actorsJson) {
+ Load_AddStaticMeshActor(actorJson);
+ }
+ } else {
+ std::cerr << "Actors data not found in the JSON file!" << std::endl;
+ }
+ }
+ }
+
+ void Load_AddStaticMeshActor(const nlohmann::json& actorJson) {
+ gWorldInstance.StaticMeshActors.push_back(new StaticMeshActor("", FVector(0, 0, 0), IRotator(0, 0, 0), FVector(1, 1, 1), "", nullptr));
+ auto actor = gWorldInstance.StaticMeshActors.back();
+ actor->from_json(actorJson);
+
+ printf("After from_json: Pos(%f, %f, %f), Name: %s, Model: %s\n",
+ actor->Pos.x, actor->Pos.y, actor->Pos.z, actor->Name.c_str(), actor->Model.c_str());
+ gEditor.AddObject(actor->Name.c_str(), &actor->Pos, &actor->Rot, &actor->Scale, (Gfx*) nullptr, 1.0f,
+ GameObject::CollisionType::BOUNDING_BOX, 20.0f, (int32_t*) &actor->bPendingDestroy, (int32_t) 1);
+ }
+
+ void SetSceneFile(std::shared_ptr<Ship::Archive> archive, std::string sceneFile) {
+ CurrentArchive = archive;
+ SceneFile = sceneFile;
+ }
+
+ void LoadMinimap(std::shared_ptr<Ship::Archive> archive, Course* course, std::string filePath) {
+ printf("LOADING MINIMAP %s\n", filePath.c_str());
+ if (archive) {
+ auto initData = std::make_shared<Ship::ResourceInitData>();
+ initData->Parent = archive;
+ initData->Format = RESOURCE_FORMAT_BINARY;
+ initData->ByteOrder = Ship::Endianness::Little;
+ initData->Type = static_cast<uint32_t>(MK64::ResourceType::Minimap);
+ initData->ResourceVersion = 0;
+
+ std::shared_ptr<MK64::Minimap> ptr = std::static_pointer_cast<MK64::Minimap>(
+ GameEngine::Instance->context->GetResourceManager()->LoadResource(filePath, true, initData));
+
+ if (ptr) {
+ printf("LOADED MINIMAP!\n");
+ MK64::MinimapTexture texture = ptr->Texture;
+ course->Props.Minimap.Texture = (const char*)texture.Data;
+ course->Props.Minimap.Width = texture.Width;
+ course->Props.Minimap.Height = texture.Height;
+ } else { // Fallback
+ course->Props.Minimap.Texture = gTextureCourseOutlineMarioRaceway;
+ course->Props.Minimap.Width = ResourceGetTexWidthByName(course->Props.Minimap.Texture);
+ course->Props.Minimap.Height = ResourceGetTexHeightByName(course->Props.Minimap.Texture);
+ }
+ }
+ }
+}
diff --git a/src/engine/editor/SceneManager.h b/src/engine/editor/SceneManager.h
new file mode 100644
index 000000000..58699107e
--- /dev/null
+++ b/src/engine/editor/SceneManager.h
@@ -0,0 +1,13 @@
+#include <libultraship/libultraship.h>
+#include "engine/courses/Course.h"
+
+namespace Editor {
+ void SaveLevel();
+ void LoadLevel(std::shared_ptr<Ship::Archive> archive, Course* course, std::string sceneFile);
+ void Load_AddStaticMeshActor(const nlohmann::json& actorJson);
+ void SetSceneFile(std::shared_ptr<Ship::Archive> archive, std::string sceneFile);
+ void LoadMinimap(std::shared_ptr<Ship::Archive> archive, Course* course, std::string filePath);
+
+ extern std::shared_ptr<Ship::Archive> CurrentArchive; // This is used to retrieve and write the scene data file
+ extern std::string SceneFile;
+}
diff --git a/src/engine/objects/Bat.cpp b/src/engine/objects/Bat.cpp
index b90f7c857..764476064 100644
--- a/src/engine/objects/Bat.cpp
+++ b/src/engine/objects/Bat.cpp
@@ -18,8 +18,8 @@ const char* sBoardwalkTexList[] = { gTextureBat1, gTextureBat2, gTextureBat3, gT
size_t OBat::_count = 0;
-OBat::OBat(const FVector& pos, const FRotation& rot) {
-
+OBat::OBat(const FVector& pos, const IRotator& rot) {
+ Name = "Bat";
find_unused_obj_index(&_objectIndex);
init_texture_object(_objectIndex, (uint8_t*)d_course_banshee_boardwalk_bat_tlut, sBoardwalkTexList, 0x20U,
diff --git a/src/engine/objects/Bat.h b/src/engine/objects/Bat.h
index f9e0df074..d6b7e8774 100644
--- a/src/engine/objects/Bat.h
+++ b/src/engine/objects/Bat.h
@@ -21,14 +21,14 @@ extern "C" {
/**
* OBat
*
- * FRotation does not appear to do anything.
+ * IRotator does not appear to do anything.
* Could not find where origin_pos was at.
* So pos does not work either
*
*/
class OBat : public OObject {
public:
- explicit OBat(const FVector& pos, const FRotation& rot);
+ explicit OBat(const FVector& pos, const IRotator& rot);
~OBat() {
_count--;
@@ -51,10 +51,8 @@ public:
void func_8007D794(s32 objectIndex);
void func_8007DA4C(s32 objectIndex);
-
private:
FVector _pos;
static size_t _count;
size_t _idx;
- s32 _objectIndex;
};
diff --git a/src/engine/objects/BombKart.cpp b/src/engine/objects/BombKart.cpp
index fc27103ed..53b4a4262 100644
--- a/src/engine/objects/BombKart.cpp
+++ b/src/engine/objects/BombKart.cpp
@@ -29,7 +29,8 @@ extern s8 gPlayerCount;
size_t OBombKart::_count = 0;
-OBombKart::OBombKart(Vec3f pos, TrackWaypoint* waypoint, uint16_t waypointIndex, uint16_t state, f32 unk_3C) {
+OBombKart::OBombKart(FVector pos, TrackWaypoint* waypoint, uint16_t waypointIndex, uint16_t state, f32 unk_3C) {
+ Name = "Bomb Kart";
_idx = _count;
Vec3f _pos = {0, 0, 0};
@@ -41,10 +42,10 @@ OBombKart::OBombKart(Vec3f pos, TrackWaypoint* waypoint, uint16_t waypointIndex,
// Set height to the default value of 2000.0f unless Pos[1] is higher.
// This allows placing these on very high surfaces.
- f32 height = (pos[1] > 2000.0f) ? pos[1] : 2000.0f;
- _pos[0] = pos[0];
- _pos[1] = spawn_actor_on_surface(pos[0], height, pos[2]);
- _pos[2] = pos[2];
+ f32 height = (pos.y > 2000.0f) ? pos.y : 2000.0f;
+ _pos[0] = pos.x;
+ _pos[1] = spawn_actor_on_surface(pos.x, height, pos.z);
+ _pos[2] = pos.z;
}
WaypointIndex = waypointIndex;
@@ -72,7 +73,7 @@ OBombKart::OBombKart(Vec3f pos, TrackWaypoint* waypoint, uint16_t waypointIndex,
WheelPos[3][2] = _pos[2];
check_bounding_collision(&_Collision, 2.0f, _pos[0], _pos[1], _pos[2]);
- find_unused_obj_index(&ObjectIndex);
+ find_unused_obj_index(&_objectIndex);
_count++;
}
@@ -329,7 +330,7 @@ void OBombKart::Tick() {
void OBombKart::Draw(s32 cameraId) {
if (gModeSelection == BATTLE) {
for (size_t playerId = 0; playerId < NUM_BOMB_KARTS_BATTLE; playerId++) {
- Object* object = &gObjectList[ObjectIndex];
+ Object* object = &gObjectList[_objectIndex];
if (object->state != 0) {
s32 primAlpha = object->primAlpha;
Player* player = &gPlayerOne[playerId];
@@ -337,9 +338,9 @@ void OBombKart::Draw(s32 cameraId) {
object->pos[1] = player->pos[1] - 2.0;
object->pos[2] = player->pos[2];
object->surfaceHeight = player->unk_074;
- func_800563DC(ObjectIndex, cameraId, primAlpha);
- func_8005669C(ObjectIndex, cameraId, primAlpha);
- func_800568A0(ObjectIndex, cameraId);
+ func_800563DC(_objectIndex, cameraId, primAlpha);
+ func_8005669C(_objectIndex, cameraId, primAlpha);
+ func_800568A0(_objectIndex, cameraId);
}
}
return;
@@ -358,27 +359,27 @@ void OBombKart::Draw(s32 cameraId) {
}
Camera* camera = &camera1[cameraId];
if (cameraId == PLAYER_ONE) {
- if (is_obj_flag_status_active(ObjectIndex, 0x00200000) != 0) {
+ if (is_obj_flag_status_active(_objectIndex, 0x00200000) != 0) {
Unk_4A = 0;
} else if (gGamestate != ENDING) {
Unk_4A = 1;
}
- clear_object_flag(ObjectIndex, 0x00200000);
+ clear_object_flag(_objectIndex, 0x00200000);
}
// huh???
s32 state = State;
if (State != States::DISABLED) {
- gObjectList[ObjectIndex].pos[0] = Pos[0];
- gObjectList[ObjectIndex].pos[1] = Pos[1];
- gObjectList[ObjectIndex].pos[2] = Pos[2];
- s32 temp_s4 = func_8008A364(ObjectIndex, cameraId, 0x31C4U, 0x000001F4);
- if (is_obj_flag_status_active(ObjectIndex, VISIBLE) != 0) {
- set_object_flag(ObjectIndex, 0x00200000);
+ gObjectList[_objectIndex].pos[0] = Pos[0];
+ gObjectList[_objectIndex].pos[1] = Pos[1];
+ gObjectList[_objectIndex].pos[2] = Pos[2];
+ s32 temp_s4 = func_8008A364(_objectIndex, cameraId, 0x31C4U, 0x000001F4);
+ if (is_obj_flag_status_active(_objectIndex, VISIBLE) != 0) {
+ set_object_flag(_objectIndex, 0x00200000);
D_80183E80[0] = 0;
D_80183E80[1] = func_800418AC(Pos[0], Pos[2], camera->pos);
D_80183E80[2] = 0x8000;
- func_800563DC(ObjectIndex, cameraId, 0x000000FF);
+ func_800563DC(_objectIndex, cameraId, 0x000000FF);
OBombKart::SomeRender(camera->pos);
if (((u32) temp_s4 < 0x4E21U) && (state != BOMB_STATE_EXPLODED)) {
OBombKart::LoadMtx();
diff --git a/src/engine/objects/BombKart.h b/src/engine/objects/BombKart.h
index 3663ee664..29069a00f 100644
--- a/src/engine/objects/BombKart.h
+++ b/src/engine/objects/BombKart.h
@@ -47,11 +47,10 @@ public:
u16 Unk_4A = 0;
s16 Unk_4C = 1;
f32 CenterY; // Center of the circle
- s32 ObjectIndex = 0; // Index into gObjectList
Collision _Collision;
// Set waypoint to NULL if using a spawn position and not a waypoint.
- explicit OBombKart(Vec3f pos, TrackWaypoint* waypoint, uint16_t waypointIndex, uint16_t state, f32 unk_3C);
+ explicit OBombKart(FVector pos, TrackWaypoint* waypoint, uint16_t waypointIndex, uint16_t state, f32 unk_3C);
~OBombKart() {
_count--;
diff --git a/src/engine/objects/Boos.cpp b/src/engine/objects/Boos.cpp
index f06abc8f7..5bdbd41cf 100644
--- a/src/engine/objects/Boos.cpp
+++ b/src/engine/objects/Boos.cpp
@@ -23,6 +23,7 @@ extern "C" {
size_t OBoos::_count = 0;
OBoos::OBoos(size_t numBoos, const IPathSpan& leftBoundary, const IPathSpan& active, const IPathSpan& rightBoundary) {
+ Name = "Boos";
// Max five boos allowed due to limited splines
// D_800E5D9C
if (numBoos > 10) {
diff --git a/src/engine/objects/ChainChomp.cpp b/src/engine/objects/ChainChomp.cpp
index 1008aab52..695df1e8a 100644
--- a/src/engine/objects/ChainChomp.cpp
+++ b/src/engine/objects/ChainChomp.cpp
@@ -17,9 +17,10 @@ extern "C" {
size_t OChainChomp::_count = 0;
OChainChomp::OChainChomp() {
+ Name = "Chain Chomp";
_idx = _count;
init_object(indexObjectList2[_count], 0);
-
+ _objectIndex = indexObjectList2[_count];
_count++;
}
diff --git a/src/engine/objects/CheepCheep.cpp b/src/engine/objects/CheepCheep.cpp
index 10cdf6602..5b4157c61 100644
--- a/src/engine/objects/CheepCheep.cpp
+++ b/src/engine/objects/CheepCheep.cpp
@@ -18,6 +18,7 @@ extern Lights1 D_800E45C0[];
}
OCheepCheep::OCheepCheep(const FVector& pos, CheepType type, IPathSpan span) {
+ Name = "Cheep Cheep";
_type = type;
_spawnPos = pos;
_span = span;
diff --git a/src/engine/objects/Crab.cpp b/src/engine/objects/Crab.cpp
index c722a9037..82d2b9330 100644
--- a/src/engine/objects/Crab.cpp
+++ b/src/engine/objects/Crab.cpp
@@ -28,6 +28,7 @@ extern "C" {
size_t OCrab::_count = 0;
OCrab::OCrab(const FVector2D& start, const FVector2D& end) {
+ Name = "Crab";
_idx = _count;
_start = start;
_end = end;
diff --git a/src/engine/objects/Crab.h b/src/engine/objects/Crab.h
index 2d1ef5e93..4cadd3b87 100644
--- a/src/engine/objects/Crab.h
+++ b/src/engine/objects/Crab.h
@@ -46,5 +46,4 @@ private:
FVector2D _end;
static size_t _count;
s32 _idx;
- s32 _objectIndex;
};
diff --git a/src/engine/objects/Flagpole.cpp b/src/engine/objects/Flagpole.cpp
index 7b5e5af20..acd74ba2b 100644
--- a/src/engine/objects/Flagpole.cpp
+++ b/src/engine/objects/Flagpole.cpp
@@ -16,6 +16,7 @@ extern "C" {
size_t OFlagpole::_count = 0;
OFlagpole::OFlagpole(const FVector& pos, s16 direction) {
+ Name = "Flagpole";
_idx = _count;
_pos = pos;
_direction = direction;
diff --git a/src/engine/objects/Flagpole.h b/src/engine/objects/Flagpole.h
index 034db865e..5824fcf18 100644
--- a/src/engine/objects/Flagpole.h
+++ b/src/engine/objects/Flagpole.h
@@ -42,5 +42,4 @@ private:
s16 _direction;
static size_t _count;
size_t _idx;
- s32 _objectIndex;
};
diff --git a/src/engine/objects/GrandPrixBalloons.cpp b/src/engine/objects/GrandPrixBalloons.cpp
new file mode 100644
index 000000000..819bde1c6
--- /dev/null
+++ b/src/engine/objects/GrandPrixBalloons.cpp
@@ -0,0 +1,231 @@
+#include "GrandPrixBalloons.h"
+
+#include "port/Game.h"
+#include "assets/other_textures.h"
+#include "assets/common_data.h"
+
+extern "C" {
+#include "update_objects.h"
+#include "render_objects.h"
+#include "code_80057C60.h"
+#include "code_80086E70.h"
+#include "math_util.h"
+#include "math_util_2.h"
+#include "menus.h"
+}
+
+size_t OGrandPrixBalloons::_count = 0;
+
+OGrandPrixBalloons::OGrandPrixBalloons(const FVector& pos) {
+ Pos = pos;
+
+ _active = 1;
+ if (gPlayerCount == 1) {
+ _numBalloons = 0x64;
+ _numBalloons2 = 0x3C;
+ _numBalloons3 = 0x1E;
+ } else {
+ _numBalloons = 0x32;
+ _numBalloons2 = 0x1E;
+ _numBalloons3 = 0xA;
+ }
+
+ for (size_t i = 0; i < _numBalloons; i++) {
+ find_unused_obj_index(&gObjectParticle3[i]);
+ init_object(gObjectParticle3[i], 0);
+ }
+}
+
+void OGrandPrixBalloons::Tick() {
+ s32 someIndex;
+ s32 objectIndex;
+ s32 someCount;
+ Object* object;
+
+ if (!_active) {
+ return;
+ }
+ someCount = 0;
+ for (someIndex = 0; someIndex < _numBalloons; someIndex++) {
+ objectIndex = gObjectParticle3[someIndex];
+ if (objectIndex != DELETED_OBJECT_ID) {
+ object = &gObjectList[objectIndex];
+ if (object->state != 0) {
+ OGrandPrixBalloons::func_80074E28(objectIndex);
+ OGrandPrixBalloons::func_80074D94(objectIndex);
+ if (object->state == 0) {
+ delete_object_wrapper(&gObjectParticle3[someIndex]);
+ this->Destroy();
+ }
+ someCount += 1;
+ }
+ }
+ }
+ if (someCount == 0) {
+ _active = 0;
+ }
+}
+
+void OGrandPrixBalloons::Draw(s32 cameraId) {
+ s32 var_s1;
+ s32 objectIndex;
+ if (!_active) {
+ return;
+ }
+
+ gSPDisplayList(gDisplayListHead++, (Gfx*)D_0D007E98);
+ gDPLoadTLUT_pal256(gDisplayListHead++, gTLUTOnomatopoeia);
+ func_8004B614(0, 0, 0, 0, 0, 0, 0);
+ gDPSetAlphaCompare(gDisplayListHead++, G_AC_THRESHOLD);
+ gDPSetRenderMode(gDisplayListHead++,
+ AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_WRAP | ZMODE_XLU | FORCE_BL |
+ GBL_c1(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA),
+ AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_WRAP | ZMODE_XLU | FORCE_BL |
+ GBL_c2(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA));
+ D_80183E80[0] = 0;
+ D_80183E80[1] = 0x8000;
+ rsp_load_texture((uint8_t*)gTextureBalloon1, 64, 32);
+ for (var_s1 = 0; var_s1 < _numBalloons; var_s1++) {
+ objectIndex = gObjectParticle3[var_s1];
+ if ((objectIndex != NULL_OBJECT_ID) && (gObjectList[objectIndex].state >= 2)) {
+ OGrandPrixBalloons::func_80053D74(objectIndex, cameraId, 0);
+ }
+ }
+ rsp_load_texture((uint8_t*)gTextureBalloon2, 64, 32);
+ for (var_s1 = 0; var_s1 < _numBalloons; var_s1++) {
+ objectIndex = gObjectParticle3[var_s1];
+ if ((objectIndex != NULL_OBJECT_ID) && (gObjectList[objectIndex].state >= 2)) {
+ OGrandPrixBalloons::func_80053D74(objectIndex, cameraId, 4);
+ }
+ }
+}
+
+void OGrandPrixBalloons::func_80053D74(s32 objectIndex, UNUSED s32 arg1, s32 vertexIndex) {
+ Object* object;
+
+ Vtx* vtx = (Vtx*) LOAD_ASSET_RAW(common_vtx_hedgehog);
+
+ if (gMatrixHudCount <= MTX_HUD_POOL_SIZE_MAX) {
+ object = &gObjectList[objectIndex];
+ D_80183E80[2] = (s16) (object->unk_084[6] + 0x8000);
+ rsp_set_matrix_transformation(object->pos, (u16*) D_80183E80, object->sizeScaling);
+ set_color_render((s32) object->unk_084[0], (s32) object->unk_084[1], (s32) object->unk_084[2],
+ (s32) object->unk_084[3], (s32) object->unk_084[4], (s32) object->unk_084[5],
+ (s32) object->primAlpha);
+ gSPVertex(gDisplayListHead++, (uintptr_t)&vtx[vertexIndex], 4, 0);
+ gSPDisplayList(gDisplayListHead++, (Gfx*)common_rectangle_display);
+ }
+}
+
+void OGrandPrixBalloons::func_80074924(s32 objectIndex) {
+ s32 sp2C = 0;
+ s32 sp28;
+ s32 sp24;
+ s32 sp20 = 0;
+ s32 temp_a0;
+ Object* object;
+
+ object = &gObjectList[objectIndex];
+ object->sizeScaling = 0.15f;
+
+ if (GetCourse() == GetMarioRaceway()) {
+ sp2C = random_int(0x00C8U);
+ sp28 = random_int(_numBalloons3);
+ sp24 = random_int(0x0096U);
+ sp20 = random_int(0x2000U);
+ object->origin_pos[0] = (f32) ((((f64) Pos.x + 100.0) - (f64) sp2C) * (f64) xOrientation);
+ object->origin_pos[1] = (f32) (Pos.y + sp28);
+ object->origin_pos[2] = (f32) (((f64) Pos.z + 200.0) - (f64) sp24);
+ } else if (GetCourse() == GetRoyalRaceway()) {
+ sp2C = random_int(0x0168U);
+ sp28 = random_int(_numBalloons3);
+ sp24 = random_int(0x00B4U);
+ sp20 = random_int(0x2000U);
+ object->origin_pos[0] = (f32) ((((f64) Pos.x + 180.0) - (f64) sp2C) * (f64) xOrientation);
+ object->origin_pos[1] = (f32) (Pos.y + sp28);
+ object->origin_pos[2] = (f32) (((f64) Pos.z + 200.0) - (f64) sp24);
+ } else if (GetCourse() == GetLuigiRaceway()) {
+ sp2C = random_int(0x012CU);
+ sp28 = random_int(_numBalloons3);
+ sp24 = random_int(0x0096U);
+ sp20 = random_int(0x2000U);
+ object->origin_pos[0] = (f32) ((((f64) Pos.x + 150.0) - (f64) sp2C) * (f64) xOrientation);
+ object->origin_pos[1] = (f32) (Pos.y + sp28);
+ object->origin_pos[2] = (f32) (((f64) Pos.z + 200.0) - (f64) sp24);
+ } else { // any track
+ sp2C = random_int(0x00C8U);
+ sp28 = random_int(_numBalloons3);
+ sp24 = random_int(0x0096U);
+ sp20 = random_int(0x2000U);
+ object->origin_pos[0] = (f32) ((((f64) Pos.x + 100.0) - (f64) sp2C) * (f64) xOrientation);
+ object->origin_pos[1] = (f32) (Pos.y + sp28);
+ object->origin_pos[2] = (f32) (((f64) Pos.z + 200.0) - (f64) sp24);
+ }
+
+ set_obj_origin_offset(objectIndex, 0, 0, 0);
+ if (gPlayerCount == 1) {
+ object->velocity[1] = (f32) (((f64) (f32) (sp2C % 4) * 0.25) + 0.8);
+ } else {
+ object->velocity[1] = (f32) (((f64) (f32) (sp2C % 3) * 0.2) + 0.4);
+ }
+ temp_a0 = sp2C % 8;
+ object->unk_084[0] = D_800E6F30[temp_a0][0];
+ object->unk_084[1] = D_800E6F30[temp_a0][1];
+ object->unk_084[2] = D_800E6F30[temp_a0][2];
+ object->unk_084[3] = D_800E6F48[temp_a0][0];
+ object->unk_084[4] = D_800E6F48[temp_a0][1];
+ object->unk_084[5] = D_800E6F48[temp_a0][2];
+ object->unk_084[6] = sp20 - 0x1000;
+ if (sp2C & 1) {
+ object->unk_084[7] = (sp20 / 32) + 0x100;
+ } else {
+ object->unk_084[7] = -0x100 - (sp20 / 32);
+ }
+ object->primAlpha = 0x00E6;
+ object_next_state(objectIndex);
+}
+
+void OGrandPrixBalloons::func_80074D94(s32 objectIndex) {
+ if (gObjectList[objectIndex].unk_0AE == 1) {
+ if ((_numBalloons2 <= gObjectList[objectIndex].offset[1]) &&
+ (s16_step_down_towards(&gObjectList[objectIndex].primAlpha, 0, 8) != 0)) {
+ func_80086F60(objectIndex);
+ }
+ object_add_velocity_offset_y(objectIndex);
+ }
+ object_calculate_new_pos_offset(objectIndex);
+}
+
+void OGrandPrixBalloons::func_80074E28(s32 objectIndex) {
+ switch (gObjectList[objectIndex].state) {
+ case 1:
+ OGrandPrixBalloons::func_80074924(objectIndex);
+ break;
+ case 2:
+ if (set_and_run_timer_object(objectIndex, 1) != false) {
+ func_80086E70(objectIndex);
+ break;
+ }
+ case 0:
+ break;
+ case 3:
+ OGrandPrixBalloons::func_80041480(&gObjectList[objectIndex].unk_084[6], -0x1000, 0x1000, &gObjectList[objectIndex].unk_084[7]);
+ if (gObjectList[objectIndex].unk_0AE == 0) {
+ func_80072428(objectIndex);
+ }
+ break;
+ }
+}
+
+void OGrandPrixBalloons::func_80041480(s16* arg0, s16 arg1, s16 arg2, s16* arg3) {
+ *arg0 += *arg3;
+ if (*arg3 >= 0) {
+ if (*arg0 >= arg2) {
+ *arg0 = arg2;
+ *arg3 = -*arg3;
+ }
+ } else if (arg1 >= *arg0) {
+ *arg0 = arg1;
+ *arg3 = -*arg3;
+ }
+} \ No newline at end of file
diff --git a/src/engine/objects/GrandPrixBalloons.h b/src/engine/objects/GrandPrixBalloons.h
new file mode 100644
index 000000000..93ec04479
--- /dev/null
+++ b/src/engine/objects/GrandPrixBalloons.h
@@ -0,0 +1,55 @@
+#pragma once
+
+#include <libultraship.h>
+#include <vector>
+
+#include "engine/World.h"
+#include "engine/objects/Object.h"
+
+extern "C" {
+#include "macros.h"
+#include "main.h"
+#include "vehicles.h"
+#include "waypoints.h"
+#include "common_structs.h"
+#include "objects.h"
+#include "camera.h"
+#include "some_data.h"
+}
+
+
+
+/**
+ * Grand Prix Balloons OObject
+ */
+class OGrandPrixBalloons : public OObject {
+public:
+
+ explicit OGrandPrixBalloons(const FVector& pos);
+
+ ~OGrandPrixBalloons() {
+ _count--;
+ }
+
+ static size_t GetCount() {
+ return _count;
+ }
+
+ virtual void Tick() override;
+ virtual void Draw(s32 cameraId) override;
+ void func_80053D74(s32 objectIndex, UNUSED s32 arg1, s32 vertexIndex);
+
+ void func_80074924(s32 objectIndex);
+ void func_80074D94(s32 objectIndex);
+ void func_80074E28(s32 objectIndex);
+ void func_80041480(s16* arg0, s16 arg1, s16 arg2, s16* arg3); // Some weird math function
+
+private:
+ static size_t _count;
+ s32 _idx;
+ FVector Pos;
+ bool _active;
+ size_t _numBalloons;
+ size_t _numBalloons2;
+ size_t _numBalloons3;
+};
diff --git a/src/engine/objects/Hedgehog.cpp b/src/engine/objects/Hedgehog.cpp
index 133a1f38d..ebc5b30bb 100644
--- a/src/engine/objects/Hedgehog.cpp
+++ b/src/engine/objects/Hedgehog.cpp
@@ -15,10 +15,12 @@ extern "C" {
size_t OHedgehog::_count = 0;
OHedgehog::OHedgehog(const FVector& pos, const FVector2D& patrolPoint, s16 unk) {
+ Name = "Hedgehog";
_idx = _count;
_pos = pos;
s32 objectId = indexObjectList2[_idx];
+ _objectIndex = objectId;
init_object(objectId, 0);
gObjectList[objectId].pos[0] = gObjectList[objectId].origin_pos[0] = pos.x * xOrientation;
gObjectList[objectId].pos[1] = gObjectList[objectId].surfaceHeight = pos.y + 6.0;
diff --git a/src/engine/objects/HotAirBalloon.cpp b/src/engine/objects/HotAirBalloon.cpp
index 917fd7354..4e337d98e 100644
--- a/src/engine/objects/HotAirBalloon.cpp
+++ b/src/engine/objects/HotAirBalloon.cpp
@@ -15,6 +15,7 @@ extern "C" {
}
OHotAirBalloon::OHotAirBalloon(const FVector& pos) {
+ Name = "Hot Air Balloon";
_pos = pos;
D_80165898 = 0;
diff --git a/src/engine/objects/HotAirBalloon.h b/src/engine/objects/HotAirBalloon.h
index 5dad406db..301e111c4 100644
--- a/src/engine/objects/HotAirBalloon.h
+++ b/src/engine/objects/HotAirBalloon.h
@@ -31,5 +31,4 @@ public:
private:
FVector _pos;
bool *_visible;
- s32 _objectIndex;
};
diff --git a/src/engine/objects/Lakitu.cpp b/src/engine/objects/Lakitu.cpp
index 93a87f5e1..12ca2d7db 100644
--- a/src/engine/objects/Lakitu.cpp
+++ b/src/engine/objects/Lakitu.cpp
@@ -37,6 +37,7 @@ extern s8 gPlayerCount;
}
OLakitu::OLakitu(s32 playerId, LakituType type) {
+ Name = "Lakitu";
_playerId = playerId;
init_object(gIndexLakituList[playerId], (s32)type);
diff --git a/src/engine/objects/Mole.cpp b/src/engine/objects/Mole.cpp
index fdf5e7b08..06bd5f56c 100644
--- a/src/engine/objects/Mole.cpp
+++ b/src/engine/objects/Mole.cpp
@@ -25,6 +25,7 @@ extern "C" {
size_t OMole::_count = 0;
OMole::OMole(FVector pos, OMoleGroup* group) {
+ Name = "Mole";
_idx = _count;
_group = group;
diff --git a/src/engine/objects/Mole.h b/src/engine/objects/Mole.h
index 7707b5383..1457c72cc 100644
--- a/src/engine/objects/Mole.h
+++ b/src/engine/objects/Mole.h
@@ -40,7 +40,6 @@ public:
void func_80081790(s32 objectIndex);
void func_8008153C(s32 objectIndex);
- s32 _objectIndex;
s32 _moleIndex;
private:
static size_t _count;
diff --git a/src/engine/objects/Object.cpp b/src/engine/objects/Object.cpp
index d532dd566..4e4fd6766 100644
--- a/src/engine/objects/Object.cpp
+++ b/src/engine/objects/Object.cpp
@@ -18,6 +18,6 @@ void OObject::Tick60fps() {}
void OObject::Draw(s32 cameraId) { }
void OObject::Expire() { }
void OObject::Destroy() {
- PendingDestroy = true;
+ bPendingDestroy = true;
}
void OObject::Reset() { }
diff --git a/src/engine/objects/Object.h b/src/engine/objects/Object.h
index b78b27240..9dd44397b 100644
--- a/src/engine/objects/Object.h
+++ b/src/engine/objects/Object.h
@@ -11,7 +11,9 @@ class OObject {
public:
uint8_t uuid[16];
Object o;
- bool PendingDestroy = false;
+ const char* Name = "";
+ bool bPendingDestroy = false;
+ s32 _objectIndex = -1;
virtual ~OObject() = default;
diff --git a/src/engine/objects/Penguin.cpp b/src/engine/objects/Penguin.cpp
index 1eeb00ff4..d283101b3 100644
--- a/src/engine/objects/Penguin.cpp
+++ b/src/engine/objects/Penguin.cpp
@@ -34,7 +34,8 @@ extern s8 gPlayerCount;
}
-OPenguin::OPenguin(Vec3f pos, u16 direction, PenguinType type, Behaviour behaviour) {
+OPenguin::OPenguin(FVector pos, u16 direction, PenguinType type, Behaviour behaviour) {
+ Name = "Penguin";
_type = type;
_bhv = behaviour;
@@ -43,9 +44,9 @@ OPenguin::OPenguin(Vec3f pos, u16 direction, PenguinType type, Behaviour behavio
init_object(_objectIndex, 0);
Object *object = &gObjectList[_objectIndex];
- object->origin_pos[0] = pos[0] * xOrientation;
- object->origin_pos[1] = pos[1];
- object->origin_pos[2] = pos[2];
+ object->origin_pos[0] = pos.x * xOrientation;
+ object->origin_pos[1] = pos.y;
+ object->origin_pos[2] = pos.z;
object->unk_0C6 = direction;
switch(type) {
diff --git a/src/engine/objects/Penguin.h b/src/engine/objects/Penguin.h
index 72ba16285..91d5687b9 100644
--- a/src/engine/objects/Penguin.h
+++ b/src/engine/objects/Penguin.h
@@ -38,7 +38,7 @@ public:
f32 Diameter = 0.0f; // Waddle in a circle around the spawn point at this diameter.
uint16_t MirrorModeAngleOffset;
- explicit OPenguin(Vec3f pos, u16 direction, PenguinType type, Behaviour behaviour);
+ explicit OPenguin(FVector pos, u16 direction, PenguinType type, Behaviour behaviour);
virtual void Tick() override;
virtual void Draw(s32 cameraId) override;
@@ -55,7 +55,6 @@ private:
void InitOtherPenguin(s32 objectIndex);
static bool _toggle;
- s32 _objectIndex;
PenguinType _type;
Behaviour _bhv;
};
diff --git a/src/engine/objects/Podium.cpp b/src/engine/objects/Podium.cpp
index d8f1e2ff2..ec396ca53 100644
--- a/src/engine/objects/Podium.cpp
+++ b/src/engine/objects/Podium.cpp
@@ -26,7 +26,7 @@ extern Vec3s D_800E634C[];
// };
OPodium::OPodium(const FVector& pos) {
-
+ Name = "Podium";
_pos = pos;
find_unused_obj_index(&_podium1Index);
diff --git a/src/engine/objects/Seagull.cpp b/src/engine/objects/Seagull.cpp
index 11043238f..17c35c07d 100644
--- a/src/engine/objects/Seagull.cpp
+++ b/src/engine/objects/Seagull.cpp
@@ -32,6 +32,7 @@ SplineData* D_800E633C[] = { &D_800E6034, &D_800E60F0, &D_800E61B4, &D_800E6280
size_t OSeagull::_count = 0;
OSeagull::OSeagull(FVector pos) {
+ Name = "Seagull";
_idx = _count;
_pos.x = pos.x;
_pos.y = pos.y;
diff --git a/src/engine/objects/Seagull.h b/src/engine/objects/Seagull.h
index a0e5cd233..42474159e 100644
--- a/src/engine/objects/Seagull.h
+++ b/src/engine/objects/Seagull.h
@@ -38,7 +38,6 @@ public:
void func_8008241C(s32 objectIndex, s32 arg1);
void func_80082714(s32 objectIndex, s32 arg1);
private:
- s32 _objectIndex;
FVector _pos;
static size_t _count;
s32 _idx;
diff --git a/src/engine/objects/Snowman.cpp b/src/engine/objects/Snowman.cpp
index 2052a8adb..12beb9e47 100644
--- a/src/engine/objects/Snowman.cpp
+++ b/src/engine/objects/Snowman.cpp
@@ -17,11 +17,13 @@ static const char* sSnowmanHeadList[] = { d_course_frappe_snowland_snowman_head
size_t OSnowman::_count = 0;
OSnowman::OSnowman(const FVector& pos) {
+ Name = "Snowman";
_idx = _count;
_pos = pos;
find_unused_obj_index(&_headIndex);
init_object(_headIndex, 0);
+ _objectIndex = _headIndex;
gObjectList[_headIndex].origin_pos[0] = pos.x * xOrientation;
gObjectList[_headIndex].origin_pos[1] = pos.y + 5.0 + 3.0;
gObjectList[_headIndex].origin_pos[2] = pos.z;
diff --git a/src/engine/objects/Snowman.h b/src/engine/objects/Snowman.h
index ffa927769..f33ee3b53 100644
--- a/src/engine/objects/Snowman.h
+++ b/src/engine/objects/Snowman.h
@@ -50,7 +50,6 @@ private:
FVector _pos;
static size_t _count;
size_t _idx;
- s32 _objectIndex;
s32 _headIndex;
s32 _bodyIndex;
};
diff --git a/src/engine/objects/Thwomp.cpp b/src/engine/objects/Thwomp.cpp
index 6a04f07bb..d3f99a8d9 100644
--- a/src/engine/objects/Thwomp.cpp
+++ b/src/engine/objects/Thwomp.cpp
@@ -47,6 +47,7 @@ s16 D_800E597C[] = { 0x0000, 0x0000, 0x4000, 0x8000, 0x8000, 0xc000 };
size_t OThwomp::_count = 0;
OThwomp::OThwomp(s16 x, s16 z, s16 direction, f32 scale, s16 behaviour, s16 primAlpha, u16 boundingBoxSize) {
+ Name = "Thwomp";
_idx = _count;
_faceDirection = direction;
_boundingBoxSize = boundingBoxSize;
diff --git a/src/engine/objects/Thwomp.h b/src/engine/objects/Thwomp.h
index 75aeaf1a0..22c674bb5 100644
--- a/src/engine/objects/Thwomp.h
+++ b/src/engine/objects/Thwomp.h
@@ -113,7 +113,6 @@ public:
private:
static size_t _count;
s32 _idx;
- s32 _objectIndex;
s16 _faceDirection;
//! @todo Write this better. This effects the squish size and the bounding box size.
// We should probably return to the programmer the pointer to the actor so they can do thwomp->squishSize = value.
diff --git a/src/engine/objects/TrashBin.cpp b/src/engine/objects/TrashBin.cpp
index 6aa556470..c94d0352f 100644
--- a/src/engine/objects/TrashBin.cpp
+++ b/src/engine/objects/TrashBin.cpp
@@ -20,7 +20,8 @@ extern "C" {
#define DEGREES_FLOAT_TO_SHORT(Degrees) ((s16)((Degrees) * (0x8000 / 180.0f)))
-OTrashBin::OTrashBin(const FVector& pos, const FRotation& rotation, f32 scale, OTrashBin::Behaviour bhv) {
+OTrashBin::OTrashBin(const FVector& pos, const IRotator& rotation, f32 scale, OTrashBin::Behaviour bhv) {
+ Name = "Trashbin";
_pos = pos;
_rot = rotation;
_scale = scale;
diff --git a/src/engine/objects/TrashBin.h b/src/engine/objects/TrashBin.h
index 2ebe13e87..3e878e1c0 100644
--- a/src/engine/objects/TrashBin.h
+++ b/src/engine/objects/TrashBin.h
@@ -24,7 +24,7 @@ public:
STATIC, // The lid stays shut
MUNCHING // The lid opens/closes in a scary munching manner
};
- explicit OTrashBin(const FVector& pos, const FRotation& rotation, f32 scale, OTrashBin::Behaviour bhv);
+ explicit OTrashBin(const FVector& pos, const IRotator& rotation, f32 scale, OTrashBin::Behaviour bhv);
virtual void Tick() override;
virtual void Draw(s32 cameraId) override;
@@ -38,9 +38,8 @@ private:
Behaviour _bhv;
FVector _pos;
- FRotation _rot;
+ IRotator _rot;
float _scale;
size_t _idx;
- s32 _objectIndex;
bool _drawBin = false;
};
diff --git a/src/engine/objects/Trophy.cpp b/src/engine/objects/Trophy.cpp
index 54bd70d3e..9f90b6be1 100644
--- a/src/engine/objects/Trophy.cpp
+++ b/src/engine/objects/Trophy.cpp
@@ -21,6 +21,7 @@ extern "C" {
}
OTrophy::OTrophy(const FVector& pos, TrophyType trophy, Behaviour bhv) {
+ Name = "Trophy";
_trophy = trophy;
_spawnPos = pos;
_spawnPos.y += 16.0f; // Adjust the height so the trophy sits on the surface when positioned to 0,0,0
diff --git a/src/engine/objects/Trophy.h b/src/engine/objects/Trophy.h
index c2bb937ab..89f130997 100644
--- a/src/engine/objects/Trophy.h
+++ b/src/engine/objects/Trophy.h
@@ -48,7 +48,6 @@ public:
private:
StarEmitter* _emitter;
- s32 _objectIndex;
TrophyType _trophy;
FVector _spawnPos;
Behaviour _bhv;
diff --git a/src/engine/vehicles/Boat.cpp b/src/engine/vehicles/Boat.cpp
index 460331f97..073974581 100644
--- a/src/engine/vehicles/Boat.cpp
+++ b/src/engine/vehicles/Boat.cpp
@@ -17,6 +17,7 @@ extern s8 gPlayerCount;
size_t ABoat::_count = 0;
ABoat::ABoat(f32 speed, u32 waypoint) {
+ Name = "Paddle Steam Boat";
Path2D* temp_a2;
u16 waypointOffset;
Index = _count;
diff --git a/src/engine/vehicles/Bus.cpp b/src/engine/vehicles/Bus.cpp
index 43b6e7406..c58cd0a6c 100644
--- a/src/engine/vehicles/Bus.cpp
+++ b/src/engine/vehicles/Bus.cpp
@@ -19,6 +19,7 @@ extern s8 gPlayerCount;
size_t ABus::_count = 0;
ABus::ABus(f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint) {
+ Name = "Bus";
TrackWaypoint* temp_v0;
u16 waypointOffset;
s32 numWaypoints = gWaypointCountByPathIndex[0];
diff --git a/src/engine/vehicles/Car.cpp b/src/engine/vehicles/Car.cpp
index a5dd49007..89409df50 100644
--- a/src/engine/vehicles/Car.cpp
+++ b/src/engine/vehicles/Car.cpp
@@ -19,6 +19,7 @@ extern s8 gPlayerCount;
size_t ACar::_count = 0;
ACar::ACar(f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint) {
+ Name = "Car";
TrackWaypoint* temp_v0;
u16 waypointOffset;
s32 numWaypoints = gWaypointCountByPathIndex[0];
diff --git a/src/engine/vehicles/TankerTruck.cpp b/src/engine/vehicles/TankerTruck.cpp
index a6b94429f..02cd9553b 100644
--- a/src/engine/vehicles/TankerTruck.cpp
+++ b/src/engine/vehicles/TankerTruck.cpp
@@ -19,6 +19,7 @@ extern s8 gPlayerCount;
size_t ATankerTruck::_count = 0;
ATankerTruck::ATankerTruck(f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint) {
+ Name = "Tanker Truck";
TrackWaypoint* temp_v0;
u16 waypointOffset;
s32 numWaypoints = gWaypointCountByPathIndex[0];
diff --git a/src/engine/vehicles/Train.cpp b/src/engine/vehicles/Train.cpp
index 14d9c9763..a3952742d 100644
--- a/src/engine/vehicles/Train.cpp
+++ b/src/engine/vehicles/Train.cpp
@@ -25,6 +25,7 @@ extern "C" {
size_t ATrain::_count = 0;
ATrain::ATrain(ATrain::TenderStatus tender, size_t numCarriages, f32 speed, uint32_t waypoint) {
+ Name = "Train";
u16 waypointOffset;
TrainCarStuff* ptr1;
Path2D* pos;
diff --git a/src/engine/vehicles/Truck.cpp b/src/engine/vehicles/Truck.cpp
index 68ef87353..585293489 100644
--- a/src/engine/vehicles/Truck.cpp
+++ b/src/engine/vehicles/Truck.cpp
@@ -19,6 +19,7 @@ extern s8 gPlayerCount;
size_t ATruck::_count = 0;
ATruck::ATruck(f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint) {
+ Name = "Truck";
TrackWaypoint* temp_v0;
u16 waypointOffset;
s32 numWaypoints = gWaypointCountByPathIndex[0];