Beispiel #1
0
/** Toggles a console variable. Useful for on/off values.
  *
  * This works on on/off, yes/no values only
  */
static void COM_Toggle_f(void)
{
	consvar_t *cvar;

	if (COM_Argc() != 2)
	{
		CONS_Printf(M_GetText("Toggle <cvar_name>: Toggle the value of a cvar\n"));
		return;
	}
	cvar = CV_FindVar(COM_Argv(1));
	if (!cvar)
	{
		CONS_Alert(CONS_NOTICE, M_GetText("%s is not a cvar\n"), COM_Argv(1));
		return;
	}

	if (!(cvar->PossibleValue == CV_YesNo || cvar->PossibleValue == CV_OnOff))
	{
		CONS_Alert(CONS_NOTICE, M_GetText("%s is not a boolean value\n"), COM_Argv(1));
		return;
	}

	// netcvar don't change imediately
	cvar->flags |= CV_SHOWMODIFONETIME;
	CV_AddValue(cvar, +1);
}
Beispiel #2
0
// Compile a script by name and dump it back to disk.
void LUA_DumpFile(const char *filename)
{
	FILE *handle;
	char filenamebuf[MAX_WADPATH];

	if (!gL) // Lua needs to be initialized
		LUA_ClearState(false);

	// find the file the SRB2 way
	strncpy(filenamebuf, filename, MAX_WADPATH);
	filenamebuf[MAX_WADPATH - 1] = '\0';
	filename = filenamebuf;
	if ((handle = fopen(filename, "rb")) == NULL)
	{
		// If we failed to load the file with the path as specified by
		// the user, strip the directories and search for the file.
		nameonly(filenamebuf);

		// If findfile finds the file, the full path will be returned
		// in filenamebuf == filename.
		if (findfile(filenamebuf, NULL, true))
		{
			if ((handle = fopen(filename, "rb")) == NULL)
			{
				CONS_Alert(CONS_ERROR, M_GetText("Can't open %s\n"), filename);
				return;
			}
		}
		else
		{
			CONS_Alert(CONS_ERROR, M_GetText("File %s not found.\n"), filename);
			return;
		}
	}
	fclose(handle);

	// pass the path we found to Lua
	// luaL_loadfile will open and read the file in as a Lua function
	if (luaL_loadfile(gL, filename)) {
		CONS_Alert(CONS_ERROR,"%s\n",lua_tostring(gL,-1));
		lua_pop(gL, 1);
		return;
	}

	// dump it back to disk
	if ((handle = fopen(filename, "wb")) == NULL)
		CONS_Alert(CONS_ERROR, M_GetText("Can't write to %s\n"), filename);
	if (lua_dump(gL, dumpWriter, handle))
		CONS_Printf("Failed while writing %s to disk... Sorry!\n", filename);
	else
		CONS_Printf("Successfully compiled %s into bytecode.\n", filename);
	fclose(handle);
	lua_pop(gL, 1); // function is still on stack after lua_dump
	lua_gc(gL, LUA_GCCOLLECT, 0);
	return;
}
Beispiel #3
0
boolean LUAh_PlayerHook(player_t *plr, enum hook which)
{
	hook_p hookp;
	boolean hooked = false;
	if (!gL || !(hooksAvailable[which/8] & (1<<(which%8))))
		return false;

	lua_settop(gL, 0);

	for (hookp = roothook; hookp; hookp = hookp->next)
		if (hookp->type == which)
		{
			if (lua_gettop(gL) == 0)
				LUA_PushUserdata(gL, plr, META_PLAYER);
			lua_pushfstring(gL, FMT_HOOKID, hookp->id);
			lua_gettable(gL, LUA_REGISTRYINDEX);
			lua_pushvalue(gL, -2);
			if (lua_pcall(gL, 1, 1, 0)) {
				if (!hookp->error || cv_debug & DBG_LUA)
					CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
				lua_pop(gL, 1);
				hookp->error = true;
				continue;
			}
			if (lua_toboolean(gL, -1))
				hooked = true;
			lua_pop(gL, 1);
		}

	lua_settop(gL, 0);
	return hooked;
}
Beispiel #4
0
// Add a new sound fx into a free sfx slot.
//
sfxenum_t S_AddSoundFx(const char *name, boolean singular, INT32 flags, boolean skinsound)
{
	sfxenum_t i, slot;

	if (skinsound)
		slot = sfx_skinsoundslot0;
	else
		slot = sfx_freeslot0;

	for (i = slot; i < NUMSFX; i++)
	{
		if (!S_sfx[i].priority)
		{
			strncpy(freeslotnames[i-sfx_freeslot0], name, 6);
			S_sfx[i].singularity = singular;
			S_sfx[i].priority = 60;
			S_sfx[i].pitch = flags;
			S_sfx[i].volume = -1;
			S_sfx[i].lumpnum = LUMPERROR;
			S_sfx[i].skinsound = -1;
			S_sfx[i].usefulness = -1;

			/// \todo if precached load it here
			S_sfx[i].data = NULL;
			return i;
		}
	}
	CONS_Alert(CONS_WARNING, M_GetText("No more free sound slots\n"));
	return 0;
}
Beispiel #5
0
static void ArchiveTables(void)
{
	int TABLESINDEX;
	UINT16 i, n;
	UINT8 e;

	if (!gL)
		return;

	TABLESINDEX = lua_gettop(gL);

	n = (UINT16)lua_objlen(gL, TABLESINDEX);
	for (i = 1; i <= n; i++)
	{
		lua_rawgeti(gL, TABLESINDEX, i);
		lua_pushnil(gL);
		while (lua_next(gL, -2))
		{
			ArchiveValue(TABLESINDEX, -2); // key should be either a number or a string, ArchiveValue can handle this.
			e = ArchiveValue(TABLESINDEX, -1);
			if (e == 1)
				n++; // the table contained a new table we'll have to archive. :(
			else if (e == 2)
			{
				lua_pushvalue(gL, -2);
				CONS_Alert(CONS_ERROR, "Type of value for table %d entry '%s' (%s) could not be archived!\n", i, lua_tostring(gL, -1), luaL_typename(gL, -1));
				lua_pop(gL, 1);
			}
			lua_pop(gL, 1);
		}
		lua_pop(gL, 1);
		WRITEUINT8(save_p, ARCH_TEND);
	}
}
Beispiel #6
0
// Hook for B_BuildTailsTiccmd by skin name
boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
{
	hook_p hookp;
	boolean hooked = false;
	if (!gL || !(hooksAvailable[hook_BotAI/8] & (1<<(hook_BotAI%8))))
		return false;

	lua_settop(gL, 0);

	for (hookp = roothook; hookp; hookp = hookp->next)
		if (hookp->type == hook_BotAI
		&& (hookp->s.skinname == NULL || !strcmp(hookp->s.skinname, ((skin_t*)tails->skin)->name)))
		{
			if (lua_gettop(gL) == 0)
			{
				LUA_PushUserdata(gL, sonic, META_MOBJ);
				LUA_PushUserdata(gL, tails, META_MOBJ);
			}
			lua_pushfstring(gL, FMT_HOOKID, hookp->id);
			lua_gettable(gL, LUA_REGISTRYINDEX);
			lua_pushvalue(gL, -3);
			lua_pushvalue(gL, -3);
			if (lua_pcall(gL, 2, 8, 0)) {
				if (!hookp->error || cv_debug & DBG_LUA)
					CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
				lua_pop(gL, 1);
				hookp->error = true;
				continue;
			}

			// This turns forward, backward, left, right, jump, and spin into a proper ticcmd for tails.
			if (lua_istable(gL, 2+1)) {
				boolean forward=false, backward=false, left=false, right=false, strafeleft=false, straferight=false, jump=false, spin=false;
#define CHECKFIELD(field) \
				lua_getfield(gL, 2+1, #field);\
				if (lua_toboolean(gL, -1))\
					field = true;\
				lua_pop(gL, 1);

				CHECKFIELD(forward)
				CHECKFIELD(backward)
				CHECKFIELD(left)
				CHECKFIELD(right)
				CHECKFIELD(strafeleft)
				CHECKFIELD(straferight)
				CHECKFIELD(jump)
				CHECKFIELD(spin)
#undef CHECKFIELD
				B_KeysToTiccmd(tails, cmd, forward, backward, left, right, strafeleft, straferight, jump, spin);
			} else
				B_KeysToTiccmd(tails, cmd, lua_toboolean(gL, 2+1), lua_toboolean(gL, 2+2), lua_toboolean(gL, 2+3), lua_toboolean(gL, 2+4), lua_toboolean(gL, 2+5), lua_toboolean(gL, 2+6), lua_toboolean(gL, 2+7), lua_toboolean(gL, 2+8));

			lua_pop(gL, 8);
			hooked = true;
		}

	lua_settop(gL, 0);
	return hooked;
}
Beispiel #7
0
// Panic function Lua calls when there's an unprotected error.
// This function cannot return. Lua would kill the application anyway if it did.
FUNCNORETURN static int LUA_Panic(lua_State *L)
{
	CONS_Alert(CONS_ERROR,"LUA PANIC! %s\n",lua_tostring(L,-1));
	I_Error("An unfortunate Lua processing error occurred in the exe itself. This is not a scripting error on your part.");
#ifndef __GNUC__
	return -1;
#endif
}
Beispiel #8
0
/** Adds text into the command buffer for later execution.
  *
  * \param ptext The text to add.
  * \sa COM_BufInsertText
  */
void COM_BufAddText(const char *ptext)
{
	size_t l;

	l = strlen(ptext);

	if (com_text.cursize + l >= com_text.maxsize)
	{
		CONS_Alert(CONS_WARNING, M_GetText("Command buffer full!\n"));
		return;
	}
	VS_Write(&com_text, ptext, l);
}
Beispiel #9
0
// Hook for player chat
boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg)
{
	hook_p hookp;
	boolean hooked = false;
	if (!gL || !(hooksAvailable[hook_PlayerMsg/8] & (1<<(hook_PlayerMsg%8))))
		return false;

	lua_settop(gL, 0);

	for (hookp = roothook; hookp; hookp = hookp->next)
		if (hookp->type == hook_PlayerMsg)
		{
			if (lua_gettop(gL) == 0)
			{
				LUA_PushUserdata(gL, &players[source], META_PLAYER); // Source player
				if (flags & 2 /*HU_CSAY*/) { // csay TODO: make HU_CSAY accessible outside hu_stuff.c
					lua_pushinteger(gL, 3); // type
					lua_pushnil(gL); // target
				} else if (target == -1) { // sayteam
					lua_pushinteger(gL, 1); // type
					lua_pushnil(gL); // target
				} else if (target == 0) { // say
					lua_pushinteger(gL, 0); // type
					lua_pushnil(gL); // target
				} else { // sayto
					lua_pushinteger(gL, 2); // type
					LUA_PushUserdata(gL, &players[target-1], META_PLAYER); // target
				}
				lua_pushstring(gL, msg); // msg
			}
			lua_pushfstring(gL, FMT_HOOKID, hookp->id);
			lua_gettable(gL, LUA_REGISTRYINDEX);
			lua_pushvalue(gL, -5);
			lua_pushvalue(gL, -5);
			lua_pushvalue(gL, -5);
			lua_pushvalue(gL, -5);
			if (lua_pcall(gL, 4, 1, 0)) {
				if (!hookp->error || cv_debug & DBG_LUA)
					CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
				lua_pop(gL, 1);
				hookp->error = true;
				continue;
			}
			if (lua_toboolean(gL, -1))
				hooked = true;
			lua_pop(gL, 1);
		}

	lua_settop(gL, 0);
	return hooked;
}
Beispiel #10
0
boolean LUA_CallAction(const char *csaction, mobj_t *actor)
{
	I_Assert(csaction != NULL);
	I_Assert(actor != NULL);

	if (!gL) // Lua isn't loaded,
		return false; // action not called.

	if (superstack && fasticmp(csaction, superactions[superstack-1])) // the action is calling itself,
		return false; // let it call the hardcoded function instead.

	// grab function by uppercase name.
	lua_getfield(gL, LUA_REGISTRYINDEX, LREG_ACTIONS);
	{
		char *action = Z_StrDup(csaction);
		strupr(action);
		lua_getfield(gL, -1, action);
		Z_Free(action);
	}
	lua_remove(gL, -2); // pop LREG_ACTIONS

	if (lua_isnil(gL, -1)) // no match
	{
		lua_pop(gL, 1); // pop nil
		return false; // action not called.
	}

	if (superstack == MAXRECURSION)
	{
		CONS_Alert(CONS_WARNING, "Max Lua Action recursion reached! Cool it on the calling A_Action functions from inside A_Action functions!\n");
		return true;
	}

	// Found a function.
	// Call it with (actor, var1, var2)
	I_Assert(lua_isfunction(gL, -1));
	LUA_PushUserdata(gL, actor, META_MOBJ);
	lua_pushinteger(gL, var1);
	lua_pushinteger(gL, var2);

	superactions[superstack] = csaction;
	++superstack;

	LUA_Call(gL, 3);

	--superstack;
	superactions[superstack] = NULL;
	return true; // action successfully called.
}
Beispiel #11
0
// Load a script from a MYFILE
static inline void LUA_LoadFile(MYFILE *f, char *name)
{
	if (!name)
		name = wadfiles[f->wad]->filename;
	CONS_Printf("Loading Lua script from %s\n", name);
	if (!gL) // Lua needs to be initialized
		LUA_ClearState();
	lua_pushinteger(gL, f->wad);
	lua_setfield(gL, LUA_REGISTRYINDEX, "WAD");
	if (luaL_loadbuffer(gL, f->data, f->size, va("@%s",name)) || lua_pcall(gL, 0, 0, 0)) {
		CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
		lua_pop(gL,1);
	}
	lua_gc(gL, LUA_GCCOLLECT, 0);
}
Beispiel #12
0
/** Parses a single line of text into arguments and tries to execute it.
  * The text can come from the command buffer, a remote client, or stdin.
  *
  * \param ptext A single line of text.
  */
