diff options
| author | Treeki <treeki@gmail.com> | 2012-01-30 00:40:28 +0100 | 
|---|---|---|
| committer | Treeki <treeki@gmail.com> | 2012-01-30 00:40:28 +0100 | 
| commit | 96bc2e0026a369ecf8598fb2168d0a4e02e9e1bd (patch) | |
| tree | 75cad32a169d79f81c1adf1945d49c9b6fc3310b | |
| parent | 4d1cccfc209619919c2cae99fb5e58aa62b2bc64 (diff) | |
| download | kamek-96bc2e0026a369ecf8598fb2168d0a4e02e9e1bd.tar.gz kamek-96bc2e0026a369ecf8598fb2168d0a4e02e9e1bd.zip | |
message boxes are now functional
Diffstat (limited to '')
| -rw-r--r-- | NewerProject.yaml | 2 | ||||
| -rw-r--r-- | NewerProjectKP.yaml | 2 | ||||
| -rw-r--r-- | msgbox.yaml | 11 | ||||
| -rw-r--r-- | src/msgbox.S | 1 | ||||
| -rw-r--r-- | src/msgbox.cpp | 576 | ||||
| -rw-r--r-- | tools/msgbox_data.py | 36 | 
6 files changed, 435 insertions, 193 deletions
| diff --git a/NewerProject.yaml b/NewerProject.yaml index 0b5dbec..0a68909 100644 --- a/NewerProject.yaml +++ b/NewerProject.yaml @@ -20,7 +20,7 @@ modules:    - processed/tilesetfixer.yaml    - processed/switchblock.yaml    - processed/eventblock.yaml -#  - processed/msgbox.yaml +  - processed/msgbox.yaml  #  - processed/replay.yaml    - processed/growup.yaml    - processed/eventlooper.yaml diff --git a/NewerProjectKP.yaml b/NewerProjectKP.yaml index 3468497..3c9657b 100644 --- a/NewerProjectKP.yaml +++ b/NewerProjectKP.yaml @@ -21,7 +21,7 @@ modules:    - processed/tilesetfixer.yaml    - processed/switchblock.yaml    - processed/eventblock.yaml -#  - processed/msgbox.yaml +  - processed/msgbox.yaml  #  - processed/replay.yaml    - processed/growup.yaml    - processed/eventlooper.yaml diff --git a/msgbox.yaml b/msgbox.yaml index 5eef67e..2ca00cd 100644 --- a/msgbox.yaml +++ b/msgbox.yaml @@ -5,5 +5,14 @@ hooks:      type: branch_insn
      branch_type: b
      src_addr_pal: 0x800B3B50
 -    src_addr_ntsc: 0xdeadbeef
      target_func: 'Query5758Replacement'
 +
 +  - name: BuildMsgManager
 +    type: add_func_pointer
 +    src_addr_pal: 0x80AF96F8
 +    target_func: 'dMsgBoxManager_c::build(void)'
 +
 +  - name: BuildMsgBlock
 +    type: add_func_pointer
 +    src_addr_pal: 0x80ADD890
 +    target_func: 'daEnMsgBlock_c::build(void)'
 diff --git a/src/msgbox.S b/src/msgbox.S index ac49676..ee8c52e 100644 --- a/src/msgbox.S +++ b/src/msgbox.S @@ -11,6 +11,7 @@  #endif  .extern Global5758 +.global MessageBoxIsShowing  # -if param & 1 /and/ messagebox is on,   # otherwise, return Global5758 & param diff --git a/src/msgbox.cpp b/src/msgbox.cpp index f99f73f..c480070 100644 --- a/src/msgbox.cpp +++ b/src/msgbox.cpp @@ -1,227 +1,423 @@  #include <common.h>  #include <game.h> -#include "layoutlib.h" -#include "fileload.h" +// Replaces: EN_LIFT_ROTATION_HALF (Sprite 107; Profile ID 481 @ 80AF96F8) -struct MsgData_Header { -	u32 magic; -	u32 msgCount; -}; +class dMsgBoxManager_c : public dStageActor_c { +	public: +		void showMessage(int id); -struct MsgData_Entry { -	u32 number; -	u32 titleOffset; -	u32 msgOffset; -}; +		dMsgBoxManager_c() : state(this, &StateID_LoadRes) { } +		int onCreate(); +		int onDelete(); +		int onExecute(); +		int onDraw(); +		int beforeExecute() { return true; } +		int afterExecute(int) { return true; } -struct dMsgBoxManager_c { -	// 0x00 -	int ID; -	unsigned int Settings; -	short Type; -	char Unk_0A; -	char Unk_0B; -	char Unk_0C; -	char Unk_0D; -	char Unk_0E; -	char Unk_0F; -	 -	// 0x10 -	void *CONNECT_parent; -	void *CONNECT_child; -	void *CONNECT_prev; -	void *CONNECT_next; -	 -	// 0x20 -	void *CONNECT_thisObj; -	void *EXECUTE_prev; -	void *EXECUTE_next; -	void *EXECUTE_thisObj; -	 -	// 0x30 -	short Unk_30; -	short Unk_32; -	void *DRAW_prev; -	void *DRAW_next; -	void *DRAW_thisObj; -	 -	// 0x40 -	short Unk_40; -	short Unk_42; -	void *IDLookup_prev; -	void *IDLookup_next; -	void *IDLookup_thisObj; -	 -	// 0x50 -	void *Unk_50; -	int Unk_54; -	int Unk_58; -	void *Unk_5C; -	 -	// 0x60 -	void *vtable; -	int Unk_64;					// dBase_c starts here -	char *weirdTypeString; -	char *actorName; -	 -	// dMsgBoxManager_c starts here (offset 0x70) -	Layout *layout; -	int state; -	FileHandle msgDataFH; -	 -	// 0x80 -	void *msgData; -	 -	// current allocated class size: 0xD0 +		m2d::EmbedLayout_c layout; +		dDvdLoader_c msgDataLoader; + +		bool layoutLoaded; +		bool visible; + +		dStateWrapper_c<dMsgBoxManager_c> state; + +		USING_STATES(dMsgBoxManager_c); +		DECLARE_STATE(LoadRes); +		DECLARE_STATE(Wait); +		DECLARE_STATE(BoxAppearWait); +//		DECLARE_STATE(ButtonAppearWait); +		DECLARE_STATE(ShownWait); +//		DECLARE_STATE(ButtonDisappearWait); +		DECLARE_STATE(BoxDisappearWait); + +		static dMsgBoxManager_c *instance; +		static dMsgBoxManager_c *build(); + +	private: +		struct entry_s { +			u32 id; +			u32 titleOffset; +			u32 msgOffset; +		}; + +		struct header_s { +			u32 count; +			entry_s entry[1]; +		};  }; +dMsgBoxManager_c *dMsgBoxManager_c::instance = 0; +dMsgBoxManager_c *dMsgBoxManager_c::build() { +	void *buffer = AllocFromGameHeap1(sizeof(dMsgBoxManager_c)); +	dMsgBoxManager_c *c = new(buffer) dMsgBoxManager_c; -#define STATE_NULL 0 -#define STATE_BOX_APPEAR_WAIT 1 -#define STATE_BUTTON_APPEAR_WAIT 2 -#define STATE_SHOWN 3 -#define STATE_BUTTON_DISAPPEAR_WAIT 4 -#define STATE_BOX_DISAPPEAR_WAIT 5 +	instance = c; +	return c; +} -#define animBoxAppear 0 -#define animBoxDisappear 1 -#define animButtonAppear 2 -#define animButtonDisappear 3 +#define ANIM_BOX_APPEAR 0 +#define ANIM_BOX_DISAPPEAR 1 +//#define ANIM_BUTTON_APPEAR 2 +//#define ANIM_BUTTON_DISAPPEAR 3  extern int MessageBoxIsShowing; -dMsgBoxManager_c *CurrentMsgBoxManager; -const char *brlan_BoxAppear = "BoxAppear.brlan"; -const char *brlan_BoxDisappear = "BoxDisappear.brlan"; -const char *brlan_ButtonAppear = "ButtonAppear.brlan"; -const char *brlan_ButtonDisappear = "ButtonDisappear.brlan"; +/*****************************************************************************/ +// Events +int dMsgBoxManager_c::onCreate() { +	if (!layoutLoaded) { +		if (!layout.loadArc("msgbox.arc", false)) +			return false; -const char *group_Box = "G_Box"; -const char *group_Button = "G_Button"; +		static const char *brlanNames[2] = { +			"BoxAppear.brlan", +			"BoxDisappear.brlan", +//			"ButtonAppear.brlan", +//			"ButtonDisappear.brlan" +		}; -bool dMsgBoxManager_c__Create(dMsgBoxManager_c *self) { -	self->layout = (Layout*)AllocFromGameHeap1(sizeof(Layout)); -	 -	if (!self->layout) { -		OSReport("memalloc fail\n"); -		InfiniteLoop; -	} -	 -	EmbeddedLayout_ctor(self->layout); -	EmbeddedLayout_LoadArc(self->layout, "NewerRes/msgbox.arc"); -	 -	if (!EmbeddedLayout_Build(self->layout, "MessageBox.brlyt", 0)) { -		OSReport("build fail\n"); -		InfiniteLoop; +		static const char *groupNames[2] = { +			"G_Box", "G_Box", +//			"G_Button", "G_Button" +		}; + +		layout.build("MessageBox.brlyt"); + +		if (IsWideScreen()) { +			layout.layout.rootPane->scale.x = 0.7711f; +		} + +		layout.loadAnimations(brlanNames, 2); +		layout.loadGroups(groupNames, (int[2]){0,1}, 2); +		layout.disableAllAnimations(); + +		layout.drawOrder = 0xA0; + +		layoutLoaded = true;  	} -	 -	 -	const char *anims[4] = {brlan_BoxAppear, brlan_BoxDisappear, brlan_ButtonAppear, brlan_ButtonDisappear}; -	EmbeddedLayout_LoadBrlans(self->layout, anims, 4); -	 -	const char *groups[4] = {group_Box, group_Box, group_Button, group_Button}; -	 -	int mappings[4] = {0, 1, 2, 3}; -	EmbeddedLayout_LoadGroups(self->layout, groups, mappings, 4); -	 -	EmbeddedLayout_DisableAllAnims(self->layout); -	 -	for (int i = 0; i < 4; i++) { -		EmbeddedLayout_ResetAnimToInitialState(self->layout, i, false); + +	visible = false; + +	return true; +} + +int dMsgBoxManager_c::onExecute() { +	//OSReport("E: %s\n", state.getCurrentState()->getName()); +	state.execute(); + +	layout.execAnimations(); +	layout.update(); + +	return true; +} + +int dMsgBoxManager_c::onDraw() { +	if (visible) { +		layout.scheduleForDrawing();  	} -	self->msgData = LoadFile(&self->msgDataFH, "/NewerRes/MsgData.bin"); -	 -	self->state = STATE_NULL; -	self->layout->drawOrder = 0xA0; -	 -	CurrentMsgBoxManager = self; -	  	return true;  } -bool dMsgBoxManager_c__Execute(dMsgBoxManager_c *self) { -	if (self->state == STATE_NULL) -		return true; -	 -	 -	switch (self->state) { -		/**************************************************************************/ -		case STATE_BOX_APPEAR_WAIT: -			if (!EmbeddedLayout_CheckIfAnimationIsOn(self->layout, animBoxAppear)) { -				EmbeddedLayout_EnableNonLoopAnim(self->layout, animButtonAppear, false); -				self->state = STATE_BUTTON_APPEAR_WAIT; -			} -			 -			break; -			 -		/**************************************************************************/ -		case STATE_BUTTON_APPEAR_WAIT: -			if (!EmbeddedLayout_CheckIfAnimationIsOn(self->layout, animButtonAppear)) { -				self->state = STATE_SHOWN; -			} -			 -			break; -			 -		/**************************************************************************/ -		case STATE_SHOWN: -			if (false) { -				EmbeddedLayout_EnableNonLoopAnim(self->layout, animButtonDisappear, false); -				self->state = STATE_BUTTON_DISAPPEAR_WAIT; -			} -			 -			break; -			 -		/**************************************************************************/ -		case STATE_BUTTON_DISAPPEAR_WAIT: -			if (!EmbeddedLayout_CheckIfAnimationIsOn(self->layout, animButtonDisappear)) { -				EmbeddedLayout_EnableNonLoopAnim(self->layout, animBoxDisappear, false); -				self->state = STATE_BOX_DISAPPEAR_WAIT; -			} -			 -			break; -			 -		/**************************************************************************/ -		case STATE_BOX_DISAPPEAR_WAIT: -			if (!EmbeddedLayout_CheckIfAnimationIsOn(self->layout, animBoxDisappear)) { -				self->state = STATE_NULL; -				 -				EmbeddedLayout_DisableAllAnims(self->layout); -				 -				for (int i = 0; i < 4; i++) { -					EmbeddedLayout_ResetAnimToInitialState(self->layout, i, false); -				} -			} +int dMsgBoxManager_c::onDelete() { +	instance = 0; + +	return layout.free(); +} + +/*****************************************************************************/ +// Load Resources +CREATE_STATE_E(dMsgBoxManager_c, LoadRes); + +void dMsgBoxManager_c::executeState_LoadRes() { +	OSReport("Trying to load\n"); +	if (msgDataLoader.load("/NewerRes/Messages.bin")) { +		OSReport(":)\n"); +		state.setState(&StateID_Wait); +		OSReport("changed\n"); +	} else { +		OSReport(":(\n"); +	} +} + +/*****************************************************************************/ +// Waiting +CREATE_STATE_E(dMsgBoxManager_c, Wait); + +void dMsgBoxManager_c::executeState_Wait() { +	// null +} + +/*****************************************************************************/ +// Show Box +void dMsgBoxManager_c::showMessage(int id) { +	// get the data file +	header_s *data = (header_s*)msgDataLoader.buffer; + +	const wchar_t *title = 0, *msg = 0; + +	for (int i = 0; i < data->count; i++) { +		if (data->entry[i].id == id) { +			title = (const wchar_t*)((u32)data + data->entry[i].titleOffset); +			msg = (const wchar_t*)((u32)data + data->entry[i].msgOffset);  			break; +		}  	} + +	if (title == 0) { +		OSReport("WARNING! Tried to show message %x but it could not be found!\n", id); +		return; +	} + +	layout.findTextBoxByName("T_title")->SetString(title); +	layout.findTextBoxByName("T_msg")->SetString(msg); + +	state.setState(&StateID_BoxAppearWait); +} + + +CREATE_STATE(dMsgBoxManager_c, BoxAppearWait); + +void dMsgBoxManager_c::beginState_BoxAppearWait() { +	visible = true; +	MessageBoxIsShowing = true; +	layout.enableNonLoopAnim(ANIM_BOX_APPEAR); +	OSReport("Enabling box appear @ %d\n", GlobalTickCount); +} + +void dMsgBoxManager_c::executeState_BoxAppearWait() { +	if (!layout.isAnimOn(ANIM_BOX_APPEAR)) { +		OSReport("Box appeared @ %d\n", GlobalTickCount); +		state.setState(&StateID_ShownWait); +	} +} + +void dMsgBoxManager_c::endState_BoxAppearWait() { } + +/*****************************************************************************/ +// Show Button +/*CREATE_STATE(dMsgBoxManager_c, ButtonAppearWait); + +void dMsgBoxManager_c::beginState_ButtonAppearWait() { +	layout.enableNonLoopAnim(ANIM_BUTTON_APPEAR); +	OSReport("Enabling button appear @ %d\n", GlobalTickCount); +} + +void dMsgBoxManager_c::executeState_ButtonAppearWait() { +	if (!layout.isAnimOn(ANIM_BUTTON_APPEAR)) { +		OSReport("Button appeared @ %d\n", GlobalTickCount); +		state.setState(&StateID_ShownWait); +	} +} + +void dMsgBoxManager_c::endState_ButtonAppearWait() { }*/ + +/*****************************************************************************/ +// Wait For Player To Finish +CREATE_STATE(dMsgBoxManager_c, ShownWait); + +void dMsgBoxManager_c::beginState_ShownWait() { } +void dMsgBoxManager_c::executeState_ShownWait() { +	int nowPressed = Remocon_GetPressed(GetActiveRemocon()); -	 -	EmbeddedLayout_Process(self->layout); -	EmbeddedLayout_UpdateMatrix(self->layout); -	 +	if (nowPressed & WPAD_TWO) { +		state.setState(&StateID_BoxDisappearWait); +	} +} +void dMsgBoxManager_c::endState_ShownWait() { } + +/*****************************************************************************/ +// Hide Button +/*CREATE_STATE(dMsgBoxManager_c, ButtonDisappearWait); + +void dMsgBoxManager_c::beginState_ButtonDisappearWait() { +	layout.enableNonLoopAnim(ANIM_BUTTON_DISAPPEAR); +	OSReport("Enabling button disappear @ %d\n", GlobalTickCount); +} + +void dMsgBoxManager_c::executeState_ButtonDisappearWait() { +	if (!layout.isAnimOn(ANIM_BUTTON_DISAPPEAR)) { +		OSReport("Button disappeared @ %d\n", GlobalTickCount); +		state.setState(&StateID_BoxDisappearWait); +	} +} + +void dMsgBoxManager_c::endState_ButtonDisappearWait() { }*/ + +/*****************************************************************************/ +// Hide Box +CREATE_STATE(dMsgBoxManager_c, BoxDisappearWait); + +void dMsgBoxManager_c::beginState_BoxDisappearWait() { +	layout.enableNonLoopAnim(ANIM_BOX_DISAPPEAR); +	OSReport("Enabling box disappear @ %d\n", GlobalTickCount); +} + +void dMsgBoxManager_c::executeState_BoxDisappearWait() { +	if (!layout.isAnimOn(ANIM_BOX_DISAPPEAR)) { +		OSReport("Box disappeared @ %d\n", GlobalTickCount); +		state.setState(&StateID_Wait); + +		for (int i = 0; i < 2; i++) +			layout.resetAnim(i); +		layout.disableAllAnimations(); +	} +} + +void dMsgBoxManager_c::endState_BoxDisappearWait() { +	visible = false; +	MessageBoxIsShowing = false; +} + + + +/*****************************************************************************/ +/*****************************************************************************/ +/*****************************************************************************/ +// Replaces: EN_BLUR (Sprite 152; Profile ID 603 @ 80ADD890) + + +class daEnMsgBlock_c : public daEnBlockMain_c { +public: +	TileRenderer tile; +	Physics::Info physicsInfo; + +	int onCreate(); +	int onDelete(); +	int onExecute(); + +	void calledWhenUpMoveExecutes(); +	void calledWhenDownMoveExecutes(); + +	void blockWasHit(bool isDown); + +	USING_STATES(daEnMsgBlock_c); +	DECLARE_STATE(Wait); + +	static daEnMsgBlock_c *build(); +}; + + +CREATE_STATE(daEnMsgBlock_c, Wait); + + +int daEnMsgBlock_c::onCreate() { +	OSReport("Creating Block\n"); +	blockInit(pos.y); + +	physicsInfo.x1 = -8; +	physicsInfo.y1 = 16; +	physicsInfo.x2 = 8; +	physicsInfo.y2 = 0; + +	physicsInfo.otherCallback1 = &daEnBlockMain_c::OPhysicsCallback1; +	physicsInfo.otherCallback2 = &daEnBlockMain_c::OPhysicsCallback2; +	physicsInfo.otherCallback3 = &daEnBlockMain_c::OPhysicsCallback3; + +	physics.setup(this, &physicsInfo, 3, currentLayerID); +	physics.flagsMaybe = 0x260; +	physics.callback1 = &daEnBlockMain_c::PhysicsCallback1; +	physics.callback2 = &daEnBlockMain_c::PhysicsCallback2; +	physics.callback3 = &daEnBlockMain_c::PhysicsCallback3; +	physics.addToList(); + +	TileRenderer::List *list = dBgGm_c::instance->getTileRendererList(0); +	list->add(&tile); + +	tile.x = pos.x - 8; +	tile.y = -(16 + pos.y); +	tile.tileNumber = 0x98; + +	doStateChange(&daEnMsgBlock_c::StateID_Wait); +	OSReport("Created Block\n"); + +	return true; +} + + +int daEnMsgBlock_c::onDelete() { +	TileRenderer::List *list = dBgGm_c::instance->getTileRendererList(0); +	list->remove(&tile); + +	physics.removeFromList(); +  	return true;  } -bool dMsgBoxManager_c__Draw(dMsgBoxManager_c *self) { -	if (self->state != STATE_NULL) { -		EmbeddedLayout_AddToDrawList(self->layout); + +int daEnMsgBlock_c::onExecute() { +	acState.execute(); +	physics.update(); +	blockUpdate(); + +	tile.setPosition(pos.x-8, -(16+pos.y), pos.z); +	tile.setVars(scale.x); + +	// now check zone bounds based on state +	if (acState.getCurrentState()->isEqual(&StateID_Wait)) { +		checkZoneBoundaries(0);  	} -	 +  	return true;  } -bool dMsgBoxManager_c__Delete(dMsgBoxManager_c *self) { -	EmbeddedLayout_FreeArc(self->layout); -	EmbeddedLayout_Free(self->layout); -	EmbeddedLayout_dtor(self->layout, false); -	FreeFromGameHeap1(self->layout); -	 -	CurrentMsgBoxManager = 0; + +daEnMsgBlock_c *daEnMsgBlock_c::build() { +	void *buffer = AllocFromGameHeap1(sizeof(daEnMsgBlock_c)); +	return new(buffer) daEnMsgBlock_c; +} + + +void daEnMsgBlock_c::blockWasHit(bool isDown) { +	pos.y = initialY; + +	dMsgBoxManager_c::instance->showMessage(settings); + +	physics.setup(this, &physicsInfo, 3, currentLayerID); +	physics.addToList(); -	return true; +	doStateChange(&StateID_Wait); +} + + + +void daEnMsgBlock_c::calledWhenUpMoveExecutes() { +	if (initialY >= pos.y) +		blockWasHit(false); +} + +void daEnMsgBlock_c::calledWhenDownMoveExecutes() { +	if (initialY <= pos.y) +		blockWasHit(true); +} + + + +void daEnMsgBlock_c::beginState_Wait() { +} + +void daEnMsgBlock_c::endState_Wait() { +} + +void daEnMsgBlock_c::executeState_Wait() { +	int result = blockResult(); + +	if (result == 0) +		return; + +	if (result == 1) { +		doStateChange(&daEnBlockMain_c::StateID_UpMove); +		anotherFlag = 2; +		isGroundPound = false; +	} else { +		doStateChange(&daEnBlockMain_c::StateID_DownMove); +		anotherFlag = 1; +		isGroundPound = true; +	}  } diff --git a/tools/msgbox_data.py b/tools/msgbox_data.py new file mode 100644 index 0000000..06eec2b --- /dev/null +++ b/tools/msgbox_data.py @@ -0,0 +1,36 @@ +messages = [ +		# Message 0 +		(0x100, 'A Test Message', +			'This is a test message.\nWith some lines.\nAnd more lines.\nAnd a really long line to see if nw4r::lyt can handle wrapping or not...\nFinal line.' +			), +		] + +import struct, sys, os.path, codecs + +if len(sys.argv) > 1: +	target = sys.argv[1] +elif os.path.exists('/home/me/Games/Newer'): +	target = '/home/me/Games/Newer/ISO/files/NewerRes/Messages.bin' +else: +	target = 'Messages.bin' + +messageCount = len(messages) + +stringOffset = (messageCount * 0xC) + 4 +infoStruct = struct.Struct('>III') + +headerData = bytearray(struct.pack('>I', messageCount)) +stringData = bytearray() + +for msgID, title, msg in messages: +	titleOffset = stringOffset + len(stringData) +	stringData += codecs.utf_16_be_encode(title)[0] + '\0\0' +	msgOffset = stringOffset + len(stringData) +	stringData += codecs.utf_16_be_encode(msg)[0] + '\0\0' + +	headerData += infoStruct.pack(msgID, titleOffset, msgOffset) + +with open(target, 'wb') as out: +	out.write(headerData) +	out.write(stringData) + | 
