diff options
author | Treeki <treeki@gmail.com> | 2012-01-15 21:31:34 +0100 |
---|---|---|
committer | Treeki <treeki@gmail.com> | 2012-01-15 21:31:34 +0100 |
commit | 83729d2427ebb9a8563dce8ca3c8c19fb9f71c4a (patch) | |
tree | 5d48147b1f8e23992fe4a921adcec83da45969cd | |
parent | 0dabea30d98d175e5d7e0655c10757db99ac8295 (diff) | |
download | kamek-83729d2427ebb9a8563dce8ca3c8c19fb9f71c4a.tar.gz kamek-83729d2427ebb9a8563dce8ca3c8c19fb9f71c4a.zip |
initial commit of the Koopatlas engine
Diffstat (limited to '')
-rw-r--r-- | NewerProject.yaml | 1 | ||||
-rw-r--r-- | NewerProjectKP.yaml | 42 | ||||
-rw-r--r-- | koopatlas.yaml | 53 | ||||
-rwxr-xr-x | makeNewerKP | 14 | ||||
-rwxr-xr-x | makeNewerKPAll | 14 | ||||
-rw-r--r-- | src/koopatlas/camera.cpp | 191 | ||||
-rw-r--r-- | src/koopatlas/camera.h | 37 | ||||
-rw-r--r-- | src/koopatlas/core.cpp | 928 | ||||
-rw-r--r-- | src/koopatlas/core.h | 99 | ||||
-rw-r--r-- | src/koopatlas/hud.cpp | 168 | ||||
-rw-r--r-- | src/koopatlas/hud.h | 28 | ||||
-rw-r--r-- | src/koopatlas/map.cpp | 259 | ||||
-rw-r--r-- | src/koopatlas/map.h | 60 | ||||
-rw-r--r-- | src/koopatlas/mapdata.cpp | 147 | ||||
-rw-r--r-- | src/koopatlas/mapdata.h | 191 | ||||
-rw-r--r-- | src/koopatlas/player.cpp | 143 | ||||
-rw-r--r-- | src/koopatlas/player.h | 25 |
17 files changed, 2400 insertions, 0 deletions
diff --git a/NewerProject.yaml b/NewerProject.yaml index 7bd958b..0b5dbec 100644 --- a/NewerProject.yaml +++ b/NewerProject.yaml @@ -38,3 +38,4 @@ modules: - processed/bossWrenchThrow.yaml - processed/effectVideo.yaml - processed/fakeStarCoin.yaml +# - processed/actorlog.yaml diff --git a/NewerProjectKP.yaml b/NewerProjectKP.yaml new file mode 100644 index 0000000..3468497 --- /dev/null +++ b/NewerProjectKP.yaml @@ -0,0 +1,42 @@ +output_dir: "NewerASM" +code_address: 0x808D9000 +modules: + - processed/prolog.yaml + - processed/bugfixes.yaml +# - processed/worldmap.yaml + - processed/koopatlas.yaml + - processed/levelnames.yaml + - processed/animtiles.yaml + - processed/soundPlayer.yaml + - processed/levelspecial.yaml + - processed/mrsun.yaml + - processed/firelaser.yaml + - processed/spritetex.yaml +# - processed/gakenoko.yaml + - processed/poweruphax.yaml +# - processed/heapbar.yaml + - processed/randtiles.yaml + - processed/tilegod.yaml + - processed/linegod.yaml + - processed/tilesetfixer.yaml + - processed/switchblock.yaml + - processed/eventblock.yaml +# - processed/msgbox.yaml +# - processed/replay.yaml + - processed/growup.yaml + - processed/eventlooper.yaml + - processed/spritespawner.yaml + - processed/spriteswapper.yaml + - processed/compression.yaml +# - processed/crowdclapper.yaml + - processed/blocksnake.yaml +# - processed/classic_controller.yaml + - processed/bossMegaGoomba.yaml + - processed/bossFuzzyBear.yaml + - processed/bossThwompaDomp.yaml + - processed/bossRamboo.yaml + - processed/bossBalboaWrench.yaml + - processed/bossWrenchThrow.yaml + - processed/effectVideo.yaml + - processed/fakeStarCoin.yaml +# - processed/actorlog.yaml diff --git a/koopatlas.yaml b/koopatlas.yaml new file mode 100644 index 0000000..9c4af7b --- /dev/null +++ b/koopatlas.yaml @@ -0,0 +1,53 @@ +--- +source_files: + - ../src/fileload.cpp + - ../src/scene.S + - ../src/levelinfo.cpp + - ../src/player.cpp + - ../src/effects.cpp + - ../src/koopatlas/core.cpp + - ../src/koopatlas/player.cpp + - ../src/koopatlas/hud.cpp + - ../src/koopatlas/camera.cpp + - ../src/koopatlas/map.cpp + - ../src/koopatlas/mapdata.cpp + +hooks: + - name: BuildWorldMap + type: add_func_pointer + src_addr_pal: 0x8098DCF0 + target_func: 'dScKoopatlas_c::build(void)' + + - name: BuildWMPlayer + type: add_func_pointer + src_addr_pal: 0x80988DDC + target_func: 'daWMPlayer_c::build(void)' + + - name: BuildWMHud + type: add_func_pointer + src_addr_pal: 0x80981A3C + target_func: 'dWMHud_c::build(void)' + + - name: BuildWorldCamera + type: add_func_pointer + src_addr_pal: 0x8098EEC8 + target_func: 'dWorldCamera_c::build(void)' + + - name: BuildWMMap + type: add_func_pointer + src_addr_pal: 0x80984710 + target_func: 'dWMMap_c::build(void)' + +# fix the STOCK_ITEM references + - name: StockItemFix + type: patch + addr_ntsc: 0x80101110 + addr_pal: 0x80101220 + data: '4E800020' + +# this isn't used! + - name: WMDrawFuncFix + type: patch + addr_pal: 0x80926800 + data: '60000000' + diff --git a/makeNewerKP b/makeNewerKP new file mode 100755 index 0000000..21f6db8 --- /dev/null +++ b/makeNewerKP @@ -0,0 +1,14 @@ +#!/bin/sh +python2 tools/mapfile_tool.py +python2 tools/kamek.py NewerProjectKP.yaml --no-rels --use-mw --use-wine --gcc-type=/opt/wiidev/bin/powerpc-elf --build=pal --mw-path=tools +if [ "$?" = "0" ]; then + echo "compile successful" +else + exit 1 +fi + +cp NewerASM/pal_loader.bin ~/Games/Newer/DolphinPatch/NewerRes/SystemEU_1.bin +cp NewerASM/ntsc_loader.bin ~/Games/Newer/DolphinPatch/NewerRes/SystemUS_1.bin +cp NewerASM/ntsc2_loader.bin ~/Games/Newer/DolphinPatch/NewerRes/SystemUS_2.bin +echo Built PAL! + diff --git a/makeNewerKPAll b/makeNewerKPAll new file mode 100755 index 0000000..065735f --- /dev/null +++ b/makeNewerKPAll @@ -0,0 +1,14 @@ +#!/bin/sh +python2 tools/mapfile_tool.py +python2 tools/kamek.py NewerProjectKP.yaml --no-rels --use-mw --use-wine --gcc-type=/opt/wiidev/bin/powerpc-elf --mw-path=tools +if [ "$?" = "0" ]; then + echo "compile successful" +else + exit 1 +fi + +cp NewerASM/pal_loader.bin ~/Games/Newer/DolphinPatch/NewerRes/SystemEU_1.bin +cp NewerASM/ntsc_loader.bin ~/Games/Newer/DolphinPatch/NewerRes/SystemUS_1.bin +cp NewerASM/ntsc2_loader.bin ~/Games/Newer/DolphinPatch/NewerRes/SystemUS_2.bin +echo Built all! + 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 = §ors[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; +}; + + |