static void COM_ExecuteString(char *ptext)
{
	xcommand_t *cmd;
	cmdalias_t *a;
	static INT32 recursion = 0; // detects recursion and stops it if it goes too far

	COM_TokenizeString(ptext);

	// execute the command line
	if (COM_Argc() == 0)
		return; // no tokens

	// check functions
	for (cmd = com_commands; cmd; cmd = cmd->next)
	{
		if (!stricmp(com_argv[0], cmd->name)) //case insensitive now that we have lower and uppercase!
		{
			recursion = 0;
			cmd->function();
			return;
		}
	}

	// check aliases
	for (a = com_alias; a; a = a->next)
	{
		if (!stricmp(com_argv[0], a->name))
		{
			if (recursion > MAX_ALIAS_RECURSION)
			{
				CONS_Alert(CONS_WARNING, M_GetText("Alias recursion cycle detected!\n"));
				recursion = 0;
				return;
			}
			recursion++;
			COM_BufInsertText(a->value);
			return;
		}
	}

	recursion = 0;

	// check cvars
	// Hurdler: added at Ebola's request ;)
	// (don't flood the console in software mode with bad gr_xxx command)
	if (!CV_Command() && con_destlines)
		CONS_Printf(M_GetText("Unknown command '%s'\n"), COM_Argv(0));
}
Beispiel #13
0
static void ArchiveExtVars(void *pointer, const char *ptype)
{
	int TABLESINDEX;
	UINT16 i;

	if (!gL) {
		if (fastcmp(ptype,"player")) // players must always be included, even if no vars
			WRITEUINT16(save_p, 0);
		return;
	}

	TABLESINDEX = lua_gettop(gL);

	lua_getfield(gL, LUA_REGISTRYINDEX, LREG_EXTVARS);
	I_Assert(lua_istable(gL, -1));
	lua_pushlightuserdata(gL, pointer);
	lua_rawget(gL, -2);
	lua_remove(gL, -2); // pop LREG_EXTVARS

	if (!lua_istable(gL, -1))
	{ // no extra values table
		lua_pop(gL, 1);
		if (fastcmp(ptype,"player")) // players must always be included, even if no vars
			WRITEUINT16(save_p, 0);
		return;
	}

	lua_pushnil(gL);
	for (i = 0; lua_next(gL, -2); i++)
		lua_pop(gL, 1);

	if (i == 0 && !fastcmp(ptype,"player")) // skip anything that has an empty table and isn't a player.
		return;
	if (fastcmp(ptype,"mobj")) // mobjs must write their mobjnum as a header
		WRITEUINT32(save_p, ((mobj_t *)pointer)->mobjnum);
	WRITEUINT16(save_p, i);
	lua_pushnil(gL);
	while (lua_next(gL, -2))
	{
		I_Assert(lua_type(gL, -2) == LUA_TSTRING);
		WRITESTRING(save_p, lua_tostring(gL, -2));
		if (ArchiveValue(TABLESINDEX, -1) == 2)
			CONS_Alert(CONS_ERROR, "Type of value for %s entry '%s' (%s) could not be archived!\n", ptype, lua_tostring(gL, -2), luaL_typename(gL, -1));
		lua_pop(gL, 1);
	}

	lua_pop(gL, 1);
}
Beispiel #14
0
// Hook for P_DamageMobj by mobj type (Should mobj take damage?)
UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage)
{
	hook_p hookp;
	UINT8 shouldDamage = 0; // 0 = default, 1 = force yes, 2 = force no.
	if (!gL || !(hooksAvailable[hook_ShouldDamage/8] & (1<<(hook_ShouldDamage%8))))
		return 0;

	lua_settop(gL, 0);

	for (hookp = roothook; hookp; hookp = hookp->next)
		if (hookp->type == hook_ShouldDamage
		&& (hookp->s.mt == MT_NULL || hookp->s.mt == target->type))
		{
			if (lua_gettop(gL) == 0)
			{
				LUA_PushUserdata(gL, target, META_MOBJ);
				LUA_PushUserdata(gL, inflictor, META_MOBJ);
				LUA_PushUserdata(gL, source, META_MOBJ);
				lua_pushinteger(gL, damage);
			}
			lua_pushfstring(gL, FMT_HOOKID, hookp->id);
			lua_gettable(gL, LUA_REGISTRYINDEX);
			lua_pushvalue(gL, -5);
			lua_pushvalue(gL, -5);
			lua_pushvalue(gL, -5);
			lua_pushvalue(gL, -5);
			if (lua_pcall(gL, 4, 1, 0)) {
				if (!hookp->error || cv_debug & DBG_LUA)
					CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
				lua_pop(gL, 1);
				hookp->error = true;
				continue;
			}
			if (!lua_isnil(gL, -1))
			{
				if (lua_toboolean(gL, -1))
					shouldDamage = 1; // Force yes
				else
					shouldDamage = 2; // Force no
			}
			lua_pop(gL, 1);
		}

	lua_settop(gL, 0);
	return shouldDamage;
}
Beispiel #15
0
/** Checks the server to see if we CAN download all the files,
  * before starting to create them and requesting.
  *
  * \return True if we can download all the files
  *
  */
