Please consider supporting The Cutting Room Floor on Patreon. Thanks for all your support!

Pajama Sam: Life is Rough When You Lose Your Stuff!

From The Cutting Room Floor
Jump to: navigation, search

Title Screen

Pajama Sam: Life is Rough When You Lose Your Stuff!

Developer: Humongous Entertainment
Publisher: Atari, SA
Platform: Windows
Released in US: 2003


SourceIcon.png This game has uncompiled source code.
MusicIcon.png This game has unused music.
SoundIcon.png This game has unused sounds.
TextIcon.png This game has unused text.
DebugIcon.png This game has debugging material.


PrereleaseIcon.png This game has a prerelease article

Produced after Atari bought Humongous Entertainment, Pajama Sam: Life is Rough When You Lose Your Stuff was the last game in the Junior Adventure line, known for being a relatively mediocre game for its lackluster voice acting and wandering story.

Despite all this, it still maintains somewhat of a following due to the extreme ease with which its resources can be modified.

Hmmm...
To do:
There's more.

Debug Rooms

Pajama-Sam-4-Debug.png

Here is the room debug screen, which allows you to jump to any room. It can be accessed by finding a line in one of the XML files located in the rooms.he file labeled "<nextRoom value = (room name)/>" to

<nextRoom value = "map"/>

This will make the room exit you specified take you to the debug screen instead. There are several things mentioned here that didn't make the final cut in the real game:

  • An area inside the aquarium (a background of it still exists in the files, though).
  • A lampcord area and a sidetable top connected to each other, which would link with the aquarium. You would reach this by going off the cliff where the fireflies were. In the final game it takes you straight to the aquarium, which completely messes up the layout.
  • The sidetable area also mentions a Roman soldier, which does have concept artwork but did not make the final cut.
  • Dr. Grime seems to be named Dr. Filth here.
  • The peanut is always picked up at the vista in normal gameplay, but this screen shows it could have been placed in the dust bunny corral too.
  • A separate area for the Chess bleachers is hinted at.

Pajama-Sam-4-Inventory-Cheat.PNG

Do the same as above to reach the inventory debug, but instead of "map" enter "inventoryCheat". This screen allows you to pick up any object at any time.

Unused Text

Subtitles exist for this game in all the XML files, but there's no possible way to turn them on. It is mentioned in the game's manual, though.

Unused Music

A single unused music file, aquarium_01.mp3, is present in the music.he folder. As the name implies, it was intended for the aquarium. It was very likely meant to be used when the aquarium interior mentioned in the debug rooms was going to be used, but since it didn't make the final cut this theme probably went along with it.

Unused Dialogue

Extracting the talkies.he file with 7-Zip will create multiple folders containing all the dialogue in the game.

The folder soiledsock-old contains the dirty sock's dialogue with a different voice actor that sounds more feminine, suggesting the dirty sock was originally female.

The grandma folder has some unused dialogue where, instead of needing yarn to knit Sam a sweater, her contact lens would have been lost and you would have to find it. It was probably an alternate path that was cut due to time constraints. According to more unused dialogue in the sam folder, you would use a static balloon to find her contact lens.

Hmmm...
To do:
Upload Sam's dialog as well.

Boot Script Source

Located near the end of the game's executable, the game runs this Python script on boot up.

#
#	Filename:	  boot.py
#	Contributors: Ben Crane
#	Notes:		  
#
#	Copyright© 2001 Humongous Entertainment
#
#	All rights reserved. Copying or other reproduction except for archival
#	purposes is prohibited without prior written consent.
#
#=============================================================================



#------------------------------------------------------------------------------
# Define true & false

import __builtin__
__builtin__.False				= 0
__builtin__.True				= 1
__builtin__.false               = __builtin__.False
__builtin__.true                = __builtin__.True

#------------------------------------------------------------------------------



#------------------------------------------------------------------------------
# Imported modules

import globals
import sys
import getopt

#------------------------------------------------------------------------------

# Import the HeDbg module and put it in the global namespace, so it will be available
# for everyone - including the debugger watch window.
# The try/except block is necessary because HeDbg will not exist if you aren't
# running under the debugger.
# This is done as early as possible so that the boot process can be monitored.
# Added by Bruce Dawson, July 19, 2002.
try:
	import HeDbg
	globals.HeDbg = HeDbg
except:
	pass

