We just released a prototype of the cancelled SNES port of Puggsy! Take a look!
As always, thank you for supporting The Cutting Room Floor on Patreon!

Development:Super Mario 64 (Nintendo 64)/Objects

From The Cutting Room Floor
Jump to navigation Jump to search

This is a sub-page of Development:Super Mario 64 (Nintendo 64).

So very stubbly.
This page is rather stubbly and could use some expansion.
Are you a bad enough dude to rescue this article?
This cactus is UNDER CONSTRUCTION
This article is a work in progress.
...Well, all the articles here are, in a way. But this one moreso, and the article may contain incomplete information and editor's notes.
Hmmm...
To do:
  • Add the rest of the test objects, data/iwa_path/dice.s, commented-out object positions, star, data/p/pathtest.p names, data/glb/pathdata.glb, and data/pathdata.glb
  • Document commented-out object placement and the objects in star.

Objects

Motos/Motosman

SM64 motos.png

An unused enemy internally referred to as "モトス" (Japanese name), "motos", and "motosman" in "sm64/shape/EnemyTest/old/motos.sou". The Behavior file was last updated on October 17, 1995. Some behavior names and an object shape's name identify it as "motosman", which is the most likely internal name. Objects that carry Mario appear to have descended from this enemy, as the grab function and object type are labeled as "MotosProc1" and "OBJNAME_MOTOS" respectively. The general structure and idea of this enemy evolved into another scrapped enemy, "katsugikun". It might also be related to Chuckya, due to having similar names in the code: Chuckya (carryboy) and Motos (motosman).

Interestingly, the "Bully the Bullies" Star is named bigmotos in the code, suggesting that it originally involved Motos.

Body (p1) Body (p2) Face Arm/Leg Skin A Skin B Skin C Skin D
SM64-InternalMaterial-Motos body1 txt.png
SM64-InternalMaterial-Motos body2 txt.png
SM64-InternalMaterial-Motos eye txt.png
SM64-InternalMaterial-Motos parts txt.png
SM64-InternalMaterial-Motos skinA txt.png
SM64-InternalMaterial-Motos skinB txt.png
SM64-InternalMaterial-Motos skinC txt.png
SM64-InternalMaterial-Motos skinD txt.png

Behavior Code

#define ANM_motos_basedata_A    	0
#define ANM_motos_carry         	1
#define ANM_motos_carry_run     	2
#define ANM_motos_carry_start   	3
#define ANM_motos_down_recover  	4
#define ANM_motos_down_stop     	5
#define ANM_motos_pitch         	6
#define ANM_motos_safe_down     	7
#define ANM_motos_wait          	8
#define ANM_motos_walk          	9

#define ANM_motos_end          	ANM_motos_walk+1

e_motos:
	p_initialize(enemyA)
	p_setbit(flag,stf_moveON | stf_YangleSAME | stf_catchON | stf_playerdistON | stf_playerangleON )
	p_set_pointer(skelanime,motos_anime)
	p_setd(objname,OBJNAME_TAKE)
	p_sethitbox(100,100)
	p_setmovedata(30,-400,-50,1000,1000,200,0,0)
	p_makeobj_child(S_NULL,e_motos_hand)
	p_hitON
	p_while
		p_program(s_motos)
	p_loop

e_motos_hand:
	p_initialize(enemyA)
	p_setbit(flag,stf_moveON | stf_YangleSAME )
	p_softspritemodeON
	p_while
		p_program(s_motos_hand)
	p_loop

#define		motos_work	(execstp->s[stw_work0].d)

extern unsigned long MotosProc1(int code,MapNode *node, void *data)
{

	if (code == MAP_CBACK_EXEC) {

		AffineMtx	 modelmtx;	
	  	StrategyRecord	*stp = (StrategyRecord *)hmsActiveShape;

		if ( stp->childobj != NULL ){
			s_calc_skeleton_glbmtx(&modelmtx,(AffineMtx *)data,hmsActiveCamera->matrix);
			s_calc_skeleton_glbpos(modelmtx,stp->childobj);
			s_copy_worldXYZmappos(stp->childobj);
		}

	}

	return(0);

}

