summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/koopatlas/camera.cpp191
-rw-r--r--src/koopatlas/camera.h37
-rw-r--r--src/koopatlas/core.cpp928
-rw-r--r--src/koopatlas/core.h99
-rw-r--r--src/koopatlas/hud.cpp168
-rw-r--r--src/koopatlas/hud.h28
-rw-r--r--src/koopatlas/map.cpp259
-rw-r--r--src/koopatlas/map.h60
-rw-r--r--src/koopatlas/mapdata.cpp147
-rw-r--r--src/koopatlas/mapdata.h191
-rw-r--r--src/koopatlas/player.cpp143
-rw-r--r--src/koopatlas/player.h25
12 files changed, 2276 insertions, 0 deletions
diff --git a/src/koopatlas/camera.cpp b/src/koopatlas/camera.cpp
new file mode 100644
index 0000000..a4c642f
--- /dev/null
+++ b/src/koopatlas/camera.cpp
@@ -0,0 +1,191 @@
+#include "koopatlas/camera.h"
+#include "koopatlas/player.h"
+
+dWorldCamera_c *dWorldCamera_c::instance = 0;
+
+dWorldCamera_c *dWorldCamera_c::build() {
+ OSReport("Creating WorldCamera\n");
+
+ void *buffer = AllocFromGameHeap1(sizeof(dWorldCamera_c));
+ dWorldCamera_c *c = new(buffer) dWorldCamera_c;
+
+ OSReport("Created WorldCamera @ %p\n", c);
+
+ instance = c;
+ return c;
+}
+
+
+dWorldCamera_c::dWorldCamera_c() {
+ camera3d.camPos = (Vec){0.0, 10.0, 0.0};
+ camera3d.target = (Vec){0.0, 0.0, 0.0};
+ camera3d.camUp = (Vec){0.0, 1.0, 0.0};
+
+ camera2d.camPos = (Vec){0.0, 10.0, 0.0};
+ camera2d.target = (Vec){0.0, 0.0, 0.0};
+ camera2d.camUp = (Vec){0.0, 1.0, 0.0};
+
+ camPos = (Vec){0.0, 0.0, 1.0};
+ camUp = (Vec){0.0, 1.0, 0.0};
+
+ projection2d.near = 1.0;
+ projection2d.far = 20000.0;
+
+ currentX = 0;
+ currentY = 0;
+ zoomLevel = 1;
+}
+
+
+
+int dWorldCamera_c::onCreate() {
+ // Bad Code
+ screen.projType = 0;
+ screen.some_flag_bit |= 1;
+
+ SSM *ssm = &ScreenSizesAndMultipliers[currentScreenSizeID];
+ screen.height = ssm->height;
+ screen.width = ssm->width;
+ screen.near = 1.0;
+ screen.far = 20000.0;
+
+ if (screen.isCentered != 1) {
+ screen.some_flag_bit |= 1;
+ screen.isCentered = 1;
+ }
+
+ doStuff(10000.0);
+ generateCameraMatrices();
+ updateCameras();
+
+ return true;
+}
+
+
+int dWorldCamera_c::onDelete() {
+ return true;
+}
+
+
+int dWorldCamera_c::onExecute() {
+ int nowPressed = Remocon_GetPressed(GetActiveRemocon());
+ bool change = false;
+ if (nowPressed & WPAD_LEFT) {
+ currentX -= 16;
+ change = true;
+ }
+ if (nowPressed & WPAD_RIGHT) {
+ currentX += 16;
+ change = true;
+ }
+ if (nowPressed & WPAD_UP) {
+ currentY += 16;
+ change = true;
+ }
+ if (nowPressed & WPAD_DOWN) {
+ currentY -= 16;
+ change = true;
+ }
+ if (nowPressed & WPAD_B) {
+ zoomLevel -= 0.02;
+ change = true;
+ }
+ if (nowPressed & WPAD_A) {
+ zoomLevel += 0.02;
+ change = true;
+ }
+ if (change) {
+ OSReport("%f, %f (%f)\n", currentX, currentY, zoomLevel);
+ }
+ calculateScreenGeometry();
+ doStuff(10000.0);
+ generateCameraMatrices();
+ updateCameras();
+ return true;
+}
+
+
+int dWorldCamera_c::onDraw() {
+ GXRenderModeObj *rmode = nw4r::g3d::G3DState::GetRenderModeObj();
+
+ nw4r::g3d::Camera cam(GetCameraByID(0));
+ nw4r::g3d::Camera cam2d(GetCameraByID(1));
+
+ if (rmode->field_rendering != 0) {
+ cam.SetViewportJitter(VIGetNextField());
+ cam2d.SetViewportJitter(VIGetNextField());
+ }
+ //cam2d.SetOrtho(rmode->efbHeight, 0.0f, 0.0f, rmode->fbWidth * (IsWideScreen() ? 1.3333334f : 1.0f), -100000.0f, 100000.0f);
+
+ return true;
+}
+
+
+void dWorldCamera_c::calculateScreenGeometry() {
+ zoomDivisor = 1.0 / zoomLevel;
+
+ screenWidth = GlobalScreenWidth / zoomDivisor;
+ screenHeight = GlobalScreenHeight / zoomDivisor;
+
+ screenLeft = currentX - (screenWidth * 0.5);
+ screenTop = currentY + (screenHeight * 0.5);
+}
+
+
+void dWorldCamera_c::doStuff(float something) {
+ camTarget = (Vec){
+ screenLeft + (screenWidth * 0.5),
+ (screenTop - screenHeight) + (screenHeight * 0.5),
+ 0.0
+ };
+
+ camPos = (Vec){camTarget.x, camTarget.y, something};
+}
+
+
+void dWorldCamera_c::generateCameraMatrices() {
+ float orthoTop = screenHeight * 0.5;
+ float orthoLeft = -screenWidth * 0.5;
+ float orthoBottom = -orthoTop;
+ float orthoRight = -orthoLeft;
+
+ camera3d.camPos = camPos;
+ camera3d.target = camTarget;
+ camera3d.camUp = camUp;
+
+ camera3d.calculateMatrix();
+
+ screen.setOrtho(orthoTop, orthoBottom, orthoLeft, orthoRight, -100000.0f, 100000.0f);
+
+ VEC2 crap = GetSomeSizeRelatedBULLSHIT();
+ Vec calcedAboutRatio = CalculateSomethingAboutRatio(orthoTop, orthoBottom, orthoLeft, orthoRight);
+ screen._44 = CalculateSomethingElseAboutRatio();
+
+ screen.width = crap.x;
+ screen.some_flag_bit |= 1;
+ screen.height = crap.y;
+ screen.horizontalMultiplier = calcedAboutRatio.x;
+ screen.verticalMultiplier = calcedAboutRatio.y;
+ screen.unk3 = calcedAboutRatio.z;
+
+ camera2d.camPos = (Vec){0.0, 0.0, 0.0};
+ camera2d.target = (Vec){0.0, 0.0, -100.0};
+ camera2d.camUp = camUp;
+
+ camera2d.calculateMatrix();
+
+ GXRenderModeObj *rmode = nw4r::g3d::G3DState::GetRenderModeObj();
+ projection2d.setVolume(rmode->efbHeight, 0.0, 0.0, rmode->fbWidth * (IsWideScreen() ? 1.3333334f : 0));
+}
+
+
+void dWorldCamera_c::updateCameras() {
+ nw4r::g3d::Camera cam0(GetCameraByID(0));
+ camera3d.assignToNW4RCamera(cam0);
+ screen.loadIntoCamera(cam0);
+
+ nw4r::g3d::Camera cam1(GetCameraByID(1));
+ projection2d.setOrthoOntoCamera(cam1);
+ //camera2d.assignToNW4RCamera(cam1);
+}
+
diff --git a/src/koopatlas/camera.h b/src/koopatlas/camera.h
new file mode 100644
index 0000000..f057374
--- /dev/null
+++ b/src/koopatlas/camera.h
@@ -0,0 +1,37 @@
+#include "koopatlas/core.h"
+
+class dWorldCamera_c : public dBase_c {
+ public:
+ int onCreate();
+ int onDelete();
+ int onExecute();
+ int onDraw();
+
+ dWorldCamera_c();
+
+ EGG::Screen screen;
+ EGG::LookAtCamera camera3d;
+
+ EGG::ProjectOrtho projection2d;
+ EGG::LookAtCamera camera2d;
+
+ Vec camPos, camTarget, camUp;
+
+
+ float currentX, currentY, zoomLevel;
+
+ void calculateScreenGeometry();
+
+
+ float zoomDivisor, screenLeft, screenTop, screenWidth, screenHeight;
+
+
+ void doStuff(float);
+ void generateCameraMatrices();
+ void updateCameras();
+
+ static dWorldCamera_c *build();
+ static dWorldCamera_c *instance;
+};
+
+
diff --git a/src/koopatlas/core.cpp b/src/koopatlas/core.cpp
new file mode 100644
index 0000000..627f828
--- /dev/null
+++ b/src/koopatlas/core.cpp
@@ -0,0 +1,928 @@
+#include "koopatlas/core.h"
+#include "koopatlas/camera.h"
+#include "koopatlas/player.h"
+#include "koopatlas/hud.h"
+
+extern "C" void LoadMapScene();
+
+dScKoopatlas_c *dScKoopatlas_c::instance = 0;
+
+CREATE_STATE_E(dScKoopatlas_c, Limbo);
+CREATE_STATE_E(dScKoopatlas_c, ContinueWait);
+CREATE_STATE_E(dScKoopatlas_c, Normal);
+CREATE_STATE_E(dScKoopatlas_c, CSMenu);
+CREATE_STATE_E(dScKoopatlas_c, TitleConfirmOpenWait);
+CREATE_STATE_E(dScKoopatlas_c, TitleConfirmSelect);
+CREATE_STATE_E(dScKoopatlas_c, TitleConfirmHitWait);
+CREATE_STATE_E(dScKoopatlas_c, PlayerChangeWait);
+CREATE_STATE_E(dScKoopatlas_c, EasyPairingWait);
+CREATE_STATE_E(dScKoopatlas_c, PowerupsWait);
+CREATE_STATE_E(dScKoopatlas_c, SaveOpen);
+CREATE_STATE_E(dScKoopatlas_c, SaveSelect);
+CREATE_STATE_E(dScKoopatlas_c, SaveWindowClose);
+CREATE_STATE_E(dScKoopatlas_c, SaveDo);
+CREATE_STATE_E(dScKoopatlas_c, SaveEndWindow);
+CREATE_STATE_E(dScKoopatlas_c, SaveEndCloseWait);
+CREATE_STATE_E(dScKoopatlas_c, QuickSaveOpen);
+CREATE_STATE_E(dScKoopatlas_c, QuickSaveSelect);
+CREATE_STATE_E(dScKoopatlas_c, QuickSaveWindowClose);
+CREATE_STATE_E(dScKoopatlas_c, QuickSaveDo);
+CREATE_STATE_E(dScKoopatlas_c, QuickSaveEndWindow);
+CREATE_STATE_E(dScKoopatlas_c, QuickSaveEndCloseWait);
+CREATE_STATE_E(dScKoopatlas_c, SaveError);
+
+dScKoopatlas_c *dScKoopatlas_c::build() {
+ // return new dScKoopatlas_c;
+ MapReport("Creating WorldMap\n");
+
+ void *buffer = AllocFromGameHeap1(sizeof(dScKoopatlas_c));
+ dScKoopatlas_c *c = new(buffer) dScKoopatlas_c;
+
+ MapReport("Created WorldMap @ %p\n", c);
+
+ instance = c;
+ return c;
+}
+
+bool WMInit_StartLoading(void*);
+bool WMInit_LoadSIAnims(void*);
+bool WMInit_EndLoading(void*);
+bool WMInit_LoadResources(void*);
+bool WMInit_SetupWait(void*);
+bool WMInit_SetupExtra(void*);
+bool WMInit_SetupWipe(void*);
+
+ChainedFunc initFunctions[] = {
+ WMInit_StartLoading,
+ WMInit_LoadSIAnims,
+ WMInit_EndLoading,
+ WMInit_LoadResources,
+ WMInit_SetupWait,
+ WMInit_SetupExtra,
+ WMInit_SetupWipe
+};
+
+dScKoopatlas_c::dScKoopatlas_c() : state(this) {
+ initChain.setup(initFunctions, 7);
+
+ setInitChain(initChain);
+}
+
+
+
+#define SELC_SETUP_DONE(sc) (*((bool*)(((u32)(sc))+0xD38)))
+
+#define EASYP_SETUP_DONE(ep) (*((bool*)(((u32)(ep))+0x278)))
+#define EASYP_ACTIVE(ep) (*((bool*)(((u32)(ep))+0x279)))
+
+#define CSMENU_SETUP_DONE(csm) (*((bool*)(((u32)(csm))+0x270)))
+#define CSMENU_ACTIVE(csm) (*((bool*)(((u32)(csm))+0x271)))
+#define CSMENU_CHOICE_OK(csm) (*((bool*)(((u32)(csm))+0x272)))
+#define CSMENU_UNK(csm) (*((bool*)(((u32)(csm))+0x273)))
+#define CSMENU_CURRENT(csm) (*((int*)(((u32)(csm))+0x268)))
+
+#define YESNO_SETUP_DONE(ynw) (*((bool*)(((u32)(ynw))+0x294)))
+#define YESNO_VISIBLE(ynw) (*((bool*)(((u32)(ynw))+0x295)))
+#define YESNO_CLOSE(ynw) (*((bool*)(((u32)(ynw))+0x296)))
+#define YESNO_OPENING(ynw) (*((bool*)(((u32)(ynw))+0x297)))
+#define YESNO_REFUSED(ynw) (*((bool*)(((u32)(ynw))+0x298)))
+#define YESNO_CANCELLED(ynw) (*((bool*)(((u32)(ynw))+0x299)))
+#define YESNO_CANCELLED2(ynw) (*((bool*)(((u32)(ynw))+0x29A)))
+#define YESNO_CURRENT(ynw) (*((int*)(((u32)(ynw))+0x284)))
+#define YESNO_TYPE(ynw) (*((int*)(((u32)(ynw))+0x28C)))
+
+#define NPCHG_SETUP_DONE(npc) (*((bool*)(((u32)(npc))+0x67C)))
+#define NPCHG_ACTIVE(npc) (*((bool*)(((u32)(npc))+0x67E)))
+#define NPCHG_HIDE_FOR_EASYP(npc) (*((bool*)(((u32)(npc))+0x67F)))
+#define NPCHG_READY(npc) (*((bool*)(((u32)(npc))+0x680)))
+#define NPCHG_CCSB(npc,idx) (((void**)(((u32)(npc))+0x74))[(idx)])
+#define NPCHG_CCSC(npc,idx) (((void**)(((u32)(npc))+0x84))[(idx)])
+#define NPCHG_CCSA(npc,idx) (((void**)(((u32)(npc))+0x94))[(idx)])
+#define NPCHG_CCI(npc,idx) (((void**)(((u32)(npc))+0xA4))[(idx)])
+#define NPCHG_2DPLAYER(npc,idx) (((void**)(((u32)(npc))+0x64C))[(idx)])
+
+#define STKI_SETUP_DONE(si) (*((bool*)(((u32)(si))+0x310)))
+#define STKI_SHADOW(si) (*((void**)(((u32)(si))+0x310)))
+#define STKI_2DPLAYER(si,idx) (((void**)(((u32)(si))+0x2E4))[(idx)])
+#define STKI_ITEM(si,idx) (((void**)(((u32)(si))+0x2F4))[(idx)])
+#define STKI_SHOW(si) (*((bool*)(((u32)(si))+0x8DD)))
+
+#define SIS_SETUP_DONE(sis) (*((bool*)(((u32)(sis))+0x260)))
+
+#define CCSB_ACTIVE(ccsb) (*((bool*)(((u32)(ccsb))+0x29C)))
+
+#define CCSC_ACTIVE(ccsc) (*((bool*)(((u32)(ccsc))+0x2A1)))
+
+#define PLAYER2D_SHOW_EASY_PAIRING(p2d) (*((bool*)(((u32)(p2d))+0x264)))
+
+#define CONT_LIVES(cont,idx) (((int*)(((u32)(cont))+0x2B8))[(idx)])
+#define CONT_SETUP_DONE(cont) (*((bool*)(((u32)(cont))+0x2D4)))
+#define CONT_UNK1(cont) (*((bool*)(((u32)(cont))+0x2D5)))
+#define CONT_UNK2(cont) (*((bool*)(((u32)(cont))+0x2D6)))
+#define CONT_DONE(cont) (*((bool*)(((u32)(cont))+0x2D7)))
+#define CONT_UNK3(cont) (*((bool*)(((u32)(cont))+0x2E0)))
+
+bool WMInit_StartLoading(void *ptr) {
+ SpammyReport("WMInit_StartLoading called\n");
+
+ DVD_Start();
+ return true;
+}
+
+bool WMInit_LoadSIAnims(void *ptr) {
+ SpammyReport("WMInit_LoadSIAnims called\n");
+
+ DVD_LoadFile(GetDVDClass(), "WorldMap", "SI_kinoko", 0);
+ DVD_LoadFile(GetDVDClass(), "WorldMap", "SI_fireflower", 0);
+ DVD_LoadFile(GetDVDClass(), "WorldMap", "SI_iceflower", 0);
+ DVD_LoadFile(GetDVDClass(), "WorldMap", "SI_penguin", 0);
+ DVD_LoadFile(GetDVDClass(), "WorldMap", "SI_propeller", 0);
+ DVD_LoadFile(GetDVDClass(), "WorldMap", "SI_star", 0);
+ return true;
+}
+
+bool WMInit_EndLoading(void *ptr) {
+ SpammyReport("WMInit_EndLoading called\n");
+
+ if (DVD_StillLoading(GetDVDClass2())) {
+ SpammyReport("WMInit_EndLoading returning false\n");
+ return false;
+ }
+
+ DVD_End();
+ SpammyReport("WMInit_EndLoading returning true\n");
+ return true;
+}
+
+bool WMInit_LoadResources(void *ptr) {
+ SpammyReport("WMInit_LoadResources returning true\n");
+
+ dScKoopatlas_c *wm = (dScKoopatlas_c*)ptr;
+ return wm->mapData.load("/Maps/yat.kpbin");
+ //TODO
+ //return wm->resMng.loadSet("MMFullWorld");
+ //return true;
+}
+
+bool WMInit_SetupWait(void *ptr) {
+ SpammyReport("WMInit_SetupWait called\n");
+
+ dScKoopatlas_c *wm = (dScKoopatlas_c*)ptr;
+
+ bool success = true;
+
+ success &= CSMENU_SETUP_DONE(wm->csMenu);
+ success &= SELC_SETUP_DONE(wm->selectCursor);
+ success &= NPCHG_SETUP_DONE(wm->numPeopleChange);
+ success &= YESNO_SETUP_DONE(wm->yesNoWindow);
+ success &= CONT_SETUP_DONE(wm->continueObj);
+ success &= STKI_SETUP_DONE(wm->stockItem);
+ success &= SIS_SETUP_DONE(wm->stockItemShadow);
+ success &= EASYP_SETUP_DONE(wm->easyPairing);
+
+ return success;
+}
+
+bool WMInit_SetupExtra(void *ptr) {
+ SpammyReport("WMInit_SetupExtra called\n");
+
+ // ok, now we can set up other required shit
+ dScKoopatlas_c *wm = (dScKoopatlas_c*)ptr;
+
+ // first up: player models for Stocked Items
+ for (int i = 0; i < 4; i++) {
+ void *obj = CreateChildObject(WM_2D_PLAYER, wm, i, 0, 0);
+ STKI_2DPLAYER(wm->stockItem,i) = obj;
+ NPCHG_2DPLAYER(wm->numPeopleChange,i) = obj;
+ }
+
+ // next: items for the Powerup screen
+ for (int i = 0; i < 7; i++) {
+ void *obj = CreateChildObject(WM_ITEM, wm, i, 0, 0);
+ STKI_ITEM(wm->stockItem,i) = obj;
+ }
+
+ // since we've got all the resources, set up the path data too
+ //wm->pathManager->setup();
+ //wm->pathManager->computeEvents();
+
+ // and now Player setup
+ wm->player = (daWMPlayer_c*)CreateParentedObject(WM_PLAYER, wm, 0, 2);
+ wm->player->modelHandler->mdlClass->setPowerup(2);
+ wm->player->modelHandler->mdlClass->startAnimation(0, 1.2f, 10.0f, 0.0f);
+ //wm->player->pos = wm->pathManager->currentPoint->position;
+
+ // is last param correct? must check :/
+ wm->map = (dWMMap_c*)CreateParentedObject(WM_MAP, wm, 0, 0);
+ wm->hud = (dWMHud_c*)CreateParentedObject(WM_HUD, wm, 0, 0);
+ // note: world_camera and wm_path_manager are not created here
+ // because we require them earlier
+ // they are created in dScKoopatlas_c::onCreate
+
+ return true;
+}
+
+bool WMInit_SetupWipe(void *ptr) {
+ SpammyReport("WMInit_SetupWipe called\n");
+
+ dScKoopatlas_c *wm = (dScKoopatlas_c*)ptr;
+
+ if (wm->hasUninitialisedProcesses()) {
+ SpammyReport("WMInit_SetupWipe returning false\n");
+ return false;
+ }
+
+ SpammyReport("WMInit_SetupWipe returning true\n");
+ return true;
+}
+
+
+
+
+
+/*void dScKoopatlas_c::startLevel(LevelInfo::Entry *entry) {
+ for (int i = 0; i < 4; i++) {
+ bool isThere = QueryPlayerAvailability(i);
+ int id = Player_ID[i];
+ Player_Active[i] = isThere ? 1 : 0;
+ if (!isThere) Player_Flags[i] = 0;
+ }
+
+ StartLevelInfo sl;
+ sl.unk1 = 0;
+ sl.unk2 = 0xFF;
+ sl.unk3 = 0;
+ sl.unk4 = 0;
+ sl.purpose = 0;
+
+ sl.world1 = entry->world;
+ sl.world2 = entry->world;
+ sl.level1 = entry->level;
+ sl.level2 = entry->level;
+
+// hopefully this will fix the Star Coin issues
+SetSomeConditionShit(entry->world, entry->level, 2);
+
+ActivateWipe(WIPE_MARIO);
+
+DoStartLevel(GetGameMgr(), &sl);
+}*/
+
+
+int dScKoopatlas_c::onCreate() {
+ SpammyReport("onCreate() called\n");
+
+ SpammyReport("LoadMapScene()\n");
+ LoadMapScene();
+
+ SpammyReport("GameSetup__LoadScene(0)\n");
+ GameSetup__LoadScene(0); // lol, stolen from GAME_SETUP
+
+
+ SpammyReport("select cursor\n");
+ this->selectCursor = CreateParentedObject(SELECT_CURSOR, this, 0, 0);
+
+ SpammyReport("cs menu\n");
+ this->csMenu = CreateParentedObject(COURSE_SELECT_MENU, this, 0, 0);
+
+ SpammyReport("yes no window\n");
+ this->yesNoWindow = CreateParentedObject(YES_NO_WINDOW, this, 0, 0);
+
+ SpammyReport("number of people change\n");
+ this->numPeopleChange = CreateParentedObject(NUMBER_OF_PEOPLE_CHANGE, this, 0, 0);
+
+ for (int i = 0; i < 4; i++) {
+ SpammyReport("ccsb %d\n", i);
+ void *ccsb = CreateParentedObject(CHARACTER_CHANGE_SELECT_BASE, this, i, 0);
+ SpammyReport("ccsc %d\n", i);
+ void *ccsc = CreateParentedObject(CHARACTER_CHANGE_SELECT_CONTENTS, this, i, 0);
+ SpammyReport("ccsa %d\n", i);
+ void *ccsa = CreateParentedObject(CHARACTER_CHANGE_SELECT_ARROW, this, i, 0);
+ SpammyReport("ccsi %d\n", i);
+ void *cci = CreateParentedObject(CHARACTER_CHANGE_INDICATOR, this, i, 0);
+
+ NPCHG_CCSB(this->numPeopleChange, i) = ccsb;
+ NPCHG_CCSC(this->numPeopleChange, i) = ccsc;
+ NPCHG_CCSA(this->numPeopleChange, i) = ccsa;
+ NPCHG_CCI(this->numPeopleChange, i) = cci;
+ }
+
+ SpammyReport("continue\n");
+ this->continueObj = CreateParentedObject(CONTINUE, this, 0, 0);
+
+ // check if we need to handle Continue
+ if (CheckIfContinueShouldBeActivated()) {
+ SpammyReport("continue is activated\n");
+ state.setState(&StateID_ContinueWait);
+ CONT_UNK1(this->continueObj) = true;
+ CONT_UNK2(this->continueObj) = true;
+ CONT_UNK3(this->continueObj) = false;
+ } else {
+ SpammyReport("continue is not activated\n");
+ state.setState(&StateID_Normal);
+ }
+
+ SpammyReport("stock item\n");
+ this->stockItem = CreateParentedObject(STOCK_ITEM, this, 0, 0);
+ SpammyReport("stock item shadow\n");
+ this->stockItemShadow = CreateParentedObject(STOCK_ITEM_SHADOW, this, 0, 0);
+ STKI_SHADOW(this->stockItem) = this->stockItemShadow;
+
+ SpammyReport("easy pairing\n");
+ this->easyPairing = CreateParentedObject(EASY_PAIRING, this, 0, 0);
+
+ SpammyReport("world camera\n");
+ CreateParentedObject(WORLD_CAMERA, this, 0, 0);
+
+ /*pathManager = (dWMPathManager_c*)CreateParentedObject(WM_PATH_MANAGER, this, 0, 0);*/
+
+ SpammyReport("setting NewerMapDrawFunc\n");
+ *CurrentDrawFunc = NewerMapDrawFunc;
+
+ // level info
+ /*SpammyReport("loading level info file\n");
+ levelInfoFile.open("/NewerRes/LevelInfo.bin");
+ SpammyReport("preparing level info\n");
+ levelInfo.load(levelInfoFile.ptr());*/
+
+ SpammyReport("onCreate() completed\n");
+ return true;
+}
+
+int dScKoopatlas_c::onDelete() {
+ FreeScene(0);
+ FreeScene(1);
+
+ DVD_FreeFile(GetDVDClass2(), "SI_kinoko");
+ DVD_FreeFile(GetDVDClass2(), "SI_fireflower");
+ DVD_FreeFile(GetDVDClass2(), "SI_iceflower");
+ DVD_FreeFile(GetDVDClass2(), "SI_penguin");
+ DVD_FreeFile(GetDVDClass2(), "SI_propeller");
+ DVD_FreeFile(GetDVDClass2(), "SI_star");
+
+ return true;
+}
+
+bool dScKoopatlas_c::canDoStuff() {
+ if (QueryGlobal5758(0xFFFFFFFF)) return false;
+ if (CheckIfWeCantDoStuff()) return false;
+ if (state.getCurrentState() == &StateID_Limbo) return false;
+ return true;
+}
+
+
+int dScKoopatlas_c::onExecute() {
+ if (!canDoStuff()) return true;
+
+ SpammyReport("Executing state: %s\n", state.getCurrentState()->getName());
+ state.execute();
+
+ return true;
+}
+
+
+void dScKoopatlas_c::executeState_Limbo() { }
+
+
+void dScKoopatlas_c::executeState_ContinueWait() {
+ // Waiting for the Continue anim to finish
+ if (CONT_DONE(this->continueObj)) {
+ CONT_UNK1(this->continueObj) = 0;
+ CONT_UNK2(this->continueObj) = 0;
+ CONT_UNK3(this->continueObj) = 0;
+
+ for (int i = 0; i < 4; i++) {
+ int idx = SearchForIndexOfPlayerID(i);
+ Player_Lives[Player_ID[idx]] = CONT_LIVES(this->continueObj, i);
+ }
+
+ state.setState(&StateID_Normal);
+ }
+}
+
+void dScKoopatlas_c::executeState_Normal() {
+ int nowPressed = Remocon_GetPressed(GetActiveRemocon());
+
+ // Nothing related to the menu is going on
+ if (nowPressed & WPAD_ONE) {
+ STKI_SHOW(this->stockItem) = true;
+ state.setState(&StateID_PowerupsWait);
+ } else if (nowPressed & WPAD_PLUS) {
+ CSMENU_ACTIVE(this->csMenu) = true;
+ state.setState(&StateID_CSMenu);
+ }
+}
+
+void dScKoopatlas_c::executeState_CSMenu() {
+ // The course select menu is currently being shown
+
+ // First off, check to see if it's been hidden
+ if (!CSMENU_ACTIVE(this->csMenu)) {
+ // That means something happened
+ if (CSMENU_CHOICE_OK(this->csMenu)) {
+ // Player pressed a button
+
+ switch (CSMENU_CURRENT(this->csMenu)) {
+ case 0:
+ // Star Coins
+ MapReport("Star Coins was pressed\n");
+ state.setState(&StateID_Normal);
+ break;
+
+ case 1:
+ // Add/Drop Players
+ MapReport("Add/Drop Players was pressed\n");
+ state.setState(&StateID_PlayerChangeWait);
+ NPCHG_ACTIVE(this->numPeopleChange) = true;
+ WpadShit(10);
+
+ break;
+
+ case 2:
+ // Save or Quick Save
+ MapReport("Save or Quick Save was pressed\n");
+ if (GetSaveFile()->GetBlock(-1)->bitfield & 2) {
+ state.setState(&StateID_SaveOpen);
+ YESNO_TYPE(this->yesNoWindow) = 1;
+ YESNO_VISIBLE(this->yesNoWindow) = 1;
+
+ } else {
+ state.setState(&StateID_QuickSaveOpen);
+ YESNO_TYPE(this->yesNoWindow) = 15;
+ YESNO_VISIBLE(this->yesNoWindow) = 1;
+
+ }
+
+ break;
+
+ case 3:
+ // Title Screen
+ MapReport("Title Screen was pressed\n");
+ state.setState(&StateID_TitleConfirmOpenWait);
+ YESNO_VISIBLE(this->yesNoWindow) = true;
+ YESNO_TYPE(this->yesNoWindow) = 10;
+ break;
+ }
+
+ } else {
+ // Ok, change back to STATE_Normal
+ state.setState(&StateID_Normal);
+ }
+ }
+}
+
+void dScKoopatlas_c::executeState_TitleConfirmOpenWait() {
+ // Waiting for the "Go to Title Screen" YesNoWindow to finish opening
+
+ if (!YESNO_OPENING(this->yesNoWindow)) {
+ state.setState(&StateID_TitleConfirmSelect);
+ }
+
+}
+
+/**********************************************************************/
+// STATE_TitleConfirmSelect : Let the user choose an option on the
+// "Go to Title Screen" YesNoWindow.
+void dScKoopatlas_c::executeState_TitleConfirmSelect() {
+ int nowPressed = Remocon_GetPressed(GetActiveRemocon());
+
+ if (nowPressed & WPAD_LEFT) {
+ // Select "OK!"
+ YESNO_CURRENT(this->yesNoWindow) = 1;
+
+ } else if (nowPressed & WPAD_RIGHT) {
+ // Select "Cancel"
+ YESNO_CURRENT(this->yesNoWindow) = 0;
+
+ } else if (Wiimote_TestButtons(GetActiveWiimote(), WPAD_A | WPAD_TWO)) {
+ // Pick the current option
+ YESNO_CLOSE(this->yesNoWindow) = true;
+ if (YESNO_CURRENT(this->yesNoWindow) != 1)
+ YESNO_REFUSED(this->yesNoWindow) = true;
+ state.setState(&StateID_TitleConfirmHitWait);
+
+ } else {
+ // Cancel using B or 1
+ if (CheckIfMenuShouldBeCancelledForSpecifiedWiimote(0)) {
+ YESNO_CANCELLED(this->yesNoWindow) = true;
+ YESNO_CURRENT(this->yesNoWindow) = true;
+ state.setState(&StateID_TitleConfirmHitWait);
+ }
+ }
+
+}
+
+/**********************************************************************/
+// STATE_TitleConfirmHitWait : Process the user's chosen option on
+// the "Go to Title Screen" YesNoWindow. Also, wait for the
+// animation to be complete.
+void dScKoopatlas_c::executeState_TitleConfirmHitWait() {
+
+ if (!YESNO_OPENING(this->yesNoWindow)) {
+ if (YESNO_CURRENT(this->yesNoWindow) == 1) {
+ state.setState(&StateID_Normal);
+ } else {
+ state.setState(&StateID_Limbo);
+ StartTitleScreenStage(false, 0);
+ }
+ }
+
+}
+
+/**********************************************************************/
+// STATE_PlayerChangeWait : Wait for the user to do something on the
+// Add/Drop Players screen.
+void dScKoopatlas_c::executeState_PlayerChangeWait() {
+ int nowPressed = Remocon_GetPressed(GetActiveRemocon());
+
+ if (NPCHG_READY(this->numPeopleChange)) {
+ if (nowPressed & WPAD_PLUS) {
+ // activate easy pairing. FUN !!
+ NPCHG_HIDE_FOR_EASYP(this->numPeopleChange) = 1;
+
+ for (int i = 0; i < 4; i++) {
+ void *obj = NPCHG_2DPLAYER(this->numPeopleChange, i);
+ void *ccsb = NPCHG_CCSB(this->numPeopleChange, i);
+ void *ccsc = NPCHG_CCSC(this->numPeopleChange, i);
+
+ PLAYER2D_SHOW_EASY_PAIRING(obj) = 1;
+ CCSB_ACTIVE(ccsb) = 1;
+ CCSC_ACTIVE(ccsc) = 1;
+ }
+
+ EASYP_ACTIVE(this->easyPairing) = 1;
+ state.setState(&StateID_EasyPairingWait);
+ }
+ } else {
+ if (!NPCHG_ACTIVE(this->numPeopleChange)) {
+ state.setState(&StateID_Normal);
+ }
+ }
+
+}
+
+/**********************************************************************/
+// STATE_EasyPairingWait : Wait for the user to exit Easy Pairing.
+void dScKoopatlas_c::executeState_EasyPairingWait() {
+
+ if (!EASYP_ACTIVE(this->easyPairing)) {
+ NPCHG_HIDE_FOR_EASYP(this->numPeopleChange) = 0;
+
+ for (int i = 0; i < 4; i++) {
+ void *obj = NPCHG_2DPLAYER(this->numPeopleChange, i);
+ void *ccsb = NPCHG_CCSB(this->numPeopleChange, i);
+ void *ccsc = NPCHG_CCSC(this->numPeopleChange, i);
+
+ PLAYER2D_SHOW_EASY_PAIRING(obj) = 0;
+ CCSB_ACTIVE(ccsb) = 0;
+ CCSC_ACTIVE(ccsc) = 0;
+ }
+
+ state.setState(&StateID_PlayerChangeWait);
+ WpadShit(10);
+ }
+
+}
+
+/**********************************************************************/
+// STATE_PowerupsWait : Wait for the user to exit the Powerups screen.
+void dScKoopatlas_c::executeState_PowerupsWait() {
+
+ if (!STKI_SHOW(this->stockItem)) {
+ state.setState(&StateID_Normal);
+ }
+
+}
+
+/**********************************************************************/
+// STATE_SaveOpen : Waiting for the "Save?" YesNoWindow to open
+void dScKoopatlas_c::executeState_SaveOpen() {
+
+ if (!YESNO_OPENING(this->yesNoWindow)) {
+ state.setState(&StateID_SaveSelect);
+ }
+
+}
+
+/**********************************************************************/
+// STATE_SaveSelect : Let the user choose an option on the
+// "Save?" YesNoWindow.
+void dScKoopatlas_c::executeState_SaveSelect() {
+ int nowPressed = Remocon_GetPressed(GetActiveRemocon());
+
+ if (nowPressed & WPAD_LEFT) {
+ // Select "OK!"
+ YESNO_CURRENT(this->yesNoWindow) = 1;
+
+ } else if (nowPressed & WPAD_RIGHT) {
+ // Select "Cancel"
+ YESNO_CURRENT(this->yesNoWindow) = 0;
+
+ } else if (Wiimote_TestButtons(GetActiveWiimote(), WPAD_A | WPAD_TWO)) {
+ // Pick the current option
+ YESNO_CLOSE(this->yesNoWindow) = true;
+
+ if (YESNO_CURRENT(this->yesNoWindow) != 1)
+ YESNO_CANCELLED2(this->yesNoWindow) = true;
+ state.setState(&StateID_SaveWindowClose);
+
+ } else {
+ // Cancel using B or 1
+ if (CheckIfMenuShouldBeCancelledForSpecifiedWiimote(0)) {
+ YESNO_CANCELLED(this->yesNoWindow) = true;
+ YESNO_CURRENT(this->yesNoWindow) = 1;
+ state.setState(&StateID_SaveWindowClose);
+ }
+ }
+
+}
+
+/**********************************************************************/
+// STATE_SaveWindowClose : Process the user's chosen option on the
+// "Save?" YesNoWindow. Also, wait for the animation to be complete.
+void dScKoopatlas_c::executeState_SaveWindowClose() {
+
+ if (!YESNO_VISIBLE(this->yesNoWindow)) {
+ if (YESNO_CURRENT(this->yesNoWindow) == 1) {
+ state.setState(&StateID_Normal);
+ } else {
+ state.setState(&StateID_SaveDo);
+ SaveGame(0, false);
+ }
+ }
+
+}
+
+/**********************************************************************/
+// STATE_SaveDo : Save the game.
+void dScKoopatlas_c::executeState_SaveDo() {
+
+ if (!GetSaveFile()->CheckIfWriting()) {
+ if (GetSaveHandler()->CurrentError == 0) {
+ YESNO_TYPE(this->yesNoWindow) = 2;
+ YESNO_VISIBLE(this->yesNoWindow) = true;
+ state.setState(&StateID_SaveEndWindow);
+ } else {
+ state.setState(&StateID_SaveError);
+ }
+ }
+
+}
+
+/**********************************************************************/
+// STATE_SaveEndWindow : Handle the Save End window.
+void dScKoopatlas_c::executeState_SaveEndWindow() {
+
+ if (!YESNO_OPENING(this->yesNoWindow)) {
+ if (Wiimote_TestButtons(GetActiveWiimote(), WPAD_A | WPAD_TWO)) {
+ YESNO_CLOSE(this->yesNoWindow) = true;
+ state.setState(&StateID_SaveEndCloseWait);
+ }
+ }
+
+}
+
+/**********************************************************************/
+// STATE_SaveEndCloseWait : Wait for the Save End window to close.
+void dScKoopatlas_c::executeState_SaveEndCloseWait() {
+
+ if (!YESNO_OPENING(this->yesNoWindow)) {
+ state.setState(&StateID_Normal);
+ }
+
+}
+
+/**********************************************************************/
+// STATE_QuickSaveOpen : Waiting for the "Save?" YesNoWindow to open
+void dScKoopatlas_c::executeState_QuickSaveOpen() {
+
+ if (!YESNO_OPENING(this->yesNoWindow)) {
+ state.setState(&StateID_QuickSaveSelect);
+ }
+
+}
+
+/**********************************************************************/
+// STATE_QuickSaveSelect : Let the user choose an option on the
+// "Save?" YesNoWindow.
+void dScKoopatlas_c::executeState_QuickSaveSelect() {
+ int nowPressed = Remocon_GetPressed(GetActiveRemocon());
+
+ if (nowPressed & WPAD_LEFT) {
+ // Select "OK!"
+ YESNO_CURRENT(this->yesNoWindow) = 1;
+
+ } else if (nowPressed & WPAD_RIGHT) {
+ // Select "Cancel"
+ YESNO_CURRENT(this->yesNoWindow) = 0;
+
+ } else if (Wiimote_TestButtons(GetActiveWiimote(), WPAD_A | WPAD_TWO)) {
+ // Pick the current option
+ YESNO_CLOSE(this->yesNoWindow) = true;
+
+ if (YESNO_CURRENT(this->yesNoWindow) != 1)
+ YESNO_CANCELLED2(this->yesNoWindow) = true;
+ state.setState(&StateID_QuickSaveWindowClose);
+
+ } else {
+ // Cancel using B or 1
+ if (CheckIfMenuShouldBeCancelledForSpecifiedWiimote(0)) {
+ YESNO_CANCELLED(this->yesNoWindow) = true;
+ YESNO_CURRENT(this->yesNoWindow) = 1;
+ state.setState(&StateID_QuickSaveWindowClose);
+ }
+ }
+
+}
+
+/**********************************************************************/
+// STATE_QuickSaveWindowClose : Process the user's chosen option on
+// the "Save?" YesNoWindow. Also, wait for the animation to be complete
+void dScKoopatlas_c::executeState_QuickSaveWindowClose() {
+
+ if (!YESNO_VISIBLE(this->yesNoWindow)) {
+ if (YESNO_CURRENT(this->yesNoWindow) == 1) {
+ state.setState(&StateID_Normal);
+ } else {
+ state.setState(&StateID_QuickSaveDo);
+ SaveGame(0, true);
+ }
+ }
+
+}
+
+/**********************************************************************/
+// STATE_QuickSaveDo : Save the game.
+void dScKoopatlas_c::executeState_QuickSaveDo() {
+
+ if (!GetSaveFile()->CheckIfWriting()) {
+ if (GetSaveHandler()->CurrentError == 0) {
+ YESNO_TYPE(this->yesNoWindow) = 16;
+ YESNO_VISIBLE(this->yesNoWindow) = true;
+ state.setState(&StateID_QuickSaveEndWindow);
+ } else {
+ state.setState(&StateID_SaveError);
+ }
+ }
+
+}
+
+// STATE_QuickSaveEndWindow : Handle the Save End window.
+void dScKoopatlas_c::executeState_QuickSaveEndWindow() {
+
+ if (!YESNO_OPENING(this->yesNoWindow)) {
+ if (Wiimote_TestButtons(GetActiveWiimote(), WPAD_A | WPAD_TWO)) {
+ YESNO_CLOSE(this->yesNoWindow) = true;
+ YESNO_REFUSED(this->yesNoWindow) = true;
+ state.setState(&StateID_QuickSaveEndCloseWait);
+ }
+ }
+
+}
+
+void dScKoopatlas_c::executeState_QuickSaveEndCloseWait() {
+ // Wait for Save End window to close
+
+ if (!YESNO_OPENING(this->yesNoWindow)) {
+ if (YESNO_CURRENT(this->yesNoWindow) == 1) {
+ state.setState(&StateID_Normal);
+ } else {
+ state.setState(&StateID_Limbo);
+ StartTitleScreenStage(false, 0);
+ }
+ }
+
+}
+
+
+void dScKoopatlas_c::executeState_SaveError() { }
+
+
+/*
+// MODELLED ON STAGE
+void NewerMapDrawFunc() {
+ DoSomethingCameraRelatedWithEGGScreen(0, &dWorldCamera_c::instance->screen);
+ LinkScene(0);
+ ChangeAlphaUpdate(false);
+ SceneCalcWorld(0);
+ SceneCameraStuff(0);
+ DrawOpa();
+ DrawXlu();
+ // Something
+ nw4r::g3d::Camera camera(GetCameraByID(0));
+ camera.GXSetViewport();
+ camera.GXSetScissor();
+ RenderEffects(0, 6);
+ SetupLYTDrawing();
+ DrawAllLayoutsBeforeX(0x81);
+ RenderEffects(0, 3);
+ RenderEffects(0, 2);
+ DrawAllLayoutsAfterX(0x80);
+ ClearLayoutDrawList();
+ UnlinkScene(0);
+}*/
+
+
+void NewerMapDrawFunc() {
+ Reset3DState();
+ SetCurrentCameraID(0);
+ DoSomethingCameraRelatedWithEGGScreen(0, &dWorldCamera_c::instance->screen);
+ LinkScene(0);
+ SceneCalcWorld(0);
+ SceneCameraStuff(0);
+ ChangeAlphaUpdate(false);
+ DrawOpa();
+ DrawXlu();
+ UnlinkScene(0);
+ // Something
+ SetupLYTDrawing();
+ DrawAllLayoutsBeforeX(0x81);
+ RenderEffects(0, 3);
+ RenderEffects(0, 2);
+ GXDrawDone();
+ RemoveAllFromScnRoot();
+ Reset3DState();
+ SetCurrentCameraID(1);
+ DoSpecialDrawing1();
+ LinkScene(1);
+ SceneCalcWorld(1);
+ SceneCameraStuff(1);
+ CalcMaterial();
+ DrawOpa();
+ DrawXlu();
+ UnlinkScene(1);
+ GXDrawDone();
+ // Leaving out some stuff here
+ DrawAllLayoutsAfterX(0x80);
+ ClearLayoutDrawList();
+ SetCurrentCameraID(0);
+}
+
+
+/*void NewerMapDrawFunc() {
+ int keepCamera = GetCurrentCameraID();
+
+ // All drawing uses scene 1, since that's the only one loaded by GAME_SETUP.
+ // Todo: Newer-specific scenes?
+
+ // Stage 1
+
+ // Stage 2
+ Reset3DState();
+ SetCurrentCameraID(0);
+ LinkScene(0);
+ SceneCalcWorld(0);
+ SceneCameraStuff(0);
+ ChangeAlphaUpdate(false);
+ CalcMaterial();
+ DrawOpa();
+ DrawXlu();
+ UnlinkScene(0);
+ GXDrawDone();
+
+ //Reset3DState();
+ //T3D::DrawQueue();
+
+ // Stage 3
+ Reset3DState();
+ SetupLYTDrawing();
+ DrawAllLayoutsBeforeX(146);
+ //DrawAllLayoutsBeforeX(129);
+ //DrawAllLayoutsAfterXandBeforeY(128, 146);
+ GXDrawDone();
+
+ // Stage 4
+ RemoveAllFromScnRoot();
+ Reset3DState();
+ SetCurrentCameraID(1);
+ DoSpecialDrawing1();
+ LinkScene(1);
+ SceneCalcWorld(1);
+ SceneCameraStuff(1);
+ CalcMaterial();
+ DrawOpa();
+ DrawXlu();
+
+ // Stage 5
+ if (GAMEMGR_GET_AFC(GameMgr)) {
+ for (int i = 0; i < 4; i++) {
+ RenderEffects(0, 11+i);
+ }
+
+ for (int i = 0; i < 4; i++) {
+ RenderEffects(0, 7+i);
+ }
+ }
+
+ RenderEffects(0, 2); // need to investigate how this thing works
+
+ DrawAllLayoutsAfterX(145);
+ ClearLayoutDrawList(); // this is REALLY IMPORTANT!
+
+ UnlinkScene(1);
+
+ // End
+ SetCurrentCameraID(0);
+}
+
+*/
diff --git a/src/koopatlas/core.h b/src/koopatlas/core.h
new file mode 100644
index 0000000..cfe5bde
--- /dev/null
+++ b/src/koopatlas/core.h
@@ -0,0 +1,99 @@
+/* KoopAtlas Map Engine
+ * Created by Treeki
+ */
+
+#ifndef __KOOPATLAS_H
+#define __KOOPATLAS_H
+
+#include <common.h>
+#include <game.h>
+#include <g3dhax.h>
+
+#include "koopatlas/mapdata.h"
+
+#define WM_DEBUGGING
+//#define WM_SPAMMY_DEBUGGING
+
+#ifdef WM_DEBUGGING
+#define MapReport OSReport
+#else
+inline void MapReport(const char *str, ...) { }
+#endif
+
+#ifdef WM_SPAMMY_DEBUGGING
+#define SpammyReport OSReport
+#else
+inline void SpammyReport(const char *str, ...) { }
+#endif
+
+void NewerMapDrawFunc();
+
+#define WM_HUD WM_ANTLION
+
+class daWMPlayer_c;
+class dWMHud_c;
+class dWMMap_c;
+class dWorldCamera_c;
+
+class dScKoopatlas_c : public dScene_c {
+ public:
+ dScKoopatlas_c();
+
+ FunctionChain initChain;
+
+ dStateWrapper_c<dScKoopatlas_c> state;
+
+ USING_STATES(dScKoopatlas_c);
+ DECLARE_STATE(Limbo);
+ DECLARE_STATE(ContinueWait);
+ DECLARE_STATE(Normal);
+ DECLARE_STATE(CSMenu);
+ DECLARE_STATE(TitleConfirmOpenWait);
+ DECLARE_STATE(TitleConfirmSelect);
+ DECLARE_STATE(TitleConfirmHitWait);
+ DECLARE_STATE(PlayerChangeWait);
+ DECLARE_STATE(EasyPairingWait);
+ DECLARE_STATE(PowerupsWait);
+ DECLARE_STATE(SaveOpen);
+ DECLARE_STATE(SaveSelect);
+ DECLARE_STATE(SaveWindowClose);
+ DECLARE_STATE(SaveDo);
+ DECLARE_STATE(SaveEndWindow);
+ DECLARE_STATE(SaveEndCloseWait);
+ DECLARE_STATE(QuickSaveOpen);
+ DECLARE_STATE(QuickSaveSelect);
+ DECLARE_STATE(QuickSaveWindowClose);
+ DECLARE_STATE(QuickSaveDo);
+ DECLARE_STATE(QuickSaveEndWindow);
+ DECLARE_STATE(QuickSaveEndCloseWait);
+ DECLARE_STATE(SaveError);
+
+ void *csMenu;
+ void *selectCursor;
+ void *numPeopleChange;
+ void *yesNoWindow;
+ void *continueObj;
+ void *stockItem;
+ void *stockItemShadow;
+ void *easyPairing;
+
+
+ int onCreate();
+ int onDelete();
+ int onExecute();
+
+ static dScKoopatlas_c *build();
+ static dScKoopatlas_c *instance;
+
+
+ daWMPlayer_c *player;
+ dWMHud_c *hud;
+ dWMMap_c *map;
+ dKPMapData_c mapData;
+
+
+ bool canDoStuff();
+};
+
+#endif
+
diff --git a/src/koopatlas/hud.cpp b/src/koopatlas/hud.cpp
new file mode 100644
index 0000000..c5b2c6e
--- /dev/null
+++ b/src/koopatlas/hud.cpp
@@ -0,0 +1,168 @@
+#include "koopatlas/hud.h"
+
+dWMHud_c *dWMHud_c::instance = 0;
+
+dWMHud_c *dWMHud_c::build() {
+ OSReport("Creating WM_Hud\n");
+
+ void *buffer = AllocFromGameHeap1(sizeof(dWMHud_c));
+ dWMHud_c *c = new(buffer) dWMHud_c;
+
+ OSReport("Created WM_Hud @ %p\n", c);
+
+ instance = c;
+ return c;
+}
+
+
+
+dWMHud_c::dWMHud_c() {
+ layoutLoaded = false;
+}
+
+
+// TODO: Need to define these in a better way, somehow
+#define ANIM_BUTTON_1 0
+#define ANIM_BUTTON_2 1
+#define ANIM_BOTTOM_SHOW 2
+#define ANIM_BOTTOM_HIDE 3
+#define ANIM_TOP_SHOW 4
+#define ANIM_TOP_HIDE 5
+
+int dWMHud_c::onCreate() {
+ if (!layoutLoaded) {
+ bool gotFile = layout.loadArc("maphud.arc", false);
+ if (!gotFile)
+ return false;
+
+ //static const char *brlanNames[3] = {"maphud_hitbutton.brlan", "maphud_in.brlan", "maphud_out.brlan"};
+ static const char *brlanNames[5] = {"maphud_hitbutton.brlan", "bottom_in.brlan", "bottom_out.brlan", "top_in.brlan", "top_out.brlan"};
+ static const char *groupNames[6] = {"B01_Button", "B02_Button", "A00_Window", "A00_Window", "A01_Window", "A01_Window"};
+
+ bool output = layout.build("maphud.brlyt");
+
+ if (!IsWideScreen()) {
+ layout.clippingEnabled = true;
+ layout.clipX = 0;
+ layout.clipY = 52;
+ layout.clipWidth = 640;
+ layout.clipHeight = 352;
+ layout.layout.rootPane->scale.x = 0.7711f;
+ layout.layout.rootPane->scale.y = 0.7711f;
+ }
+
+ layout.loadAnimations(brlanNames, 5);
+ layout.loadGroups(groupNames, (int[6]){0, 0, 1, 2, 3, 4}, 6);
+ layout.disableAllAnimations();
+ layout.enableNonLoopAnim(ANIM_BOTTOM_SHOW);
+
+ showPointBar();
+
+ layoutLoaded = true;
+ }
+
+ return true;
+}
+
+
+int dWMHud_c::onDelete() {
+ return layout.free();
+}
+
+
+int dWMHud_c::onExecute() {
+ layout.execAnimations();
+ layout.update();
+
+ return true;
+}
+
+
+int dWMHud_c::onDraw() {
+ layout.scheduleForDrawing();
+
+ return true;
+}
+
+
+void dWMHud_c::updateText() {
+ setPointName();
+}
+
+
+void dWMHud_c::setPointName() {
+ wchar_t newPointName[120];
+ int length;
+
+ // figure this out...
+ /*WMPathPoint *point = dWMPathManager_c::instance->currentPoint;
+
+ if (point->type == WMPathPoint::LEVEL_TYPE) {
+ LevelInfo *li = &dScNewerWorldMap_c::instance->levelInfo;
+ LevelInfo::Entry *entry = li->search(point->params[0] - 1, point->params[1] - 1);
+
+ char *levelName = li->getNameForLevel(entry);
+
+ // copy it
+ // I need to make this into a function.
+ for (int i = 0; i < 120 && i < entry->nameLength; i++) {
+ newPointName[i] = levelName[i];
+ }
+ length = entry->nameLength;
+ newPointName[entry->nameLength] = 0;
+
+ } else {
+ newPointName[0] = 0;
+ length = 0;
+ }*/
+
+ const char *str = "This needs to be done\0";
+ length = 21;
+ for (int i = 0; i < length; i++)
+ newPointName[i] = str[i];
+ newPointName[length] = 0;
+
+ nw4r::lyt::TextBox *box = layout.findTextBoxByName("T_levelname_01");
+
+ nw4r::ut::TextWriter tw;
+ tw.font = box->font;
+ tw.SetFontSize(box->fontSizeX, box->fontSizeY);
+ tw.somethingRelatedToLineHeight = box->lineSpace;
+ tw.charSpace = box->charSpace;
+ if (box->tagProc != 0)
+ tw.tagProcessorMaybe = box->tagProc;
+
+ float width = tw.CalcStringWidth(newPointName, length);
+ SpammyReport("Text width: %f\n", width);
+
+ layout.findWindowByName("W_levelname")->size.x = width + 22;
+ layout.findPictureByName("P_topleftboxbg")->size.x = width;
+ layout.findPictureByName("P_topthinboxbg")->size.x = 597 - width;
+
+ box->SetString(newPointName);
+}
+
+
+void dWMHud_c::showPointBar() {
+ //WMPathPoint *point = dWMPathManager_c::instance->currentPoint;
+
+ if (true) {//point->type == WMPathPoint::LEVEL_TYPE) {
+ isPointBarShown = true;
+
+ updateText();
+
+ layout.enableNonLoopAnim(ANIM_TOP_SHOW);
+ }
+}
+
+
+void dWMHud_c::hidePointBar() {
+ if (isPointBarShown) {
+ isPointBarShown = false;
+
+ layout.enableNonLoopAnim(ANIM_TOP_HIDE);
+ }
+}
+
+
+
diff --git a/src/koopatlas/hud.h b/src/koopatlas/hud.h
new file mode 100644
index 0000000..71dacdd
--- /dev/null
+++ b/src/koopatlas/hud.h
@@ -0,0 +1,28 @@
+#include "koopatlas/core.h"
+
+class dWMHud_c : public dBase_c {
+ public:
+ dWMHud_c();
+
+ int onCreate();
+ int onDelete();
+ int onExecute();
+ int onDraw();
+
+ bool layoutLoaded;
+ m2d::EmbedLayout_c layout;
+
+ void updateText();
+
+ void showPointBar();
+ void hidePointBar();
+
+ void setPointName();
+
+ static dWMHud_c *build();
+ static dWMHud_c *instance;
+
+ private:
+ bool isPointBarShown;
+};
+
diff --git a/src/koopatlas/map.cpp b/src/koopatlas/map.cpp
new file mode 100644
index 0000000..ef63eb1
--- /dev/null
+++ b/src/koopatlas/map.cpp
@@ -0,0 +1,259 @@
+#include "koopatlas/map.h"
+#include "koopatlas/camera.h"
+
+//#define TILE_DEBUGGING
+//#define BOUND_DEBUGGING
+
+#ifdef TILE_DEBUGGING
+#define TileReport OSReport
+#else
+inline void TileReport(const char *str, ...) { }
+#endif
+
+#ifdef BOUND_DEBUGGING
+#define BoundReport OSReport
+#else
+inline void BoundReport(const char *str, ...) { }
+#endif
+
+dWMMap_c *dWMMap_c::instance = 0;
+
+dWMMap_c *dWMMap_c::build() {
+ OSReport("Creating WM_Map\n");
+
+ void *buffer = AllocFromGameHeap1(sizeof(dWMMap_c));
+ dWMMap_c *c = new(buffer) dWMMap_c;
+
+ OSReport("Created WM_Map @ %p\n", c);
+
+ instance = c;
+ return c;
+}
+
+
+
+dWMMap_c::dWMMap_c() {
+}
+
+
+int dWMMap_c::onCreate() {
+ renderer.allocator.setup(GameHeaps[0], 0x20);
+ OSReport("Setting up Renderer\n");
+ bool result = renderer.setup(&renderer.allocator);
+ if (result)
+ OSReport("Set up Renderer\n");
+ else
+ OSReport(":(\n");
+
+ return true;
+}
+
+int dWMMap_c::onDelete() { return true; }
+int dWMMap_c::onExecute() { return true; }
+
+int dWMMap_c::onDraw() {
+ renderer.scheduleForDrawing();
+
+ return true;
+}
+
+
+
+
+void dWMMap_c::renderer_c::drawOpa() {
+ //drawTiles();
+}
+
+void dWMMap_c::renderer_c::drawXlu() {
+ drawTiles();
+}
+
+
+
+void dWMMap_c::renderer_c::drawTiles() {
+ beginRendering();
+
+ dKPMapData_c *dataCls = &dScKoopatlas_c::instance->mapData;
+ dKPMapFile_s *data = dataCls->data;
+
+ baseZ = 1000 - (10 * data->layerCount);
+
+ for (int iLayer = data->layerCount - 1; iLayer >= 0; iLayer--) {
+ dKPLayer_s *layer = data->layers[iLayer];
+
+ TileReport("Checking layer %d with type %d\n", iLayer, layer->type);
+ if (layer->type == dKPLayer_s::OBJECTS)
+ renderTileLayer(layer, data->sectors);
+ }
+
+ endRendering();
+}
+
+void dWMMap_c::renderer_c::beginRendering() {
+ currentTexture = 0;
+
+ nw4r::g3d::Camera cam3d(GetCameraByID(0));
+ cam3d.GetCameraMtx(&renderMtx);
+ MTXTransApply(renderMtx, renderMtx, 0, 0, baseZ);
+ /*OSReport("MTX:\n");
+ OSReport("%f, %f, %f, %f:\n", renderMtx[0][0], renderMtx[0][1], renderMtx[0][2], renderMtx[0][3]);
+ OSReport("%f, %f, %f, %f:\n", renderMtx[1][0], renderMtx[1][1], renderMtx[1][2], renderMtx[1][3]);
+ OSReport("%f, %f, %f, %f:\n", renderMtx[2][0], renderMtx[2][1], renderMtx[2][2], renderMtx[2][3]);//*/
+
+ GXSetCurrentMtx(GX_PNMTX0);
+
+ dWorldCamera_c *camObj = dWorldCamera_c::instance;
+ minX = ((int)camObj->screenLeft) / 16;
+ minY = ((int)(-camObj->screenTop)) / 16;
+ maxX = (((int)(camObj->screenLeft + camObj->screenWidth)) + 15) / 16;
+ maxY = (((int)(-camObj->screenTop + camObj->screenHeight)) + 15) / 16;
+
+ GXClearVtxDesc();
+
+ GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
+ GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
+
+ GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XY, GX_S16, 0);
+ GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_U8, 8);
+
+ GXSetNumIndStages(0);
+ for (int i = 0; i < 0x10; i++)
+ GXSetTevDirect((GXTevStageID)i);
+
+ GXSetNumChans(0);
+ GXSetNumTexGens(1);
+
+ GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY);
+
+ GXSetNumTevStages(1);
+ GXSetNumIndStages(0);
+
+ GXSetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA);
+
+ GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
+ GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_C1, GX_CC_C0, GX_CC_TEXC, GX_CC_ZERO);
+ GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
+ GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_A0, GX_CA_TEXA, GX_CA_ZERO);
+ GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
+
+ GXSetZCompLoc(GX_FALSE);
+ GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_SET);
+ GXSetZMode(GX_TRUE, GX_LEQUAL, GX_FALSE);
+ GXSetAlphaCompare(GX_GREATER, 0, GX_AOP_OR, GX_GREATER, 0);
+
+ GXSetFog(GX_FOG_NONE, 0, 0, 0, 0, (GXColor){0,0,0,0});
+ GXSetFogRangeAdj(GX_FALSE, 0, 0);
+
+ GXSetCullMode(GX_CULL_NONE);
+
+ GXSetDither(GX_TRUE);
+
+ GXSetTevColor(GX_TEVREG0, (GXColor){255,255,255,255});
+ GXSetTevColor(GX_TEVREG1, (GXColor){0,0,0,255});
+}
+
+void dWMMap_c::renderer_c::renderTileLayer(dKPLayer_s *layer, dKPLayer_s::sector_s *sectors) {
+ //TileReport("Rendering layer %p\n", layer);
+ renderMtx[2][3] += 10;
+
+ // don't render it if we don't need to
+ if (maxX < layer->left || minX > layer->right)
+ return;
+ if (maxY < layer->top || minY > layer->bottom)
+ return;
+
+ // set up
+ loadCamera();
+
+ loadTexture(layer->tileset);
+
+ // figure out -what- to render
+ BoundReport("Regular render area: %d,%d to %d,%d\n", minX, minY, maxX, maxY);
+ BoundReport("Layer bounds: %d,%d to %d,%d\n", layer->left, layer->top, layer->right, layer->bottom);
+ int toRenderMinX = max(minX, layer->left);
+ int toRenderMinY = max(minY, layer->top);
+
+ int toRenderMaxX = min(maxX, layer->right);
+ int toRenderMaxY = min(maxY, layer->bottom);
+
+ int sectorBaseX = layer->sectorLeft;
+ int sectorBaseY = layer->sectorTop;
+ int sectorIndexStride = (layer->sectorRight - layer->sectorLeft + 1);
+
+ int sectorMinX = toRenderMinX / 16;
+ int sectorMinY = toRenderMinY / 16;
+ int sectorMaxX = toRenderMaxX / 16;
+ int sectorMaxY = toRenderMaxY / 16;
+ BoundReport("To render: %d,%d to %d,%d\n", toRenderMinX, toRenderMinY, toRenderMaxX, toRenderMaxY);
+ BoundReport("sectors %d,%d to %d,%d\n", sectorMinX, sectorMinY, sectorMaxX, sectorMaxY);
+
+ for (int sectorY = sectorMinY; sectorY <= sectorMaxY; sectorY++) {
+ int baseIndex = (sectorY - sectorBaseY) * sectorIndexStride;
+
+ int iMinY = (sectorY == sectorMinY) ? (toRenderMinY & 0xF) : 0;
+ int iMaxY = (sectorY == sectorMaxY) ? (toRenderMaxY & 0xF) : 15;
+
+ int worldSectorY = sectorY << 4;
+
+ for (int sectorX = sectorMinX; sectorX <= sectorMaxX; sectorX++) {
+ u16 index = layer->indices[baseIndex + sectorX - sectorBaseX];
+ TileReport("Sector index @ %d,%d: %d\n", sectorX, sectorY, index);
+ if (index == 0xFFFF)
+ continue;
+
+ dKPLayer_s::sector_s *sector = &sectors[index];
+
+ int iMinX = (sectorX == sectorMinX) ? (toRenderMinX & 0xF) : 0;
+ int iMaxX = (sectorX == sectorMaxX) ? (toRenderMaxX & 0xF) : 15;
+ TileReport("Min/Max: X: %d,%d Y: %d,%d\n", iMinX, iMaxX, iMinY, iMaxY);
+
+ int worldSectorX = sectorX << 4;
+
+ for (int inY = iMinY; inY <= iMaxY; inY++) {
+ for (int inX = iMinX; inX <= iMaxX; inX++) {
+ u16 tileID = (*sector)[inY][inX];
+ if (tileID == 0xFFFF)
+ continue;
+
+ s16 worldX = (worldSectorX | inX) << 4;
+ s16 worldY = -((worldSectorY | inY) << 4);
+
+ u8 tileX = (tileID & 0x1F) * 8;
+ u8 tileY = ((tileID & 0x1E0) / 32) * 16;
+ TileReport("Drawing tile %d at %d,%d\n", tileID, worldX, worldY);
+
+ GXBegin(GX_QUADS, GX_VTXFMT0, 4);
+ GXPosition2s16(worldX + 16, worldY - 16);
+ GXTexCoord2u8(tileX + 7, tileY + 14);
+ GXPosition2s16(worldX + 16, worldY);
+ GXTexCoord2u8(tileX + 7, tileY + 2);
+ GXPosition2s16(worldX, worldY);
+ GXTexCoord2u8(tileX + 1, tileY + 2);
+ GXPosition2s16(worldX, worldY - 16);
+ GXTexCoord2u8(tileX + 1, tileY + 14);//*/
+ GXEnd();
+ }
+ }
+
+ TileReport("Sector complete\n");
+ }
+ }
+
+ //TileReport("Layer complete\n");
+}
+
+void dWMMap_c::renderer_c::endRendering() {
+}
+
+void dWMMap_c::renderer_c::loadTexture(GXTexObj *obj) {
+ if (currentTexture == obj)
+ return;
+
+ GXLoadTexObj(obj, GX_TEXMAP0);
+ currentTexture = obj;
+}
+
+void dWMMap_c::renderer_c::loadCamera() {
+ GXLoadPosMtxImm(renderMtx, GX_PNMTX0);
+}
+
diff --git a/src/koopatlas/map.h b/src/koopatlas/map.h
new file mode 100644
index 0000000..6f07ddf
--- /dev/null
+++ b/src/koopatlas/map.h
@@ -0,0 +1,60 @@
+#include "koopatlas/core.h"
+
+// Can't remember why I had this. Who cares
+#define GEKKO
+#include "rvl/mtx.h"
+#include "rvl/GXEnum.h"
+#include "rvl/GXStruct.h"
+#include "rvl/GXTransform.h"
+#include "rvl/GXGeometry.h"
+#include "rvl/GXDispList.h"
+#include "rvl/GXLighting.h"
+#include "rvl/GXTev.h"
+#include "rvl/GXTexture.h"
+#include "rvl/GXCull.h"
+#include "rvl/GXPixel.h"
+#include "rvl/GXBump.h"
+#include "rvl/GXVert.h"
+#include "rvl/vifuncs.h"
+
+class dWMMap_c : public dBase_c {
+ public:
+ dWMMap_c();
+
+ int onCreate();
+ int onDelete();
+ int onExecute();
+ int onDraw();
+
+ class renderer_c : public m3d::proc_c {
+ public:
+ mAllocator_c allocator;
+
+ void drawOpa();
+ void drawXlu();
+
+ private:
+ void drawTiles();
+
+ void beginRendering();
+ void endRendering();
+
+ void renderTileLayer(dKPLayer_s *layer, dKPLayer_s::sector_s *sector);
+
+ void loadTexture(GXTexObj *obj);
+
+ void loadCamera();
+
+ GXTexObj *currentTexture;
+ Mtx renderMtx;
+ float baseZ;
+
+ int minX, minY, maxX, maxY;
+ };
+
+ renderer_c renderer;
+
+ static dWMMap_c *build();
+ static dWMMap_c *instance;
+};
+
diff --git a/src/koopatlas/mapdata.cpp b/src/koopatlas/mapdata.cpp
new file mode 100644
index 0000000..37565ea
--- /dev/null
+++ b/src/koopatlas/mapdata.cpp
@@ -0,0 +1,147 @@
+#include "koopatlas/mapdata.h"
+
+
+dKPMapData_c::dKPMapData_c() {
+ data = 0;
+ fixedUp = false;
+ tilesetLoaders = 0;
+ tilesetsLoaded = false;
+}
+
+dKPMapData_c::~dKPMapData_c() {
+ m_fileLoader.unload();
+
+ unloadTilesets();
+}
+
+bool dKPMapData_c::load(const char *filename) {
+ OSReport("Loading %s\n", filename);
+ data = (dKPMapFile_s*)m_fileLoader.load(filename);
+ OSReport("%p\n", data);
+
+ if (data == 0)
+ return false;
+
+ if (!fixedUp)
+ fixup();
+
+ return loadTilesets();
+}
+
+bool dKPMapData_c::loadTilesets() {
+ if (tilesetsLoaded)
+ return true;
+
+ OSReport("Loading tilesets: %d\n", data->tilesetCount);
+ if (tilesetLoaders == 0)
+ tilesetLoaders = new dDvdLoader_c[data->tilesetCount];
+
+ bool result = true;
+
+ for (int i = 0; i < data->tilesetCount; i++) {
+ char *filename = ((char*)data) + (data->tilesets[i].dummy[3] - 0x10000000);
+ OSReport("Loading tileset: %s\n", filename);
+ result &= (tilesetLoaders[i].load(filename) != 0);
+ }
+
+ if (result) {
+ tilesetsLoaded = true;
+
+ for (int i = 0; i < data->tilesetCount; i++) {
+ data->tilesets[i].dummy[3] = (((u32)tilesetLoaders[i].buffer & ~0xC0000000) >> 5);
+ }
+ }
+
+ return tilesetsLoaded;
+}
+
+void dKPMapData_c::unloadTilesets() {
+ if (tilesetLoaders != 0)
+ delete[] tilesetLoaders;
+}
+
+void dKPMapData_c::fixup() {
+ fixedUp = true;
+
+ fixRef(data->layers);
+
+ for (int iLayer = 0; iLayer < data->layerCount; iLayer++) {
+ dKPLayer_s *layer = fixRef(data->layers[iLayer]);
+
+ switch (layer->type) {
+ case dKPLayer_s::OBJECTS:
+ fixRef(layer->tileset);
+ break;
+
+ case dKPLayer_s::DOODADS:
+ for (int iDood = 0; iDood < layer->doodadCount; iDood++) {
+ dKPDoodad_s *doodad = fixRef(layer->doodads[iDood]);
+
+ fixRef(doodad->texObj);
+ fixTexObjSafe(doodad->texObj);
+ }
+ break;
+
+ case dKPLayer_s::PATHS:
+ fixRef(layer->paths);
+ fixRef(layer->nodes);
+
+ for (int iPath = 0; iPath < layer->pathCount; iPath++) {
+ dKPPath_s *path = fixRef(layer->paths[iPath]);
+
+ fixRef(path->start);
+ fixRef(path->end);
+
+ fixRef(path->tileLayer);
+ fixRef(path->doodadLayer);
+ }
+
+ for (int iNode = 0; iNode < layer->nodeCount; iNode++) {
+ dKPNode_s *node = fixRef(layer->nodes[iNode]);
+
+ for (int i = 0; i < 4; i++)
+ fixRef(node->exits[i]);
+
+ fixRef(node->tileLayer);
+ fixRef(node->doodadLayer);
+
+ if (node->type == dKPNode_s::CHANGE)
+ fixRef(node->destMap);
+ }
+ break;
+ }
+ }
+
+ fixRef(data->unlocks);
+
+ for (int iUnlock = 0; iUnlock < data->unlockCount; iUnlock++) {
+ dKPUnlock_s *unlock = &data->unlocks[iUnlock];
+
+ fixRef(unlock->targetPath);
+ }
+
+ fixRef(data->tilesets);
+}
+
+
+/******************************************************************************
+ * Generic Layer
+ ******************************************************************************/
+
+
+/******************************************************************************
+ * Tile Layer
+ ******************************************************************************/
+
+
+/******************************************************************************
+ * Doodad Layer
+ ******************************************************************************/
+
+
+/******************************************************************************
+ * Path Layer
+ ******************************************************************************/
+
+
+
diff --git a/src/koopatlas/mapdata.h b/src/koopatlas/mapdata.h
new file mode 100644
index 0000000..2b643bd
--- /dev/null
+++ b/src/koopatlas/mapdata.h
@@ -0,0 +1,191 @@
+#include <game.h>
+
+// forward declarations
+struct dKPLayer_s;
+
+/******************************************************************************
+ * Doodads
+ ******************************************************************************/
+struct dKPDoodad_s {
+ struct animation_s {
+ enum LoopTypes {
+ CONTIGUOUS, LOOP, REVERSE_LOOP
+ };
+
+ enum CurveTypes {
+ LINEAR, SIN, COS
+ };
+
+ enum AnimTypes {
+ X_POS, Y_POS, ANGLE, X_SCALE, Y_SCALE, OPACITY
+ };
+
+ LoopTypes loop;
+ CurveTypes curve;
+ float frameCount;
+ AnimTypes type;
+ float start, end;
+ };
+
+ float x, y;
+ float width, height;
+ float angle;
+
+ GXTexObj *texObj;
+ int animationCount;
+ animation_s animations[1]; // variable size
+};
+
+/******************************************************************************
+ * Paths
+ ******************************************************************************/
+struct dKPPath_s;
+
+struct dKPNode_s {
+ enum NodeTypes {
+ PASS_THROUGH, STOP, LEVEL, CHANGE
+ };
+
+ short x, y;
+ dKPPath_s *exits[4];
+ dKPLayer_s *tileLayer, *doodadLayer;
+
+ int type;
+ union {
+ struct { u8 levelNumber[2]; };
+ struct { char *destMap; u8 thisID, foreignID, transition; };
+ };
+};
+
+struct dKPPath_s {
+ dKPNode_s *start, *end;
+ dKPLayer_s *tileLayer, *doodadLayer;
+
+ u8 unlockType; // 0 = always, 1 = start, 2 = end
+ u8 unlockIsSecret;
+ float speed;
+ int animation;
+};
+
+/******************************************************************************
+ * Tying It All Together
+ ******************************************************************************/
+struct dKPLayer_s {
+ enum LayerTypes {
+ OBJECTS, DOODADS, PATHS
+ };
+
+ LayerTypes type;
+
+ typedef u16 sector_s[16][16];
+
+ union {
+ struct {
+ GXTexObj *tileset;
+ union {
+ int sectorBounds[4];
+ struct {
+ int sectorLeft;
+ int sectorTop;
+ int sectorRight;
+ int sectorBottom;
+ };
+ };
+ union {
+ int bounds[4];
+ struct {
+ int left;
+ int top;
+ int right;
+ int bottom;
+ };
+ };
+ u16 indices[1]; // variable size
+ };
+
+ struct {
+ int doodadCount;
+ dKPDoodad_s *doodads[1]; // variable size
+ };
+
+ struct {
+ int nodeCount;
+ dKPNode_s **nodes;
+ int pathCount;
+ dKPPath_s **paths;
+ };
+ };
+};
+
+struct dKPUnlock_s {
+ u8 isSecret;
+ u8 level[2];
+ u8 _;
+
+ dKPPath_s *targetPath;
+};
+
+struct dKPMapFile_s {
+ int layerCount;
+ dKPLayer_s **layers;
+
+ int unlockCount;
+ dKPUnlock_s *unlocks;
+
+ int tilesetCount;
+ GXTexObj *tilesets;
+
+ dKPLayer_s::sector_s sectors[1]; // variable size
+};
+
+class dKPMapData_c {
+ private:
+ dDvdLoader_c m_fileLoader;
+
+ template <typename T>
+ inline T* fixRef(T*& indexAsPtr) {
+ unsigned int index = (unsigned int)indexAsPtr;
+ if (index == 0xFFFFFFFF)
+ indexAsPtr = 0;
+ else
+ indexAsPtr = (T*)(((char*)data) + index);
+ return indexAsPtr;
+ }
+
+ template <typename T>
+ inline T* fixRefSafe(T*& indexAsPtr) {
+ unsigned int index = (unsigned int)indexAsPtr;
+ if (index == 0xFFFFFFFF)
+ indexAsPtr = 0;
+ else if (index < 0x80000000)
+ indexAsPtr = (T*)(((char*)data) + index);
+ return indexAsPtr;
+ }
+
+ inline void fixTexObjSafe(GXTexObj *obj) {
+ if (obj->dummy[3] >= 0x10000000) {
+ obj->dummy[3] = (((u32)data) & 0x7FFFFFFF) + (obj->dummy[3] - 0x10000000);
+ obj->dummy[3] >>= 5;
+ }
+ }
+
+ bool fixedUp;
+ bool tilesetsLoaded;
+
+ void fixup();
+
+ bool loadTilesets();
+ void unloadTilesets();
+
+
+ public:
+ dDvdLoader_c *tilesetLoaders;
+ dKPMapFile_s *data;
+ dKPLayer_s *pathLayer;
+
+ dKPMapData_c();
+ bool load(const char *filename);
+ ~dKPMapData_c();
+};
+
+
diff --git a/src/koopatlas/player.cpp b/src/koopatlas/player.cpp
new file mode 100644
index 0000000..ee881ab
--- /dev/null
+++ b/src/koopatlas/player.cpp
@@ -0,0 +1,143 @@
+#include "koopatlas/player.h"
+
+daWMPlayer_c *daWMPlayer_c::instance;
+
+int daWMPlayer_c::onCreate() {
+ OSReport("* dWMPlayer_c created\n");
+
+ OSReport("Init handler...\n");
+ this->modelHandler = new dPlayerModelHandler_c(0);
+ this->modelHandler->loadModel(0, 3, 2);
+ this->modelHandler->mdlClass->startAnimation(0, 1.2, 10.0, 0.0);
+ this->modelHandler->setSRT((Vec){0.0,100.0,-100.0}, (S16Vec){0,0,0}, (Vec){2.0,2.0,2.0});
+ this->modelHandler->draw();
+ OSReport("Init done!\n");
+
+ pos = (Vec){0.0f,-32.0f,0.0f};
+ rot = (S16Vec){0,0,0};
+ scale = (Vec){1.0f,1.0f,1.0f};
+
+ current_param = 0;
+
+ return true;
+}
+
+int daWMPlayer_c::onDelete() {
+ delete modelHandler;
+ OSReport("* dWMPlayer_c deleted\n");
+
+ return true;
+}
+
+
+int daWMPlayer_c::onExecute() {
+ this->modelHandler->update();
+ this->modelHandler->setSRT(this->pos, this->rot, this->scale);
+
+#ifdef MARIO_OPTIONS
+ // Before we leave, do the debug movement stuff
+ int heldButtons = Remocon_GetButtons(GetActiveRemocon());
+ int nowPressed = Remocon_GetPressed(GetActiveRemocon());
+ char buf[100];
+ bool updated = false;
+
+ if (nowPressed & WPAD_LEFT) {
+ current_param--;
+ updated = true;
+ }
+
+ if (nowPressed & WPAD_RIGHT) {
+ current_param++;
+ updated = true;
+ }
+
+ if (current_param < 0)
+ current_param = 8;
+
+ if (current_param > 8)
+ current_param = 0;
+
+ float pos_mod = 0.0f;
+ short rot_mod = 0.0f;
+ float scale_mod = 0.0f;
+ if (nowPressed & WPAD_ONE) {
+ pos_mod -= 5.0f;
+ rot_mod -= 0x1000;
+ scale_mod -= 0.1f;
+ updated = true;
+ } else if (nowPressed & WPAD_TWO) {
+ pos_mod += 5.0f;
+ rot_mod += 0x1000;
+ scale_mod += 0.1f;
+ updated = true;
+ }
+
+ if (!updated) return true;
+
+ if (current_param == 0) {
+ pos.x += pos_mod;
+ sprintf(buf, "X position: %f", pos.x);
+ } else if (current_param == 1) {
+ pos.y += pos_mod;
+ sprintf(buf, "Y position: %f", pos.y);
+ } else if (current_param == 2) {
+ pos.z += pos_mod;
+ sprintf(buf, "Z position: %f", pos.z);
+ } else if (current_param == 3) {
+ rot.x += rot_mod;
+ sprintf(buf, "X rotation: 0x%04x", rot.x);
+ } else if (current_param == 4) {
+ rot.y += rot_mod;
+ sprintf(buf, "Y rotation: 0x%04x", rot.y);
+ } else if (current_param == 5) {
+ rot.z += rot_mod;
+ sprintf(buf, "Z rotation: 0x%04x", rot.z);
+ } else if (current_param == 6) {
+ scale.x += scale_mod;
+ sprintf(buf, "X scale: %f", scale.x);
+ } else if (current_param == 7) {
+ scale.y += scale_mod;
+ sprintf(buf, "Y scale: %f", scale.y);
+ } else if (current_param == 8) {
+ scale.z += scale_mod;
+ sprintf(buf, "Z scale: %f", scale.z);
+ }
+
+ dScNewerWorldMap_c::instance->SetTitle(buf);
+#endif
+
+ return true;
+}
+
+int daWMPlayer_c::onDraw() {
+ this->modelHandler->draw();
+
+ return true;
+}
+
+
+void daWMPlayer_c::startAnimation(int id, float frame, float unk, float updateRate) {
+ if (id == currentAnim && frame == currentFrame && unk == currentUnk && updateRate == currentUpdateRate)
+ return;
+
+ currentAnim = id;
+ currentFrame = frame;
+ currentUnk = unk;
+ currentUpdateRate = updateRate;
+ this->modelHandler->mdlClass->startAnimation(id, frame, unk, updateRate);
+}
+
+
+
+daWMPlayer_c *daWMPlayer_c::build() {
+ OSReport("Creating WMPlayer\n");
+
+ void *buffer = AllocFromGameHeap1(sizeof(daWMPlayer_c));
+ daWMPlayer_c *c = new(buffer) daWMPlayer_c;
+
+ OSReport("Created WMPlayer @ %p\n", c);
+
+ instance = c;
+ return c;
+}
+
diff --git a/src/koopatlas/player.h b/src/koopatlas/player.h
new file mode 100644
index 0000000..d5fcc33
--- /dev/null
+++ b/src/koopatlas/player.h
@@ -0,0 +1,25 @@
+#include "koopatlas/core.h"
+
+class daWMPlayer_c : public dActor_c {
+ public:
+ dPlayerModelHandler_c *modelHandler;
+
+ int onCreate();
+ int onDelete();
+ int onExecute();
+ int onDraw();
+
+ int current_param;
+
+ int currentAnim;
+ float currentFrame;
+ float currentUnk;
+ float currentUpdateRate;
+
+ void startAnimation(int id, float frame, float unk, float updateRate);
+
+ static daWMPlayer_c *build();
+ static daWMPlayer_c *instance;
+};
+
+