boolean CL_CheckDownloadable(void)
{
	UINT8 i,dlstatus = 0;

	for (i = 0; i < fileneedednum; i++)
		if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN && fileneeded[i].important)
		{
			if (fileneeded[i].willsend == 1)
				continue;

			if (fileneeded[i].willsend == 0)
				dlstatus = 1;
			else //if (fileneeded[i].willsend == 2)
				dlstatus = 2;
		}

	// Downloading locally disabled
	if (!dlstatus && M_CheckParm("-nodownload"))
		dlstatus = 3;

	if (!dlstatus)
		return true;

	// not downloadable, put reason in console
	CONS_Alert(CONS_NOTICE, M_GetText("You need additional files to connect to this server:\n"));
	for (i = 0; i < fileneedednum; i++)
		if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN && fileneeded[i].important)
		{
			CONS_Printf(" * \"%s\" (%dK)", fileneeded[i].filename, fileneeded[i].totalsize >> 10);

				if (fileneeded[i].status == FS_NOTFOUND)
					CONS_Printf(M_GetText(" not found, md5: "));
				else if (fileneeded[i].status == FS_MD5SUMBAD)
					CONS_Printf(M_GetText(" wrong version, md5: "));

			{
				INT32 j;
				char md5tmp[33];
				for (j = 0; j < 16; j++)
					sprintf(&md5tmp[j*2], "%02x", fileneeded[i].md5sum[j]);
				CONS_Printf("%s", md5tmp);
			}
			CONS_Printf("\n");
		}