# Global timing system. Put named values into here representing, for instance,
# number of calls to a function, and they will be printed and zeroed each
# frame. For instance, to count calls to player_machine.__getattr__ you might
# put code like this at the beginning of it.
# A more robust timing system would be very useful.
#		value = timings.get("player_machine_attr", 0)
#		timings["player_machine_attr"] = value + 1
globals.timings = {}

# Utility function that uses the timing system to instrument all GetAttr
# functions. Just call it from each function and pass in a name
# and how much you want the count incremented by. Typically the count
# will be the 'cost' of the function, which is usually how many lines
# of code in it.
# You can insert code like this: RecordExecution(str(self.__class__), 10)
def RecordExecution( name, count ):
	value = globals.timings.get(name, 0)
	globals.timings[name] = value + count

# Handy/ugly way of making the instrumentation function globally available.
# Handy for debugging/optimising, but not recommended for day to day usage.
globals.RecordExecution = RecordExecution

#------------------------------------------------------------------------------


#------------------------------------------------------------------------------
# Python systems setup


if( globals.DEBUG_BUILD ):
	sys.path.append( "./lib" ) # extra debug libraries

# This sets it up so that the garbage collector's leak detection
# nags us whenever any objects are leaking due to circular references, etc.
if( globals.DEBUG_BUILD ):
	import gc
	gc.set_debug( gc.DEBUG_LEAK )

# Turn off case-sensitivity when searching for modules
import os
os.environ["PYTHONCASEOK"] = "0"

#------------------------------------------------------------------------------



#------------------------------------------------------------------------------
# Check for diedie.die and demo time-out

if( os.path.isfile( "diedie.die" ) ):
	raise "ERROR: A diedie.die file was found"
	sys.exit()

if( globals.DEMO_BUILD ):
	import time
	lc = time.localtime()
	timeout = false
	if( lc[0] > globals.DEMO_TIME_OUT_DATE[0] ):
		timeout = true
	elif( lc[0] == globals.DEMO_TIME_OUT_DATE[0] ):
		if( lc[1] > globals.DEMO_TIME_OUT_DATE[1] ):
			timeout = true
		elif( lc[1] == globals.DEMO_TIME_OUT_DATE[1] ):
			if( lc[2] >= globals.DEMO_TIME_OUT_DATE[2] ):
				timeout = true
				
	if( timeout ):
		print "This E3 game build has expired and can no longer be played. Keep your eyes open for Backyard Hockey in stores this fall."
		sys.exit()

#------------------------------------------------------------------------------



#------------------------------------------------------------------------------
def BOOT_Main( fullscreen=false, hardware=false ):
	"""BOOT SCRIPT -- MAIN ENTRY POINT FOR THE YAGA SYSTEM"""

	# set software or hardware mode
	if( hardware ):
		yagagraphics.GraphicsSystem().systemType = yagagraphics.GraphicsHardware.SYSTEM_HARDWARE
	else:
		yagagraphics.GraphicsSystem().systemType = yagagraphics.GraphicsHardware.SYSTEM_SOFTWARE

	# Initialize the render target
	try:
		BOOT_InitializeRenderTarget()
	except:
		if( yagagraphics.GraphicsSystem().systemType == yagagraphics.GraphicsHardware.SYSTEM_HARDWARE ):
			yagagraphics.GraphicsSystem().systemType = yagagraphics.GraphicsHardware.SYSTEM_SOFTWARE
			BOOT_InitializeRenderTarget()
		else:
			import traceback
			traceback.print_exc(None,sys.stderr)
			sys.exit()

	# Set the title to be the name of the project
	globals.g_RenderTarget.title = globals.PROJECT_NAME

	# Turn off the windows cursor
	globals.g_RenderTarget.cursorVisible = false

	# Perform setup operations and start the game
	
	print "YAGA: Boot process"
	print "Processing boot script..."

	# Import global objects
	print "Getting global objects..."
	globals.Init()

	# Initialize the main timer objects
	print "Initializing timer objects..."
	import main
	main.MAIN_InitializeTiming()

	# Log that we're starting
	BOOT_Log() 

	# Start the event loop
	globals.eventManager.StartEventLoop()

	# Log that we're done
	BOOT_Log(true)

	# Log profiling info
	if( globals.g_RunProfiler ):
		globals.g_Profiler.Dump()

	if globals.g_AutoPlayActive:
		globals.g_AutoPlayManager.Release()

	globals.Release()

	# We're done!
	print "Fin."