extern void s_motos_hand(void)
{

	StrategyRecord *firep;

	execstp->s[stw_skeletonX].f = 100;
	execstp->s[stw_skeletonY].f = 0;
	execstp->s[stw_skeletonZ].f = 150;

	obj_angleY = execstp->motherobj->s[stw_angleY].d;

	switch (execstp->motherobj->s[stw_imm].d ){
	 	case	0:
			break;
		case	1:
			s_copy_mapwork(player1stp,execstp);
			break;
		case	2:
			player1stp->s[stw_mail].d |= PLAYERMAIL_CARRYMODE_OFF;
			playerWorks[0].velocity = 50;
			execstp->motherobj->s[stw_imm].d = 0;
			break;
	}


#if 0
	if (execstp->motherobj->s[stw_imm].d != 0){
		execstp->motherobj->s[stw_imm].d = 0;
	 	firep = s_makeobj_nowpos(execstp,S_green_kame,e_enemyfire);
		firep->s[stw_speedF].f = 40;
		firep->s[stw_speedY].f = 20;
		firep->s[stw_angleY].d = execstp->motherobj->s[stw_angleY].d;
	}
#endif

}

static int s_ai_pitch(short angle,float dist)
{

	if ( (s_chase_angleY(obj_targetangle,angle)) && (obj_playerdist < dist) ) return(1);
	else																	  
return(0);

}

static void motos_wait(void)
{ 
	obj_speedF = 0;
	obj_speedY = 0;
	s_set_skelanimeNo(ANM_motos_wait);

	if ( obj_playerdist < 500 )	obj_mode = mode_motos_player_search;

}

static void motos_player_search(void)
{

	s_set_skelanimeNo(ANM_motos_walk);

	obj_speedF = 2;
	s_chase_angleY(obj_targetangle,300);

	if ( execstp->s[stw_mail].d & EMAIL_CARRYMODE_ON ){
		obj_mode = mode_motos_player_carry;
	 	execstp->s[stw_imm].d = 1;
	}

}

static void motos_player_carry(void)
{

	s_set_skelanimeNo(ANM_motos_carry_start);
	if ( s_check_animeend() )	obj_mode = mode_motos_player_pitch;

}

static void motos_player_pitch(void)
{

	obj_speedF = 0;
	s_set_skelanimeNo(ANM_motos_pitch);
	if ( s_check_animenumber(14) ){
		execstp->s[stw_imm].d = 2;		/* nageru shyn kan	*/
		execstp->hit_counter = 10;		/* hit time wait!!	*/
	}
	if ( s_check_animeend() ){
		obj_mode = mode_motos_wait;
		Mbitclr(execstp->s[stw_mail].d,EMAIL_CARRYMODE_ON);
	}

}

static void motos_carry_start(void)
{ 
	s_set_skelanimeNo(ANM_motos_carry_start);
	if ( s_check_animeend() ){
		if ( s_ai_pitch(0x200,500) ) obj_mode = mode_motos_pitch;
		else			   			 obj_mode = mode_motos_carry_run;
	}		

}

static void motos_carry_run(void)
{

	obj_speedF = 5;

	s_set_skelanimeNo(ANM_motos_carry_run);
	if ( s_ai_pitch(0x200,500) ) obj_mode = mode_motos_pitch;
	else			   			 obj_mode = mode_motos_carry_run;

}

static void motos_pitch(void)
{ 
	obj_speedF = 0;
	s_set_skelanimeNo(ANM_motos_pitch);

	if ( s_check_animenumber(14) ){
		execstp->s[stw_imm].d = 0;
	}
	if ( s_check_animeend() )	obj_mode = mode_motos_wait;

}

static void motos_fly(void)
{

	s_set_skelanimeNo(ANM_motos_walk);
	
	if ( obj_movestatus & MOVESTAT_BGTOUCH ) obj_mode = mode_motos_wait;

}

static void motos_main(void)
{

	s_enemybgcheck();						/*  monky bgcheck 	*/

	switch (obj_mode){
		case		mode_motos_wait:		motos_wait();		break;
		case		mode_motos_player_search:		motos_player_search();		break;
		case		mode_motos_player_carry:		motos_player_carry();		break;
		case		mode_motos_player_pitch:		motos_player_pitch();		break;
		case		mode_motos_carry_start:		motos_carry_start();		break;
		case		mode_motos_carry_run:		motos_carry_run();		break;
		case		mode_motos_pitch:		motos_pitch();		break;
		case		mode_motos_fly:		motos_fly();		break;
	default: rmonpf(("Error objmode motos\n")); }

	s_enemymove(-78);							/*	monky moving 	*/

}