Beispiel #16
0
fixed_t LUA_EvalMath(const char *word)
{
	lua_State *L = NULL;
	char buf[1024], *b;
	const char *p;
	fixed_t res = 0;

	// make a new state so SOC can't interefere with scripts
	// allocate state
	L = lua_newstate(LUA_Alloc, NULL);
	lua_atpanic(L, LUA_Panic);

	// open only enum lib
	lua_pushcfunction(L, LUA_EnumLib);
	lua_pushboolean(L, true);
	lua_call(L, 1, 0);

	// change ^ into ^^ for Lua.
	strcpy(buf, "return ");
	b = buf+strlen(buf);
	for (p = word; *p && b < &buf[1022]; p++)
	{
		*b++ = *p;
		if (*p == '^')
			*b++ = '^';
	}
	*b = '\0';

	// eval string.
	lua_pop(L, -1);
	if (luaL_dostring(L, buf))
	{
		p = lua_tostring(L, -1);
		while (*p++ != ':' && *p) ;
		p += 3; // "1: "
		CONS_Alert(CONS_WARNING, "%s\n", p);
	}
	else
		res = lua_tointeger(L, -1);

	// clean up and return.
	lua_close(L);
	return res;
}
Beispiel #17
0
boolean I_SetSongTrack(INT32 track)
{
	if (track != current_track) // If the track's already playing, then why bother?
	{
		FMOD_RESULT e;

		#ifdef HAVE_LIBGME
		// If the specified track is within the number of tracks playing, then change it
		if (gme)
		{
			if (track >= 0
				&& track < gme_track_count(gme))
			{
				gme_err_t gme_e = gme_start_track(gme,track);
				if (gme_e == NULL)
				{
					current_track = track;
					return true;
				}
				else
					CONS_Alert(CONS_ERROR, "Encountered GME error: %s\n", gme_e);
			}
			return false;
		}
		#endif // HAVE_LIBGME

		// Try to set it via FMOD
		e = FMOD_Channel_SetPosition(music_channel, (UINT32)track, FMOD_TIMEUNIT_MODORDER);
		if (e == FMOD_OK) // We good
		{
			current_track = track;
			return true;
		}
		else if (e == FMOD_ERR_UNSUPPORTED // Only music modules, numbnuts!
				|| e == FMOD_ERR_INVALID_POSITION) // Out-of-bounds!
			return false;
		else // Congrats, you horribly broke it somehow
		{
			FMR_MUSIC(e);
			return false;
		}
	}
	return false;
}
Beispiel #18
0
// Hook for frame (after mobj and player thinkers)
void LUAh_ThinkFrame(void)
{
	hook_p hookp;
	if (!gL || !(hooksAvailable[hook_ThinkFrame/8] & (1<<(hook_ThinkFrame%8))))
		return;

	for (hookp = roothook; hookp; hookp = hookp->next)
		if (hookp->type == hook_ThinkFrame)
		{
			lua_pushfstring(gL, FMT_HOOKID, hookp->id);
			lua_gettable(gL, LUA_REGISTRYINDEX);
			if (lua_pcall(gL, 0, 0, 0)) {
				if (!hookp->error || cv_debug & DBG_LUA)
					CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
				lua_pop(gL, 1);
				hookp->error = true;
			}
		}
}
Beispiel #19
0
// Hook for mobj collisions
UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which)
{
	hook_p hookp;
	UINT8 shouldCollide = 0; // 0 = default, 1 = force yes, 2 = force no.
	if (!gL || !(hooksAvailable[which/8] & (1<<(which%8))))
		return 0;

	lua_settop(gL, 0);

	for (hookp = roothook; hookp; hookp = hookp->next)
		if (hookp->type == which
		&& (hookp->s.mt == MT_NULL || hookp->s.mt == thing1->type))
		{
			if (lua_gettop(gL) == 0)
			{
				LUA_PushUserdata(gL, thing1, META_MOBJ);
				LUA_PushUserdata(gL, thing2, META_MOBJ);
			}
			lua_pushfstring(gL, FMT_HOOKID, hookp->id);
			lua_gettable(gL, LUA_REGISTRYINDEX);
			lua_pushvalue(gL, -3);
			lua_pushvalue(gL, -3);
			if (lua_pcall(gL, 2, 1, 0)) {
				if (!hookp->error || cv_debug & DBG_LUA)
					CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
				lua_pop(gL, 1);
				hookp->error = true;
				continue;
			}
			if (!lua_isnil(gL, -1))
			{ // if nil, leave shouldCollide = 0.
				if (lua_toboolean(gL, -1))
					shouldCollide = 1; // Force yes
				else
					shouldCollide = 2; // Force no
			}
			lua_pop(gL, 1);
		}

	lua_settop(gL, 0);
	return shouldCollide;
}
Beispiel #20
0
// Hook for P_DamageMobj by mobj type (Mobj actually takes damage!)
boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage)
{
	hook_p hookp;
	boolean hooked = false;
	if (!gL || !(hooksAvailable[hook_MobjDamage/8] & (1<<(hook_MobjDamage%8))))
		return 0;

	lua_settop(gL, 0);

	for (hookp = roothook; hookp; hookp = hookp->next)
		if (hookp->type == hook_MobjDamage
		&& (hookp->s.mt == MT_NULL || hookp->s.mt == target->type))
		{
			if (lua_gettop(gL) == 0)
			{
				LUA_PushUserdata(gL, target, META_MOBJ);
				LUA_PushUserdata(gL, inflictor, META_MOBJ);
				LUA_PushUserdata(gL, source, META_MOBJ);
				lua_pushinteger(gL, damage);
			}
			lua_pushfstring(gL, FMT_HOOKID, hookp->id);
			lua_gettable(gL, LUA_REGISTRYINDEX);
			lua_pushvalue(gL, -5);
			lua_pushvalue(gL, -5);
			lua_pushvalue(gL, -5);
			lua_pushvalue(gL, -5);
			if (lua_pcall(gL, 4, 1, 0)) {
				if (!hookp->error || cv_debug & DBG_LUA)
					CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
				lua_pop(gL, 1);
				hookp->error = true;
				continue;
			}
			if (lua_toboolean(gL, -1))
				hooked = true;
			lua_pop(gL, 1);
		}

	lua_settop(gL, 0);
	return hooked;
}
Beispiel #21
0
// Helper function for "objects" search
static UINT8 lib_searchBlockmap_Objects(lua_State *L, INT32 x, INT32 y, mobj_t *thing)
{
	mobj_t *mobj, *bnext = NULL;

	if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight)
		return 0;

	// Check interaction with the objects in the blockmap.
	for (mobj = blocklinks[y*bmapwidth + x]; mobj; mobj = bnext)
	{
		P_SetTarget(&bnext, mobj->bnext); // We want to note our reference to bnext here incase it is MF_NOTHINK and gets removed!
		if (mobj == thing)
			continue; // our thing just found itself, so move on
		lua_pushvalue(L, 1); // push function
		LUA_PushUserdata(L, thing, META_MOBJ);
		LUA_PushUserdata(L, mobj, META_MOBJ);
		if (lua_pcall(gL, 2, 1, 0)) {
			if (!blockfuncerror || cv_debug & DBG_LUA)
				CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
			lua_pop(gL, 1);
			blockfuncerror = true;
			return 0; // *shrugs*
		}
		if (!lua_isnil(gL, -1))
		{ // if nil, continue
			if (lua_toboolean(gL, -1))
				return 2; // stop whole search
			else
				return 1; // stop block search
		}
		lua_pop(gL, 1);
		if (P_MobjWasRemoved(thing) // func just popped our thing, cannot continue.
		|| (bnext && P_MobjWasRemoved(bnext))) // func just broke blockmap chain, cannot continue.
		{
			P_SetTarget(&bnext, NULL);
			return (P_MobjWasRemoved(thing)) ? 2 : 1;
		}
	}
	return 0;
}
Beispiel #22
0
// Hook for hurt messages
boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source)
{
	hook_p hookp;
	boolean hooked = false;
	if (!gL || !(hooksAvailable[hook_HurtMsg/8] & (1<<(hook_HurtMsg%8))))
		return false;

	lua_settop(gL, 0);

	for (hookp = roothook; hookp; hookp = hookp->next)
		if (hookp->type == hook_HurtMsg
		&& (hookp->s.mt == MT_NULL || (inflictor && hookp->s.mt == inflictor->type)))
		{
			if (lua_gettop(gL) == 0)
			{
				LUA_PushUserdata(gL, player, META_PLAYER);
				LUA_PushUserdata(gL, inflictor, META_MOBJ);
				LUA_PushUserdata(gL, source, META_MOBJ);
			}
			lua_pushfstring(gL, FMT_HOOKID, hookp->id);
			lua_gettable(gL, LUA_REGISTRYINDEX);
			lua_pushvalue(gL, -4);
			lua_pushvalue(gL, -4);
			lua_pushvalue(gL, -4);
			if (lua_pcall(gL, 3, 1, 0)) {
				if (!hookp->error || cv_debug & DBG_LUA)
					CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
				lua_pop(gL, 1);
				hookp->error = true;
				continue;
			}
			if (lua_toboolean(gL, -1))
				hooked = true;
			lua_pop(gL, 1);
		}

	lua_settop(gL, 0);
	return hooked;
}
Beispiel #23
0
// Hook for P_TouchSpecialThing by mobj type
boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher)
{
	hook_p hookp;
	boolean hooked = false;
	if (!gL || !(hooksAvailable[hook_TouchSpecial/8] & (1<<(hook_TouchSpecial%8))))
		return 0;

	lua_settop(gL, 0);

	for (hookp = roothook; hookp; hookp = hookp->next)
		if (hookp->type == hook_TouchSpecial
		&& (hookp->s.mt == MT_NULL || hookp->s.mt == special->type))
		{
			if (lua_gettop(gL) == 0)
			{
				LUA_PushUserdata(gL, special, META_MOBJ);
				LUA_PushUserdata(gL, toucher, META_MOBJ);
			}
			lua_pushfstring(gL, FMT_HOOKID, hookp->id);
			lua_gettable(gL, LUA_REGISTRYINDEX);
			lua_pushvalue(gL, -3);
			lua_pushvalue(gL, -3);
			if (lua_pcall(gL, 2, 1, 0)) {
				if (!hookp->error || cv_debug & DBG_LUA)
					CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
				lua_pop(gL, 1);
				hookp->error = true;
				continue;
			}
			if (lua_toboolean(gL, -1))
				hooked = true;
			lua_pop(gL, 1);
		}

	lua_settop(gL, 0);
	return hooked;
}
Beispiel #24
0
// Hook for B_BuildTiccmd
boolean LUAh_BotTiccmd(player_t *bot, ticcmd_t *cmd)
{
	hook_p hookp;
	boolean hooked = false;
	if (!gL || !(hooksAvailable[hook_BotTiccmd/8] & (1<<(hook_BotTiccmd%8))))
		return false;

	lua_settop(gL, 0);

	for (hookp = roothook; hookp; hookp = hookp->next)
		if (hookp->type == hook_BotTiccmd)
		{
			if (lua_gettop(gL) == 0)
			{
				LUA_PushUserdata(gL, bot, META_PLAYER);
				LUA_PushUserdata(gL, cmd, META_TICCMD);
			}
			lua_pushfstring(gL, FMT_HOOKID, hookp->id);
			lua_gettable(gL, LUA_REGISTRYINDEX);
			lua_pushvalue(gL, -3);
			lua_pushvalue(gL, -3);
			if (lua_pcall(gL, 2, 1, 0)) {
				if (!hookp->error || cv_debug & DBG_LUA)
					CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
				lua_pop(gL, 1);
				hookp->error = true;
				continue;
			}
			if (lua_toboolean(gL, -1))
				hooked = true;
			lua_pop(gL, 1);
		}

	lua_settop(gL, 0);
	return hooked;
}
Beispiel #25
0
//
// D_CheckNetGame
// Works out player numbers among the net participants
//
boolean D_CheckNetGame(void)
{
	boolean ret = false;

	InitAck();
	rebound_tail = rebound_head = 0;

	statstarttic = I_GetTime();

	I_NetGet = Internal_Get;
	I_NetSend = Internal_Send;
	I_NetCanSend = NULL;
	I_NetCloseSocket = NULL;
	I_NetFreeNodenum = Internal_FreeNodenum;
	I_NetMakeNodewPort = NULL;

	hardware_MAXPACKETLENGTH = MAXPACKETLENGTH;
	net_bandwidth = 30000;
	// I_InitNetwork sets doomcom and netgame
	// check and initialize the network driver
	multiplayer = false;

	// only dos version with external driver will return true
	netgame = I_InitNetwork();
	if (!netgame && !I_NetOpenSocket)
	{
		D_SetDoomcom();
		netgame = I_InitTcpNetwork();
	}

	if (netgame)
		ret = true;
	if (!server && netgame)
		netgame = false;
	server = true; // WTF? server always true???
		// no! The deault mode is server. Client is set elsewhere
		// when the client executes connect command.
	doomcom->ticdup = 1;

	if (M_CheckParm("-extratic"))
	{
		if (M_IsNextParm())
			doomcom->extratics = (INT16)atoi(M_GetNextParm());
		else
			doomcom->extratics = 1;
		CONS_Printf(M_GetText("Set extratics to %d\n"), doomcom->extratics);
	}

	if (M_CheckParm("-bandwidth"))
	{
		if (M_IsNextParm())
		{
			net_bandwidth = atoi(M_GetNextParm());
			if (net_bandwidth < 1000)
				net_bandwidth = 1000;
			if (net_bandwidth > 100000)
				hardware_MAXPACKETLENGTH = MAXPACKETLENGTH;
			CONS_Printf(M_GetText("Network bandwidth set to %d\n"), net_bandwidth);
		}
		else
			I_Error("usage: -bandwidth <byte_per_sec>");
	}

	software_MAXPACKETLENGTH = hardware_MAXPACKETLENGTH;
	if (M_CheckParm("-packetsize"))
	{
		if (M_IsNextParm())
		{
			INT32 p = atoi(M_GetNextParm());
			if (p < 75)
				p = 75;
			if (p > hardware_MAXPACKETLENGTH)
				p = hardware_MAXPACKETLENGTH;
			software_MAXPACKETLENGTH = (UINT16)p;
		}
		else
			I_Error("usage: -packetsize <bytes_per_packet>");
	}

	if (netgame)
		multiplayer = true;

	if (doomcom->id != DOOMCOM_ID)
		I_Error("Doomcom buffer invalid!");
	if (doomcom->numnodes > MAXNETNODES)
		I_Error("Too many nodes (%d), max:%d", doomcom->numnodes, MAXNETNODES);

	netbuffer = (doomdata_t *)(void *)&doomcom->data;

#ifdef DEBUGFILE
#ifdef _arch_dreamcast
	//debugfile = stderr;
	if (debugfile)
			CONS_Printf(M_GetText("debug output to: %s\n"), "STDERR");
#else
	if (M_CheckParm("-debugfile"))
	{
		char filename[20];
		INT32 k = doomcom->consoleplayer - 1;
		if (M_IsNextParm())
			k = atoi(M_GetNextParm()) - 1;
		while (!debugfile && k < MAXPLAYERS)
		{
			k++;
			sprintf(filename, "debug%d.txt", k);
			debugfile = fopen(filename, "w");
		}
		if (debugfile)
			CONS_Printf(M_GetText("debug output to: %s\n"), filename);
		else
			CONS_Alert(CONS_WARNING, M_GetText("cannot debug output to file %s!\n"), filename);
	}
#endif
#endif

	D_ClientServerInit();

	return ret;
}
Beispiel #26
0
void Got_Luacmd(UINT8 **cp, INT32 playernum)
{
	UINT8 i, argc, flags;
	char buf[256];

	// don't use I_Assert here, goto the deny code below
	// to clean up and kick people who try nefarious exploits
	// like sending random junk lua commands to crash the server

	if (!gL) goto deny;
	lua_getfield(gL, LUA_REGISTRYINDEX, "COM_Command"); // push COM_Command
	if (!lua_istable(gL, -1)) goto deny;

	argc = READUINT8(*cp);
	READSTRINGN(*cp, buf, 255);
	strlwr(buf); // must lowercase buffer
	lua_getfield(gL, -1, buf); // push command info table
	if (!lua_istable(gL, -1)) goto deny;

	lua_remove(gL, -2); // pop COM_Command

	lua_rawgeti(gL, -1, 2); // push flags from command info table
	if (lua_isboolean(gL, -1))
		flags = (lua_toboolean(gL, -1) ? 1 : 0);
	else
		flags = (UINT8)lua_tointeger(gL, -1);
	lua_pop(gL, 1); // pop flags

	// requires server/admin and the player is not one of them
	if ((flags & 1) && playernum != serverplayer && !IsPlayerAdmin(playernum))
		goto deny;

	lua_rawgeti(gL, -1, 1); // push function from command info table

	// although honestly this should be true anyway
	// BUT GODDAMNIT I SAID NO I_ASSERTS SO NO I_ASSERTS IT IS
	if (!lua_isfunction(gL, -1)) goto deny;

	lua_remove(gL, -2); // pop command info table

	LUA_PushUserdata(gL, &players[playernum], META_PLAYER);
	for (i = 1; i < argc; i++)
	{
		READSTRINGN(*cp, buf, 255);
		lua_pushstring(gL, buf);
	}
	LUA_Call(gL, (int)argc); // argc is 1-based, so this will cover the player we passed too.
	return;

deny:
	//must be hacked/buggy client
	if (gL) // check if Lua is actually turned on first, you dummmy -- Monster Iestyn 04/07/18
		lua_settop(gL, 0); // clear stack

	CONS_Alert(CONS_WARNING, M_GetText("Illegal lua command received from %s\n"), player_names[playernum]);
	if (server)
	{
		XBOXSTATIC UINT8 bufn[2];

		bufn[0] = (UINT8)playernum;
		bufn[1] = KICK_MSG_CON_FAIL;
		SendNetXCmd(XD_KICK, &bufn, 2);
	}
}
Beispiel #27
0
// allocate a socket
static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen)
{
	SOCKET_TYPE s = socket(family, SOCK_DGRAM, IPPROTO_UDP);
	int opt;
	socklen_t opts;
#ifdef FIONBIO
#ifdef WATTCP
	char trueval = true;
#else
	unsigned long trueval = true;
#endif
#endif
	mysockaddr_t straddr;

	if (s == (SOCKET_TYPE)ERRSOCKET || s == BADSOCKET)
		return (SOCKET_TYPE)ERRSOCKET;
#ifdef USE_WINSOCK
	{ // Alam_GBC: disable the new UDP connection reset behavior for Win2k and up
#ifdef USE_WINSOCK2
		DWORD dwBytesReturned = 0;
		BOOL bfalse = FALSE;
		WSAIoctl(s, SIO_UDP_CONNRESET, &bfalse, sizeof(bfalse),
		         NULL, 0, &dwBytesReturned, NULL, NULL);
#else
		unsigned long falseval = false;
		ioctl(s, SIO_UDP_CONNRESET, &falseval);
#endif
	}
#endif

	straddr.any = *addr;
	I_OutputMsg("Binding to %s\n", SOCK_AddrToStr(&straddr));

	if (family == AF_INET)
	{
		mysockaddr_t tmpaddr;
		tmpaddr.any = *addr ;
		if (tmpaddr.ip4.sin_addr.s_addr == htonl(INADDR_ANY))
		{
			opt = true;
			opts = (socklen_t)sizeof(opt);
			setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, opts);
		}
		// make it broadcastable
		opt = true;
		opts = (socklen_t)sizeof(opt);
		if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&opt, opts))
		{
			CONS_Alert(CONS_WARNING, M_GetText("Could not get broadcast rights\n")); // I do not care anymore
		}
	}
