diff options
| -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; +}; + +  | 