extern void s_motos(void)
{
	float	f,y;
	f = 5;
	y = 0;

	s_set_scale(2.0);

	Mbitset(execstp->s[stw_enemyinfo].d,ENEMYINFO_CARRY);

	switch(execstp->s[stw_actionmode].d){
		case	CHILEDMODE_NO_CATCH:	motos_main();									break;
		case	CHILEDMODE_CATCH:		s_mode_catch(ANM_motos_walk,mode_motos_wait);	break;
		case	CHILEDMODE_THROW:		s_mode_throw(f,y,mode_motos_fly);				break;
	 //	case	CHILEDMODE_DROP:		s_mode_drop();									break;
		case	CHILEDMODE_DROP:		s_mode_throw(f,y,mode_motos_fly);				break;
	}
	s_erase_shape(obj_playerdist,2000);
 
}

Behavior Code

e_motos:
e_motosman:
	p_initialize(option)
	p_killshape

Katsugikun

An enemy with an interesting tale. No actual model exists and the code file only has a header, but the number of remnants it had allowed it to possibly identify a mysterious render. Code remnants indicate it evolved from Motos and was possibly a boss variant of Chuckya, since Chuckya uses sounds labeled "Katsuginage". Interestingly, it's referenced in the Lethal Lava Land object shape bank.

Behavior Code & Remnants

#define NA_SE3_KATSUGI_WALK        0x50158081
#define NA_SE3_KATSUGINAGE_DOWN    0x516E0081        /** katsugi nage down **/
#define NA_LSE3_KATSUGINAGE_MOVE    0x600A4001        /* katugi nage */
#define                S_katugikun         S_B1_bankenemy_01

/********************************************************************************
        C Program (katsugi)
 ********************************************************************************/
extern void s_motoshand_main(float f,float v,long mail)
{
    switch (execstp->motherobj->s[stw_imm].d ){
         case    0:
            break;
        case    1:
            s_copy_mapwork(player1stp,execstp);
            break;
        case    2:
            player1stp->s[stw_mail].d |= ( PLAYERMAIL_CARRYMODE_OFF + mail );
            playerWorks[0].velocity = f; 
            playerWorks[0].speed[1] = v; 
            execstp->motherobj->s[stw_imm].d = 0;
            break;
        case    3:
            player1stp->s[stw_mail].d |= ( PLAYERMAIL_CARRYMODE_OFF + PLAYERMAIL_CARRYTHROW_SMALL );
            playerWorks[0].velocity = 10; 
            playerWorks[0].speed[1] = 10; 
            execstp->motherobj->s[stw_imm].d = 0;
            break;
    }
    obj_angleY = execstp->motherobj->s[stw_angleY].d;
    if ( execstp->motherobj->status == 0 )    s_remove_obj(execstp);
}

e_katsugi:
    p_initialize(enemyA)
    p_setbit(flag,stf_moveON | stf_YangleSAME | stf_playerdistON | stf_playerangleON | stf_alldispON )
    p_set_pointer(skelanime,bomking_anime)
    p_setd(objname,OBJNAME_TAKE)
    p_sethitbox(100,100)
    p_setmovedata(30,-400,-50,1000,1000,200,0,0)
    p_makeobj_child(S_NULL,e_bomking_hand)
    p_hitON
    p_save_nowpos
    p_while
        p_program(s_bomking)
    p_loop

e_katsugi_hand:
    p_initialize(enemyA)
    p_setbit(flag,stf_moveON | stf_YangleSAME )
    p_softspritemodeON
    p_while
        p_program(s_bomking_hand)
    p_loop

Test Lift

SM64-Testlift-InGame.png

Directory: "sm64/shape/keep/OLD/etc/testlift.sou"

Path (Behavior code): "sm64/data/p/pathtestlift.p"

A yellow test platform that was created to test out how elevators would work, and has an unused path file associated with it. A smaller .shape version of this model is left over in the final game, unused.

Behavior Code

/********************************************************************************

#define	road_root(p)		(p->s[stw_work2].pointer)
#define	road_pointer(p)		(p->s[stw_work3].pointer)
#define	road_flag(p)		(p->s[stw_work4].d)
#define	road_angleX(p)		(p->s[stw_work5].d)
#define	road_angleY(p)		(p->s[stw_work6].d)
#define	road_groundY(p)		(p->s[stw_work7].f)

 ********************************************************************************/

e_testlift:
	p_initialize(moveBG)
	p_setbit(flag,stf_moveON )
	p_movebginfo(testlift_info)
	p_while
		p_program(s_testlift)
	p_loop

/********************************************************************************

C Program (testlift)

 ********************************************************************************/