#ifdef HAVE_IPV6
	else if (family == AF_INET6)
	{
		if (memcmp(addr, &in6addr_any, sizeof(in6addr_any)) == 0) //IN6_ARE_ADDR_EQUAL
		{
			opt = true;
			opts = (socklen_t)sizeof(opt);
			setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, opts);
		}
#ifdef IPV6_V6ONLY
		// make it IPv6 ony
		opt = true;
		opts = (socklen_t)sizeof(opt);
		if (setsockopt(s, SOL_SOCKET, IPV6_V6ONLY, (char *)&opt, opts))
		{
			CONS_Alert(CONS_WARNING, M_GetText("Could not limit IPv6 bind\n")); // I do not care anymore
		}
#endif
	}
#endif

	if (bind(s, addr, addrlen) == ERRSOCKET)
	{
		close(s);
		I_OutputMsg("Binding failed\n");
		return (SOCKET_TYPE)ERRSOCKET;
	}

#ifdef FIONBIO
	// make it non blocking
	opt = true;
	if (ioctl(s, FIONBIO, &trueval) != 0)
	{
		close(s);
		I_OutputMsg("Seting FIOBIO on failed\n");
		return (SOCKET_TYPE)ERRSOCKET;
	}
#endif

	opts = (socklen_t)sizeof(opt);
	getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&opt, &opts);
	CONS_Printf(M_GetText("Network system buffer: %dKb\n"), opt>>10);

	if (opt < 64<<10) // 64k
	{
		opt = 64<<10;
		opts = (socklen_t)sizeof(opt);
		setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&opt, opts);
		getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&opt, &opts);
		if (opt < 64<<10)
			CONS_Alert(CONS_WARNING, M_GetText("Can't set buffer length to 64k, file transfer will be bad\n"));
		else
			CONS_Printf(M_GetText("Network system buffer set to: %dKb\n"), opt>>10);
	}