# def BOOT_Main()    
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
def BOOT_InitializeRenderTarget():
	
	try:
		# Try to create a 5-6-5 render target
		BOOT_CreateRenderTarget( globals.DEFAULT_WIDTH, globals.DEFAULT_HEIGHT, yagagraphics.PixelFormat.PXL_R5G6B5, globals.DEFAULT_BUFFERS, fullscreen )
	except:
		# Next, try to create a 5-5-5 render target
		BOOT_CreateRenderTarget( globals.DEFAULT_WIDTH, globals.DEFAULT_HEIGHT, yagagraphics.PixelFormat.PXL_X1R5G5B5, globals.DEFAULT_BUFFERS, fullscreen )

#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
def BOOT_EnumFullscreenModes( targetMode ):
	
	# try the primaryVideoDev first
	try:
		primDev = yagagraphics.GraphicsSystem().primaryVideoDev
	except:
		primDev = None
	
	if( primDev ):
		for mode in primDev.modes:
			if( (mode.width == targetMode.width) and (mode.height == targetMode.height) and
				(mode.format == targetMode.format) ):
					
				return primDev

	# try all of the video devices
	for dev in yagagraphics.GraphicsSystem().videoDevices:
		for mode in dev.modes:
			if( (mode.width == targetMode.width) and (mode.height == targetMode.height) and
				(mode.format == targetMode.format) ):
					
				return dev

	return None

#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
def BOOT_CreateRenderTarget( width, height, format, buffers, fullscreen ):
	
	if( yagagraphics.GraphicsSystem().systemType == yagagraphics.GraphicsHardware.SYSTEM_HARDWARE ):
		type = "hardware"
	else:
		type = "software" 

	print "Attempting to create a %s %s render target..." % ( YagaFormat2Str(format), type )

	vm = yagagraphics.VideoMode( width, height, format )
	device = BOOT_EnumFullscreenModes( vm )

	if( fullscreen ):
		targetType = yagagraphics.TargetType.TARGET_FULL_SCREEN
	else:
		targetType = yagagraphics.TargetType.TARGET_WINDOWED

	if( device ):
		
		if( (targetType == yagagraphics.TargetType.TARGET_WINDOWED) and
			(device.currentMode.format != format) ):
			print "WARNING: The desktop color depth should be set to %s to run in windowed mode!" % ( YagaFormat2Str(format) )
			print "WARNING: Switching format to %s" % ( YagaFormat2Str(device.currentMode.format) )
			vm.format = device.currentMode.format

		globals.g_RenderTarget = device.CreateRenderTarget( vm, buffers, targetType )	

	else:
		globals.g_RenderTarget = None
		print "ERROR: Unable to find a device with an acceptable %s format!" % ( YagaFormat2Str(format) )
		raise "Exception"

	if( not globals.g_RenderTarget ):
		print "ERROR: Unable to initialize the engine!"
		raise "Exception"

	return globals.g_RenderTarget

#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
def YagaFormat2Str( format ):
	
	if( format == yagagraphics.PixelFormat.PXL_R5G6B5 ):
		return "16-bit (5-6-5)"
	elif( format in [yagagraphics.PixelFormat.PXL_X1R5G5B5,
				   yagagraphics.PixelFormat.PXL_A1R5G5B5] ):
		return "16-bit (5-5-5)"
	elif( format == yagagraphics.PixelFormat.PXL_R8G8B8 ):
		return "24-bit"
	elif( format in [yagagraphics.PixelFormat.PXL_X8R8G8B8,
					 yagagraphics.PixelFormat.PXL_A8R8G8B8] ):
		return "32-bit"
    
  	return "UNKNOWN FORMAT" 
  
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
def BOOT_Log( end = false ):
	
	file = "count.txt"
			
	try:	

		if( os.path.isfile(os.path.join(globals.g_SaveGamePath,file)) ):	
	
			lines = open(os.path.join(globals.g_SaveGamePath,file),"r").readlines()			
			starts = int(lines[0].split()[1])
			ends = int(lines[1].split()[1])
	
		else:
			starts = 0
			ends = 0
		
		if( end ):
			ends += 1
		else:
			starts += 1	
	
		fobj = open(os.path.join(globals.g_SaveGamePath,file),"w")
		fobj.write( "starts: " + str(starts) + "\n" )
		fobj.write( "ends: " + str(ends) + "\n" )
		fobj.close()

	except:
		if( end ):
			print "WARNING: Unable to log end"
		else:
			print "WARNING: Unable to log start"