static short test_liftdata[] = {

	0,0,	0,1000,	/* (X),(Y),(Z) */
	1,1000, 100,1000,	/* (X),(Y),(Z) */
	2,1000, 200,   0,	/* (X),(Y),(Z) */
	3,   0, 100,   0,	/* (X),(Y),(Z) */
	-1,
};

extern void s_testlift(void)
{

	int	flag;

	road_root(execstp) = test_liftdata;		/* data read	*/

	flag = s_road_move(0);

	obj_speedF = 10;						/* set speed     */
	obj_angleX = road_angleX(execstp);		/* speed X Angle */
	obj_angleY = road_angleY(execstp);		/* speed Y Angle */

	s_3Dmove();
	stMainMoveBG();

	rmonpf(("%d,%d\n",flag,road_flag(execstp) ));

}

Dice

Directory: sm64/data/iwa_path/dice.s

A dice block with rudimentary physics that is meant to use a 50x50x50 cube. In its current state the object is a bit broken, the angle resets when it lands and only the X angle rotates, fixing them results in the object working as intended. Interestingly, this object lines up with a quote said by (Assisant Director) Yoshiaki Koizumi in an interview.

"I wanted to have more tools, toys, and things for Mario to play around with: balls, cars, etc. I really think we could have worked a lot more of those in."

Behavior Code

e_dice:
	p_initialize(enemyA)
	p_setbit(flag,stf_moveON |stf_YangleSAME | stf_catchON)
	p_setd(objname,OBJNAME_TAKE)
	p_BGcheckYset
	p_sethitbox(40,40)
	p_program(s_dice_init)

dice_main:
	p_while
		p_hitON
		p_program(s_diceMove)
	p_loop

extern void s_dice_init(void)
{

	execstp->s[stw_gravity].f   = 2.5;
	execstp->s[stw_friction].f  = 0.98;
	execstp->s[stw_specificG].f = 1.3;
	
}

static void DiceRotateEvent(void)
{
	short angleY = (short)execstp->s[stw_angleY].d ;

	execstp->s[stw_animeangleX].d += (short)(execstp->s[stw_speedF].f*500);


}

extern void DiceMoveEvent(void)
{
	short bg_flag = 0;
	float offsety;
		
	bg_flag = ObjMoveEvent();

	DiceRotateEvent();

	if ((bg_flag & 0x0001)!= 0x00) {
		offsety = sin(execstp->s[stw_animeangleX].d*2)*10;
		if (offsety < 0) offsety *= -1;
		execstp->s[stw_animepositionY].f = (offsety+25);


		if (execstp->s[stw_speedF].f < 5.0 && ( (int)offsety==10 || (int)offsety==0)) {
			execstp->s[stw_speedF].f = 0.0;
		}



	}

}

static void DiceCatch(void)
{

	MapHideShape(&execstp->map);


}

static void DiceDrop(void)
{

	s_drop_object();	

	execstp->s[stw_actionmode].d = CHILEDMODE_NO_CATCH;

}

static void DiceThrow(void)
{

	s_throw_object();	
	execstp->s[stw_actionmode].d = CHILEDMODE_NO_CATCH;
//	execstp->s[stw_flag].d &= (stf_YangleSAME^0xffffffff); 
	
	execstp->s[stw_speedF].f = 25.;
	execstp->s[stw_speedY].f = 20.;
	execstp->s[state_flag].d = 2;
}

extern void s_diceMove(void)
{

	switch(execstp->s[stw_actionmode].d) {
		case CHILEDMODE_NO_CATCH:	DiceMoveEvent();		break;
		case CHILEDMODE_CATCH:		DiceCatch();			break;
		case CHILEDMODE_THROW:		DiceThrow();			break;
		case CHILEDMODE_DROP:		DiceDrop();				break;
	}


}

Name-Only Objects

The only remaining data for these objects is their names, found either in include/funlike.h or include/tagdecode.h. The former appears to come from mid-to-late 1995, while the latter has remnants from late '95.

Snow Objects

e_koori, e_yukigoro, e_bigsnowman, e_icemotos

e_koori is an unknown object that could be related to the unused breakable ice object, as "koori" translates to "ice".

e_yukigoro appears to be a snowglobe object, as the name would suggest.

e_bigsnowman is a bigger variant of Mr. Blizzard. Interestingly, the final behavior appears to have a remnant from this version, as the size is still set with a value in the behavior header.

e_icemotos, as the name implies, was a variant of Motos; it was the original boss in Snowman's Land instead of the Big Chilly Bully. It likely functioned similarly to Motos.

Desert Objects

e_sun, e_gourem