Beispiel #28
0
void *I_GetSfx(sfxinfo_t *sfx)
{
	FMOD_SOUND *sound;
	char *lump;
	FMOD_CREATESOUNDEXINFO fmt;
#ifdef HAVE_LIBGME
	Music_Emu *emu;
	gme_info_t *info;
#endif

	if (sfx->lumpnum == LUMPERROR)
		sfx->lumpnum = S_GetSfxLumpNum(sfx);
	sfx->length = W_LumpLength(sfx->lumpnum);

	lump = W_CacheLumpNum(sfx->lumpnum, PU_SOUND);
	sound = ds2fmod(lump);
	if (sound)
	{
		Z_Free(lump);
		return sound;
	}

	// It's not a doom sound.
	// Try to read it as an FMOD sound?

	memset(&fmt, 0, sizeof(FMOD_CREATESOUNDEXINFO));
	fmt.cbsize = sizeof(FMOD_CREATESOUNDEXINFO);
	fmt.length = sfx->length;

#ifdef HAVE_LIBGME
	// VGZ format
	if ((UINT8)lump[0] == 0x1F
		&& (UINT8)lump[1] == 0x8B)
	{
#ifdef HAVE_ZLIB
		UINT8 *inflatedData;
		size_t inflatedLen;
		z_stream stream;
		int zErr; // Somewhere to handle any error messages zlib tosses out

		memset(&stream, 0x00, sizeof (z_stream)); // Init zlib stream
		// Begin the inflation process
		inflatedLen = *(UINT32 *)(lump + (sfx->length-4)); // Last 4 bytes are the decompressed size, typically
		inflatedData = (UINT8 *)Z_Malloc(inflatedLen, PU_SOUND, NULL); // Make room for the decompressed data
		stream.total_in = stream.avail_in = sfx->length;
		stream.total_out = stream.avail_out = inflatedLen;
		stream.next_in = (UINT8 *)lump;
		stream.next_out = inflatedData;

		zErr = inflateInit2(&stream, 32 + MAX_WBITS);
		if (zErr == Z_OK) // We're good to go
		{
			zErr = inflate(&stream, Z_FINISH);
			if (zErr == Z_STREAM_END) {
				// Run GME on new data
				if (!gme_open_data(inflatedData, inflatedLen, &emu, 44100))
				{
					Z_Free(inflatedData); // GME supposedly makes a copy for itself, so we don't need this lying around
					Z_Free(lump); // We're done with the uninflated lump now, too.

					gme_start_track(emu, 0);
					gme_track_info(emu, &info, 0);

					fmt.format = FMOD_SOUND_FORMAT_PCM16;
					fmt.defaultfrequency = 44100;
					fmt.numchannels = 2;
					fmt.length = ((UINT32)info->play_length * 441 / 10) * 4;
					fmt.decodebuffersize = (44100 * 2) / 35;
					fmt.pcmreadcallback = GMEReadCallback;
					fmt.userdata = emu;

					FMR(FMOD_System_CreateSound(fsys, NULL, FMOD_CREATESAMPLE|FMOD_OPENUSER|FMOD_SOFTWARE|FMOD_LOWMEM, &fmt, &sound));
					return sound;
				}
			}
			else
			{
				const char *errorType;
				switch (zErr)
				{
					case Z_ERRNO:
						errorType = "Z_ERRNO"; break;
					case Z_STREAM_ERROR:
						errorType = "Z_STREAM_ERROR"; break;
					case Z_DATA_ERROR:
						errorType = "Z_DATA_ERROR"; break;
					case Z_MEM_ERROR:
						errorType = "Z_MEM_ERROR"; break;
					case Z_BUF_ERROR:
						errorType = "Z_BUF_ERROR"; break;
					case Z_VERSION_ERROR:
						errorType = "Z_VERSION_ERROR"; break;
					default:
						errorType = "unknown error";
				}
				CONS_Alert(CONS_ERROR,"Encountered %s when running inflate: %s\n", errorType, stream.msg);
			}
			(void)inflateEnd(&stream);
		}
		else // Hold up, zlib's got a problem
		{
			const char *errorType;
			switch (zErr)
			{
				case Z_ERRNO:
					errorType = "Z_ERRNO"; break;
				case Z_STREAM_ERROR:
					errorType = "Z_STREAM_ERROR"; break;
				case Z_DATA_ERROR:
					errorType = "Z_DATA_ERROR"; break;
				case Z_MEM_ERROR:
					errorType = "Z_MEM_ERROR"; break;
				case Z_BUF_ERROR:
					errorType = "Z_BUF_ERROR"; break;
				case Z_VERSION_ERROR:
					errorType = "Z_VERSION_ERROR"; break;
				default:
					errorType = "unknown error";
			}
			CONS_Alert(CONS_ERROR,"Encountered %s when running inflateInit: %s\n", errorType, stream.msg);
		}
		Z_Free(inflatedData); // GME didn't open jack, but don't let that stop us from freeing this up
#else
		//CONS_Alert(CONS_ERROR,"Cannot decompress VGZ; no zlib support\n");
#endif
	}
	// Try to read it as a GME sound
	else if (!gme_open_data(lump, sfx->length, &emu, 44100))
	{
		Z_Free(lump);

		gme_start_track(emu, 0);
		gme_track_info(emu, &info, 0);

		fmt.format = FMOD_SOUND_FORMAT_PCM16;
		fmt.defaultfrequency = 44100;
		fmt.numchannels = 2;
		fmt.length = ((UINT32)info->play_length * 441 / 10) * 4;
		fmt.decodebuffersize = (44100 * 2) / 35;
		fmt.pcmreadcallback = GMEReadCallback;
		fmt.userdata = emu;

		gme_free_info(info);

		FMR(FMOD_System_CreateSound(fsys, NULL, FMOD_CREATESAMPLE|FMOD_OPENUSER|FMOD_SOFTWARE|FMOD_LOWMEM, &fmt, &sound));
		return sound;
	}
#endif

	// Ogg, Mod, Midi, etc.
	FMR(FMOD_System_CreateSound(fsys, lump, FMOD_CREATESAMPLE|FMOD_OPENMEMORY|FMOD_SOFTWARE|FMOD_LOWMEM, &fmt, &sound));
	Z_Free(lump); // We're done with the lump now, at least.
	return sound;
}
Beispiel #29
0
boolean I_StartDigSong(const char *musicname, boolean looping)
{
	char *data;
	size_t len;
	FMOD_CREATESOUNDEXINFO fmt;
	lumpnum_t lumpnum = W_CheckNumForName(va("O_%s",musicname));

	if (lumpnum == LUMPERROR)
	{
		lumpnum = W_CheckNumForName(va("D_%s",musicname));
		if (lumpnum == LUMPERROR)
			return false;
		midimode = true;
	}
	else
		midimode = false;

	data = (char *)W_CacheLumpNum(lumpnum, PU_MUSIC);
	len = W_LumpLength(lumpnum);

	memset(&fmt, 0, sizeof(FMOD_CREATESOUNDEXINFO));
	fmt.cbsize = sizeof(FMOD_CREATESOUNDEXINFO);

#ifdef HAVE_LIBGME
	if ((UINT8)data[0] == 0x1F
		&& (UINT8)data[1] == 0x8B)
	{
#ifdef HAVE_ZLIB
		UINT8 *inflatedData;
		size_t inflatedLen;
		z_stream stream;
		int zErr; // Somewhere to handle any error messages zlib tosses out

		memset(&stream, 0x00, sizeof (z_stream)); // Init zlib stream
		// Begin the inflation process
		inflatedLen = *(UINT32 *)(data + (len-4)); // Last 4 bytes are the decompressed size, typically
		inflatedData = (UINT8 *)Z_Calloc(inflatedLen, PU_MUSIC, NULL); // Make room for the decompressed data
		stream.total_in = stream.avail_in = len;
		stream.total_out = stream.avail_out = inflatedLen;
		stream.next_in = (UINT8 *)data;
		stream.next_out = inflatedData;

		zErr = inflateInit2(&stream, 32 + MAX_WBITS);
		if (zErr == Z_OK) // We're good to go
		{
			zErr = inflate(&stream, Z_FINISH);
			if (zErr == Z_STREAM_END) {
				// Run GME on new data
				if (!gme_open_data(inflatedData, inflatedLen, &gme, 44100))
				{
					gme_equalizer_t gmeq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0};
					Z_Free(inflatedData); // GME supposedly makes a copy for itself, so we don't need this lying around
					Z_Free(data); // We don't need this, either.
					gme_start_track(gme, 0);
					current_track = 0;
					gme_set_equalizer(gme,&gmeq);
					fmt.format = FMOD_SOUND_FORMAT_PCM16;
					fmt.defaultfrequency = 44100;
					fmt.numchannels = 2;
					fmt.length = -1;
					fmt.decodebuffersize = (44100 * 2) / 35;
					fmt.pcmreadcallback = GMEReadCallback;
					fmt.userdata = gme;
					FMR(FMOD_System_CreateStream(fsys, NULL, FMOD_OPENUSER | (looping ? FMOD_LOOP_NORMAL : 0), &fmt, &music_stream));
					FMR(FMOD_System_PlaySound(fsys, FMOD_CHANNEL_FREE, music_stream, false, &music_channel));
					FMR(FMOD_Channel_SetVolume(music_channel, music_volume / 31.0));
					FMR(FMOD_Channel_SetPriority(music_channel, 0));
					return true;
				}
			}
			else
			{
				const char *errorType;
				switch (zErr)
				{
					case Z_ERRNO:
						errorType = "Z_ERRNO"; break;
					case Z_STREAM_ERROR:
						errorType = "Z_STREAM_ERROR"; break;
					case Z_DATA_ERROR:
						errorType = "Z_DATA_ERROR"; break;
					case Z_MEM_ERROR:
						errorType = "Z_MEM_ERROR"; break;
					case Z_BUF_ERROR:
						errorType = "Z_BUF_ERROR"; break;
					case Z_VERSION_ERROR:
						errorType = "Z_VERSION_ERROR"; break;
					default:
						errorType = "unknown error";
				}
				CONS_Alert(CONS_ERROR,"Encountered %s when running inflate: %s\n", errorType, stream.msg);
			}
			(void)inflateEnd(&stream);
		}
		else // Hold up, zlib's got a problem
		{
			const char *errorType;
			switch (zErr)
			{
				case Z_ERRNO:
					errorType = "Z_ERRNO"; break;
				case Z_STREAM_ERROR:
					errorType = "Z_STREAM_ERROR"; break;
				case Z_DATA_ERROR:
					errorType = "Z_DATA_ERROR"; break;
				case Z_MEM_ERROR:
					errorType = "Z_MEM_ERROR"; break;
				case Z_BUF_ERROR:
					errorType = "Z_BUF_ERROR"; break;
				case Z_VERSION_ERROR:
					errorType = "Z_VERSION_ERROR"; break;
				default:
					errorType = "unknown error";
			}
			CONS_Alert(CONS_ERROR,"Encountered %s when running inflateInit: %s\n", errorType, stream.msg);
		}
		Z_Free(inflatedData); // GME didn't open jack, but don't let that stop us from freeing this up
#else
		//CONS_Alert(CONS_ERROR,"Cannot decompress VGZ; no zlib support\n");
#endif
	}
	else if (!gme_open_data(data, len, &gme, 44100))
	{
		gme_equalizer_t gmeq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0};
		Z_Free(data); // We don't need this anymore.
		gme_start_track(gme, 0);
		current_track = 0;
		gme_set_equalizer(gme,&gmeq);
		fmt.format = FMOD_SOUND_FORMAT_PCM16;
		fmt.defaultfrequency = 44100;
		fmt.numchannels = 2;
		fmt.length = -1;
		fmt.decodebuffersize = (44100 * 2) / 35;
		fmt.pcmreadcallback = GMEReadCallback;
		fmt.userdata = gme;
		FMR(FMOD_System_CreateStream(fsys, NULL, FMOD_OPENUSER | (looping ? FMOD_LOOP_NORMAL : 0), &fmt, &music_stream));
		FMR(FMOD_System_PlaySound(fsys, FMOD_CHANNEL_FREE, music_stream, false, &music_channel));
		FMR(FMOD_Channel_SetVolume(music_channel, music_volume / 31.0));
		FMR(FMOD_Channel_SetPriority(music_channel, 0));
		return true;
	}