#------------------------------------------------------------------------------



#------------------------------------------------------------------------------
class CStdoutRedirect:

	#------------------------------------------------------------------------------
	def __init__( self, stdout = None ):

		try:
			self.__file = open( globals.PROJECT_NAME + ".log", "w" )
		except:
			self.__file = None
	
		self.__stdout = stdout

	#------------------------------------------------------------------------------

	#------------------------------------------------------------------------------
	def __del__( self ):

		if( self.__file ):
			self.__file.close()
			
			if( globals.g_PythonExceptionRaised ):
				try:
					fObj = open( globals.PROJECT_NAME + ".log", "r" )
				except:
					return
					
				lines = fObj.readlines()
				
				try:
					errFObj = open("lastcrash.txt","w")
				except:
					return
					
				for line in lines:
					errFObj.write(line)
					
				errFObj.close()

	#------------------------------------------------------------------------------

	#------------------------------------------------------------------------------
	def write( self, strOut ):

		if( self.__file ):
			self.__file.write( strOut )
	
		if( self.__stdout ):
			self.__stdout.write( strOut )

	#------------------------------------------------------------------------------

# class CStdoutRedirect
#------------------------------------------------------------------------------



#------------------------------------------------------------------------------
def PrintArgs():
	
	print "Command line args:"
	print "\t-f\tRun fullscreen (only valid in DEBUG)"
	print "\t-w\tRun windowed (only valid in RELEASE)"
	print "\t-l\tCreate %s.log file (only valid in DEBUG)" % ( globals.PROJECT_NAME )
	print "\t-u XXXX\tSets the USER global variable"
	print "\t-e\tRuns Maude, the menu editor"
	print "\t-v\tRuns the Bittie Viewer"
	print "\t-p\tEnables code profiling"
	print "\t-s\tForce software rendering"
	print "\t-m (yagabin|noyagabin)\tForces or removes yagabin from the module search path"
	print "\t-?\tPrint this help"

#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
if( __name__ == "__main__" ):

	log = false

	if( globals.DEBUG_BUILD ):
		fullscreen = false
	else:
		fullscreen = true

	# BUGBUG - use software rendering by default
	hwTarget = false
	#hwTarget = true

	try:
		optlist, args = getopt.getopt( sys.argv[1:], "?fwlevtpshu:m:" )
	except getopt.GetoptError:
		print "ERROR: Invalid args: %s" % ( sys.argv[1:] )
		PrintArgs()
		sys.exit()

	for o, a in optlist:
		if( o == "-f" ):
			fullscreen = true
		elif( o == "-w" ):
			fullscreen = false
		elif( o == "-l" ):
			log = true
		elif( o == "-u" ):
			globals.USER = a
			print "USER = " + globals.USER
		elif( o == "-e" ):
			#globals.INITIAL_SCENE = "maude"
			print "Maude menu editor not available for this projects."
		elif( o == "-v" ):
			globals.INITIAL_SCENE = "bittie_viewer"
		elif( o == "-t" ):
			globals.INITIAL_SCENE = "talkie_viewer"
		elif( o == "-p" ):
			globals.g_RunProfiler = true
		elif( o == "-s" ):
			hwTarget = false
		elif( o == "-h" ):
			hwTarget = true
		elif( o == "-m" ):
			if( a == "yagabin" ):
				if( "./yagabin" not in sys.path ):
					sys.path.append( "./yagabin" )
			elif( a == "noyagabin" ):
				if( "./yagabin" in sys.path ):
					sys.path.remove( "./yagabin" )
			else:
				print "ERROR: Invalid args: %s" % ( sys.argv[1:] )
				PrintArgs()
				sys.exit()
		elif( o == "-?" ):
			PrintArgs()
			sys.exit()

	if( log or (not globals.DEBUG_BUILD) ):
		
		if( globals.DEBUG_BUILD ):
			rout = CStdoutRedirect( sys.stdout )
		else:
			rout = CStdoutRedirect()

		sys.stdout = rout
		sys.stderr = rout

	# now that our paths have been finalized, we can import YAGA libs
	import yagagraphics
	
	BOOT_Main( fullscreen, hwTarget )

#------------------------------------------------------------------------------