e_sun might have been the Angry Sun from Super Mario Bros. 3.

e_gourem is a bit more interesting: its name suggests that it was possibly the original boss in Shifting Sand Land instead of Eyerock.

Water Objects

e_gesso, e_ufo

e_gesso was presumably a Blooper, easily identified thanks to it using its Japanese name.

e_ufo is more mysterious, however. It had a Star labeled ufo catcher, so it might have been related to a "UFO Catcher" (Claw Game)-style minigame.

Grass/Battlefield Objects

e_bigbomb, e_minipakun, e_groundmine

e_bigbomb was a later version of Katsugi, just before the final one. It appears to be a late change, as the Star name still references the old name, Big Bob-omb.

e_minipakun could be either the Nippers from Super Mario Bros. 3 or a smaller version of the regular Piranha Plant.

e_groundmine was a landmine object, possibly meant for Bob-omb Battlefield, considering it was designed with a "battlefield" theme in mind. May have been scrapped due to being a bit too difficult of an obstacle for the first level in the game. Perhaps notably, a landmine object can be found unused in Super Mario Galaxy. Maybe Nintendo doesn't like landmines?

Misc. Objects

e_coin_5, e_1up_tree, e_batta, e_rabbit, e_camerajugem

e_coin_5, as the name implies, was an early version of Blue Coins, possibly a stationary version of them.

e_1up_tree was replaced later in development by a more finished 1-Up tree.

e_batta is a bit more interesting: the name translated means "grasshopper", which could mean it was either an early version of the Crazy Box item or a later revision/implementation of Hopper, who still has a model in the leaked source code.

e_rabbit is likely an earlier version of MIPS, perhaps the same actor mentioned in an interview.

e_camerajugem is likely an earlier version of the Camera Lakitu/Lakitu Bro.

Underground Objects

e_namazu

This is one of the more intriguing enemies, as the name suggests that a giant catfish was planned for Hazy Maze Cave's underground. This object might have inspired how Mario needs to ground pound Dorrie to get on its head.

Funlike Objects

Objects that are in include/funlike.h, funlike is name of the format that Polygonal Collision uses, while the objects that are assigned to these ids have been updated, the names have not.

OBJSETCODE_PLAYER

What appears to be an early way to set the starting position for a player, called for in most stages flk files, now empty.

OBJSETCODE_STAR

Supposed to be a 2D Star, now empty.

OBJSETCODE_ELEVATOR

Likely an elevator object, calls for a now removed model, and static object.

OBJSETCODE_MAINROOM_TRAP

The floor trap that leads to BITDW, interestingly calls for a removed model.

OBJSETCODE_MOTOS_OBJ02

Removed LLL Object, a comment in the LLL Stage Object file labels it as "moving field", the Rolling Snowball in CCM is assigned instead.

OBJSETCODE_MOTOS_OBJ04

Another Removed LLL Stage Object, labeled as "bridge" in it's path file, now empty.

OBJSETCODE_MOTOS

Either Chuckya or an earlier version of Motos, overwritten by the Small Bully which is e_otos.

OBJSETCODE_BIGMOTOS

Likely the boss variant of Motos, overwritten by the Big Bully which is e_big_otos.

OBJSETCODE_BLOCK

Removed generic block, possibly a breakable brick block from previous games, now an empty definition.

OBJSETCODE_FIREMOTOS

What is possibly a fire throwing variant of motos, interestingly commented out code in pathmotos.p has it throwing a shell using e_enemyfire.

OBJSETCODE_FIREBAR

Likely a firebar as seen in previous games, another firebar object was created as a rotating stone, empty definition.

OBJSETCODE_LAVA

It appears lava was originally an object instead of a collision type, empty definition.

OBJSETCODE_FIRE

Likely a podobo from previous games, uses an empty definition.

OBJSETCODE_BIRD

What is likely Hoot, based on the name, empty definition.

OBJSETCODE_FLOWER

Either a Piranha Plant, Fire Flower, or a generic flower, empty definition.

OBJSETCODE_TREE4

Unused Tree Definition, refers to tree_04 from tree.sou

Object Placements

Snowman's Land - Cracked Ice

SM64 Internal CrackedIce.png

In sm64/maps/stage10/Sstage10.s, a commented-out object reveals that the unused cracked ice texture belongs to Snowman's Land. The line specifying the actor placement:...

seqActor(S_movebg02,  4377,1843,4361,  0,0,0,  0,0,0,  e_ice)

The coordinates result in it covering the hole above the ice maze's Star.