#endif

	fmt.length = len;
	{
		FMOD_RESULT e = FMOD_System_CreateStream(fsys, data, FMOD_OPENMEMORY_POINT|(looping ? FMOD_LOOP_NORMAL : 0), &fmt, &music_stream);
		if (e != FMOD_OK)
		{
			if (e == FMOD_ERR_FORMAT)
				CONS_Alert(CONS_WARNING, "Failed to play music lump %s due to invalid format.\n", W_CheckNameForNum(lumpnum));
			else
				FMR(e);
			return false;
		}
	}
	FMR(FMOD_System_PlaySound(fsys, FMOD_CHANNEL_FREE, music_stream, false, &music_channel));
	if (midimode)
		FMR(FMOD_Channel_SetVolume(music_channel, midi_volume / 31.0));
	else
		FMR(FMOD_Channel_SetVolume(music_channel, music_volume / 31.0));
	FMR(FMOD_Channel_SetPriority(music_channel, 0));
	current_track = 0;

	// Try to find a loop point in streaming music formats (ogg, mp3)
	if (looping)
	{
		FMOD_RESULT e;
		FMOD_TAG tag;
		unsigned int loopstart, loopend;

		// A proper LOOPPOINT is its own tag, stupid.
		e = FMOD_Sound_GetTag(music_stream, "LOOPPOINT", 0, &tag);
		if (e != FMOD_ERR_TAGNOTFOUND)
		{
			FMR(e);
			loopstart = atoi((char *)tag.data); // assumed to be a string data tag.
			FMR(FMOD_Sound_GetLoopPoints(music_stream, NULL, FMOD_TIMEUNIT_PCM, &loopend, FMOD_TIMEUNIT_PCM));
			if (loopstart > 0)
				FMR(FMOD_Sound_SetLoopPoints(music_stream, loopstart, FMOD_TIMEUNIT_PCM, loopend, FMOD_TIMEUNIT_PCM));
			return true;
		}

		// Use LOOPMS for time in miliseconds.
		e = FMOD_Sound_GetTag(music_stream, "LOOPMS", 0, &tag);
		if (e != FMOD_ERR_TAGNOTFOUND)
		{
			FMR(e);
			loopstart = atoi((char *)tag.data); // assumed to be a string data tag.
			FMR(FMOD_Sound_GetLoopPoints(music_stream, NULL, FMOD_TIMEUNIT_MS, &loopend, FMOD_TIMEUNIT_PCM));
			if (loopstart > 0)
				FMR(FMOD_Sound_SetLoopPoints(music_stream, loopstart, FMOD_TIMEUNIT_MS, loopend, FMOD_TIMEUNIT_PCM));
			return true;
		}

		// Try to fetch it from the COMMENT tag, like A.J. Freda
		e = FMOD_Sound_GetTag(music_stream, "COMMENT", 0, &tag);
		if (e != FMOD_ERR_TAGNOTFOUND)
		{
			char *loopText;
			// Handle any errors that arose, first
			FMR(e);
			// Figure out where the number starts
			loopText = strstr((char *)tag.data,"LOOPPOINT=");
			if (loopText != NULL)
			{
				// Skip the "LOOPPOINT=" part.
				loopText += 10;
				// Convert it to our looppoint
				// FMOD seems to ensure the tag is properly NULL-terminated.
				// atoi will stop when it reaches anything that's not a number.
				loopstart = atoi(loopText);
				// Now do the rest like above
				FMR(FMOD_Sound_GetLoopPoints(music_stream, NULL, FMOD_TIMEUNIT_PCM, &loopend, FMOD_TIMEUNIT_PCM));
				if (loopstart > 0)
					FMR(FMOD_Sound_SetLoopPoints(music_stream, loopstart, FMOD_TIMEUNIT_PCM, loopend, FMOD_TIMEUNIT_PCM));
			}
			return true;
		}
	}

	// No special loop point, but we're playing so it's all good.
	return true;
}
Beispiel #30
0
// spew console messages for general errors.
static void FMR_Debug(FMOD_RESULT e, int line)
{
	if (e != FMOD_OK)
		CONS_Alert(CONS_ERROR, "FMOD:%d - %s\n", line, FMOD_ErrorString(e));
}