mirror of
https://git.do.srb2.org/KartKrew/Kart-Public.git
synced 2024-12-31 23:00:57 +00:00
Merge remote-tracking branch 'remotes/pub/next' into followme
# Conflicts: # src/r_things.h
This commit is contained in:
commit
5d7b7afd17
79 changed files with 5111 additions and 1999 deletions
|
@ -401,7 +401,11 @@ if(${SRB2_CONFIG_HWRENDER})
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_light.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_main.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2load.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md3load.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_model.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_trick.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/u_list.c
|
||||
)
|
||||
|
||||
set (SRB2_HWRENDER_HEADERS
|
||||
|
@ -415,6 +419,10 @@ if(${SRB2_CONFIG_HWRENDER})
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_light.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_main.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2load.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md3load.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_model.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hardware/u_list.h
|
||||
)
|
||||
|
||||
set(SRB2_R_OPENGL_SOURCES
|
||||
|
|
28
src/Makefile
28
src/Makefile
|
@ -282,7 +282,8 @@ ifndef DC
|
|||
endif
|
||||
OPTS+=-DHWRENDER
|
||||
OBJS+=$(OBJDIR)/hw_bsp.o $(OBJDIR)/hw_draw.o $(OBJDIR)/hw_light.o \
|
||||
$(OBJDIR)/hw_main.o $(OBJDIR)/hw_clip.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o $(OBJDIR)/hw_trick.o
|
||||
$(OBJDIR)/hw_main.o $(OBJDIR)/hw_clip.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o $(OBJDIR)/hw_trick.o \
|
||||
$(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o $(OBJDIR)/u_list.o
|
||||
endif
|
||||
|
||||
ifdef NOHS
|
||||
|
@ -741,16 +742,18 @@ ifdef MINGW
|
|||
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
|
||||
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
|
||||
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
|
||||
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
|
||||
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
|
||||
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \
|
||||
hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \
|
||||
am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
|
||||
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
|
||||
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
|
||||
else
|
||||
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
|
||||
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
|
||||
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
|
||||
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
|
||||
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
|
||||
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \
|
||||
hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \
|
||||
am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
|
||||
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
|
||||
$(CC) $(CFLAGS) $(WFLAGS) -I/usr/X11R6/include -c $< -o $@
|
||||
endif
|
||||
|
@ -902,24 +905,27 @@ ifndef NOHW
|
|||
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
|
||||
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
|
||||
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
|
||||
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
|
||||
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
|
||||
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \
|
||||
hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \
|
||||
am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
|
||||
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
|
||||
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@
|
||||
|
||||
$(OBJDIR)/ogl_win.o: hardware/r_opengl/ogl_win.c hardware/r_opengl/r_opengl.h \
|
||||
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
|
||||
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
|
||||
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
|
||||
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
|
||||
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \
|
||||
hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \
|
||||
am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
|
||||
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
|
||||
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@
|
||||
|
||||
$(OBJDIR)/r_minigl.o: hardware/r_minigl/r_minigl.c hardware/r_opengl/r_opengl.h \
|
||||
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
|
||||
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
|
||||
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
|
||||
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
|
||||
hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \
|
||||
hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \
|
||||
am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
|
||||
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
|
||||
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@
|
||||
endif
|
||||
|
|
|
@ -96,6 +96,37 @@ boolean I_SetSongSpeed(float speed)
|
|||
return false;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
// MUSIC SEEKING
|
||||
/// ------------------------
|
||||
|
||||
UINT32 I_GetSongLength(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean I_SetSongLoopPoint(UINT32 looppoint)
|
||||
{
|
||||
(void)looppoint;
|
||||
return false;
|
||||
}
|
||||
|
||||
UINT32 I_GetSongLoopPoint(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean I_SetSongPosition(UINT32 position)
|
||||
{
|
||||
(void)position;
|
||||
return false;
|
||||
}
|
||||
|
||||
UINT32 I_GetSongPosition(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
// MUSIC PLAYBACK
|
||||
/// ------------------------
|
||||
|
@ -140,3 +171,44 @@ void I_SetMusicVolume(INT32 volume)
|
|||
{
|
||||
(void)volume;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
// MUSIC FADING
|
||||
/// ------------------------
|
||||
|
||||
void I_SetInternalMusicVolume(UINT8 volume)
|
||||
{
|
||||
(void)volume;
|
||||
}
|
||||
|
||||
void I_StopFadingSong(void)
|
||||
{
|
||||
}
|
||||
|
||||
boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void));
|
||||
{
|
||||
(void)target_volume;
|
||||
(void)source_volume;
|
||||
(void)ms;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void));
|
||||
{
|
||||
(void)target_volume;
|
||||
(void)ms;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean I_FadeOutStopSong(UINT32 ms)
|
||||
{
|
||||
(void)ms;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean I_FadeInPlaySong(UINT32 ms, boolean looping)
|
||||
{
|
||||
(void)ms;
|
||||
(void)looping;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ static void COM_Exec_f(void);
|
|||
static void COM_Wait_f(void);
|
||||
static void COM_Help_f(void);
|
||||
static void COM_Toggle_f(void);
|
||||
static void COM_Add_f(void);
|
||||
|
||||
static void CV_EnforceExecVersion(void);
|
||||
static boolean CV_FilterVarByVersion(consvar_t *v, const char *valstr);
|
||||
|
@ -156,6 +157,20 @@ void COM_BufInsertText(const char *ptext)
|
|||
}
|
||||
}
|
||||
|
||||
/** Progress the wait timer and flush waiting console commands when ready.
|
||||
*/
|
||||
void
|
||||
COM_BufTicker(void)
|
||||
{
|
||||
if (com_wait)
|
||||
{
|
||||
com_wait--;
|
||||
return;
|
||||
}
|
||||
|
||||
COM_BufExecute();
|
||||
}
|
||||
|
||||
/** Flushes (executes) console commands in the buffer.
|
||||
*/
|
||||
void COM_BufExecute(void)
|
||||
|
@ -165,12 +180,6 @@ void COM_BufExecute(void)
|
|||
char line[1024] = "";
|
||||
INT32 quotes;
|
||||
|
||||
if (com_wait)
|
||||
{
|
||||
com_wait--;
|
||||
return;
|
||||
}
|
||||
|
||||
while (com_text.cursize)
|
||||
{
|
||||
// find a '\n' or; line break
|
||||
|
@ -291,6 +300,7 @@ void COM_Init(void)
|
|||
COM_AddCommand("wait", COM_Wait_f);
|
||||
COM_AddCommand("help", COM_Help_f);
|
||||
COM_AddCommand("toggle", COM_Toggle_f);
|
||||
COM_AddCommand("add", COM_Add_f);
|
||||
RegisterNetXCmd(XD_NETVAR, Got_NetVar);
|
||||
}
|
||||
|
||||
|
@ -537,10 +547,41 @@ static void COM_ExecuteString(char *ptext)
|
|||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Alias recursion cycle detected!\n"));
|
||||
recursion = 0;
|
||||
return;
|
||||
}
|
||||
recursion++;
|
||||
COM_BufInsertText(a->value);
|
||||
else
|
||||
{
|
||||
char buf[1024];
|
||||
char *write = buf, *read = a->value, *seek = read;
|
||||
|
||||
while ((seek = strchr(seek, '$')) != NULL)
|
||||
{
|
||||
memcpy(write, read, seek-read);
|
||||
write += seek-read;
|
||||
|
||||
seek++;
|
||||
|
||||
if (*seek >= '1' && *seek <= '9')
|
||||
{
|
||||
if (com_argc > (size_t)(*seek - '0'))
|
||||
{
|
||||
memcpy(write, com_argv[*seek - '0'], strlen(com_argv[*seek - '0']));
|
||||
write += strlen(com_argv[*seek - '0']);
|
||||
}
|
||||
seek++;
|
||||
}
|
||||
else
|
||||
{
|
||||
*write = '$';
|
||||
write++;
|
||||
}
|
||||
|
||||
read = seek;
|
||||
}
|
||||
WRITESTRING(write, read);
|
||||
|
||||
recursion++;
|
||||
COM_BufInsertText(buf);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -563,8 +604,6 @@ static void COM_ExecuteString(char *ptext)
|
|||
static void COM_Alias_f(void)
|
||||
{
|
||||
cmdalias_t *a;
|
||||
char cmd[1024];
|
||||
size_t i, c;
|
||||
|
||||
if (COM_Argc() < 3)
|
||||
{
|
||||
|
@ -577,19 +616,9 @@ static void COM_Alias_f(void)
|
|||
com_alias = a;
|
||||
|
||||
a->name = Z_StrDup(COM_Argv(1));
|
||||
|
||||
// copy the rest of the command line
|
||||
cmd[0] = 0; // start out with a null string
|
||||
c = COM_Argc();
|
||||
for (i = 2; i < c; i++)
|
||||
{
|
||||
strcat(cmd, COM_Argv(i));
|
||||
if (i != c)
|
||||
strcat(cmd, " ");
|
||||
}
|
||||
strcat(cmd, "\n");
|
||||
|
||||
a->value = Z_StrDup(cmd);
|
||||
// Just use arg 2 if it's the only other argument, in case the alias is wrapped in quotes (backward compat, or multiple commands in one string).
|
||||
// Otherwise pull the whole string and seek to the end of the alias name. The strctr is in case the alias is quoted.
|
||||
a->value = Z_StrDup(COM_Argc() == 3 ? COM_Argv(2) : (strchr(COM_Args() + strlen(a->name), ' ') + 1));
|
||||
}
|
||||
|
||||
/** Prints a line of text to the console.
|
||||
|
@ -855,6 +884,27 @@ static void COM_Toggle_f(void)
|
|||
CV_AddValue(cvar, +1);
|
||||
}
|
||||
|
||||
/** Command variant of CV_AddValue
|
||||
*/
|
||||
static void COM_Add_f(void)
|
||||
{
|
||||
consvar_t *cvar;
|
||||
|
||||
if (COM_Argc() != 3)
|
||||
{
|
||||
CONS_Printf(M_GetText("Add <cvar_name> <value>: Add to the value of a cvar. Negative values work too!\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;
|
||||
}
|
||||
|
||||
CV_AddValue(cvar, atoi(COM_Argv(2)));
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// VARIABLE SIZE BUFFERS
|
||||
// =========================================================================
|
||||
|
|
|
@ -45,6 +45,9 @@ void COM_ImmedExecute(const char *ptext);
|
|||
// Execute commands in buffer, flush them
|
||||
void COM_BufExecute(void);
|
||||
|
||||
// As above; and progress the wait timer.
|
||||
void COM_BufTicker(void);
|
||||
|
||||
// setup command buffer, at game tartup
|
||||
void COM_Init(void);
|
||||
|
||||
|
|
|
@ -96,6 +96,7 @@ static size_t input_len; // length of current line, used to bound cursor and suc
|
|||
// protos.
|
||||
static void CON_InputInit(void);
|
||||
static void CON_RecalcSize(void);
|
||||
static void CON_ChangeHeight(void);
|
||||
|
||||
static void CONS_hudlines_Change(void);
|
||||
static void CONS_backcolor_Change(void);
|
||||
|
@ -467,6 +468,12 @@ static void CON_RecalcSize(void)
|
|||
con_destlines = vid.height;
|
||||
}
|
||||
|
||||
if (con_destlines > 0) // Resize console if already open
|
||||
{
|
||||
CON_ChangeHeight();
|
||||
con_curlines = con_destlines;
|
||||
}
|
||||
|
||||
// check for change of video width
|
||||
if (conw == con_width)
|
||||
return; // didn't change
|
||||
|
@ -516,6 +523,20 @@ static void CON_RecalcSize(void)
|
|||
Z_Free(tmp_buffer);
|
||||
}
|
||||
|
||||
static void CON_ChangeHeight(void)
|
||||
{
|
||||
INT32 minheight = 20 * con_scalefactor; // 20 = 8+8+4
|
||||
|
||||
// toggle console in
|
||||
con_destlines = (cons_height.value*vid.height)/100;
|
||||
if (con_destlines < minheight)
|
||||
con_destlines = minheight;
|
||||
else if (con_destlines > vid.height)
|
||||
con_destlines = vid.height;
|
||||
|
||||
con_destlines &= ~0x3; // multiple of text row height
|
||||
}
|
||||
|
||||
// Handles Console moves in/out of screen (per frame)
|
||||
//
|
||||
static void CON_MoveConsole(void)
|
||||
|
@ -620,16 +641,7 @@ void CON_Ticker(void)
|
|||
CON_ClearHUD();
|
||||
}
|
||||
else
|
||||
{
|
||||
// toggle console in
|
||||
con_destlines = (cons_height.value*vid.height)/100;
|
||||
if (con_destlines < minheight)
|
||||
con_destlines = minheight;
|
||||
else if (con_destlines > vid.height)
|
||||
con_destlines = vid.height;
|
||||
|
||||
con_destlines &= ~0x3; // multiple of text row height
|
||||
}
|
||||
CON_ChangeHeight();
|
||||
}
|
||||
|
||||
// console movement
|
||||
|
@ -1149,6 +1161,7 @@ static void CON_Print(char *msg)
|
|||
{
|
||||
size_t l;
|
||||
INT32 controlchars = 0; // for color changing
|
||||
char color = '\x80'; // keep color across lines
|
||||
|
||||
if (msg == NULL)
|
||||
return;
|
||||
|
@ -1174,7 +1187,7 @@ static void CON_Print(char *msg)
|
|||
{
|
||||
if (*msg & 0x80)
|
||||
{
|
||||
con_line[con_cx++] = *(msg++);
|
||||
color = con_line[con_cx++] = *(msg++);
|
||||
controlchars++;
|
||||
continue;
|
||||
}
|
||||
|
@ -1182,12 +1195,14 @@ static void CON_Print(char *msg)
|
|||
{
|
||||
con_cy--;
|
||||
CON_Linefeed();
|
||||
color = '\x80';
|
||||
controlchars = 0;
|
||||
}
|
||||
else if (*msg == '\n') // linefeed
|
||||
{
|
||||
CON_Linefeed();
|
||||
controlchars = 0;
|
||||
con_line[con_cx++] = color;
|
||||
controlchars = 1;
|
||||
}
|
||||
else if (*msg == ' ') // space
|
||||
{
|
||||
|
@ -1195,7 +1210,8 @@ static void CON_Print(char *msg)
|
|||
if (con_cx - controlchars >= con_width-11)
|
||||
{
|
||||
CON_Linefeed();
|
||||
controlchars = 0;
|
||||
con_line[con_cx++] = color;
|
||||
controlchars = 1;
|
||||
}
|
||||
}
|
||||
else if (*msg == '\t')
|
||||
|
@ -1210,7 +1226,8 @@ static void CON_Print(char *msg)
|
|||
if (con_cx - controlchars >= con_width-11)
|
||||
{
|
||||
CON_Linefeed();
|
||||
controlchars = 0;
|
||||
con_line[con_cx++] = color;
|
||||
controlchars = 1;
|
||||
}
|
||||
}
|
||||
msg++;
|
||||
|
@ -1227,7 +1244,8 @@ static void CON_Print(char *msg)
|
|||
if ((con_cx - controlchars) + l > con_width-11)
|
||||
{
|
||||
CON_Linefeed();
|
||||
controlchars = 0;
|
||||
con_line[con_cx++] = color;
|
||||
controlchars = 1;
|
||||
}
|
||||
|
||||
// a word at a time
|
||||
|
@ -1582,8 +1600,7 @@ static void CON_DrawConsole(void)
|
|||
i = con_cy - con_scrollup;
|
||||
|
||||
// skip the last empty line due to the cursor being at the start of a new line
|
||||
if (!con_scrollup && !con_cx)
|
||||
i--;
|
||||
i--;
|
||||
|
||||
i -= (con_curlines - minheight) / charheight;
|
||||
|
||||
|
|
|
@ -91,12 +91,10 @@ tic_t jointimeout = (3*TICRATE);
|
|||
static boolean sendingsavegame[MAXNETNODES]; // Are we sending the savegame?
|
||||
static tic_t freezetimeout[MAXNETNODES]; // Until when can this node freeze the server before getting a timeout?
|
||||
|
||||
#ifdef NEWPING
|
||||
UINT16 pingmeasurecount = 1;
|
||||
UINT32 realpingtable[MAXPLAYERS]; //the base table of ping where an average will be sent to everyone.
|
||||
UINT32 playerpingtable[MAXPLAYERS]; //table of player latency values.
|
||||
tic_t servermaxping = 800; // server's max ping. Defaults to 800
|
||||
#endif
|
||||
SINT8 nodetoplayer[MAXNETNODES];
|
||||
SINT8 nodetoplayer2[MAXNETNODES]; // say the numplayer for this node if any (splitscreen)
|
||||
SINT8 nodetoplayer3[MAXNETNODES]; // say the numplayer for this node if any (splitscreen == 2)
|
||||
|
@ -167,7 +165,7 @@ ticcmd_t netcmds[BACKUPTICS][MAXPLAYERS];
|
|||
static textcmdtic_t *textcmds[TEXTCMD_HASH_SIZE] = {NULL};
|
||||
|
||||
|
||||
consvar_t cv_showjoinaddress = {"showjoinaddress", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_showjoinaddress = {"showjoinaddress", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
static CV_PossibleValue_t playbackspeed_cons_t[] = {{1, "MIN"}, {10, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_playbackspeed = {"playbackspeed", "1", 0, playbackspeed_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
@ -1451,33 +1449,13 @@ static void SV_SendPlayerInfo(INT32 node)
|
|||
continue;
|
||||
}
|
||||
|
||||
netbuffer->u.playerinfo[i].node = (UINT8)playernode[i];
|
||||
netbuffer->u.playerinfo[i].node = i;
|
||||
strncpy(netbuffer->u.playerinfo[i].name, (const char *)&player_names[i], MAXPLAYERNAME+1);
|
||||
netbuffer->u.playerinfo[i].name[MAXPLAYERNAME] = '\0';
|
||||
|
||||
//fetch IP address
|
||||
{
|
||||
const char *claddress;
|
||||
UINT32 numericaddress[4];
|
||||
|
||||
memset(netbuffer->u.playerinfo[i].address, 0, 4);
|
||||
if (playernode[i] == 0)
|
||||
{
|
||||
//127.0.0.1
|
||||
netbuffer->u.playerinfo[i].address[0] = 127;
|
||||
netbuffer->u.playerinfo[i].address[3] = 1;
|
||||
}
|
||||
else if (playernode[i] > 0 && I_GetNodeAddress && (claddress = I_GetNodeAddress(playernode[i])) != NULL)
|
||||
{
|
||||
if (sscanf(claddress, "%d.%d.%d.%d", &numericaddress[0], &numericaddress[1], &numericaddress[2], &numericaddress[3]) < 4)
|
||||
goto badaddress;
|
||||
netbuffer->u.playerinfo[i].address[0] = (UINT8)numericaddress[0];
|
||||
netbuffer->u.playerinfo[i].address[1] = (UINT8)numericaddress[1];
|
||||
netbuffer->u.playerinfo[i].address[2] = (UINT8)numericaddress[2];
|
||||
netbuffer->u.playerinfo[i].address[3] = (UINT8)numericaddress[3];
|
||||
}
|
||||
}
|
||||
badaddress:
|
||||
//No, don't do that, you fuckface.
|
||||
memset(netbuffer->u.playerinfo[i].address, 0, 4);
|
||||
|
||||
if (G_GametypeHasTeams())
|
||||
{
|
||||
|
@ -2318,17 +2296,11 @@ static void CL_ConnectToServer(boolean viams)
|
|||
|
||||
if (i != -1)
|
||||
{
|
||||
INT32 j;
|
||||
UINT8 num = serverlist[i].info.gametype;
|
||||
const char *gametypestr = NULL;
|
||||
CONS_Printf(M_GetText("Connecting to: %s\n"), serverlist[i].info.servername);
|
||||
for (j = 0; gametype_cons_t[j].strvalue; j++)
|
||||
{
|
||||
if (gametype_cons_t[j].value == serverlist[i].info.gametype)
|
||||
{
|
||||
gametypestr = gametype_cons_t[j].strvalue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (num < NUMGAMETYPES)
|
||||
gametypestr = Gametype_Names[num];
|
||||
if (gametypestr)
|
||||
CONS_Printf(M_GetText("Gametype: %s\n"), gametypestr);
|
||||
CONS_Printf(M_GetText("Version: %d.%d.%u\n"), serverlist[i].info.version/100,
|
||||
|
@ -3094,12 +3066,10 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
|
|||
HU_AddChatText(va("\x82*%s has been kicked (Go away)", player_names[pnum]), false);
|
||||
kickreason = KR_KICK;
|
||||
break;
|
||||
#ifdef NEWPING
|
||||
case KICK_MSG_PING_HIGH:
|
||||
HU_AddChatText(va("\x82*%s left the game (Broke ping limit)", player_names[pnum]), false);
|
||||
kickreason = KR_PINGLIMIT;
|
||||
break;
|
||||
#endif
|
||||
case KICK_MSG_CON_FAIL:
|
||||
HU_AddChatText(va("\x82*%s left the game (Synch Failure)", player_names[pnum]), false);
|
||||
kickreason = KR_SYNCH;
|
||||
|
@ -3172,10 +3142,8 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
|
|||
D_StartTitle();
|
||||
if (msg == KICK_MSG_CON_FAIL)
|
||||
M_StartMessage(M_GetText("Server closed connection\n(Synch failure)\nPress ESC\n"), NULL, MM_NOTHING);
|
||||
#ifdef NEWPING
|
||||
else if (msg == KICK_MSG_PING_HIGH)
|
||||
M_StartMessage(M_GetText("Server closed connection\n(Broke ping limit)\nPress ESC\n"), NULL, MM_NOTHING);
|
||||
#endif
|
||||
else if (msg == KICK_MSG_BANNED)
|
||||
M_StartMessage(M_GetText("You have been banned by the server\n\nPress ESC\n"), NULL, MM_NOTHING);
|
||||
else if (msg == KICK_MSG_CUSTOM_KICK)
|
||||
|
@ -3219,15 +3187,15 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
|
|||
static CV_PossibleValue_t netticbuffer_cons_t[] = {{0, "MIN"}, {3, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_netticbuffer = {"netticbuffer", "1", CV_SAVE, netticbuffer_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_allownewplayer = {"allowjoin", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL };
|
||||
consvar_t cv_allownewplayer = {"allowjoin", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL };
|
||||
#ifdef VANILLAJOINNEXTROUND
|
||||
consvar_t cv_joinnextround = {"joinnextround", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; /// \todo not done
|
||||
consvar_t cv_joinnextround = {"joinnextround", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; /// \todo not done
|
||||
#endif
|
||||
static CV_PossibleValue_t maxplayers_cons_t[] = {{2, "MIN"}, {MAXPLAYERS, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_maxplayers = {"maxplayers", "8", CV_SAVE, maxplayers_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
static CV_PossibleValue_t resynchattempts_cons_t[] = {{0, "MIN"}, {20, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_resynchattempts = {"resynchattempts", "5", CV_SAVE, resynchattempts_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL };
|
||||
consvar_t cv_blamecfail = {"blamecfail", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL };
|
||||
consvar_t cv_blamecfail = {"blamecfail", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL };
|
||||
|
||||
// max file size to send to a player (in kilobytes)
|
||||
static CV_PossibleValue_t maxsend_cons_t[] = {{0, "MIN"}, {51200, "MAX"}, {0, NULL}};
|
||||
|
@ -3270,12 +3238,6 @@ void D_ClientServerInit(void)
|
|||
RegisterNetXCmd(XD_ADDPLAYER, Got_AddPlayer);
|
||||
RegisterNetXCmd(XD_REMOVEPLAYER, Got_RemovePlayer);
|
||||
#ifndef NONET
|
||||
CV_RegisterVar(&cv_allownewplayer);
|
||||
#ifdef VANILLAJOINNEXTROUND
|
||||
CV_RegisterVar(&cv_joinnextround);
|
||||
#endif
|
||||
CV_RegisterVar(&cv_showjoinaddress);
|
||||
CV_RegisterVar(&cv_blamecfail);
|
||||
#ifdef DUMPCONSISTENCY
|
||||
CV_RegisterVar(&cv_dumpconsistency);
|
||||
#endif
|
||||
|
@ -4630,7 +4592,6 @@ FILESTAMP
|
|||
resynch_local_inprogress = true;
|
||||
CL_AcknowledgeResynch(&netbuffer->u.resynchpak);
|
||||
break;
|
||||
#ifdef NEWPING
|
||||
case PT_PING:
|
||||
// Only accept PT_PING from the server.
|
||||
if (node != servernode)
|
||||
|
@ -4660,7 +4621,6 @@ FILESTAMP
|
|||
}
|
||||
|
||||
break;
|
||||
#endif
|
||||
case PT_SERVERCFG:
|
||||
break;
|
||||
case PT_FILEFRAGMENT:
|
||||
|
@ -5232,7 +5192,7 @@ void TryRunTics(tic_t realtics)
|
|||
|
||||
if (realtics >= 1)
|
||||
{
|
||||
COM_BufExecute();
|
||||
COM_BufTicker();
|
||||
if (mapchangepending)
|
||||
D_MapChange(-1, 0, encoremode, false, 2, false, fromlevelselect); // finish the map change
|
||||
}
|
||||
|
@ -5298,7 +5258,6 @@ void TryRunTics(tic_t realtics)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef NEWPING
|
||||
|
||||
/* Ping Update except better:
|
||||
We call this once per second and check for people's pings. If their ping happens to be too high, we increment some timer and kick them out.
|
||||
|
@ -5382,11 +5341,9 @@ static inline void PingUpdate(void)
|
|||
|
||||
pingmeasurecount = 1; //Reset count
|
||||
}
|
||||
#endif
|
||||
|
||||
static tic_t gametime = 0;
|
||||
|
||||
#ifdef NEWPING
|
||||
static void UpdatePingTable(void)
|
||||
{
|
||||
INT32 i;
|
||||
|
@ -5401,7 +5358,6 @@ static void UpdatePingTable(void)
|
|||
pingmeasurecount++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Handle timeouts to prevent definitive freezes from happenning
|
||||
static void HandleNodeTimeouts(void)
|
||||
|
@ -5426,9 +5382,7 @@ void NetKeepAlive(void)
|
|||
if (realtics <= 0) // nothing new to update
|
||||
return;
|
||||
|
||||
#ifdef NEWPING
|
||||
UpdatePingTable();
|
||||
#endif
|
||||
|
||||
if (server)
|
||||
CL_SendClientKeepAlive();
|
||||
|
@ -5475,9 +5429,7 @@ void NetUpdate(void)
|
|||
|
||||
gametime = nowtime;
|
||||
|
||||
#ifdef NEWPING
|
||||
UpdatePingTable();
|
||||
#endif
|
||||
|
||||
if (client)
|
||||
maketic = neededtic;
|
||||
|
|
|
@ -93,9 +93,7 @@ typedef enum
|
|||
PT_NODETIMEOUT, // Packet sent to self if the connection times out.
|
||||
PT_RESYNCHING, // Packet sent to resync players.
|
||||
// Blocks game advance until synched.
|
||||
#ifdef NEWPING
|
||||
PT_PING, // Packet sent to tell clients the other client's latency to server.
|
||||
#endif
|
||||
NUMPACKETTYPE
|
||||
} packettype_t;
|
||||
|
||||
|
@ -473,9 +471,7 @@ typedef struct
|
|||
msaskinfo_pak msaskinfo; // 22 bytes
|
||||
plrinfo playerinfo[MAXPLAYERS]; // 576 bytes(?)
|
||||
plrconfig playerconfig[MAXPLAYERS]; // (up to) 528 bytes(?)
|
||||
#ifdef NEWPING
|
||||
UINT32 pingtable[MAXPLAYERS+1]; // 68 bytes
|
||||
#endif
|
||||
} u; // This is needed to pack diff packet types data together
|
||||
} ATTRPACK doomdata_t;
|
||||
|
||||
|
@ -509,9 +505,7 @@ extern consvar_t cv_playbackspeed;
|
|||
#define KICK_MSG_PLAYER_QUIT 3
|
||||
#define KICK_MSG_TIMEOUT 4
|
||||
#define KICK_MSG_BANNED 5
|
||||
#ifdef NEWPING
|
||||
#define KICK_MSG_PING_HIGH 6
|
||||
#endif
|
||||
#define KICK_MSG_CUSTOM_KICK 7
|
||||
#define KICK_MSG_CUSTOM_BAN 8
|
||||
|
||||
|
@ -536,12 +530,10 @@ extern SINT8 servernode;
|
|||
void Command_Ping_f(void);
|
||||
extern tic_t connectiontimeout;
|
||||
extern tic_t jointimeout;
|
||||
#ifdef NEWPING
|
||||
extern UINT16 pingmeasurecount;
|
||||
extern UINT32 realpingtable[MAXPLAYERS];
|
||||
extern UINT32 playerpingtable[MAXPLAYERS];
|
||||
extern tic_t servermaxping;
|
||||
#endif
|
||||
|
||||
extern consvar_t
|
||||
#ifdef VANILLAJOINNEXTROUND
|
||||
|
|
47
src/d_main.c
47
src/d_main.c
|
@ -636,9 +636,6 @@ void D_SRB2Loop(void)
|
|||
if (dedicated)
|
||||
server = true;
|
||||
|
||||
if (M_CheckParm("-voodoo")) // 256x256 Texture Limiter
|
||||
COM_BufAddText("gr_voodoocompatibility on\n");
|
||||
|
||||
// Pushing of + parameters is now done back in D_SRB2Main, not here.
|
||||
|
||||
CONS_Printf("I_StartupKeyboard()...\n");
|
||||
|
@ -820,7 +817,6 @@ void D_StartTitle(void)
|
|||
paused = false;
|
||||
advancedemo = false;
|
||||
F_StartTitleScreen();
|
||||
CON_ToggleOff();
|
||||
|
||||
// Reset the palette -- SRB2Kart: actually never mind let's do this in the middle of every fade
|
||||
/*if (rendermode != render_none)
|
||||
|
@ -1218,6 +1214,10 @@ void D_SRB2Main(void)
|
|||
// Setup default unlockable conditions
|
||||
M_SetupDefaultConditionSets();
|
||||
|
||||
// Setup character tables
|
||||
// Have to be done here before files are loaded
|
||||
M_InitCharacterTables();
|
||||
|
||||
// load wad, including the main wad file
|
||||
CONS_Printf("W_InitMultipleFiles(): Adding IWAD and main PWADs.\n");
|
||||
if (!W_InitMultipleFiles(startupwadfiles, false))
|
||||
|
@ -1391,10 +1391,9 @@ void D_SRB2Main(void)
|
|||
midi_disabled = true;
|
||||
#endif
|
||||
}
|
||||
if (M_CheckParm("-nosound"))
|
||||
sound_disabled = true;
|
||||
if (M_CheckParm("-nomusic")) // combines -nomidimusic and -nodigmusic
|
||||
if (M_CheckParm("-noaudio")) // combines -nosound and -nomusic
|
||||
{
|
||||
sound_disabled = true;
|
||||
digital_disabled = true;
|
||||
#ifndef NO_MIDI
|
||||
midi_disabled = true;
|
||||
|
@ -1402,12 +1401,24 @@ void D_SRB2Main(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (M_CheckParm("-nosound"))
|
||||
sound_disabled = true;
|
||||
if (M_CheckParm("-nomusic")) // combines -nomidimusic and -nodigmusic
|
||||
{
|
||||
digital_disabled = true;
|
||||
#ifndef NO_MIDI
|
||||
if (M_CheckParm("-nomidimusic"))
|
||||
midi_disabled = true; // WARNING: DOS version initmusic in I_StartupSound
|
||||
midi_disabled = true;
|
||||
#endif
|
||||
if (M_CheckParm("-nodigmusic"))
|
||||
digital_disabled = true; // WARNING: DOS version initmusic in I_StartupSound
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef NO_MIDI
|
||||
if (M_CheckParm("-nomidimusic"))
|
||||
midi_disabled = true; // WARNING: DOS version initmusic in I_StartupSound
|
||||
#endif
|
||||
if (M_CheckParm("-nodigmusic"))
|
||||
digital_disabled = true; // WARNING: DOS version initmusic in I_StartupSound
|
||||
}
|
||||
}
|
||||
if (!( sound_disabled && digital_disabled
|
||||
#ifndef NO_MIDI
|
||||
|
@ -1537,13 +1548,9 @@ void D_SRB2Main(void)
|
|||
INT16 newgametype = -1;
|
||||
const char *sgametype = M_GetNextParm();
|
||||
|
||||
for (j = 0; gametype_cons_t[j].strvalue; j++)
|
||||
if (!strcasecmp(gametype_cons_t[j].strvalue, sgametype))
|
||||
{
|
||||
newgametype = (INT16)gametype_cons_t[j].value;
|
||||
break;
|
||||
}
|
||||
if (!gametype_cons_t[j].strvalue) // reached end of the list with no match
|
||||
newgametype = G_GetGametypeByName(sgametype);
|
||||
|
||||
if (newgametype == -1) // reached end of the list with no match
|
||||
{
|
||||
j = atoi(sgametype); // assume they gave us a gametype number, which is okay too
|
||||
if (j >= 0 && j < NUMGAMETYPES)
|
||||
|
@ -1598,13 +1605,13 @@ void D_SRB2Main(void)
|
|||
}
|
||||
else if (M_CheckParm("-skipintro"))
|
||||
{
|
||||
CON_ToggleOff();
|
||||
CON_ClearHUD();
|
||||
F_StartTitleScreen();
|
||||
}
|
||||
else
|
||||
F_StartIntro(); // Tails 03-03-2002
|
||||
|
||||
CON_ToggleOff();
|
||||
|
||||
if (dedicated && server)
|
||||
{
|
||||
pagename = "TITLESKY";
|
||||
|
|
125
src/d_net.c
125
src/d_net.c
|
@ -185,22 +185,10 @@ typedef struct
|
|||
UINT8 nextacknum;
|
||||
|
||||
UINT8 flags;
|
||||
#ifndef NEWPING
|
||||
// jacobson tcp timeout evaluation algorithm (Karn variation)
|
||||
fixed_t ping;
|
||||
fixed_t varping;
|
||||
INT32 timeout; // computed with ping and varping
|
||||
#endif
|
||||
} node_t;
|
||||
|
||||
static node_t nodes[MAXNETNODES];
|
||||
#ifndef NEWPING
|
||||
#define PINGDEFAULT ((200*TICRATE*FRACUNIT)/1000)
|
||||
#define VARPINGDEFAULT ((50*TICRATE*FRACUNIT)/1000)
|
||||
#define TIMEOUT(p,v) (p+4*v+FRACUNIT/2)>>FRACBITS;
|
||||
#else
|
||||
#define NODETIMEOUT 14 //What the above boiled down to...
|
||||
#endif
|
||||
#define NODETIMEOUT 14
|
||||
|
||||
#ifndef NONET
|
||||
// return <0 if a < b (mod 256)
|
||||
|
@ -320,19 +308,7 @@ static UINT8 GetAcktosend(INT32 node)
|
|||
static void RemoveAck(INT32 i)
|
||||
{
|
||||
INT32 node = ackpak[i].destinationnode;
|
||||
#ifndef NEWPING
|
||||
fixed_t trueping = (I_GetTime() - ackpak[i].senttime)<<FRACBITS;
|
||||
if (ackpak[i].resentnum)
|
||||
{
|
||||
// +FRACUNIT/2 for round
|
||||
nodes[node].ping = (nodes[node].ping*7 + trueping)/8;
|
||||
nodes[node].varping = (nodes[node].varping*7 + abs(nodes[node].ping-trueping))/8;
|
||||
nodes[node].timeout = TIMEOUT(nodes[node].ping,nodes[node].varping);
|
||||
}
|
||||
DEBFILE(va("Remove ack %d trueping %d ping %f var %f timeout %d\n",ackpak[i].acknum,trueping>>FRACBITS,(double)FIXED_TO_FLOAT(nodes[node].ping),(double)FIXED_TO_FLOAT(nodes[node].varping),nodes[node].timeout));
|
||||
#else
|
||||
DEBFILE(va("Remove ack %d\n",ackpak[i].acknum));
|
||||
#endif
|
||||
ackpak[i].acknum = 0;
|
||||
if (nodes[node].flags & NF_CLOSE)
|
||||
Net_CloseConnection(node);
|
||||
|
@ -519,11 +495,7 @@ void Net_AckTicker(void)
|
|||
{
|
||||
const INT32 nodei = ackpak[i].destinationnode;
|
||||
node_t *node = &nodes[nodei];
|
||||
#ifdef NEWPING
|
||||
if (ackpak[i].acknum && ackpak[i].senttime + NODETIMEOUT < I_GetTime())
|
||||
#else
|
||||
if (ackpak[i].acknum && ackpak[i].senttime + node->timeout < I_GetTime())
|
||||
#endif
|
||||
{
|
||||
if (ackpak[i].resentnum > 10 && (node->flags & NF_CLOSE))
|
||||
{
|
||||
|
@ -534,13 +506,8 @@ void Net_AckTicker(void)
|
|||
ackpak[i].acknum = 0;
|
||||
continue;
|
||||
}
|
||||
#ifdef NEWPING
|
||||
DEBFILE(va("Resend ack %d, %u<%d at %u\n", ackpak[i].acknum, ackpak[i].senttime,
|
||||
NODETIMEOUT, I_GetTime()));
|
||||
#else
|
||||
DEBFILE(va("Resend ack %d, %u<%d at %u\n", ackpak[i].acknum, ackpak[i].senttime,
|
||||
node->timeout, I_GetTime()));
|
||||
#endif
|
||||
M_Memcpy(netbuffer, ackpak[i].pak.raw, ackpak[i].length);
|
||||
ackpak[i].senttime = I_GetTime();
|
||||
ackpak[i].resentnum++;
|
||||
|
@ -658,11 +625,6 @@ void Net_WaitAllAckReceived(UINT32 timeout)
|
|||
static void InitNode(node_t *node)
|
||||
{
|
||||
node->acktosend_head = node->acktosend_tail = 0;
|
||||
#ifndef NEWPING
|
||||
node->ping = PINGDEFAULT;
|
||||
node->varping = VARPINGDEFAULT;
|
||||
node->timeout = TIMEOUT(node->ping, node->varping);
|
||||
#endif
|
||||
node->firstacktosend = 0;
|
||||
node->nextacknum = 1;
|
||||
node->remotefirstack = 0;
|
||||
|
@ -854,9 +816,7 @@ static const char *packettypename[NUMPACKETTYPE] =
|
|||
"CLIENTJOIN",
|
||||
"NODETIMEOUT",
|
||||
"RESYNCHING",
|
||||
#ifdef NEWPING
|
||||
"PING"
|
||||
#endif
|
||||
};
|
||||
|
||||
static void DebugPrintpacket(const char *header)
|
||||
|
@ -1410,30 +1370,73 @@ boolean D_CheckNetGame(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
struct pingcell
|
||||
{
|
||||
INT32 num;
|
||||
INT32 ms;
|
||||
};
|
||||
|
||||
static int pingcellcmp(const void *va, const void *vb)
|
||||
{
|
||||
const struct pingcell *a, *b;
|
||||
a = va;
|
||||
b = vb;
|
||||
return ( a->ms - b->ms );
|
||||
}
|
||||
|
||||
/*
|
||||
New ping command formatted nicely to present ping in
|
||||
ascending order. And with equally spaced columns.
|
||||
The caller's ping is presented at the bottom too, for
|
||||
convenience.
|
||||
*/
|
||||
|
||||
void Command_Ping_f(void)
|
||||
{
|
||||
#ifndef NEWPING
|
||||
if(server)
|
||||
struct pingcell pingv[MAXPLAYERS];
|
||||
INT32 pingc;
|
||||
|
||||
int name_width = 0;
|
||||
int ms_width = 0;
|
||||
|
||||
int n;
|
||||
INT32 i;
|
||||
|
||||
pingc = 0;
|
||||
for (i = 1; i < MAXPLAYERS; ++i)
|
||||
if (playeringame[i])
|
||||
{
|
||||
#endif
|
||||
INT32 i;
|
||||
for (i = 0; i < MAXPLAYERS;i++)
|
||||
{
|
||||
#ifndef NEWPING
|
||||
const INT32 node = playernode[i];
|
||||
if (playeringame[i] && node != 0)
|
||||
CONS_Printf(M_GetText("%.2d : %s\n %d tics, %d ms.\n"), i, player_names[i],
|
||||
GetLag(node), G_TicsToMilliseconds(GetLag(node)));
|
||||
#else
|
||||
if (playeringame[i] && i != 0)
|
||||
CONS_Printf(M_GetText("%.2d : %s\n %d ms\n"), i, player_names[i], playerpingtable[i]);
|
||||
#endif
|
||||
}
|
||||
#ifndef NEWPING
|
||||
n = strlen(player_names[i]);
|
||||
if (n > name_width)
|
||||
name_width = n;
|
||||
|
||||
n = playerpingtable[i];
|
||||
if (n > ms_width)
|
||||
ms_width = n;
|
||||
|
||||
pingv[pingc].num = i;
|
||||
pingv[pingc].ms = playerpingtable[i];
|
||||
pingc++;
|
||||
}
|
||||
|
||||
if (ms_width < 10) ms_width = 1;
|
||||
else if (ms_width < 100) ms_width = 2;
|
||||
else ms_width = 3;
|
||||
|
||||
qsort(pingv, pingc, sizeof (struct pingcell), &pingcellcmp);
|
||||
|
||||
for (i = 0; i < pingc; ++i)
|
||||
{
|
||||
CONS_Printf("%02d : %-*s %*d ms\n",
|
||||
pingv[i].num,
|
||||
name_width, player_names[pingv[i].num],
|
||||
ms_width, pingv[i].ms);
|
||||
}
|
||||
|
||||
if (!server && playeringame[consoleplayer])
|
||||
{
|
||||
CONS_Printf("\nYour ping is %d ms\n", playerpingtable[consoleplayer]);
|
||||
}
|
||||
else
|
||||
CONS_Printf(M_GetText("Only the server can use this.\n"));
|
||||
#endif
|
||||
}
|
||||
|
||||
void D_CloseConnection(void)
|
||||
|
|
146
src/d_netcmd.c
146
src/d_netcmd.c
|
@ -433,7 +433,7 @@ consvar_t cv_numlaps = {"numlaps", "3", CV_NETVAR|CV_CALL|CV_NOINIT, numlaps_con
|
|||
static CV_PossibleValue_t basenumlaps_cons_t[] = {{1, "MIN"}, {50, "MAX"}, {0, "Map default"}, {0, NULL}};
|
||||
consvar_t cv_basenumlaps = {"basenumlaps", "Map default", CV_NETVAR|CV_CALL|CV_CHEAT, basenumlaps_cons_t, BaseNumLaps_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_forceskin = {"forceskin", "-1", CV_NETVAR|CV_CALL|CV_CHEAT, NULL, ForceSkin_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_forceskin = {"forceskin", "Off", CV_NETVAR|CV_CALL|CV_CHEAT, Forceskin_cons_t, ForceSkin_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_downloading = {"downloading", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_allowexitlevel = {"allowexitlevel", "No", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
|
@ -444,7 +444,6 @@ static CV_PossibleValue_t nettimeout_cons_t[] = {{TICRATE/7, "MIN"}, {60*TICRATE
|
|||
consvar_t cv_nettimeout = {"nettimeout", "105", CV_CALL|CV_SAVE, nettimeout_cons_t, NetTimeout_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
//static CV_PossibleValue_t jointimeout_cons_t[] = {{5*TICRATE, "MIN"}, {60*TICRATE, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_jointimeout = {"jointimeout", "105", CV_CALL|CV_SAVE, nettimeout_cons_t, JoinTimeout_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
#ifdef NEWPING
|
||||
static CV_PossibleValue_t maxping_cons_t[] = {{0, "MIN"}, {1000, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_maxping = {"maxping", "800", CV_SAVE, maxping_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
|
@ -455,7 +454,6 @@ consvar_t cv_pingtimeout = {"pingtimeout", "10", CV_SAVE, pingtimeout_cons_t, NU
|
|||
static CV_PossibleValue_t showping_cons_t[] = {{0, "Off"}, {1, "Always"}, {2, "Warning"}, {0, NULL}};
|
||||
consvar_t cv_showping = {"showping", "Always", CV_SAVE, showping_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
#endif
|
||||
// Intermission time Tails 04-19-2002
|
||||
static CV_PossibleValue_t inttime_cons_t[] = {{0, "MIN"}, {3600, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_inttime = {"inttime", "20", CV_NETVAR, inttime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
@ -524,6 +522,24 @@ const char *netxcmdnames[MAXNETXCMD - 1] =
|
|||
*/
|
||||
void D_RegisterServerCommands(void)
|
||||
{
|
||||
INT32 i;
|
||||
Forceskin_cons_t[0].value = -1;
|
||||
Forceskin_cons_t[0].strvalue = "Off";
|
||||
|
||||
for (i = 0; i < NUMGAMETYPES; i++)
|
||||
{
|
||||
gametype_cons_t[i].value = i;
|
||||
gametype_cons_t[i].strvalue = Gametype_Names[i];
|
||||
}
|
||||
gametype_cons_t[NUMGAMETYPES].value = 0;
|
||||
gametype_cons_t[NUMGAMETYPES].strvalue = NULL;
|
||||
|
||||
// Set the values to 0/NULL, it will be overwritten later when a skin is assigned to the slot.
|
||||
for (i = 1; i < MAXSKINS; i++)
|
||||
{
|
||||
Forceskin_cons_t[i].value = 0;
|
||||
Forceskin_cons_t[i].strvalue = NULL;
|
||||
}
|
||||
RegisterNetXCmd(XD_NAMEANDCOLOR, Got_NameAndColor);
|
||||
RegisterNetXCmd(XD_WEAPONPREF, Got_WeaponPref);
|
||||
RegisterNetXCmd(XD_MAP, Got_Mapcmd);
|
||||
|
@ -677,6 +693,14 @@ void D_RegisterServerCommands(void)
|
|||
CV_RegisterVar(&cv_maxsend);
|
||||
CV_RegisterVar(&cv_noticedownload);
|
||||
CV_RegisterVar(&cv_downloadspeed);
|
||||
#ifndef NONET
|
||||
CV_RegisterVar(&cv_allownewplayer);
|
||||
#ifdef VANILLAJOINNEXTROUND
|
||||
CV_RegisterVar(&cv_joinnextround);
|
||||
#endif
|
||||
CV_RegisterVar(&cv_showjoinaddress);
|
||||
CV_RegisterVar(&cv_blamecfail);
|
||||
#endif
|
||||
|
||||
COM_AddCommand("ping", Command_Ping_f);
|
||||
CV_RegisterVar(&cv_nettimeout);
|
||||
|
@ -684,11 +708,9 @@ void D_RegisterServerCommands(void)
|
|||
|
||||
CV_RegisterVar(&cv_skipmapcheck);
|
||||
CV_RegisterVar(&cv_sleep);
|
||||
#ifdef NEWPING
|
||||
CV_RegisterVar(&cv_maxping);
|
||||
CV_RegisterVar(&cv_pingtimeout);
|
||||
CV_RegisterVar(&cv_showping);
|
||||
#endif
|
||||
|
||||
#ifdef SEENAMES
|
||||
CV_RegisterVar(&cv_allowseenames);
|
||||
|
@ -2261,13 +2283,15 @@ static void Command_Map_f(void)
|
|||
{
|
||||
const char *mapname;
|
||||
size_t i;
|
||||
INT32 j, newmapnum;
|
||||
boolean newresetplayers;
|
||||
INT32 newmapnum;
|
||||
boolean newresetplayers, newencoremode;
|
||||
INT32 newgametype = gametype;
|
||||
|
||||
// max length of command: map map03 -gametype coop -noresetplayers -force
|
||||
// 1 2 3 4 5 6
|
||||
// max length of command: map map03 -gametype race -noresetplayers -force -encore
|
||||
// 1 2 3 4 5 6 7
|
||||
// = 8 arg max
|
||||
// i don't know whether this is intrinsic to the system or just someone being weird but
|
||||
// "noresetplayers" is pretty useless for kart if it turns out this is too close to the limit
|
||||
if (COM_Argc() < 2 || COM_Argc() > 8)
|
||||
{
|
||||
CONS_Printf(M_GetText("map <mapname> [-gametype <type> [-force]: warp to map\n"));
|
||||
|
@ -2327,29 +2351,30 @@ static void Command_Map_f(void)
|
|||
return;
|
||||
}
|
||||
|
||||
for (j = 0; gametype_cons_t[j].strvalue; j++)
|
||||
if (!strcasecmp(gametype_cons_t[j].strvalue, COM_Argv(i+1)))
|
||||
{
|
||||
// Don't do any variable setting here. Wait until you get your
|
||||
// map packet first to avoid sending the same info twice!
|
||||
newgametype = gametype_cons_t[j].value;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!gametype_cons_t[j].strvalue) // reached end of the list with no match
|
||||
newgametype = G_GetGametypeByName(COM_Argv(i+1));
|
||||
if (newgametype == -1) // reached end of the list with no match
|
||||
{
|
||||
// assume they gave us a gametype number, which is okay too
|
||||
for (j = 0; gametype_cons_t[j].strvalue != NULL; j++)
|
||||
{
|
||||
if (atoi(COM_Argv(i+1)) == gametype_cons_t[j].value)
|
||||
{
|
||||
newgametype = gametype_cons_t[j].value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
INT32 j = atoi(COM_Argv(i+1)); // assume they gave us a gametype number, which is okay too
|
||||
if (j >= 0 && j < NUMGAMETYPES)
|
||||
newgametype = (INT16)j;
|
||||
}
|
||||
}
|
||||
|
||||
// new encoremode value
|
||||
// use cvar by default
|
||||
|
||||
newencoremode = (boolean)cv_kartencore.value;
|
||||
|
||||
if (COM_CheckParm("-encore"))
|
||||
{
|
||||
if (!M_SecretUnlocked(SECRET_ENCORE) && !newencoremode)
|
||||
{
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("You haven't unlocked Encore Mode yet!\n"));
|
||||
return;
|
||||
}
|
||||
newencoremode = !newencoremode;
|
||||
}
|
||||
|
||||
if (!(i = COM_CheckParm("-force")) && newgametype == gametype) // SRB2Kart
|
||||
newresetplayers = false; // if not forcing and gametypes is the same
|
||||
|
||||
|
@ -2358,15 +2383,20 @@ static void Command_Map_f(void)
|
|||
; // The player wants us to trek on anyway. Do so.
|
||||
// G_TOLFlag handles both multiplayer gametype and ignores it for !multiplayer
|
||||
// Alternatively, bail if the map header is completely missing anyway.
|
||||
else
|
||||
else if (!mapheaderinfo[newmapnum-1]
|
||||
|| !(mapheaderinfo[newmapnum-1]->typeoflevel & G_TOLFlag(newgametype)))
|
||||
{
|
||||
if (!mapheaderinfo[newmapnum-1]
|
||||
|| !(mapheaderinfo[newmapnum-1]->typeoflevel & G_TOLFlag(newgametype)))
|
||||
char gametypestring[32] = "Single Player";
|
||||
|
||||
if (multiplayer)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("%s doesn't support %s mode!\n(Use -force to override)\n"), mapname,
|
||||
(multiplayer ? gametype_cons_t[newgametype].strvalue : "Single Player"));
|
||||
return;
|
||||
if (newgametype >= 0 && newgametype < NUMGAMETYPES
|
||||
&& Gametype_Names[newgametype])
|
||||
strcpy(gametypestring, Gametype_Names[newgametype]);
|
||||
}
|
||||
|
||||
CONS_Alert(CONS_WARNING, M_GetText("%s doesn't support %s mode!\n(Use -force to override)\n"), mapname, gametypestring);
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent warping to locked levels
|
||||
|
@ -2380,7 +2410,7 @@ static void Command_Map_f(void)
|
|||
}
|
||||
|
||||
fromlevelselect = false;
|
||||
D_MapChange(newmapnum, newgametype, (boolean)cv_kartencore.value, newresetplayers, 0, false, false);
|
||||
D_MapChange(newmapnum, newgametype, newencoremode, newresetplayers, 0, false, false);
|
||||
}
|
||||
|
||||
/** Receives a map command and changes the map.
|
||||
|
@ -2451,9 +2481,6 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
|
|||
CON_LogMessage(M_GetText("Speeding off to level...\n"));
|
||||
}
|
||||
|
||||
CON_ToggleOff();
|
||||
CON_ClearHUD();
|
||||
|
||||
if (demoplayback && !timingdemo)
|
||||
precache = false;
|
||||
|
||||
|
@ -4426,12 +4453,22 @@ static void Command_ModDetails_f(void)
|
|||
//
|
||||
static void Command_ShowGametype_f(void)
|
||||
{
|
||||
const char *gametypestr = NULL;
|
||||
|
||||
if (!(netgame || multiplayer)) // print "Single player" instead of "Race"
|
||||
{
|
||||
CONS_Printf(M_GetText("Current gametype is %s\n"), "Single Player");
|
||||
return;
|
||||
}
|
||||
CONS_Printf(M_GetText("Current gametype is %s\n"), gametype_cons_t[gametype].strvalue);
|
||||
|
||||
// get name string for current gametype
|
||||
if (gametype >= 0 && gametype < NUMGAMETYPES)
|
||||
gametypestr = Gametype_Names[gametype];
|
||||
|
||||
if (gametypestr)
|
||||
CONS_Printf(M_GetText("Current gametype is %s\n"), gametypestr);
|
||||
else // string for current gametype was not found above (should never happen)
|
||||
CONS_Printf(M_GetText("Unknown gametype set (%d)\n"), gametype);
|
||||
}
|
||||
|
||||
/** Plays the intro.
|
||||
|
@ -4575,9 +4612,18 @@ static void TimeLimit_OnChange(void)
|
|||
*/
|
||||
void D_GameTypeChanged(INT32 lastgametype)
|
||||
{
|
||||
if (multiplayer)
|
||||
CONS_Printf(M_GetText("Gametype was changed from %s to %s\n"), gametype_cons_t[lastgametype].strvalue, gametype_cons_t[gametype].strvalue);
|
||||
if (netgame)
|
||||
{
|
||||
const char *oldgt = NULL, *newgt = NULL;
|
||||
|
||||
if (lastgametype >= 0 && lastgametype < NUMGAMETYPES)
|
||||
oldgt = Gametype_Names[lastgametype];
|
||||
if (gametype >= 0 && lastgametype < NUMGAMETYPES)
|
||||
newgt = Gametype_Names[gametype];
|
||||
|
||||
if (oldgt && newgt)
|
||||
CONS_Printf(M_GetText("Gametype was changed from %s to %s\n"), oldgt, newgt);
|
||||
}
|
||||
// Only do the following as the server, not as remote admin.
|
||||
// There will always be a server, and this only needs to be done once.
|
||||
if (server && (multiplayer || netgame))
|
||||
|
@ -5210,27 +5256,11 @@ static void Command_Archivetest_f(void)
|
|||
|
||||
/** Makes a change to ::cv_forceskin take effect immediately.
|
||||
*
|
||||
* \todo Move the enforcement code out of SendNameAndColor() so this hack
|
||||
* isn't needed.
|
||||
* \sa Command_SetForcedSkin_f, cv_forceskin, forcedskin
|
||||
* \author Graue <graue@oceanbase.org>
|
||||
*/
|
||||
static void ForceSkin_OnChange(void)
|
||||
{
|
||||
if ((server || IsPlayerAdmin(consoleplayer)) && (cv_forceskin.value < -1 || cv_forceskin.value >= numskins))
|
||||
{
|
||||
if (cv_forceskin.value == -2)
|
||||
CV_SetValue(&cv_forceskin, numskins-1);
|
||||
else
|
||||
{
|
||||
// hack because I can't restrict this and still allow added skins to be used with forceskin.
|
||||
if (!menuactive)
|
||||
CONS_Printf(M_GetText("Valid skin numbers are 0 to %d (-1 disables)\n"), numskins - 1);
|
||||
CV_SetValue(&cv_forceskin, -1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// NOT in SP, silly!
|
||||
if (!(netgame || multiplayer))
|
||||
return;
|
||||
|
@ -5239,7 +5269,7 @@ static void ForceSkin_OnChange(void)
|
|||
CONS_Printf("The server has lifted the forced skin restrictions.\n");
|
||||
else
|
||||
{
|
||||
CONS_Printf("The server is restricting all players to skin \"%s\".\n",skins[cv_forceskin.value].name);
|
||||
CONS_Printf("The server is restricting all players to skin \"%s\".\n",cv_forceskin.string);
|
||||
ForceAllSkins(cv_forceskin.value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -147,11 +147,9 @@ extern consvar_t cv_ringslinger, cv_soundtest;
|
|||
|
||||
extern consvar_t cv_specialrings, cv_powerstones, cv_matchboxes, cv_competitionboxes;
|
||||
|
||||
#ifdef NEWPING
|
||||
extern consvar_t cv_maxping;
|
||||
extern consvar_t cv_pingtimeout;
|
||||
extern consvar_t cv_showping;
|
||||
#endif
|
||||
|
||||
extern consvar_t cv_skipmapcheck;
|
||||
|
||||
|
|
|
@ -1452,6 +1452,13 @@ static void readlevelheader(MYFILE *f, INT32 num)
|
|||
#endif
|
||||
else if (fastcmp(word, "MUSICTRACK"))
|
||||
mapheaderinfo[num-1]->mustrack = ((UINT16)i - 1);
|
||||
else if (fastcmp(word, "MUSICPOS"))
|
||||
mapheaderinfo[num-1]->muspos = (UINT32)get_number(word2);
|
||||
else if (fastcmp(word, "MUSICINTERFADEOUT"))
|
||||
mapheaderinfo[num-1]->musinterfadeout = (UINT32)get_number(word2);
|
||||
else if (fastcmp(word, "MUSICINTER"))
|
||||
deh_strlcpy(mapheaderinfo[num-1]->musintername, word2,
|
||||
sizeof(mapheaderinfo[num-1]->musintername), va("Level header %d: intermission music", num));
|
||||
else if (fastcmp(word, "FORCECHARACTER"))
|
||||
{
|
||||
strlcpy(mapheaderinfo[num-1]->forcecharacter, word2, SKINNAMESIZE+1);
|
||||
|
@ -1775,6 +1782,11 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum)
|
|||
DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].musswitchflags), UNDO_NONE);
|
||||
cutscenes[num]->scene[scenenum].musswitchflags = ((UINT16)i) & MUSIC_TRACKMASK;
|
||||
}
|
||||
else if (fastcmp(word, "MUSICPOS"))
|
||||
{
|
||||
DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].musswitchposition), UNDO_NONE);
|
||||
cutscenes[num]->scene[scenenum].musswitchposition = (UINT32)get_number(word2);
|
||||
}
|
||||
else if (fastcmp(word, "MUSICLOOP"))
|
||||
{
|
||||
DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].musicloop), UNDO_NONE);
|
||||
|
@ -8757,6 +8769,7 @@ struct {
|
|||
|
||||
// doomdef.h constants
|
||||
{"TICRATE",TICRATE},
|
||||
{"MUSICRATE",MUSICRATE},
|
||||
{"RING_DIST",RING_DIST},
|
||||
{"PUSHACCEL",PUSHACCEL},
|
||||
{"MODID",MODID}, // I don't know, I just thought it would be cool for a wad to potentially know what mod it was loaded into.
|
||||
|
@ -10139,6 +10152,9 @@ static inline int lib_getenum(lua_State *L)
|
|||
} else if (fastcmp(word,"mapmusflags")) {
|
||||
lua_pushinteger(L, mapmusflags);
|
||||
return 1;
|
||||
} else if (fastcmp(word,"mapmusposition")) {
|
||||
lua_pushinteger(L, mapmusposition);
|
||||
return 1;
|
||||
} else if (fastcmp(word,"server")) {
|
||||
if ((!multiplayer || !netgame) && !playeringame[serverplayer])
|
||||
return 0;
|
||||
|
@ -10192,6 +10208,9 @@ static inline int lib_getenum(lua_State *L)
|
|||
} else if (fastcmp(word,"mapobjectscale")) {
|
||||
lua_pushinteger(L, mapobjectscale);
|
||||
return 1;
|
||||
} else if (fastcmp(word,"numlaps")) {
|
||||
lua_pushinteger(L, cv_numlaps.value);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -438,6 +438,37 @@ boolean I_SetSongSpeed(float speed)
|
|||
return false;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
// MUSIC SEEKING
|
||||
/// ------------------------
|
||||
|
||||
UINT32 I_GetSongLength(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean I_SetSongLoopPoint(UINT32 looppoint)
|
||||
{
|
||||
(void)looppoint;
|
||||
return false;
|
||||
}
|
||||
|
||||
UINT32 I_GetSongLoopPoint(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean I_SetSongPosition(UINT32 position)
|
||||
{
|
||||
(void)position;
|
||||
return false;
|
||||
}
|
||||
|
||||
UINT32 I_GetSongPosition(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
// MUSIC PLAYBACK
|
||||
/// ------------------------
|
||||
|
@ -545,3 +576,44 @@ int I_QrySongPlaying(int handle)
|
|||
return (midi_pos==-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// ------------------------
|
||||
// MUSIC FADING
|
||||
/// ------------------------
|
||||
|
||||
void I_SetInternalMusicVolume(UINT8 volume)
|
||||
{
|
||||
(void)volume;
|
||||
}
|
||||
|
||||
void I_StopFadingSong(void)
|
||||
{
|
||||
}
|
||||
|
||||
boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void));
|
||||
{
|
||||
(void)target_volume;
|
||||
(void)source_volume;
|
||||
(void)ms;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void));
|
||||
{
|
||||
(void)target_volume;
|
||||
(void)ms;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean I_FadeOutStopSong(UINT32 ms)
|
||||
{
|
||||
(void)ms;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean I_FadeInPlaySong(UINT32 ms, boolean looping)
|
||||
{
|
||||
(void)ms;
|
||||
(void)looping;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -418,6 +418,8 @@ typedef enum
|
|||
#define NEWTICRATERATIO 1 // try 4 for 140 fps :)
|
||||
#define NEWTICRATE (TICRATE*NEWTICRATERATIO)
|
||||
|
||||
#define MUSICRATE 1000 // sound timing is calculated by milliseconds
|
||||
|
||||
#define RING_DIST 1280*FRACUNIT // how close you need to be to a ring to attract it
|
||||
|
||||
#define PUSHACCEL (2*FRACUNIT) // Acceleration for MF2_SLIDEPUSH items.
|
||||
|
@ -601,9 +603,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
|
|||
/// Polyobject fake flat code
|
||||
#define POLYOBJECTS_PLANES
|
||||
|
||||
/// Improved way of dealing with ping values and a ping limit.
|
||||
#define NEWPING
|
||||
|
||||
/// See name of player in your crosshair
|
||||
#define SEENAMES
|
||||
|
||||
|
|
|
@ -33,8 +33,10 @@
|
|||
extern INT16 gamemap;
|
||||
extern char mapmusname[7];
|
||||
extern UINT16 mapmusflags;
|
||||
extern UINT32 mapmusposition;
|
||||
#define MUSIC_TRACKMASK 0x0FFF // ----************
|
||||
#define MUSIC_RELOADRESET 0x8000 // *---------------
|
||||
#define MUSIC_FORCERESET 0x4000 // -*--------------
|
||||
// Use other bits if necessary.
|
||||
|
||||
extern INT16 maptol;
|
||||
|
@ -156,6 +158,7 @@ typedef struct
|
|||
|
||||
char musswitch[7];
|
||||
UINT16 musswitchflags;
|
||||
UINT32 musswitchposition;
|
||||
|
||||
UINT8 fadecolor; // Color number for fade, 0 means don't do the first fade
|
||||
UINT8 fadeinid; // ID of the first fade, to a color -- ignored if fadecolor is 0
|
||||
|
@ -227,6 +230,7 @@ typedef struct
|
|||
INT16 nextlevel; ///< Map number of next level, or 1100-1102 to end.
|
||||
char musname[7]; ///< Music track to play. "" for no music.
|
||||
UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore.
|
||||
UINT32 muspos; ///< Music position to jump to.
|
||||
char forcecharacter[17]; ///< (SKINNAMESIZE+1) Skin to switch to or "" to disable.
|
||||
UINT8 weather; ///< 0 = sunny day, 1 = storm, 2 = snow, 3 = rain, 4 = blank, 5 = thunder w/o rain, 6 = rain w/o lightning, 7 = heat wave.
|
||||
INT16 skynum; ///< Sky number to use.
|
||||
|
@ -260,6 +264,10 @@ typedef struct
|
|||
//boolean automap; ///< Displays a level's white map outline in modified games
|
||||
fixed_t mobj_scale; ///< Replacement for TOL_ERZ3
|
||||
|
||||
// Music stuff.
|
||||
UINT32 musinterfadeout; ///< Fade out level music on intermission screen in milliseconds
|
||||
char musintername[7]; ///< Intermission screen music.
|
||||
|
||||
// Lua stuff.
|
||||
// (This is not ifdeffed so the map header structure can stay identical, just in case.)
|
||||
UINT8 numCustomOptions; ///< Internal. For Lua custom value support.
|
||||
|
@ -330,7 +338,10 @@ enum GameType // SRB2Kart
|
|||
GT_HIDEANDSEEK,
|
||||
GT_CTF
|
||||
};
|
||||
// If you alter this list, update gametype_cons_t in m_menu.c
|
||||
// If you alter this list, update dehacked.c, and Gametype_Names in g_game.c
|
||||
|
||||
// String names for gametypes
|
||||
extern const char *Gametype_Names[NUMGAMETYPES];
|
||||
|
||||
extern tic_t totalplaytime;
|
||||
extern UINT32 matchesplayed;
|
||||
|
@ -543,9 +554,7 @@ extern consvar_t cv_forceskin; // force clients to use the server's skin
|
|||
extern consvar_t cv_downloading; // allow clients to downloading WADs.
|
||||
extern consvar_t cv_nettimeout; // SRB2Kart: Advanced server options menu
|
||||
extern consvar_t cv_jointimeout;
|
||||
#ifdef NEWPING
|
||||
extern consvar_t cv_maxping;
|
||||
#endif
|
||||
extern ticcmd_t netcmds[BACKUPTICS][MAXPLAYERS];
|
||||
extern INT32 serverplayer;
|
||||
extern INT32 adminplayers[MAXPLAYERS];
|
||||
|
|
|
@ -366,16 +366,18 @@ size_t strlcpy(char *dst, const char *src, size_t siz);
|
|||
|
||||
/* Miscellaneous types that don't fit anywhere else (Can this be changed?) */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT8 red;
|
||||
UINT8 green;
|
||||
UINT8 blue;
|
||||
UINT8 alpha;
|
||||
} byteColor_t;
|
||||
|
||||
union FColorRGBA
|
||||
{
|
||||
UINT32 rgba;
|
||||
struct
|
||||
{
|
||||
UINT8 red;
|
||||
UINT8 green;
|
||||
UINT8 blue;
|
||||
UINT8 alpha;
|
||||
} s;
|
||||
byteColor_t s;
|
||||
} ATTRPACK;
|
||||
typedef union FColorRGBA RGBA_t;
|
||||
|
||||
|
|
|
@ -95,6 +95,37 @@ boolean I_SetSongSpeed(float speed)
|
|||
return false;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
// MUSIC SEEKING
|
||||
/// ------------------------
|
||||
|
||||
UINT32 I_GetSongLength(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean I_SetSongLoopPoint(UINT32 looppoint)
|
||||
{
|
||||
(void)looppoint;
|
||||
return false;
|
||||
}
|
||||
|
||||
UINT32 I_GetSongLoopPoint(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean I_SetSongPosition(UINT32 position)
|
||||
{
|
||||
(void)position;
|
||||
return false;
|
||||
}
|
||||
|
||||
UINT32 I_GetSongPosition(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
// MUSIC PLAYBACK
|
||||
/// ------------------------
|
||||
|
@ -142,4 +173,45 @@ boolean I_SetSongTrack(int track)
|
|||
{
|
||||
(void)track;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
// MUSIC FADING
|
||||
/// ------------------------
|
||||
|
||||
void I_SetInternalMusicVolume(UINT8 volume)
|
||||
{
|
||||
(void)volume;
|
||||
}
|
||||
|
||||
void I_StopFadingSong(void)
|
||||
{
|
||||
}
|
||||
|
||||
boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void));
|
||||
{
|
||||
(void)target_volume;
|
||||
(void)source_volume;
|
||||
(void)ms;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void));
|
||||
{
|
||||
(void)target_volume;
|
||||
(void)ms;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean I_FadeOutStopSong(UINT32 ms)
|
||||
{
|
||||
(void)ms;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean I_FadeInPlaySong(UINT32 ms, boolean looping)
|
||||
{
|
||||
(void)ms;
|
||||
(void)looping;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -238,7 +238,6 @@ void F_StartIntro(void)
|
|||
gameaction = ga_nothing;
|
||||
paused = false;
|
||||
CON_ToggleOff();
|
||||
CON_ClearHUD();
|
||||
F_NewCutscene(introtext[0]);
|
||||
|
||||
intro_scenenum = 0;
|
||||
|
@ -580,7 +579,6 @@ void F_StartCredits(void)
|
|||
gameaction = ga_nothing;
|
||||
paused = false;
|
||||
CON_ToggleOff();
|
||||
CON_ClearHUD();
|
||||
S_StopMusic();
|
||||
|
||||
S_ChangeMusicInternal("credit", false);
|
||||
|
@ -773,7 +771,6 @@ void F_StartGameEvaluation(void)
|
|||
gameaction = ga_nothing;
|
||||
paused = false;
|
||||
CON_ToggleOff();
|
||||
CON_ClearHUD();
|
||||
|
||||
finalecount = 0;
|
||||
}
|
||||
|
@ -883,7 +880,6 @@ void F_StartGameEnd(void)
|
|||
gameaction = ga_nothing;
|
||||
paused = false;
|
||||
CON_ToggleOff();
|
||||
CON_ClearHUD();
|
||||
S_StopMusic();
|
||||
|
||||
// In case menus are still up?!!
|
||||
|
@ -1177,7 +1173,6 @@ void F_StartContinue(void)
|
|||
keypressed = false;
|
||||
paused = false;
|
||||
CON_ToggleOff();
|
||||
CON_ClearHUD();
|
||||
|
||||
// In case menus are still up?!!
|
||||
M_ClearMenus(true);
|
||||
|
@ -1297,9 +1292,10 @@ static void F_AdvanceToNextScene(void)
|
|||
picypos = cutscenes[cutnum]->scene[scenenum].ycoord[picnum];
|
||||
|
||||
if (cutscenes[cutnum]->scene[scenenum].musswitch[0])
|
||||
S_ChangeMusic(cutscenes[cutnum]->scene[scenenum].musswitch,
|
||||
S_ChangeMusicEx(cutscenes[cutnum]->scene[scenenum].musswitch,
|
||||
cutscenes[cutnum]->scene[scenenum].musswitchflags,
|
||||
cutscenes[cutnum]->scene[scenenum].musicloop);
|
||||
cutscenes[cutnum]->scene[scenenum].musicloop,
|
||||
cutscenes[cutnum]->scene[scenenum].musswitchposition, 0, 0);
|
||||
|
||||
// Fade to the next
|
||||
dofadenow = true;
|
||||
|
@ -1348,8 +1344,6 @@ void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean reset
|
|||
|
||||
F_NewCutscene(cutscenes[cutscenenum]->scene[0].text);
|
||||
|
||||
CON_ClearHUD();
|
||||
|
||||
cutsceneover = false;
|
||||
runningprecutscene = precutscene;
|
||||
precutresetplayer = resetplayer;
|
||||
|
@ -1370,9 +1364,10 @@ void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean reset
|
|||
stoptimer = 0;
|
||||
|
||||
if (cutscenes[cutnum]->scene[0].musswitch[0])
|
||||
S_ChangeMusic(cutscenes[cutnum]->scene[0].musswitch,
|
||||
S_ChangeMusicEx(cutscenes[cutnum]->scene[0].musswitch,
|
||||
cutscenes[cutnum]->scene[0].musswitchflags,
|
||||
cutscenes[cutnum]->scene[0].musicloop);
|
||||
cutscenes[cutnum]->scene[0].musicloop,
|
||||
cutscenes[cutnum]->scene[scenenum].musswitchposition, 0, 0);
|
||||
else
|
||||
S_StopMusic();
|
||||
}
|
||||
|
|
34
src/g_game.c
34
src/g_game.c
|
@ -77,6 +77,7 @@ static void G_DoStartVote(void);
|
|||
|
||||
char mapmusname[7]; // Music name
|
||||
UINT16 mapmusflags; // Track and reset bit
|
||||
UINT32 mapmusposition; // Position to jump to
|
||||
|
||||
INT16 gamemap = 1;
|
||||
INT16 maptol;
|
||||
|
@ -2572,7 +2573,8 @@ void G_PlayerReborn(INT32 player)
|
|||
{
|
||||
strncpy(mapmusname, mapheaderinfo[gamemap-1]->musname, 7);
|
||||
mapmusname[6] = 0;
|
||||
mapmusflags = mapheaderinfo[gamemap-1]->mustrack & MUSIC_TRACKMASK;
|
||||
mapmusflags = (mapheaderinfo[gamemap-1]->mustrack & MUSIC_TRACKMASK);
|
||||
mapmusposition = mapheaderinfo[gamemap-1]->muspos;
|
||||
songcredit = true;
|
||||
}
|
||||
}
|
||||
|
@ -3103,6 +3105,36 @@ void G_ExitLevel(void)
|
|||
}
|
||||
}
|
||||
|
||||
// See also the enum GameType in doomstat.h
|
||||
const char *Gametype_Names[NUMGAMETYPES] =
|
||||
{
|
||||
"Race", // GT_RACE
|
||||
"Battle" // GT_MATCH
|
||||
|
||||
/*"Co-op", // GT_COOP
|
||||
"Competition", // GT_COMPETITION
|
||||
"Team Match", // GT_TEAMMATCH
|
||||
"Tag", // GT_TAG
|
||||
"Hide and Seek", // GT_HIDEANDSEEK
|
||||
"CTF" // GT_CTF*/
|
||||
};
|
||||
|
||||
//
|
||||
// G_GetGametypeByName
|
||||
//
|
||||
// Returns the number for the given gametype name string, or -1 if not valid.
|
||||
//
|
||||
INT32 G_GetGametypeByName(const char *gametypestr)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; i < NUMGAMETYPES; i++)
|
||||
if (!stricmp(gametypestr, Gametype_Names[i]))
|
||||
return i;
|
||||
|
||||
return -1; // unknown gametype
|
||||
}
|
||||
|
||||
//
|
||||
// G_IsSpecialStage
|
||||
//
|
||||
|
|
|
@ -195,6 +195,7 @@ ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void);
|
|||
void G_StopDemo(void);
|
||||
boolean G_CheckDemoStatus(void);
|
||||
|
||||
INT32 G_GetGametypeByName(const char *gametypestr);
|
||||
boolean G_IsSpecialStage(INT32 mapnum);
|
||||
boolean G_GametypeUsesLives(void);
|
||||
boolean G_GametypeHasTeams(void);
|
||||
|
|
|
@ -1239,6 +1239,8 @@ void G_ClearAllControlKeys(void)
|
|||
{
|
||||
G_ClearControlKeys(gamecontrol, i);
|
||||
G_ClearControlKeys(gamecontrolbis, i);
|
||||
G_ClearControlKeys(gamecontrol3, i);
|
||||
G_ClearControlKeys(gamecontrol4, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -241,43 +241,6 @@ static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight,
|
|||
if (blockheight < 1)
|
||||
I_Error("3D GenerateTexture : too small");
|
||||
}
|
||||
else if (cv_voodoocompatibility.value)
|
||||
{
|
||||
if (originalwidth > 256 || originalheight > 256)
|
||||
{
|
||||
blockwidth = 256;
|
||||
while (originalwidth < blockwidth)
|
||||
blockwidth >>= 1;
|
||||
if (blockwidth < 1)
|
||||
I_Error("3D GenerateTexture : too small");
|
||||
|
||||
blockheight = 256;
|
||||
while (originalheight < blockheight)
|
||||
blockheight >>= 1;
|
||||
if (blockheight < 1)
|
||||
I_Error("3D GenerateTexture : too small");
|
||||
}
|
||||
else
|
||||
{
|
||||
//size up to nearest power of 2
|
||||
blockwidth = 1;
|
||||
while (blockwidth < originalwidth)
|
||||
blockwidth <<= 1;
|
||||
// scale down the original graphics to fit in 256
|
||||
if (blockwidth > 256)
|
||||
blockwidth = 256;
|
||||
//I_Error("3D GenerateTexture : too big");
|
||||
|
||||
//size up to nearest power of 2
|
||||
blockheight = 1;
|
||||
while (blockheight < originalheight)
|
||||
blockheight <<= 1;
|
||||
// scale down the original graphics to fit in 256
|
||||
if (blockheight > 256)
|
||||
blockheight = 255;
|
||||
//I_Error("3D GenerateTexture : too big");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//size up to nearest power of 2
|
||||
|
@ -508,18 +471,6 @@ void HWR_MakePatch (const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipm
|
|||
newwidth = blockwidth;
|
||||
newheight = blockheight;
|
||||
}
|
||||
else if (cv_voodoocompatibility.value) // Only scales down textures that exceed 256x256.
|
||||
{
|
||||
// no rounddown, do not size up patches, so they don't look 'scaled'
|
||||
newwidth = min(grPatch->width, blockwidth);
|
||||
newheight = min(grPatch->height, blockheight);
|
||||
|
||||
if (newwidth > 256 || newheight > 256)
|
||||
{
|
||||
newwidth = blockwidth;
|
||||
newheight = blockheight;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// no rounddown, do not size up patches, so they don't look 'scaled'
|
||||
|
@ -935,18 +886,6 @@ GLPatch_t *HWR_GetPic(lumpnum_t lumpnum)
|
|||
newwidth = blockwidth;
|
||||
newheight = blockheight;
|
||||
}
|
||||
else if (cv_voodoocompatibility.value) // Only scales down textures that exceed 256x256.
|
||||
{
|
||||
// no rounddown, do not size up patches, so they don't look 'scaled'
|
||||
newwidth = min(SHORT(pic->width),blockwidth);
|
||||
newheight = min(SHORT(pic->height),blockheight);
|
||||
|
||||
if (newwidth > 256 || newheight > 256)
|
||||
{
|
||||
newwidth = blockwidth;
|
||||
newheight = blockheight;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// no rounddown, do not size up patches, so they don't look 'scaled'
|
||||
|
|
|
@ -78,8 +78,8 @@
|
|||
#include "r_opengl/r_opengl.h"
|
||||
|
||||
#ifdef HAVE_SPHEREFRUSTRUM
|
||||
static GLdouble viewMatrix[16];
|
||||
static GLdouble projMatrix[16];
|
||||
static GLfloat viewMatrix[16];
|
||||
static GLfloat projMatrix[16];
|
||||
float frustum[6][4];
|
||||
#endif
|
||||
|
||||
|
@ -381,8 +381,8 @@ void gld_FrustrumSetup(void)
|
|||
float t;
|
||||
float clip[16];
|
||||
|
||||
pglGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
|
||||
pglGetDoublev(GL_MODELVIEW_MATRIX, viewMatrix);
|
||||
pglGeFloatv(GL_PROJECTION_MATRIX, projMatrix);
|
||||
pglGetFloatv(GL_MODELVIEW_MATRIX, viewMatrix);
|
||||
|
||||
clip[0] = CALCMATRIX(0, 0, 1, 4, 2, 8, 3, 12);
|
||||
clip[1] = CALCMATRIX(0, 1, 1, 5, 2, 9, 3, 13);
|
||||
|
|
|
@ -101,15 +101,29 @@ typedef struct
|
|||
|
||||
//Hurdler: Transform (coords + angles)
|
||||
//BP: transform order : scale(rotation_x(rotation_y(translation(v))))
|
||||
|
||||
// Kart features
|
||||
#define USE_FTRANSFORM_ANGLEZ
|
||||
#define USE_FTRANSFORM_MIRROR
|
||||
|
||||
// Vanilla features
|
||||
//#define USE_MODEL_NEXTFRAME
|
||||
|
||||
typedef struct
|
||||
{
|
||||
FLOAT x,y,z; // position
|
||||
#ifdef USE_FTRANSFORM_ANGLEZ
|
||||
FLOAT anglex,angley,anglez; // aimingangle / viewangle
|
||||
#else
|
||||
FLOAT anglex,angley; // aimingangle / viewangle
|
||||
#endif
|
||||
FLOAT scalex,scaley,scalez;
|
||||
FLOAT fovxangle, fovyangle;
|
||||
UINT8 splitscreen;
|
||||
boolean flip; // screenflip
|
||||
#ifdef USE_FTRANSFORM_MIRROR
|
||||
boolean mirror; // SRB2Kart: Encore Mode
|
||||
#endif
|
||||
} FTransform;
|
||||
|
||||
// Transformed vector, as passed to HWR API
|
||||
|
@ -152,7 +166,7 @@ enum EPolyFlags
|
|||
// When set, pass the color constant into the FSurfaceInfo -> FlatColor
|
||||
PF_NoTexture = 0x00002000, // Use the small white texture
|
||||
PF_Corona = 0x00004000, // Tell the rendrer we are drawing a corona
|
||||
PF_MD2 = 0x00008000, // Tell the rendrer we are drawing an MD2
|
||||
PF_Unused = 0x00008000, // Unused
|
||||
PF_RemoveYWrap = 0x00010000, // Force clamp texture on Y
|
||||
PF_ForceWrapX = 0x00020000, // Force repeat texture on X
|
||||
PF_ForceWrapY = 0x00040000, // Force repeat texture on Y
|
||||
|
@ -210,8 +224,6 @@ enum hwdsetspecialstate
|
|||
HWD_SET_FOG_COLOR,
|
||||
HWD_SET_FOG_DENSITY,
|
||||
HWD_SET_FOV,
|
||||
HWD_SET_POLYGON_SMOOTH,
|
||||
HWD_SET_PALETTECOLOR,
|
||||
HWD_SET_TEXTUREFILTERMODE,
|
||||
HWD_SET_TEXTUREANISOTROPICMODE,
|
||||
HWD_NUMSTATE
|
||||
|
|
|
@ -58,20 +58,18 @@ EXPORT void HWRAPI(ClearMipMapCache) (void);
|
|||
EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value);
|
||||
|
||||
//Hurdler: added for new development
|
||||
EXPORT void HWRAPI(DrawMD2) (INT32 *gl_cmd_buffer, md2_frame_t *frame, FTransform *pos, float scale);
|
||||
EXPORT void HWRAPI(DrawMD2i) (INT32 *gl_cmd_buffer, md2_frame_t *frame, INT32 duration, INT32 tics, md2_frame_t *nextframe, FTransform *pos, float scale, UINT8 flipped, UINT8 *color);
|
||||
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 *color);
|
||||
EXPORT void HWRAPI(CreateModelVBOs) (model_t *model);
|
||||
EXPORT void HWRAPI(SetTransform) (FTransform *ptransform);
|
||||
EXPORT INT32 HWRAPI(GetTextureUsed) (void);
|
||||
EXPORT INT32 HWRAPI(GetRenderVersion) (void);
|
||||
|
||||
#ifdef SHUFFLE
|
||||
#define SCREENVERTS 10
|
||||
EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]);
|
||||
#endif
|
||||
EXPORT void HWRAPI(FlushScreenTextures) (void);
|
||||
EXPORT void HWRAPI(StartScreenWipe) (void);
|
||||
EXPORT void HWRAPI(EndScreenWipe) (void);
|
||||
EXPORT void HWRAPI(DoScreenWipe) (float alpha);
|
||||
EXPORT void HWRAPI(DoScreenWipe) (void);
|
||||
EXPORT void HWRAPI(DrawIntermissionBG) (void);
|
||||
EXPORT void HWRAPI(MakeScreenTexture) (void);
|
||||
EXPORT void HWRAPI(MakeScreenFinalTexture) (void);
|
||||
|
@ -96,8 +94,8 @@ struct hwdriver_s
|
|||
GClipRect pfnGClipRect;
|
||||
ClearMipMapCache pfnClearMipMapCache;
|
||||
SetSpecialState pfnSetSpecialState;//Hurdler: added for backward compatibility
|
||||
DrawMD2 pfnDrawMD2;
|
||||
DrawMD2i pfnDrawMD2i;
|
||||
DrawModel pfnDrawModel;
|
||||
CreateModelVBOs pfnCreateModelVBOs;
|
||||
SetTransform pfnSetTransform;
|
||||
GetTextureUsed pfnGetTextureUsed;
|
||||
GetRenderVersion pfnGetRenderVersion;
|
||||
|
@ -107,9 +105,7 @@ struct hwdriver_s
|
|||
#ifndef HAVE_SDL
|
||||
Shutdown pfnShutdown;
|
||||
#endif
|
||||
#ifdef SHUFFLE
|
||||
PostImgRedraw pfnPostImgRedraw;
|
||||
#endif
|
||||
FlushScreenTextures pfnFlushScreenTextures;
|
||||
StartScreenWipe pfnStartScreenWipe;
|
||||
EndScreenWipe pfnEndScreenWipe;
|
||||
|
|
|
@ -4259,10 +4259,45 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t
|
|||
}
|
||||
}
|
||||
|
||||
// This is expecting a pointer to an array containing 4 wallVerts for a sprite
|
||||
static void HWR_RotateSpritePolyToAim(gr_vissprite_t *spr, FOutVector *wallVerts)
|
||||
{
|
||||
if (cv_grspritebillboarding.value
|
||||
&& spr && spr->mobj && !(spr->mobj->frame & FF_PAPERSPRITE)
|
||||
&& wallVerts)
|
||||
{
|
||||
float basey = FIXED_TO_FLOAT(spr->mobj->z);
|
||||
float lowy = wallVerts[0].y;
|
||||
if (P_MobjFlip(spr->mobj) == -1)
|
||||
{
|
||||
basey = FIXED_TO_FLOAT(spr->mobj->z + spr->mobj->height);
|
||||
}
|
||||
// Rotate sprites to fully billboard with the camera
|
||||
// X, Y, AND Z need to be manipulated for the polys to rotate around the
|
||||
// origin, because of how the origin setting works I believe that should
|
||||
// be mobj->z or mobj->z + mobj->height
|
||||
wallVerts[2].y = wallVerts[3].y = (spr->ty - basey) * gr_viewludsin + basey;
|
||||
wallVerts[0].y = wallVerts[1].y = (lowy - basey) * gr_viewludsin + basey;
|
||||
// translate back to be around 0 before translating back
|
||||
wallVerts[3].x += ((spr->ty - basey) * gr_viewludcos) * gr_viewcos;
|
||||
wallVerts[2].x += ((spr->ty - basey) * gr_viewludcos) * gr_viewcos;
|
||||
|
||||
wallVerts[0].x += ((lowy - basey) * gr_viewludcos) * gr_viewcos;
|
||||
wallVerts[1].x += ((lowy - basey) * gr_viewludcos) * gr_viewcos;
|
||||
|
||||
wallVerts[3].z += ((spr->ty - basey) * gr_viewludcos) * gr_viewsin;
|
||||
wallVerts[2].z += ((spr->ty - basey) * gr_viewludcos) * gr_viewsin;
|
||||
|
||||
wallVerts[0].z += ((lowy - basey) * gr_viewludcos) * gr_viewsin;
|
||||
wallVerts[1].z += ((lowy - basey) * gr_viewludcos) * gr_viewsin;
|
||||
}
|
||||
}
|
||||
|
||||
static void HWR_SplitSprite(gr_vissprite_t *spr)
|
||||
{
|
||||
float this_scale = 1.0f;
|
||||
FOutVector wallVerts[4];
|
||||
FOutVector baseWallVerts[4]; // This is what the verts should end up as
|
||||
GLPatch_t *gpatch;
|
||||
FSurfaceInfo Surf;
|
||||
const boolean hires = (spr->mobj && spr->mobj->skin && ((skin_t *)spr->mobj->skin)->flags & SF_HIRES);
|
||||
|
@ -4275,11 +4310,13 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
|
|||
float realtop, realbot, top, bot;
|
||||
float towtop, towbot, towmult;
|
||||
float bheight;
|
||||
float realheight, heightmult;
|
||||
const sector_t *sector = spr->mobj->subsector->sector;
|
||||
const lightlist_t *list = sector->lightlist;
|
||||
#ifdef ESLOPE
|
||||
float endrealtop, endrealbot, endtop, endbot;
|
||||
float endbheight;
|
||||
float endrealheight;
|
||||
fixed_t temp;
|
||||
fixed_t v1x, v1y, v2x, v2y;
|
||||
#endif
|
||||
|
@ -4312,16 +4349,16 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
|
|||
HWR_DrawSpriteShadow(spr, gpatch, this_scale);
|
||||
}
|
||||
|
||||
wallVerts[0].x = wallVerts[3].x = spr->x1;
|
||||
wallVerts[2].x = wallVerts[1].x = spr->x2;
|
||||
wallVerts[0].z = wallVerts[3].z = spr->z1;
|
||||
wallVerts[1].z = wallVerts[2].z = spr->z2;
|
||||
baseWallVerts[0].x = baseWallVerts[3].x = spr->x1;
|
||||
baseWallVerts[2].x = baseWallVerts[1].x = spr->x2;
|
||||
baseWallVerts[0].z = baseWallVerts[3].z = spr->z1;
|
||||
baseWallVerts[1].z = baseWallVerts[2].z = spr->z2;
|
||||
|
||||
wallVerts[2].y = wallVerts[3].y = spr->ty;
|
||||
baseWallVerts[2].y = baseWallVerts[3].y = spr->ty;
|
||||
if (spr->mobj && fabsf(this_scale - 1.0f) > 1.0E-36f)
|
||||
wallVerts[0].y = wallVerts[1].y = spr->ty - gpatch->height * this_scale;
|
||||
baseWallVerts[0].y = baseWallVerts[1].y = spr->ty - gpatch->height * this_scale;
|
||||
else
|
||||
wallVerts[0].y = wallVerts[1].y = spr->ty - gpatch->height;
|
||||
baseWallVerts[0].y = baseWallVerts[1].y = spr->ty - gpatch->height;
|
||||
|
||||
v1x = FLOAT_TO_FIXED(spr->x1);
|
||||
v1y = FLOAT_TO_FIXED(spr->z1);
|
||||
|
@ -4330,44 +4367,56 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
|
|||
|
||||
if (spr->flip)
|
||||
{
|
||||
wallVerts[0].sow = wallVerts[3].sow = gpatch->max_s;
|
||||
wallVerts[2].sow = wallVerts[1].sow = 0;
|
||||
}else{
|
||||
wallVerts[0].sow = wallVerts[3].sow = 0;
|
||||
wallVerts[2].sow = wallVerts[1].sow = gpatch->max_s;
|
||||
baseWallVerts[0].sow = baseWallVerts[3].sow = gpatch->max_s;
|
||||
baseWallVerts[2].sow = baseWallVerts[1].sow = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
baseWallVerts[0].sow = baseWallVerts[3].sow = 0;
|
||||
baseWallVerts[2].sow = baseWallVerts[1].sow = gpatch->max_s;
|
||||
}
|
||||
|
||||
// flip the texture coords (look familiar?)
|
||||
if (spr->vflip)
|
||||
{
|
||||
wallVerts[3].tow = wallVerts[2].tow = gpatch->max_t;
|
||||
wallVerts[0].tow = wallVerts[1].tow = 0;
|
||||
}else{
|
||||
wallVerts[3].tow = wallVerts[2].tow = 0;
|
||||
wallVerts[0].tow = wallVerts[1].tow = gpatch->max_t;
|
||||
baseWallVerts[3].tow = baseWallVerts[2].tow = gpatch->max_t;
|
||||
baseWallVerts[0].tow = baseWallVerts[1].tow = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
baseWallVerts[3].tow = baseWallVerts[2].tow = 0;
|
||||
baseWallVerts[0].tow = baseWallVerts[1].tow = gpatch->max_t;
|
||||
}
|
||||
|
||||
// if it has a dispoffset, push it a little towards the camera
|
||||
if (spr->dispoffset) {
|
||||
float co = -gr_viewcos*(0.05f*spr->dispoffset);
|
||||
float si = -gr_viewsin*(0.05f*spr->dispoffset);
|
||||
wallVerts[0].z = wallVerts[3].z = wallVerts[0].z+si;
|
||||
wallVerts[1].z = wallVerts[2].z = wallVerts[1].z+si;
|
||||
wallVerts[0].x = wallVerts[3].x = wallVerts[0].x+co;
|
||||
wallVerts[1].x = wallVerts[2].x = wallVerts[1].x+co;
|
||||
baseWallVerts[0].z = baseWallVerts[3].z = baseWallVerts[0].z+si;
|
||||
baseWallVerts[1].z = baseWallVerts[2].z = baseWallVerts[1].z+si;
|
||||
baseWallVerts[0].x = baseWallVerts[3].x = baseWallVerts[0].x+co;
|
||||
baseWallVerts[1].x = baseWallVerts[2].x = baseWallVerts[1].x+co;
|
||||
}
|
||||
|
||||
realtop = top = wallVerts[3].y;
|
||||
realbot = bot = wallVerts[0].y;
|
||||
towtop = wallVerts[3].tow;
|
||||
towbot = wallVerts[0].tow;
|
||||
// Let dispoffset work first since this adjust each vertex
|
||||
HWR_RotateSpritePolyToAim(spr, baseWallVerts);
|
||||
|
||||
realtop = top = baseWallVerts[3].y;
|
||||
realbot = bot = baseWallVerts[0].y;
|
||||
towtop = baseWallVerts[3].tow;
|
||||
towbot = baseWallVerts[0].tow;
|
||||
towmult = (towbot - towtop) / (top - bot);
|
||||
|
||||
#ifdef ESLOPE
|
||||
endrealtop = endtop = wallVerts[2].y;
|
||||
endrealbot = endbot = wallVerts[1].y;
|
||||
endrealtop = endtop = baseWallVerts[2].y;
|
||||
endrealbot = endbot = baseWallVerts[1].y;
|
||||
#endif
|
||||
|
||||
// copy the contents of baseWallVerts into the drawn wallVerts array
|
||||
// baseWallVerts is used to know the final shape to easily get the vertex
|
||||
// co-ordinates
|
||||
memcpy(wallVerts, baseWallVerts, sizeof(baseWallVerts));
|
||||
|
||||
if (!cv_translucency.value) // translucency disabled
|
||||
{
|
||||
Surf.FlatColor.s.alpha = 0xFF;
|
||||
|
@ -4494,12 +4543,55 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
|
|||
wallVerts[2].y = endtop;
|
||||
wallVerts[0].y = bot;
|
||||
wallVerts[1].y = endbot;
|
||||
|
||||
// The x and y only need to be adjusted in the case that it's not a papersprite
|
||||
if (cv_grspritebillboarding.value
|
||||
&& spr->mobj && !(spr->mobj->frame & FF_PAPERSPRITE))
|
||||
{
|
||||
// Get the x and z of the vertices so billboarding draws correctly
|
||||
realheight = realbot - realtop;
|
||||
endrealheight = endrealbot - endrealtop;
|
||||
heightmult = (realtop - top) / realheight;
|
||||
wallVerts[3].x = baseWallVerts[3].x + (baseWallVerts[3].x - baseWallVerts[0].x) * heightmult;
|
||||
wallVerts[3].z = baseWallVerts[3].z + (baseWallVerts[3].z - baseWallVerts[0].z) * heightmult;
|
||||
|
||||
heightmult = (endrealtop - endtop) / endrealheight;
|
||||
wallVerts[2].x = baseWallVerts[2].x + (baseWallVerts[2].x - baseWallVerts[1].x) * heightmult;
|
||||
wallVerts[2].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult;
|
||||
|
||||
heightmult = (realtop - bot) / realheight;
|
||||
wallVerts[0].x = baseWallVerts[3].x + (baseWallVerts[3].x - baseWallVerts[0].x) * heightmult;
|
||||
wallVerts[0].z = baseWallVerts[3].z + (baseWallVerts[3].z - baseWallVerts[0].z) * heightmult;
|
||||
|
||||
heightmult = (endrealtop - endbot) / endrealheight;
|
||||
wallVerts[1].x = baseWallVerts[2].x + (baseWallVerts[2].x - baseWallVerts[1].x) * heightmult;
|
||||
wallVerts[1].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult;
|
||||
}
|
||||
#else
|
||||
wallVerts[3].tow = wallVerts[2].tow = towtop + ((realtop - top) * towmult);
|
||||
wallVerts[0].tow = wallVerts[1].tow = towtop + ((realtop - bot) * towmult);
|
||||
|
||||
wallVerts[2].y = wallVerts[3].y = top;
|
||||
wallVerts[0].y = wallVerts[1].y = bot;
|
||||
|
||||
// The x and y only need to be adjusted in the case that it's not a papersprite
|
||||
if (cv_grspritebillboarding.value
|
||||
&& spr->mobj && !(spr->mobj->frame & FF_PAPERSPRITE))
|
||||
{
|
||||
// Get the x and z of the vertices so billboarding draws correctly
|
||||
realheight = realbot - realtop;
|
||||
heightmult = (realtop - top) / realheight;
|
||||
wallVerts[3].x = baseWallVerts[3].x + (baseWallVerts[3].x - baseWallVerts[0].x) * heightmult;
|
||||
wallVerts[3].z = baseWallVerts[3].z + (baseWallVerts[3].z - baseWallVerts[0].z) * heightmult;
|
||||
wallVerts[2].x = baseWallVerts[2].x + (baseWallVerts[2].x - baseWallVerts[1].x) * heightmult;
|
||||
wallVerts[2].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult;
|
||||
|
||||
heightmult = (realtop - bot) / realheight;
|
||||
wallVerts[0].x = baseWallVerts[3].x + (baseWallVerts[3].x - baseWallVerts[0].x) * heightmult;
|
||||
wallVerts[0].z = baseWallVerts[3].z + (baseWallVerts[3].z - baseWallVerts[0].z) * heightmult;
|
||||
wallVerts[1].x = baseWallVerts[2].x + (baseWallVerts[2].x - baseWallVerts[1].x) * heightmult;
|
||||
wallVerts[1].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (colormap)
|
||||
|
@ -4669,6 +4761,9 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
|
|||
wallVerts[1].x = wallVerts[2].x = wallVerts[1].x+co;
|
||||
}
|
||||
|
||||
// Let dispoffset work first since this adjust each vertex
|
||||
HWR_RotateSpritePolyToAim(spr, wallVerts);
|
||||
|
||||
// This needs to be AFTER the shadows so that the regular sprites aren't drawn completely black.
|
||||
// sprite lighting by modulating the RGB components
|
||||
/// \todo coloured
|
||||
|
@ -4750,6 +4845,9 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr)
|
|||
wallVerts[0].z = wallVerts[3].z = spr->z1;
|
||||
wallVerts[1].z = wallVerts[2].z = spr->z2;
|
||||
|
||||
// Let dispoffset work first since this adjust each vertex
|
||||
HWR_RotateSpritePolyToAim(spr, wallVerts);
|
||||
|
||||
wallVerts[0].sow = wallVerts[3].sow = 0;
|
||||
wallVerts[2].sow = wallVerts[1].sow = gpatch->max_s;
|
||||
|
||||
|
@ -5261,14 +5359,14 @@ static void HWR_DrawSprites(void)
|
|||
if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
|
||||
{
|
||||
// 8/1/19: Only don't display player models if no default SPR_PLAY is found.
|
||||
if (!cv_grmd2.value || ((md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f) && (md2_models[SPR_PLAY].notfound || md2_models[SPR_PLAY].scale < 0.0f)))
|
||||
if (!cv_grmdls.value || ((md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f) && (md2_models[SPR_PLAY].notfound || md2_models[SPR_PLAY].scale < 0.0f)))
|
||||
HWR_DrawSprite(spr);
|
||||
else
|
||||
HWR_DrawMD2(spr);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!cv_grmd2.value || md2_models[spr->mobj->sprite].notfound || md2_models[spr->mobj->sprite].scale < 0.0f)
|
||||
if (!cv_grmdls.value || md2_models[spr->mobj->sprite].notfound || md2_models[spr->mobj->sprite].scale < 0.0f)
|
||||
HWR_DrawSprite(spr);
|
||||
else
|
||||
HWR_DrawMD2(spr);
|
||||
|
@ -5435,7 +5533,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
tz = (tr_x * gr_viewcos) + (tr_y * gr_viewsin);
|
||||
|
||||
// thing is behind view plane?
|
||||
if (tz < ZCLIP_PLANE && !papersprite && (!cv_grmd2.value || md2_models[thing->sprite].notfound == true)) //Yellow: Only MD2's dont disappear
|
||||
if (tz < ZCLIP_PLANE && !papersprite && (!cv_grmdls.value || md2_models[thing->sprite].notfound == true)) //Yellow: Only MD2's dont disappear
|
||||
return;
|
||||
|
||||
// The above can stay as it works for cutting sprites that are too close
|
||||
|
@ -6795,11 +6893,6 @@ static void HWR_RenderWall(wallVert3D *wallVerts, FSurfaceInfo *pSurf, FBITFIE
|
|||
#endif
|
||||
}
|
||||
|
||||
void HWR_SetPaletteColor(INT32 palcolor)
|
||||
{
|
||||
HWD.pfnSetSpecialState(HWD_SET_PALETTECOLOR, palcolor);
|
||||
}
|
||||
|
||||
INT32 HWR_GetTextureUsed(void)
|
||||
{
|
||||
return HWD.pfnGetTextureUsed();
|
||||
|
@ -6850,7 +6943,6 @@ void HWR_DoPostProcessor(player_t *player)
|
|||
if (splitscreen) // Not supported in splitscreen - someone want to add support?
|
||||
return;
|
||||
|
||||
#ifdef SHUFFLE
|
||||
// Drunken vision! WooOOooo~
|
||||
if (*type == postimg_water || *type == postimg_heat)
|
||||
{
|
||||
|
@ -6893,7 +6985,6 @@ void HWR_DoPostProcessor(player_t *player)
|
|||
HWD.pfnMakeScreenTexture();
|
||||
}
|
||||
// Flipping of the screen isn't done here anymore
|
||||
#endif // SHUFFLE
|
||||
}
|
||||
|
||||
void HWR_StartScreenWipe(void)
|
||||
|
@ -6940,7 +7031,7 @@ void HWR_DoWipe(UINT8 wipenum, UINT8 scrnnum)
|
|||
|
||||
HWR_GetFadeMask(lumpnum);
|
||||
|
||||
HWD.pfnDoScreenWipe(HWRWipeCounter); // Still send in wipecounter since old stuff might not support multitexturing
|
||||
HWD.pfnDoScreenWipe();
|
||||
|
||||
HWRWipeCounter += 0.05f; // increase opacity of end screen
|
||||
|
||||
|
|
|
@ -58,7 +58,6 @@ void HWR_AddCommands(void);
|
|||
void HWR_CorrectSWTricks(void);
|
||||
void transform(float *cx, float *cy, float *cz);
|
||||
FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf);
|
||||
void HWR_SetPaletteColor(INT32 palcolor);
|
||||
INT32 HWR_GetTextureUsed(void);
|
||||
void HWR_DoPostProcessor(player_t *player);
|
||||
void HWR_StartScreenWipe(void);
|
||||
|
@ -80,7 +79,7 @@ extern consvar_t cv_grstaticlighting;
|
|||
extern consvar_t cv_grcoronas;
|
||||
extern consvar_t cv_grcoronasize;
|
||||
#endif
|
||||
extern consvar_t cv_grmd2;
|
||||
extern consvar_t cv_grmdls;
|
||||
extern consvar_t cv_grfog;
|
||||
extern consvar_t cv_grfogcolor;
|
||||
extern consvar_t cv_grfogdensity;
|
||||
|
@ -91,9 +90,9 @@ extern consvar_t cv_grgammablue;
|
|||
extern consvar_t cv_grfiltermode;
|
||||
extern consvar_t cv_granisotropicmode;
|
||||
extern consvar_t cv_grcorrecttricks;
|
||||
extern consvar_t cv_voodoocompatibility;
|
||||
extern consvar_t cv_grfovchange;
|
||||
extern consvar_t cv_grsolvetjoin;
|
||||
extern consvar_t cv_grspritebillboarding;
|
||||
|
||||
extern float gr_viewwidth, gr_viewheight, gr_baseviewwindowx, gr_baseviewwindowy;
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "../r_draw.h"
|
||||
#include "../p_tick.h"
|
||||
#include "../k_kart.h" // colortranslations
|
||||
#include "hw_model.h"
|
||||
|
||||
#include "hw_main.h"
|
||||
#include "../v_video.h"
|
||||
|
@ -75,172 +76,6 @@
|
|||
#include "errno.h"
|
||||
#endif
|
||||
|
||||
#define NUMVERTEXNORMALS 162
|
||||
float avertexnormals[NUMVERTEXNORMALS][3] = {
|
||||
{-0.525731f, 0.000000f, 0.850651f},
|
||||
{-0.442863f, 0.238856f, 0.864188f},
|
||||
{-0.295242f, 0.000000f, 0.955423f},
|
||||
{-0.309017f, 0.500000f, 0.809017f},
|
||||
{-0.162460f, 0.262866f, 0.951056f},
|
||||
{0.000000f, 0.000000f, 1.000000f},
|
||||
{0.000000f, 0.850651f, 0.525731f},
|
||||
{-0.147621f, 0.716567f, 0.681718f},
|
||||
{0.147621f, 0.716567f, 0.681718f},
|
||||
{0.000000f, 0.525731f, 0.850651f},
|
||||
{0.309017f, 0.500000f, 0.809017f},
|
||||
{0.525731f, 0.000000f, 0.850651f},
|
||||
{0.295242f, 0.000000f, 0.955423f},
|
||||
{0.442863f, 0.238856f, 0.864188f},
|
||||
{0.162460f, 0.262866f, 0.951056f},
|
||||
{-0.681718f, 0.147621f, 0.716567f},
|
||||
{-0.809017f, 0.309017f, 0.500000f},
|
||||
{-0.587785f, 0.425325f, 0.688191f},
|
||||
{-0.850651f, 0.525731f, 0.000000f},
|
||||
{-0.864188f, 0.442863f, 0.238856f},
|
||||
{-0.716567f, 0.681718f, 0.147621f},
|
||||
{-0.688191f, 0.587785f, 0.425325f},
|
||||
{-0.500000f, 0.809017f, 0.309017f},
|
||||
{-0.238856f, 0.864188f, 0.442863f},
|
||||
{-0.425325f, 0.688191f, 0.587785f},
|
||||
{-0.716567f, 0.681718f, -0.147621f},
|
||||
{-0.500000f, 0.809017f, -0.309017f},
|
||||
{-0.525731f, 0.850651f, 0.000000f},
|
||||
{0.000000f, 0.850651f, -0.525731f},
|
||||
{-0.238856f, 0.864188f, -0.442863f},
|
||||
{0.000000f, 0.955423f, -0.295242f},
|
||||
{-0.262866f, 0.951056f, -0.162460f},
|
||||
{0.000000f, 1.000000f, 0.000000f},
|
||||
{0.000000f, 0.955423f, 0.295242f},
|
||||
{-0.262866f, 0.951056f, 0.162460f},
|
||||
{0.238856f, 0.864188f, 0.442863f},
|
||||
{0.262866f, 0.951056f, 0.162460f},
|
||||
{0.500000f, 0.809017f, 0.309017f},
|
||||
{0.238856f, 0.864188f, -0.442863f},
|
||||
{0.262866f, 0.951056f, -0.162460f},
|
||||
{0.500000f, 0.809017f, -0.309017f},
|
||||
{0.850651f, 0.525731f, 0.000000f},
|
||||
{0.716567f, 0.681718f, 0.147621f},
|
||||
{0.716567f, 0.681718f, -0.147621f},
|
||||
{0.525731f, 0.850651f, 0.000000f},
|
||||
{0.425325f, 0.688191f, 0.587785f},
|
||||
{0.864188f, 0.442863f, 0.238856f},
|
||||
{0.688191f, 0.587785f, 0.425325f},
|
||||
{0.809017f, 0.309017f, 0.500000f},
|
||||
{0.681718f, 0.147621f, 0.716567f},
|
||||
{0.587785f, 0.425325f, 0.688191f},
|
||||
{0.955423f, 0.295242f, 0.000000f},
|
||||
{1.000000f, 0.000000f, 0.000000f},
|
||||
{0.951056f, 0.162460f, 0.262866f},
|
||||
{0.850651f, -0.525731f, 0.000000f},
|
||||
{0.955423f, -0.295242f, 0.000000f},
|
||||
{0.864188f, -0.442863f, 0.238856f},
|
||||
{0.951056f, -0.162460f, 0.262866f},
|
||||
{0.809017f, -0.309017f, 0.500000f},
|
||||
{0.681718f, -0.147621f, 0.716567f},
|
||||
{0.850651f, 0.000000f, 0.525731f},
|
||||
{0.864188f, 0.442863f, -0.238856f},
|
||||
{0.809017f, 0.309017f, -0.500000f},
|
||||
{0.951056f, 0.162460f, -0.262866f},
|
||||
{0.525731f, 0.000000f, -0.850651f},
|
||||
{0.681718f, 0.147621f, -0.716567f},
|
||||
{0.681718f, -0.147621f, -0.716567f},
|
||||
{0.850651f, 0.000000f, -0.525731f},
|
||||
{0.809017f, -0.309017f, -0.500000f},
|
||||
{0.864188f, -0.442863f, -0.238856f},
|
||||
{0.951056f, -0.162460f, -0.262866f},
|
||||
{0.147621f, 0.716567f, -0.681718f},
|
||||
{0.309017f, 0.500000f, -0.809017f},
|
||||
{0.425325f, 0.688191f, -0.587785f},
|
||||
{0.442863f, 0.238856f, -0.864188f},
|
||||
{0.587785f, 0.425325f, -0.688191f},
|
||||
{0.688191f, 0.587785f, -0.425325f},
|
||||
{-0.147621f, 0.716567f, -0.681718f},
|
||||
{-0.309017f, 0.500000f, -0.809017f},
|
||||
{0.000000f, 0.525731f, -0.850651f},
|
||||
{-0.525731f, 0.000000f, -0.850651f},
|
||||
{-0.442863f, 0.238856f, -0.864188f},
|
||||
{-0.295242f, 0.000000f, -0.955423f},
|
||||
{-0.162460f, 0.262866f, -0.951056f},
|
||||
{0.000000f, 0.000000f, -1.000000f},
|
||||
{0.295242f, 0.000000f, -0.955423f},
|
||||
{0.162460f, 0.262866f, -0.951056f},
|
||||
{-0.442863f, -0.238856f, -0.864188f},
|
||||
{-0.309017f, -0.500000f, -0.809017f},
|
||||
{-0.162460f, -0.262866f, -0.951056f},
|
||||
{0.000000f, -0.850651f, -0.525731f},
|
||||
{-0.147621f, -0.716567f, -0.681718f},
|
||||
{0.147621f, -0.716567f, -0.681718f},
|
||||
{0.000000f, -0.525731f, -0.850651f},
|
||||
{0.309017f, -0.500000f, -0.809017f},
|
||||
{0.442863f, -0.238856f, -0.864188f},
|
||||
{0.162460f, -0.262866f, -0.951056f},
|
||||
{0.238856f, -0.864188f, -0.442863f},
|
||||
{0.500000f, -0.809017f, -0.309017f},
|
||||
{0.425325f, -0.688191f, -0.587785f},
|
||||
{0.716567f, -0.681718f, -0.147621f},
|
||||
{0.688191f, -0.587785f, -0.425325f},
|
||||
{0.587785f, -0.425325f, -0.688191f},
|
||||
{0.000000f, -0.955423f, -0.295242f},
|
||||
{0.000000f, -1.000000f, 0.000000f},
|
||||
{0.262866f, -0.951056f, -0.162460f},
|
||||
{0.000000f, -0.850651f, 0.525731f},
|
||||
{0.000000f, -0.955423f, 0.295242f},
|
||||
{0.238856f, -0.864188f, 0.442863f},
|
||||
{0.262866f, -0.951056f, 0.162460f},
|
||||
{0.500000f, -0.809017f, 0.309017f},
|
||||
{0.716567f, -0.681718f, 0.147621f},
|
||||
{0.525731f, -0.850651f, 0.000000f},
|
||||
{-0.238856f, -0.864188f, -0.442863f},
|
||||
{-0.500000f, -0.809017f, -0.309017f},
|
||||
{-0.262866f, -0.951056f, -0.162460f},
|
||||
{-0.850651f, -0.525731f, 0.000000f},
|
||||
{-0.716567f, -0.681718f, -0.147621f},
|
||||
{-0.716567f, -0.681718f, 0.147621f},
|
||||
{-0.525731f, -0.850651f, 0.000000f},
|
||||
{-0.500000f, -0.809017f, 0.309017f},
|
||||
{-0.238856f, -0.864188f, 0.442863f},
|
||||
{-0.262866f, -0.951056f, 0.162460f},
|
||||
{-0.864188f, -0.442863f, 0.238856f},
|
||||
{-0.809017f, -0.309017f, 0.500000f},
|
||||
{-0.688191f, -0.587785f, 0.425325f},
|
||||
{-0.681718f, -0.147621f, 0.716567f},
|
||||
{-0.442863f, -0.238856f, 0.864188f},
|
||||
{-0.587785f, -0.425325f, 0.688191f},
|
||||
{-0.309017f, -0.500000f, 0.809017f},
|
||||
{-0.147621f, -0.716567f, 0.681718f},
|
||||
{-0.425325f, -0.688191f, 0.587785f},
|
||||
{-0.162460f, -0.262866f, 0.951056f},
|
||||
{0.442863f, -0.238856f, 0.864188f},
|
||||
{0.162460f, -0.262866f, 0.951056f},
|
||||
{0.309017f, -0.500000f, 0.809017f},
|
||||
{0.147621f, -0.716567f, 0.681718f},
|
||||
{0.000000f, -0.525731f, 0.850651f},
|
||||
{0.425325f, -0.688191f, 0.587785f},
|
||||
{0.587785f, -0.425325f, 0.688191f},
|
||||
{0.688191f, -0.587785f, 0.425325f},
|
||||
{-0.955423f, 0.295242f, 0.000000f},
|
||||
{-0.951056f, 0.162460f, 0.262866f},
|
||||
{-1.000000f, 0.000000f, 0.000000f},
|
||||
{-0.850651f, 0.000000f, 0.525731f},
|
||||
{-0.955423f, -0.295242f, 0.000000f},
|
||||
{-0.951056f, -0.162460f, 0.262866f},
|
||||
{-0.864188f, 0.442863f, -0.238856f},
|
||||
{-0.951056f, 0.162460f, -0.262866f},
|
||||
{-0.809017f, 0.309017f, -0.500000f},
|
||||
{-0.864188f, -0.442863f, -0.238856f},
|
||||
{-0.951056f, -0.162460f, -0.262866f},
|
||||
{-0.809017f, -0.309017f, -0.500000f},
|
||||
{-0.681718f, 0.147621f, -0.716567f},
|
||||
{-0.681718f, -0.147621f, -0.716567f},
|
||||
{-0.850651f, 0.000000f, -0.525731f},
|
||||
{-0.688191f, 0.587785f, -0.425325f},
|
||||
{-0.587785f, 0.425325f, -0.688191f},
|
||||
{-0.425325f, 0.688191f, -0.587785f},
|
||||
{-0.425325f, -0.688191f, -0.587785f},
|
||||
{-0.587785f, -0.425325f, -0.688191f},
|
||||
{-0.688191f, -0.587785f, -0.425325f},
|
||||
};
|
||||
|
||||
md2_t md2_models[NUMSPRITES];
|
||||
md2_t md2_playermodels[MAXSKINS];
|
||||
|
||||
|
@ -248,198 +83,29 @@ md2_t md2_playermodels[MAXSKINS];
|
|||
/*
|
||||
* free model
|
||||
*/
|
||||
static void md2_freeModel (md2_model_t *model)
|
||||
#if 0
|
||||
static void md2_freeModel (model_t *model)
|
||||
{
|
||||
if (model)
|
||||
{
|
||||
if (model->skins)
|
||||
free(model->skins);
|
||||
|
||||
if (model->texCoords)
|
||||
free(model->texCoords);
|
||||
|
||||
if (model->triangles)
|
||||
free(model->triangles);
|
||||
|
||||
if (model->frames)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < model->header.numFrames; i++)
|
||||
{
|
||||
if (model->frames[i].vertices)
|
||||
free(model->frames[i].vertices);
|
||||
}
|
||||
free(model->frames);
|
||||
}
|
||||
|
||||
if (model->glCommandBuffer)
|
||||
free(model->glCommandBuffer);
|
||||
|
||||
free(model);
|
||||
}
|
||||
UnloadModel(model);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//
|
||||
// load model
|
||||
//
|
||||
// Hurdler: the current path is the Legacy.exe path
|
||||
static md2_model_t *md2_readModel(const char *filename)
|
||||
static model_t *md2_readModel(const char *filename)
|
||||
{
|
||||
FILE *file;
|
||||
md2_model_t *model;
|
||||
UINT8 buffer[MD2_MAX_FRAMESIZE];
|
||||
size_t i;
|
||||
|
||||
model = calloc(1, sizeof (*model));
|
||||
if (model == NULL)
|
||||
return 0;
|
||||
|
||||
//Filename checking fixed ~Monster Iestyn and Golden
|
||||
file = fopen(va("%s"PATHSEP"%s", srb2home, filename), "rb");
|
||||
if (!file)
|
||||
{
|
||||
file = fopen(va("%s"PATHSEP"%s", srb2path, filename), "rb");
|
||||
if (!file)
|
||||
{
|
||||
free(model);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// initialize model and read header
|
||||
|
||||
if (fread(&model->header, sizeof (model->header), 1, file) != 1
|
||||
|| model->header.magic != MD2_IDENT
|
||||
|| model->header.version != MD2_VERSION)
|
||||
{
|
||||
fclose(file);
|
||||
free(model);
|
||||
return 0;
|
||||
}
|
||||
|
||||
model->header.numSkins = 1;
|
||||
|
||||
#define MD2LIMITCHECK(field, max, msgname) \
|
||||
if (field > max) \
|
||||
{ \
|
||||
CONS_Alert(CONS_ERROR, "md2_readModel: %s has too many " msgname " (# found: %d, maximum: %d)\n", filename, field, max); \
|
||||
md2_freeModel (model); \
|
||||
fclose(file); \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
// Uncomment if these are actually needed
|
||||
// MD2LIMITCHECK(model->header.numSkins, MD2_MAX_SKINS, "skins")
|
||||
// MD2LIMITCHECK(model->header.numTexCoords, MD2_MAX_TEXCOORDS, "texture coordinates")
|
||||
MD2LIMITCHECK(model->header.numTriangles, MD2_MAX_TRIANGLES, "triangles")
|
||||
MD2LIMITCHECK(model->header.numFrames, MD2_MAX_FRAMES, "frames")
|
||||
MD2LIMITCHECK(model->header.numVertices, MD2_MAX_VERTICES, "vertices")
|
||||
|
||||
#undef MD2LIMITCHECK
|
||||
|
||||
// read skins
|
||||
fseek(file, model->header.offsetSkins, SEEK_SET);
|
||||
if (model->header.numSkins > 0)
|
||||
{
|
||||
model->skins = calloc(sizeof (md2_skin_t), model->header.numSkins);
|
||||
if (!model->skins || model->header.numSkins !=
|
||||
fread(model->skins, sizeof (md2_skin_t), model->header.numSkins, file))
|
||||
{
|
||||
md2_freeModel (model);
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// read texture coordinates
|
||||
fseek(file, model->header.offsetTexCoords, SEEK_SET);
|
||||
if (model->header.numTexCoords > 0)
|
||||
{
|
||||
model->texCoords = calloc(sizeof (md2_textureCoordinate_t), model->header.numTexCoords);
|
||||
if (!model->texCoords || model->header.numTexCoords !=
|
||||
fread(model->texCoords, sizeof (md2_textureCoordinate_t), model->header.numTexCoords, file))
|
||||
{
|
||||
md2_freeModel (model);
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// read triangles
|
||||
fseek(file, model->header.offsetTriangles, SEEK_SET);
|
||||
if (model->header.numTriangles > 0)
|
||||
{
|
||||
model->triangles = calloc(sizeof (md2_triangle_t), model->header.numTriangles);
|
||||
if (!model->triangles || model->header.numTriangles !=
|
||||
fread(model->triangles, sizeof (md2_triangle_t), model->header.numTriangles, file))
|
||||
{
|
||||
md2_freeModel (model);
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// read alias frames
|
||||
fseek(file, model->header.offsetFrames, SEEK_SET);
|
||||
if (model->header.numFrames > 0)
|
||||
{
|
||||
model->frames = calloc(sizeof (md2_frame_t), model->header.numFrames);
|
||||
if (!model->frames)
|
||||
{
|
||||
md2_freeModel (model);
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < model->header.numFrames; i++)
|
||||
{
|
||||
md2_alias_frame_t *frame = (md2_alias_frame_t *)(void *)buffer;
|
||||
size_t j;
|
||||
|
||||
model->frames[i].vertices = calloc(sizeof (md2_triangleVertex_t), model->header.numVertices);
|
||||
if (!model->frames[i].vertices || model->header.frameSize !=
|
||||
fread(frame, 1, model->header.frameSize, file))
|
||||
{
|
||||
md2_freeModel (model);
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
strcpy(model->frames[i].name, frame->name);
|
||||
for (j = 0; j < model->header.numVertices; j++)
|
||||
{
|
||||
model->frames[i].vertices[j].vertex[0] = (float) ((INT32) frame->alias_vertices[j].vertex[0]) * frame->scale[0] + frame->translate[0];
|
||||
model->frames[i].vertices[j].vertex[2] = -1* ((float) ((INT32) frame->alias_vertices[j].vertex[1]) * frame->scale[1] + frame->translate[1]);
|
||||
model->frames[i].vertices[j].vertex[1] = (float) ((INT32) frame->alias_vertices[j].vertex[2]) * frame->scale[2] + frame->translate[2];
|
||||
model->frames[i].vertices[j].normal[0] = avertexnormals[frame->alias_vertices[j].lightNormalIndex][0];
|
||||
model->frames[i].vertices[j].normal[1] = avertexnormals[frame->alias_vertices[j].lightNormalIndex][1];
|
||||
model->frames[i].vertices[j].normal[2] = avertexnormals[frame->alias_vertices[j].lightNormalIndex][2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// read gl commands
|
||||
fseek(file, model->header.offsetGlCommands, SEEK_SET);
|
||||
if (model->header.numGlCommands)
|
||||
{
|
||||
model->glCommandBuffer = calloc(sizeof (INT32), model->header.numGlCommands);
|
||||
if (!model->glCommandBuffer || model->header.numGlCommands !=
|
||||
fread(model->glCommandBuffer, sizeof (INT32), model->header.numGlCommands, file))
|
||||
{
|
||||
md2_freeModel (model);
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
|
||||
return model;
|
||||
if (FIL_FileExists(va("%s"PATHSEP"%s", srb2home, filename)))
|
||||
return LoadModel(va("%s"PATHSEP"%s", srb2home, filename), PU_STATIC);
|
||||
else if (FIL_FileExists(va("%s"PATHSEP"%s", srb2path, filename)))
|
||||
return LoadModel(va("%s"PATHSEP"%s", srb2path, filename), PU_STATIC);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void md2_printModelInfo (md2_model_t *model)
|
||||
static inline void md2_printModelInfo (model_t *model)
|
||||
{
|
||||
#if 0
|
||||
INT32 i;
|
||||
|
@ -498,13 +164,13 @@ static GrTextureFormat_t PNG_Load(const char *filename, int *w, int *h, GLPatch_
|
|||
#endif
|
||||
volatile png_FILE_p png_FILE;
|
||||
//Filename checking fixed ~Monster Iestyn and Golden
|
||||
char *pngfilename = va("%s"PATHSEP"md2"PATHSEP"%s", srb2home, filename);
|
||||
char *pngfilename = va("%s"PATHSEP"mdls"PATHSEP"%s", srb2home, filename);
|
||||
|
||||
FIL_ForceExtension(pngfilename, ".png");
|
||||
png_FILE = fopen(pngfilename, "rb");
|
||||
if (!png_FILE)
|
||||
{
|
||||
pngfilename = va("%s"PATHSEP"md2"PATHSEP"%s", srb2path, filename);
|
||||
pngfilename = va("%s"PATHSEP"mdls"PATHSEP"%s", srb2path, filename);
|
||||
FIL_ForceExtension(pngfilename, ".png");
|
||||
png_FILE = fopen(pngfilename, "rb");
|
||||
//CONS_Debug(DBG_RENDER, "M_SavePNG: Error on opening %s for loading\n", filename);
|
||||
|
@ -631,13 +297,13 @@ static GrTextureFormat_t PCX_Load(const char *filename, int *w, int *h,
|
|||
INT32 ch, rep;
|
||||
FILE *file;
|
||||
//Filename checking fixed ~Monster Iestyn and Golden
|
||||
char *pcxfilename = va("%s"PATHSEP"md2"PATHSEP"%s", srb2home, filename);
|
||||
char *pcxfilename = va("%s"PATHSEP"mdls"PATHSEP"%s", srb2home, filename);
|
||||
|
||||
FIL_ForceExtension(pcxfilename, ".pcx");
|
||||
file = fopen(pcxfilename, "rb");
|
||||
if (!file)
|
||||
{
|
||||
pcxfilename = va("%s"PATHSEP"md2"PATHSEP"%s", srb2path, filename);
|
||||
pcxfilename = va("%s"PATHSEP"mdls"PATHSEP"%s", srb2path, filename);
|
||||
FIL_ForceExtension(pcxfilename, ".pcx");
|
||||
file = fopen(pcxfilename, "rb");
|
||||
if (!file)
|
||||
|
@ -826,16 +492,16 @@ void HWR_InitMD2(void)
|
|||
md2_models[i].error = false;
|
||||
}
|
||||
|
||||
// read the md2.dat file
|
||||
// read the mdls.dat file
|
||||
//Filename checking fixed ~Monster Iestyn and Golden
|
||||
f = fopen(va("%s"PATHSEP"%s", srb2home, "kmd2.dat"), "rt");
|
||||
f = fopen(va("%s"PATHSEP"%s", srb2home, "mdls.dat"), "rt");
|
||||
|
||||
if (!f)
|
||||
{
|
||||
f = fopen(va("%s"PATHSEP"%s", srb2path, "kmd2.dat"), "rt");
|
||||
f = fopen(va("%s"PATHSEP"%s", srb2path, "mdls.dat"), "rt");
|
||||
if (!f)
|
||||
{
|
||||
CONS_Printf("%s %s\n", M_GetText("Error while loading kmd2.dat:"), strerror(errno));
|
||||
CONS_Printf("%s %s\n", M_GetText("Error while loading mdls.dat:"), strerror(errno));
|
||||
nomd2s = true;
|
||||
return;
|
||||
}
|
||||
|
@ -844,7 +510,7 @@ void HWR_InitMD2(void)
|
|||
{
|
||||
/*if (stricmp(name, "PLAY") == 0)
|
||||
{
|
||||
CONS_Printf("MD2 for sprite PLAY detected in kmd2.dat, use a player skin instead!\n");
|
||||
CONS_Printf("MD2 for sprite PLAY detected in mdls.dat, use a player skin instead!\n");
|
||||
continue;
|
||||
}*/
|
||||
// 8/1/19: Allow PLAY to load for default MD2.
|
||||
|
@ -879,7 +545,7 @@ void HWR_InitMD2(void)
|
|||
}
|
||||
}
|
||||
// no sprite/player skin name found?!?
|
||||
CONS_Printf("Unknown sprite/player skin %s detected in kmd2.dat\n", name);
|
||||
CONS_Printf("Unknown sprite/player skin %s detected in mdls.dat\n", name);
|
||||
md2found:
|
||||
// move on to next line...
|
||||
continue;
|
||||
|
@ -898,16 +564,16 @@ void HWR_AddPlayerMD2(int skin) // For MD2's that were added after startup
|
|||
|
||||
CONS_Printf("AddPlayerMD2()...\n");
|
||||
|
||||
// read the md2.dat file
|
||||
// read the mdls.dat file
|
||||
//Filename checking fixed ~Monster Iestyn and Golden
|
||||
f = fopen(va("%s"PATHSEP"%s", srb2home, "kmd2.dat"), "rt");
|
||||
f = fopen(va("%s"PATHSEP"%s", srb2home, "mdls.dat"), "rt");
|
||||
|
||||
if (!f)
|
||||
{
|
||||
f = fopen(va("%s"PATHSEP"%s", srb2path, "kmd2.dat"), "rt");
|
||||
f = fopen(va("%s"PATHSEP"%s", srb2path, "mdls.dat"), "rt");
|
||||
if (!f)
|
||||
{
|
||||
CONS_Printf("%s %s\n", M_GetText("Error while loading kmd2.dat:"), strerror(errno));
|
||||
CONS_Printf("%s %s\n", M_GetText("Error while loading mdls.dat:"), strerror(errno));
|
||||
nomd2s = true;
|
||||
return;
|
||||
}
|
||||
|
@ -937,7 +603,7 @@ playermd2found:
|
|||
void HWR_AddSpriteMD2(size_t spritenum) // For MD2s that were added after startup
|
||||
{
|
||||
FILE *f;
|
||||
// name[18] is used to check for names in the kmd2.dat file that match with sprites or player skins
|
||||
// name[18] is used to check for names in the mdls.dat file that match with sprites or player skins
|
||||
// sprite names are always 4 characters long, and names is for player skins can be up to 19 characters long
|
||||
char name[18], filename[32];
|
||||
float scale, offset;
|
||||
|
@ -950,20 +616,20 @@ void HWR_AddSpriteMD2(size_t spritenum) // For MD2s that were added after startu
|
|||
|
||||
// Read the md2.dat file
|
||||
//Filename checking fixed ~Monster Iestyn and Golden
|
||||
f = fopen(va("%s"PATHSEP"%s", srb2home, "kmd2.dat"), "rt");
|
||||
f = fopen(va("%s"PATHSEP"%s", srb2home, "mdls.dat"), "rt");
|
||||
|
||||
if (!f)
|
||||
{
|
||||
f = fopen(va("%s"PATHSEP"%s", srb2path, "kmd2.dat"), "rt");
|
||||
f = fopen(va("%s"PATHSEP"%s", srb2path, "mdls.dat"), "rt");
|
||||
if (!f)
|
||||
{
|
||||
CONS_Printf("%s %s\n", M_GetText("Error while loading kmd2.dat:"), strerror(errno));
|
||||
CONS_Printf("%s %s\n", M_GetText("Error while loading mdls.dat:"), strerror(errno));
|
||||
nomd2s = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for any MD2s that match the names of player skins!
|
||||
// Check for any MD2s that match the names of sprite names!
|
||||
while (fscanf(f, "%19s %31s %f %f", name, filename, &scale, &offset) == 4)
|
||||
{
|
||||
if (stricmp(name, sprnames[spritenum]) == 0)
|
||||
|
@ -1195,12 +861,13 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
|
|||
FSurfaceInfo Surf;
|
||||
|
||||
char filename[64];
|
||||
INT32 frame;
|
||||
INT32 frame = 0;
|
||||
INT32 nextFrame = -1;
|
||||
FTransform p;
|
||||
md2_t *md2;
|
||||
UINT8 color[4];
|
||||
|
||||
if (!cv_grmd2.value)
|
||||
if (!cv_grmdls.value)
|
||||
return;
|
||||
|
||||
if (spr->precip)
|
||||
|
@ -1248,10 +915,9 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
|
|||
// Look at HWR_ProjectSprite for more
|
||||
{
|
||||
GLPatch_t *gpatch;
|
||||
INT32 *buff;
|
||||
INT32 durs = spr->mobj->state->tics;
|
||||
INT32 tics = spr->mobj->tics;
|
||||
md2_frame_t *curr, *next = NULL;
|
||||
//mdlframe_t *next = NULL;
|
||||
const UINT8 flip = (UINT8)((spr->mobj->eflags & MFE_VERTICALFLIP) == MFE_VERTICALFLIP);
|
||||
spritedef_t *sprdef;
|
||||
spriteframe_t *sprframe;
|
||||
|
@ -1285,13 +951,14 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
|
|||
return; // we already failed loading this before :(
|
||||
if (!md2->model)
|
||||
{
|
||||
CONS_Debug(DBG_RENDER, "Loading MD2... (%s, %s)", sprnames[spr->mobj->sprite], md2->filename);
|
||||
sprintf(filename, "md2/%s", md2->filename);
|
||||
CONS_Debug(DBG_RENDER, "Loading model... (%s, %s)", sprnames[spr->mobj->sprite], md2->filename);
|
||||
sprintf(filename, "mdls/%s", md2->filename);
|
||||
md2->model = md2_readModel(filename);
|
||||
|
||||
if (md2->model)
|
||||
{
|
||||
md2_printModelInfo(md2->model);
|
||||
HWD.pfnCreateModelVBOs(md2->model);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1364,27 +1031,27 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
|
|||
}
|
||||
|
||||
//FIXME: this is not yet correct
|
||||
frame = (spr->mobj->frame & FF_FRAMEMASK) % md2->model->header.numFrames;
|
||||
buff = md2->model->glCommandBuffer;
|
||||
curr = &md2->model->frames[frame];
|
||||
#if 0
|
||||
if (cv_grmd2.value == 1 && tics <= durs)
|
||||
frame = (spr->mobj->frame & FF_FRAMEMASK) % md2->model->meshes[0].numFrames;
|
||||
|
||||
#ifdef USE_MODEL_NEXTFRAME
|
||||
if (cv_grmdls.value == 1 && tics <= durs)
|
||||
{
|
||||
// frames are handled differently for states with FF_ANIMATE, so get the next frame differently for the interpolation
|
||||
if (spr->mobj->frame & FF_ANIMATE)
|
||||
{
|
||||
UINT32 nextframe = (spr->mobj->frame & FF_FRAMEMASK) + 1;
|
||||
if (nextframe >= (UINT32)spr->mobj->state->var1)
|
||||
nextframe = (spr->mobj->state->frame & FF_FRAMEMASK);
|
||||
nextframe %= md2->model->header.numFrames;
|
||||
next = &md2->model->frames[nextframe];
|
||||
nextFrame = (spr->mobj->frame & FF_FRAMEMASK) + 1;
|
||||
if (nextFrame >= spr->mobj->state->var1)
|
||||
nextFrame = (spr->mobj->state->frame & FF_FRAMEMASK);
|
||||
nextFrame %= md2->model->meshes[0].numFrames;
|
||||
//next = &md2->model->meshes[0].frames[nextFrame];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (spr->mobj->state->nextstate != S_NULL && states[spr->mobj->state->nextstate].sprite != SPR_NULL)
|
||||
if (spr->mobj->state->nextstate != S_NULL && states[spr->mobj->state->nextstate].sprite != SPR_NULL
|
||||
&& !(spr->mobj->player && (spr->mobj->state->nextstate == S_PLAY_TAP1 || spr->mobj->state->nextstate == S_PLAY_TAP2) && spr->mobj->state == &states[S_PLAY_STND]))
|
||||
{
|
||||
const UINT32 nextframe = (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) % md2->model->header.numFrames;
|
||||
next = &md2->model->frames[nextframe];
|
||||
nextFrame = (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) % md2->model->meshes[0].numFrames;
|
||||
//next = &md2->model->meshes[0].frames[nextFrame];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1421,6 +1088,8 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
|
|||
p.angley = FIXED_TO_FLOAT(anglef);
|
||||
}
|
||||
p.anglex = 0.0f;
|
||||
#ifdef USE_FTRANSFORM_ANGLEZ
|
||||
// Slope rotation from Kart
|
||||
p.anglez = 0.0f;
|
||||
if (spr->mobj->standingslope)
|
||||
{
|
||||
|
@ -1432,7 +1101,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
|
|||
tempangle = -AngleFixed(R_PointToAngle2(0, 0, tempz, tempy));
|
||||
p.anglex = FIXED_TO_FLOAT(tempangle);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
color[0] = Surf.FlatColor.s.red;
|
||||
color[1] = Surf.FlatColor.s.green;
|
||||
|
@ -1443,9 +1112,11 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
|
|||
finalscale *= FIXED_TO_FLOAT(spr->mobj->scale);
|
||||
|
||||
p.flip = atransform.flip;
|
||||
p.mirror = atransform.mirror;
|
||||
#ifdef USE_FTRANSFORM_MIRROR
|
||||
p.mirror = atransform.mirror; // from Kart
|
||||
#endif
|
||||
|
||||
HWD.pfnDrawMD2i(buff, curr, durs, tics, next, &p, finalscale, flip, color);
|
||||
HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, color);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,97 +22,7 @@
|
|||
#define _HW_MD2_H_
|
||||
|
||||
#include "hw_glob.h"
|
||||
|
||||
// magic number "IDP2" or 844121161
|
||||
#define MD2_IDENT (INT32)(('2' << 24) + ('P' << 16) + ('D' << 8) + 'I')
|
||||
// model version
|
||||
#define MD2_VERSION 8
|
||||
|
||||
#define MD2_MAX_TRIANGLES 16384
|
||||
#define MD2_MAX_VERTICES 4096
|
||||
#define MD2_MAX_TEXCOORDS 4096
|
||||
#define MD2_MAX_FRAMES 512
|
||||
#define MD2_MAX_SKINS 32
|
||||
#define MD2_MAX_FRAMESIZE (MD2_MAX_VERTICES * 4 + 128)
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
typedef struct
|
||||
{
|
||||
UINT32 magic;
|
||||
UINT32 version;
|
||||
UINT32 skinWidth;
|
||||
UINT32 skinHeight;
|
||||
UINT32 frameSize;
|
||||
UINT32 numSkins;
|
||||
UINT32 numVertices;
|
||||
UINT32 numTexCoords;
|
||||
UINT32 numTriangles;
|
||||
UINT32 numGlCommands;
|
||||
UINT32 numFrames;
|
||||
UINT32 offsetSkins;
|
||||
UINT32 offsetTexCoords;
|
||||
UINT32 offsetTriangles;
|
||||
UINT32 offsetFrames;
|
||||
UINT32 offsetGlCommands;
|
||||
UINT32 offsetEnd;
|
||||
} ATTRPACK md2_header_t; //NOTE: each of md2_header's members are 4 unsigned bytes
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT8 vertex[3];
|
||||
UINT8 lightNormalIndex;
|
||||
} ATTRPACK md2_alias_triangleVertex_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float vertex[3];
|
||||
float normal[3];
|
||||
} ATTRPACK md2_triangleVertex_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
INT16 vertexIndices[3];
|
||||
INT16 textureIndices[3];
|
||||
} ATTRPACK md2_triangle_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
INT16 s, t;
|
||||
} ATTRPACK md2_textureCoordinate_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float scale[3];
|
||||
float translate[3];
|
||||
char name[16];
|
||||
md2_alias_triangleVertex_t alias_vertices[1];
|
||||
} ATTRPACK md2_alias_frame_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char name[16];
|
||||
md2_triangleVertex_t *vertices;
|
||||
} ATTRPACK md2_frame_t;
|
||||
|
||||
typedef char md2_skin_t[64];
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float s, t;
|
||||
INT32 vertexIndex;
|
||||
} ATTRPACK md2_glCommandVertex_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
md2_header_t header;
|
||||
md2_skin_t *skins;
|
||||
md2_textureCoordinate_t *texCoords;
|
||||
md2_triangle_t *triangles;
|
||||
md2_frame_t *frames;
|
||||
INT32 *glCommandBuffer;
|
||||
} ATTRPACK md2_model_t;
|
||||
#include "hw_model.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma pack()
|
||||
|
@ -123,7 +33,7 @@ typedef struct
|
|||
char filename[32];
|
||||
float scale;
|
||||
float offset;
|
||||
md2_model_t *model;
|
||||
model_t *model;
|
||||
void *grpatch;
|
||||
void *blendgrpatch;
|
||||
boolean notfound;
|
||||
|
|
564
src/hardware/hw_md2load.c
Normal file
564
src/hardware/hw_md2load.c
Normal file
|
@ -0,0 +1,564 @@
|
|||
/*
|
||||
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
|
||||
An experimental work-in-progress.
|
||||
|
||||
Donated to Sonic Team Junior and adapted to work with
|
||||
Sonic Robo Blast 2. The license of this code matches whatever
|
||||
the licensing is for Sonic Robo Blast 2.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "../doomdef.h"
|
||||
#include "hw_md2load.h"
|
||||
#include "hw_model.h"
|
||||
#include "../z_zone.h"
|
||||
|
||||
#define NUMVERTEXNORMALS 162
|
||||
|
||||
// Quake 2 normals are indexed. Use avertexnormals[normalindex][x/y/z] and
|
||||
// you'll have your normals.
|
||||
float avertexnormals[NUMVERTEXNORMALS][3] = {
|
||||
{-0.525731f, 0.000000f, 0.850651f},
|
||||
{-0.442863f, 0.238856f, 0.864188f},
|
||||
{-0.295242f, 0.000000f, 0.955423f},
|
||||
{-0.309017f, 0.500000f, 0.809017f},
|
||||
{-0.162460f, 0.262866f, 0.951056f},
|
||||
{0.000000f, 0.000000f, 1.000000f},
|
||||
{0.000000f, 0.850651f, 0.525731f},
|
||||
{-0.147621f, 0.716567f, 0.681718f},
|
||||
{0.147621f, 0.716567f, 0.681718f},
|
||||
{0.000000f, 0.525731f, 0.850651f},
|
||||
{0.309017f, 0.500000f, 0.809017f},
|
||||
{0.525731f, 0.000000f, 0.850651f},
|
||||
{0.295242f, 0.000000f, 0.955423f},
|
||||
{0.442863f, 0.238856f, 0.864188f},
|
||||
{0.162460f, 0.262866f, 0.951056f},
|
||||
{-0.681718f, 0.147621f, 0.716567f},
|
||||
{-0.809017f, 0.309017f, 0.500000f},
|
||||
{-0.587785f, 0.425325f, 0.688191f},
|
||||
{-0.850651f, 0.525731f, 0.000000f},
|
||||
{-0.864188f, 0.442863f, 0.238856f},
|
||||
{-0.716567f, 0.681718f, 0.147621f},
|
||||
{-0.688191f, 0.587785f, 0.425325f},
|
||||
{-0.500000f, 0.809017f, 0.309017f},
|
||||
{-0.238856f, 0.864188f, 0.442863f},
|
||||
{-0.425325f, 0.688191f, 0.587785f},
|
||||
{-0.716567f, 0.681718f, -0.147621f},
|
||||
{-0.500000f, 0.809017f, -0.309017f},
|
||||
{-0.525731f, 0.850651f, 0.000000f},
|
||||
{0.000000f, 0.850651f, -0.525731f},
|
||||
{-0.238856f, 0.864188f, -0.442863f},
|
||||
{0.000000f, 0.955423f, -0.295242f},
|
||||
{-0.262866f, 0.951056f, -0.162460f},
|
||||
{0.000000f, 1.000000f, 0.000000f},
|
||||
{0.000000f, 0.955423f, 0.295242f},
|
||||
{-0.262866f, 0.951056f, 0.162460f},
|
||||
{0.238856f, 0.864188f, 0.442863f},
|
||||
{0.262866f, 0.951056f, 0.162460f},
|
||||
{0.500000f, 0.809017f, 0.309017f},
|
||||
{0.238856f, 0.864188f, -0.442863f},
|
||||
{0.262866f, 0.951056f, -0.162460f},
|
||||
{0.500000f, 0.809017f, -0.309017f},
|
||||
{0.850651f, 0.525731f, 0.000000f},
|
||||
{0.716567f, 0.681718f, 0.147621f},
|
||||
{0.716567f, 0.681718f, -0.147621f},
|
||||
{0.525731f, 0.850651f, 0.000000f},
|
||||
{0.425325f, 0.688191f, 0.587785f},
|
||||
{0.864188f, 0.442863f, 0.238856f},
|
||||
{0.688191f, 0.587785f, 0.425325f},
|
||||
{0.809017f, 0.309017f, 0.500000f},
|
||||
{0.681718f, 0.147621f, 0.716567f},
|
||||
{0.587785f, 0.425325f, 0.688191f},
|
||||
{0.955423f, 0.295242f, 0.000000f},
|
||||
{1.000000f, 0.000000f, 0.000000f},
|
||||
{0.951056f, 0.162460f, 0.262866f},
|
||||
{0.850651f, -0.525731f, 0.000000f},
|
||||
{0.955423f, -0.295242f, 0.000000f},
|
||||
{0.864188f, -0.442863f, 0.238856f},
|
||||
{0.951056f, -0.162460f, 0.262866f},
|
||||
{0.809017f, -0.309017f, 0.500000f},
|
||||
{0.681718f, -0.147621f, 0.716567f},
|
||||
{0.850651f, 0.000000f, 0.525731f},
|
||||
{0.864188f, 0.442863f, -0.238856f},
|
||||
{0.809017f, 0.309017f, -0.500000f},
|
||||
{0.951056f, 0.162460f, -0.262866f},
|
||||
{0.525731f, 0.000000f, -0.850651f},
|
||||
{0.681718f, 0.147621f, -0.716567f},
|
||||
{0.681718f, -0.147621f, -0.716567f},
|
||||
{0.850651f, 0.000000f, -0.525731f},
|
||||
{0.809017f, -0.309017f, -0.500000f},
|
||||
{0.864188f, -0.442863f, -0.238856f},
|
||||
{0.951056f, -0.162460f, -0.262866f},
|
||||
{0.147621f, 0.716567f, -0.681718f},
|
||||
{0.309017f, 0.500000f, -0.809017f},
|
||||
{0.425325f, 0.688191f, -0.587785f},
|
||||
{0.442863f, 0.238856f, -0.864188f},
|
||||
{0.587785f, 0.425325f, -0.688191f},
|
||||
{0.688191f, 0.587785f, -0.425325f},
|
||||
{-0.147621f, 0.716567f, -0.681718f},
|
||||
{-0.309017f, 0.500000f, -0.809017f},
|
||||
{0.000000f, 0.525731f, -0.850651f},
|
||||
{-0.525731f, 0.000000f, -0.850651f},
|
||||
{-0.442863f, 0.238856f, -0.864188f},
|
||||
{-0.295242f, 0.000000f, -0.955423f},
|
||||
{-0.162460f, 0.262866f, -0.951056f},
|
||||
{0.000000f, 0.000000f, -1.000000f},
|
||||
{0.295242f, 0.000000f, -0.955423f},
|
||||
{0.162460f, 0.262866f, -0.951056f},
|
||||
{-0.442863f, -0.238856f, -0.864188f},
|
||||
{-0.309017f, -0.500000f, -0.809017f},
|
||||
{-0.162460f, -0.262866f, -0.951056f},
|
||||
{0.000000f, -0.850651f, -0.525731f},
|
||||
{-0.147621f, -0.716567f, -0.681718f},
|
||||
{0.147621f, -0.716567f, -0.681718f},
|
||||
{0.000000f, -0.525731f, -0.850651f},
|
||||
{0.309017f, -0.500000f, -0.809017f},
|
||||
{0.442863f, -0.238856f, -0.864188f},
|
||||
{0.162460f, -0.262866f, -0.951056f},
|
||||
{0.238856f, -0.864188f, -0.442863f},
|
||||
{0.500000f, -0.809017f, -0.309017f},
|
||||
{0.425325f, -0.688191f, -0.587785f},
|
||||
{0.716567f, -0.681718f, -0.147621f},
|
||||
{0.688191f, -0.587785f, -0.425325f},
|
||||
{0.587785f, -0.425325f, -0.688191f},
|
||||
{0.000000f, -0.955423f, -0.295242f},
|
||||
{0.000000f, -1.000000f, 0.000000f},
|
||||
{0.262866f, -0.951056f, -0.162460f},
|
||||
{0.000000f, -0.850651f, 0.525731f},
|
||||
{0.000000f, -0.955423f, 0.295242f},
|
||||
{0.238856f, -0.864188f, 0.442863f},
|
||||
{0.262866f, -0.951056f, 0.162460f},
|
||||
{0.500000f, -0.809017f, 0.309017f},
|
||||
{0.716567f, -0.681718f, 0.147621f},
|
||||
{0.525731f, -0.850651f, 0.000000f},
|
||||
{-0.238856f, -0.864188f, -0.442863f},
|
||||
{-0.500000f, -0.809017f, -0.309017f},
|
||||
{-0.262866f, -0.951056f, -0.162460f},
|
||||
{-0.850651f, -0.525731f, 0.000000f},
|
||||
{-0.716567f, -0.681718f, -0.147621f},
|
||||
{-0.716567f, -0.681718f, 0.147621f},
|
||||
{-0.525731f, -0.850651f, 0.000000f},
|
||||
{-0.500000f, -0.809017f, 0.309017f},
|
||||
{-0.238856f, -0.864188f, 0.442863f},
|
||||
{-0.262866f, -0.951056f, 0.162460f},
|
||||
{-0.864188f, -0.442863f, 0.238856f},
|
||||
{-0.809017f, -0.309017f, 0.500000f},
|
||||
{-0.688191f, -0.587785f, 0.425325f},
|
||||
{-0.681718f, -0.147621f, 0.716567f},
|
||||
{-0.442863f, -0.238856f, 0.864188f},
|
||||
{-0.587785f, -0.425325f, 0.688191f},
|
||||
{-0.309017f, -0.500000f, 0.809017f},
|
||||
{-0.147621f, -0.716567f, 0.681718f},
|
||||
{-0.425325f, -0.688191f, 0.587785f},
|
||||
{-0.162460f, -0.262866f, 0.951056f},
|
||||
{0.442863f, -0.238856f, 0.864188f},
|
||||
{0.162460f, -0.262866f, 0.951056f},
|
||||
{0.309017f, -0.500000f, 0.809017f},
|
||||
{0.147621f, -0.716567f, 0.681718f},
|
||||
{0.000000f, -0.525731f, 0.850651f},
|
||||
{0.425325f, -0.688191f, 0.587785f},
|
||||
{0.587785f, -0.425325f, 0.688191f},
|
||||
{0.688191f, -0.587785f, 0.425325f},
|
||||
{-0.955423f, 0.295242f, 0.000000f},
|
||||
{-0.951056f, 0.162460f, 0.262866f},
|
||||
{-1.000000f, 0.000000f, 0.000000f},
|
||||
{-0.850651f, 0.000000f, 0.525731f},
|
||||
{-0.955423f, -0.295242f, 0.000000f},
|
||||
{-0.951056f, -0.162460f, 0.262866f},
|
||||
{-0.864188f, 0.442863f, -0.238856f},
|
||||
{-0.951056f, 0.162460f, -0.262866f},
|
||||
{-0.809017f, 0.309017f, -0.500000f},
|
||||
{-0.864188f, -0.442863f, -0.238856f},
|
||||
{-0.951056f, -0.162460f, -0.262866f},
|
||||
{-0.809017f, -0.309017f, -0.500000f},
|
||||
{-0.681718f, 0.147621f, -0.716567f},
|
||||
{-0.681718f, -0.147621f, -0.716567f},
|
||||
{-0.850651f, 0.000000f, -0.525731f},
|
||||
{-0.688191f, 0.587785f, -0.425325f},
|
||||
{-0.587785f, 0.425325f, -0.688191f},
|
||||
{-0.425325f, 0.688191f, -0.587785f},
|
||||
{-0.425325f, -0.688191f, -0.587785f},
|
||||
{-0.587785f, -0.425325f, -0.688191f},
|
||||
{-0.688191f, -0.587785f, -0.425325f},
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int ident; // A "magic number" that's used to identify the .md2 file
|
||||
int version; // The version of the file, always 8
|
||||
int skinwidth; // Width of the skin(s) in pixels
|
||||
int skinheight; // Height of the skin(s) in pixels
|
||||
int framesize; // Size of each frame in bytes
|
||||
int numSkins; // Number of skins with the model
|
||||
int numXYZ; // Number of vertices in each frame
|
||||
int numST; // Number of texture coordinates in each frame.
|
||||
int numTris; // Number of triangles in each frame
|
||||
int numGLcmds; // Number of dwords (4 bytes) in the gl command list.
|
||||
int numFrames; // Number of frames
|
||||
int offsetSkins; // Offset, in bytes from the start of the file, to the list of skin names.
|
||||
int offsetST; // Offset, in bytes from the start of the file, to the list of texture coordinates
|
||||
int offsetTris; // Offset, in bytes from the start of the file, to the list of triangles
|
||||
int offsetFrames; // Offset, in bytes from the start of the file, to the list of frames
|
||||
int offsetGLcmds; // Offset, in bytes from the start of the file, to the list of gl commands
|
||||
int offsetEnd; // Offset, in bytes from the start of the file, to the end of the file (filesize)
|
||||
} md2header_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned short meshIndex[3]; // indices into the array of vertices in each frames
|
||||
unsigned short stIndex[3]; // indices into the array of texture coordinates
|
||||
} md2triangle_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short s;
|
||||
short t;
|
||||
} md2texcoord_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char v[3]; // Scaled vertices. You'll need to multiply them with scale[x] to make them normal.
|
||||
unsigned char lightNormalIndex; // Index to the array of normals
|
||||
} md2vertex_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float scale[3]; // Used by the v member in the md2framePoint structure
|
||||
float translate[3]; // Used by the v member in the md2framePoint structure
|
||||
char name[16]; // Name of the frame
|
||||
} md2frame_t;
|
||||
|
||||
// Load the model
|
||||
model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat)
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
model_t *retModel = NULL;
|
||||
md2header_t *header;
|
||||
|
||||
size_t fileLen;
|
||||
int i, j;
|
||||
size_t namelen;
|
||||
char *texturefilename;
|
||||
const char *texPos;
|
||||
|
||||
char *buffer;
|
||||
|
||||
const float WUNITS = 1.0f;
|
||||
float dataScale = WUNITS;
|
||||
|
||||
md2triangle_t *tris;
|
||||
md2texcoord_t *texcoords;
|
||||
md2frame_t *frames;
|
||||
|
||||
int t;
|
||||
|
||||
// MD2 currently does not work with tinyframes, so force useFloat = true
|
||||
//
|
||||
// <SSNTails>
|
||||
// the UV coordinates in MD2 are not compatible with glDrawElements like MD3 is. So they need to be loaded as full float.
|
||||
//
|
||||
// MD2 is intended to be draw in triangle strips and fans
|
||||
// not very compatible with a modern GL implementation, either
|
||||
// so the idea would be to full float expand it, and put it in a vertex buffer object
|
||||
// I'm sure there's a way to convert the UVs to 'tinyframes', but maybe that's a job for someone else.
|
||||
// You'd have to decompress the model, then recompress, reindexing the triangles and weeding out duplicate coordinates
|
||||
// I already have the decompression work done
|
||||
|
||||
useFloat = true;
|
||||
|
||||
f = fopen(fileName, "rb");
|
||||
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
retModel = (model_t*)Z_Calloc(sizeof(model_t), ztag, 0);
|
||||
|
||||
//size_t fileLen;
|
||||
|
||||
//int i, j;
|
||||
|
||||
//size_t namelen;
|
||||
//char *texturefilename;
|
||||
texPos = strchr(fileName, '/');
|
||||
|
||||
if (texPos)
|
||||
{
|
||||
texPos++;
|
||||
namelen = strlen(texPos) + 1;
|
||||
texturefilename = (char*)Z_Malloc(namelen, PU_CACHE, 0);
|
||||
strcpy(texturefilename, texPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
namelen = strlen(fileName) + 1;
|
||||
texturefilename = (char*)Z_Malloc(namelen, PU_CACHE, 0);
|
||||
strcpy(texturefilename, fileName);
|
||||
}
|
||||
|
||||
texturefilename[namelen - 2] = 'z';
|
||||
texturefilename[namelen - 3] = 'u';
|
||||
texturefilename[namelen - 4] = 'b';
|
||||
|
||||
// find length of file
|
||||
fseek(f, 0, SEEK_END);
|
||||
fileLen = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
// read in file
|
||||
buffer = malloc(fileLen);
|
||||
if (fread(buffer, fileLen, 1, f)) { } // squash ignored fread error
|
||||
fclose(f);
|
||||
|
||||
// get pointer to file header
|
||||
header = (md2header_t*)buffer;
|
||||
|
||||
retModel->numMeshes = 1; // MD2 only has one mesh
|
||||
retModel->meshes = (mesh_t*)Z_Calloc(sizeof(mesh_t) * retModel->numMeshes, ztag, 0);
|
||||
retModel->meshes[0].numFrames = header->numFrames;
|
||||
// const float WUNITS = 1.0f;
|
||||
// float dataScale = WUNITS;
|
||||
|
||||
// Tris and ST are simple structures that can be straight-copied
|
||||
tris = (md2triangle_t*)&buffer[header->offsetTris];
|
||||
texcoords = (md2texcoord_t*)&buffer[header->offsetST];
|
||||
frames = (md2frame_t*)&buffer[header->offsetFrames];
|
||||
|
||||
// Read in textures
|
||||
retModel->numMaterials = header->numSkins;
|
||||
|
||||
if (retModel->numMaterials <= 0) // Always at least one skin, duh
|
||||
retModel->numMaterials = 1;
|
||||
|
||||
retModel->materials = (material_t*)Z_Calloc(sizeof(material_t)*retModel->numMaterials, ztag, 0);
|
||||
|
||||
// int t;
|
||||
for (t = 0; t < retModel->numMaterials; t++)
|
||||
{
|
||||
retModel->materials[t].ambient[0] = 0.8f;
|
||||
retModel->materials[t].ambient[1] = 0.8f;
|
||||
retModel->materials[t].ambient[2] = 0.8f;
|
||||
retModel->materials[t].ambient[3] = 1.0f;
|
||||
retModel->materials[t].diffuse[0] = 0.8f;
|
||||
retModel->materials[t].diffuse[1] = 0.8f;
|
||||
retModel->materials[t].diffuse[2] = 0.8f;
|
||||
retModel->materials[t].diffuse[3] = 1.0f;
|
||||
retModel->materials[t].emissive[0] = 0.0f;
|
||||
retModel->materials[t].emissive[1] = 0.0f;
|
||||
retModel->materials[t].emissive[2] = 0.0f;
|
||||
retModel->materials[t].emissive[3] = 1.0f;
|
||||
retModel->materials[t].specular[0] = 0.0f;
|
||||
retModel->materials[t].specular[1] = 0.0f;
|
||||
retModel->materials[t].specular[2] = 0.0f;
|
||||
retModel->materials[t].specular[3] = 1.0f;
|
||||
retModel->materials[t].shininess = 0.0f;
|
||||
retModel->materials[t].spheremap = false;
|
||||
|
||||
/* retModel->materials[t].texture = Texture::ReadTexture((char*)texturefilename, ZT_TEXTURE);
|
||||
|
||||
if (!systemSucks)
|
||||
{
|
||||
// Check for a normal map...??
|
||||
char openfilename[1024];
|
||||
char normalMapName[1024];
|
||||
strcpy(normalMapName, texturefilename);
|
||||
size_t len = strlen(normalMapName);
|
||||
char *ptr = &normalMapName[len];
|
||||
ptr--; // z
|
||||
ptr--; // u
|
||||
ptr--; // b
|
||||
ptr--; // .
|
||||
*ptr++ = '_';
|
||||
*ptr++ = 'n';
|
||||
*ptr++ = '.';
|
||||
*ptr++ = 'b';
|
||||
*ptr++ = 'u';
|
||||
*ptr++ = 'z';
|
||||
*ptr++ = '\0';
|
||||
|
||||
sprintf(openfilename, "%s/%s", "textures", normalMapName);
|
||||
// Convert backslashes to forward slashes
|
||||
for (int k = 0; k < 1024; k++)
|
||||
{
|
||||
if (openfilename[k] == '\0')
|
||||
break;
|
||||
|
||||
if (openfilename[k] == '\\')
|
||||
openfilename[k] = '/';
|
||||
}
|
||||
|
||||
Resource::resource_t *res = Resource::Open(openfilename);
|
||||
if (res)
|
||||
{
|
||||
Resource::Close(res);
|
||||
retModel->materials[t].lightmap = Texture::ReadTexture(normalMapName, ZT_TEXTURE);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
retModel->meshes[0].numTriangles = header->numTris;
|
||||
|
||||
if (!useFloat) // Decompress to MD3 'tinyframe' space
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
md2triangle_t *trisPtr;
|
||||
unsigned short *indexptr;
|
||||
float *uvptr;
|
||||
|
||||
dataScale = 0.015624f; // 1 / 64.0f
|
||||
retModel->meshes[0].tinyframes = (tinyframe_t*)Z_Calloc(sizeof(tinyframe_t)*header->numFrames, ztag, 0);
|
||||
retModel->meshes[0].numVertices = header->numXYZ;
|
||||
retModel->meshes[0].uvs = (float*)Z_Malloc(sizeof(float) * 2 * retModel->meshes[0].numVertices, ztag, 0);
|
||||
|
||||
ptr = (char*)frames;
|
||||
for (i = 0; i < header->numFrames; i++, ptr += header->framesize)
|
||||
{
|
||||
short *vertptr;
|
||||
char *normptr;
|
||||
// char *tanptr;
|
||||
|
||||
md2vertex_t *vertex;
|
||||
|
||||
md2frame_t *framePtr = (md2frame_t*)ptr;
|
||||
retModel->meshes[0].tinyframes[i].vertices = (short*)Z_Malloc(sizeof(short) * 3 * header->numXYZ, ztag, 0);
|
||||
retModel->meshes[0].tinyframes[i].normals = (char*)Z_Malloc(sizeof(char) * 3 * header->numXYZ, ztag, 0);
|
||||
|
||||
// if (retModel->materials[0].lightmap)
|
||||
// retModel->meshes[0].tinyframes[i].tangents = (char*)malloc(sizeof(char));//(char*)Z_Malloc(sizeof(char)*3*header->numVerts, ztag);
|
||||
retModel->meshes[0].indices = (unsigned short*)Z_Malloc(sizeof(unsigned short) * 3 * header->numTris, ztag, 0);
|
||||
|
||||
vertptr = retModel->meshes[0].tinyframes[i].vertices;
|
||||
normptr = retModel->meshes[0].tinyframes[i].normals;
|
||||
|
||||
// tanptr = retModel->meshes[0].tinyframes[i].tangents;
|
||||
retModel->meshes[0].tinyframes[i].material = &retModel->materials[0];
|
||||
|
||||
framePtr++; // Advance to vertex list
|
||||
vertex = (md2vertex_t*)framePtr;
|
||||
framePtr--;
|
||||
for (j = 0; j < header->numXYZ; j++, vertex++)
|
||||
{
|
||||
*vertptr = (short)(((vertex->v[0] * framePtr->scale[0]) + framePtr->translate[0]) / dataScale);
|
||||
vertptr++;
|
||||
*vertptr = (short)(((vertex->v[2] * framePtr->scale[2]) + framePtr->translate[2]) / dataScale);
|
||||
vertptr++;
|
||||
*vertptr = -1.0f * (short)(((vertex->v[1] * framePtr->scale[1]) + framePtr->translate[1]) / dataScale);
|
||||
vertptr++;
|
||||
|
||||
// Normal
|
||||
*normptr++ = (char)(avertexnormals[vertex->lightNormalIndex][0] * 127);
|
||||
*normptr++ = (char)(avertexnormals[vertex->lightNormalIndex][2] * 127);
|
||||
*normptr++ = (char)(avertexnormals[vertex->lightNormalIndex][1] * 127);
|
||||
}
|
||||
}
|
||||
|
||||
// This doesn't need to be done every frame!
|
||||
trisPtr = tris;
|
||||
indexptr = retModel->meshes[0].indices;
|
||||
uvptr = (float*)retModel->meshes[0].uvs;
|
||||
for (j = 0; j < header->numTris; j++, trisPtr++)
|
||||
{
|
||||
*indexptr = trisPtr->meshIndex[0];
|
||||
indexptr++;
|
||||
*indexptr = trisPtr->meshIndex[1];
|
||||
indexptr++;
|
||||
*indexptr = trisPtr->meshIndex[2];
|
||||
indexptr++;
|
||||
|
||||
uvptr[trisPtr->meshIndex[0] * 2] = texcoords[trisPtr->stIndex[0]].s / (float)header->skinwidth;
|
||||
uvptr[trisPtr->meshIndex[0] * 2 + 1] = (texcoords[trisPtr->stIndex[0]].t / (float)header->skinheight);
|
||||
uvptr[trisPtr->meshIndex[1] * 2] = texcoords[trisPtr->stIndex[1]].s / (float)header->skinwidth;
|
||||
uvptr[trisPtr->meshIndex[1] * 2 + 1] = (texcoords[trisPtr->stIndex[1]].t / (float)header->skinheight);
|
||||
uvptr[trisPtr->meshIndex[2] * 2] = texcoords[trisPtr->stIndex[2]].s / (float)header->skinwidth;
|
||||
uvptr[trisPtr->meshIndex[2] * 2 + 1] = (texcoords[trisPtr->stIndex[2]].t / (float)header->skinheight);
|
||||
}
|
||||
}
|
||||
else // Full float loading method
|
||||
{
|
||||
md2triangle_t *trisPtr;
|
||||
float *uvptr;
|
||||
|
||||
char *ptr;
|
||||
|
||||
retModel->meshes[0].numVertices = header->numTris * 3;
|
||||
retModel->meshes[0].frames = (mdlframe_t*)Z_Calloc(sizeof(mdlframe_t)*header->numFrames, ztag, 0);
|
||||
retModel->meshes[0].uvs = (float*)Z_Malloc(sizeof(float) * 2 * retModel->meshes[0].numVertices, ztag, 0);
|
||||
|
||||
trisPtr = tris;
|
||||
uvptr = retModel->meshes[0].uvs;
|
||||
for (i = 0; i < retModel->meshes[0].numTriangles; i++, trisPtr++)
|
||||
{
|
||||
*uvptr++ = texcoords[trisPtr->stIndex[0]].s / (float)header->skinwidth;
|
||||
*uvptr++ = (texcoords[trisPtr->stIndex[0]].t / (float)header->skinheight);
|
||||
*uvptr++ = texcoords[trisPtr->stIndex[1]].s / (float)header->skinwidth;
|
||||
*uvptr++ = (texcoords[trisPtr->stIndex[1]].t / (float)header->skinheight);
|
||||
*uvptr++ = texcoords[trisPtr->stIndex[2]].s / (float)header->skinwidth;
|
||||
*uvptr++ = (texcoords[trisPtr->stIndex[2]].t / (float)header->skinheight);
|
||||
}
|
||||
|
||||
ptr = (char*)frames;
|
||||
for (i = 0; i < header->numFrames; i++, ptr += header->framesize)
|
||||
{
|
||||
float *vertptr, *normptr;
|
||||
|
||||
md2vertex_t *vertex;
|
||||
|
||||
md2frame_t *framePtr = (md2frame_t*)ptr;
|
||||
retModel->meshes[0].frames[i].normals = (float*)Z_Malloc(sizeof(float) * 3 * header->numTris * 3, ztag, 0);
|
||||
retModel->meshes[0].frames[i].vertices = (float*)Z_Malloc(sizeof(float) * 3 * header->numTris * 3, ztag, 0);
|
||||
// if (retModel->materials[0].lightmap)
|
||||
// retModel->meshes[0].frames[i].tangents = (float*)malloc(sizeof(float));//(float*)Z_Malloc(sizeof(float)*3*header->numTris*3, ztag);
|
||||
//float *vertptr, *normptr;
|
||||
normptr = (float*)retModel->meshes[0].frames[i].normals;
|
||||
vertptr = (float*)retModel->meshes[0].frames[i].vertices;
|
||||
trisPtr = tris;
|
||||
|
||||
retModel->meshes[0].frames[i].material = &retModel->materials[0];
|
||||
|
||||
framePtr++; // Advance to vertex list
|
||||
vertex = (md2vertex_t*)framePtr;
|
||||
framePtr--;
|
||||
for (j = 0; j < header->numTris; j++, trisPtr++)
|
||||
{
|
||||
*vertptr = ((vertex[trisPtr->meshIndex[0]].v[0] * framePtr->scale[0]) + framePtr->translate[0]) * WUNITS;
|
||||
vertptr++;
|
||||
*vertptr = ((vertex[trisPtr->meshIndex[0]].v[2] * framePtr->scale[2]) + framePtr->translate[2]) * WUNITS;
|
||||
vertptr++;
|
||||
*vertptr = -1.0f * ((vertex[trisPtr->meshIndex[0]].v[1] * framePtr->scale[1]) + framePtr->translate[1]) * WUNITS;
|
||||
vertptr++;
|
||||
|
||||
*vertptr = ((vertex[trisPtr->meshIndex[1]].v[0] * framePtr->scale[0]) + framePtr->translate[0]) * WUNITS;
|
||||
vertptr++;
|
||||
*vertptr = ((vertex[trisPtr->meshIndex[1]].v[2] * framePtr->scale[2]) + framePtr->translate[2]) * WUNITS;
|
||||
vertptr++;
|
||||
*vertptr = -1.0f * ((vertex[trisPtr->meshIndex[1]].v[1] * framePtr->scale[1]) + framePtr->translate[1]) * WUNITS;
|
||||
vertptr++;
|
||||
|
||||
*vertptr = ((vertex[trisPtr->meshIndex[2]].v[0] * framePtr->scale[0]) + framePtr->translate[0]) * WUNITS;
|
||||
vertptr++;
|
||||
*vertptr = ((vertex[trisPtr->meshIndex[2]].v[2] * framePtr->scale[2]) + framePtr->translate[2]) * WUNITS;
|
||||
vertptr++;
|
||||
*vertptr = -1.0f * ((vertex[trisPtr->meshIndex[2]].v[1] * framePtr->scale[1]) + framePtr->translate[1]) * WUNITS;
|
||||
vertptr++;
|
||||
|
||||
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[0]].lightNormalIndex][0];
|
||||
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[0]].lightNormalIndex][2];
|
||||
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[0]].lightNormalIndex][1];
|
||||
|
||||
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[1]].lightNormalIndex][0];
|
||||
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[1]].lightNormalIndex][2];
|
||||
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[1]].lightNormalIndex][1];
|
||||
|
||||
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[2]].lightNormalIndex][0];
|
||||
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[2]].lightNormalIndex][2];
|
||||
*normptr++ = avertexnormals[vertex[trisPtr->meshIndex[2]].lightNormalIndex][1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
return retModel;
|
||||
}
|
19
src/hardware/hw_md2load.h
Normal file
19
src/hardware/hw_md2load.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
|
||||
An experimental work-in-progress.
|
||||
|
||||
Donated to Sonic Team Junior and adapted to work with
|
||||
Sonic Robo Blast 2. The license of this code matches whatever
|
||||
the licensing is for Sonic Robo Blast 2.
|
||||
*/
|
||||
|
||||
#ifndef _HW_MD2LOAD_H_
|
||||
#define _HW_MD2LOAD_H_
|
||||
|
||||
#include "hw_model.h"
|
||||
#include "../doomtype.h"
|
||||
|
||||
// Load the Model
|
||||
model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat);
|
||||
|
||||
#endif
|
510
src/hardware/hw_md3load.c
Normal file
510
src/hardware/hw_md3load.c
Normal file
|
@ -0,0 +1,510 @@
|
|||
/*
|
||||
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
|
||||
An experimental work-in-progress.
|
||||
|
||||
Donated to Sonic Team Junior and adapted to work with
|
||||
Sonic Robo Blast 2. The license of this code matches whatever
|
||||
the licensing is for Sonic Robo Blast 2.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "../doomdef.h"
|
||||
#include "hw_md3load.h"
|
||||
#include "hw_model.h"
|
||||
#include "../z_zone.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int ident; // A "magic number" that's used to identify the .md3 file
|
||||
int version; // The version of the file, always 15
|
||||
char name[64];
|
||||
int flags;
|
||||
int numFrames; // Number of frames
|
||||
int numTags;
|
||||
int numSurfaces;
|
||||
int numSkins; // Number of skins with the model
|
||||
int offsetFrames;
|
||||
int offsetTags;
|
||||
int offsetSurfaces;
|
||||
int offsetEnd; // Offset, in bytes from the start of the file, to the end of the file (filesize)
|
||||
} md3modelHeader;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float minBounds[3]; // First corner of the bounding box
|
||||
float maxBounds[3]; // Second corner of the bounding box
|
||||
float localOrigin[3]; // Local origin, usually (0, 0, 0)
|
||||
float radius; // Radius of bounding sphere
|
||||
char name[16]; // Name of frame
|
||||
} md3Frame;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char name[64]; // Name of tag
|
||||
float origin[3]; // Coordinates of tag
|
||||
float axis[9]; // Orientation of tag object
|
||||
} md3Tag;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int ident;
|
||||
char name[64]; // Name of this surface
|
||||
int flags;
|
||||
int numFrames; // # of keyframes
|
||||
int numShaders; // # of shaders
|
||||
int numVerts; // # of vertices
|
||||
int numTriangles; // # of triangles
|
||||
int offsetTriangles; // Relative offset from start of this struct to where the list of Triangles start
|
||||
int offsetShaders; // Relative offset from start of this struct to where the list of Shaders start
|
||||
int offsetST; // Relative offset from start of this struct to where the list of tex coords start
|
||||
int offsetXYZNormal; // Relative offset from start of this struct to where the list of vertices start
|
||||
int offsetEnd; // Relative offset from start of this struct to where this surface ends
|
||||
} md3Surface;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char name[64]; // Name of this shader
|
||||
int shaderIndex; // Shader index number
|
||||
} md3Shader;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int index[3]; // List of offset values into the list of Vertex objects that constitute the corners of the Triangle object.
|
||||
} md3Triangle;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float st[2];
|
||||
} md3TexCoord;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short x, y, z, n;
|
||||
} md3Vertex;
|
||||
|
||||
static float latlnglookup[256][256][3];
|
||||
|
||||
static void GetNormalFromLatLong(short latlng, float *out)
|
||||
{
|
||||
float *lookup = latlnglookup[(unsigned char)(latlng >> 8)][(unsigned char)(latlng & 255)];
|
||||
|
||||
out[0] = *lookup++;
|
||||
out[1] = *lookup++;
|
||||
out[2] = *lookup++;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void NormalToLatLng(float *n, short *out)
|
||||
{
|
||||
// Special cases
|
||||
if (0.0f == n[0] && 0.0f == n[1])
|
||||
{
|
||||
if (n[2] > 0.0f)
|
||||
*out = 0;
|
||||
else
|
||||
*out = 128;
|
||||
}
|
||||
else
|
||||
{
|
||||
char x, y;
|
||||
|
||||
x = (char)(57.2957795f * (atan2(n[1], n[0])) * (255.0f / 360.0f));
|
||||
y = (char)(57.2957795f * (acos(n[2])) * (255.0f / 360.0f));
|
||||
|
||||
*out = (x << 8) + y;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void LatLngToNormal(short n, float *out)
|
||||
{
|
||||
const float PI = (3.1415926535897932384626433832795f);
|
||||
float lat = (float)(n >> 8);
|
||||
float lng = (float)(n & 255);
|
||||
|
||||
lat *= PI / 128.0f;
|
||||
lng *= PI / 128.0f;
|
||||
|
||||
out[0] = cosf(lat) * sinf(lng);
|
||||
out[1] = sinf(lat) * sinf(lng);
|
||||
out[2] = cosf(lng);
|
||||
}
|
||||
|
||||
static void LatLngInit(void)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
for (j = 0; j < 256; j++)
|
||||
LatLngToNormal((short)((i << 8) + j), latlnglookup[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
static boolean latlnginit = false;
|
||||
|
||||
model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat)
|
||||
{
|
||||
const float WUNITS = 1.0f;
|
||||
model_t *retModel = NULL;
|
||||
md3modelHeader *mdh;
|
||||
long fileLen;
|
||||
long fileReadLen;
|
||||
char *buffer;
|
||||
int surfEnd;
|
||||
int i, t;
|
||||
int matCount;
|
||||
FILE *f;
|
||||
|
||||
if (!latlnginit)
|
||||
{
|
||||
LatLngInit();
|
||||
latlnginit = true;
|
||||
}
|
||||
|
||||
f = fopen(fileName, "rb");
|
||||
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
retModel = (model_t*)Z_Calloc(sizeof(model_t), ztag, 0);
|
||||
|
||||
// find length of file
|
||||
fseek(f, 0, SEEK_END);
|
||||
fileLen = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
// read in file
|
||||
buffer = malloc(fileLen);
|
||||
fileReadLen = fread(buffer, fileLen, 1, f);
|
||||
fclose(f);
|
||||
|
||||
(void)fileReadLen; // intentionally ignore return value, per buildbot
|
||||
|
||||
// get pointer to file header
|
||||
mdh = (md3modelHeader*)buffer;
|
||||
|
||||
retModel->numMeshes = mdh->numSurfaces;
|
||||
|
||||
retModel->numMaterials = 0;
|
||||
surfEnd = 0;
|
||||
for (i = 0; i < mdh->numSurfaces; i++)
|
||||
{
|
||||
md3Surface *mdS = (md3Surface*)&buffer[mdh->offsetSurfaces];
|
||||
surfEnd += mdS->offsetEnd;
|
||||
|
||||
retModel->numMaterials += mdS->numShaders;
|
||||
}
|
||||
|
||||
// Initialize materials
|
||||
if (retModel->numMaterials <= 0) // Always at least one skin, duh
|
||||
retModel->numMaterials = 1;
|
||||
|
||||
retModel->materials = (material_t*)Z_Calloc(sizeof(material_t)*retModel->numMaterials, ztag, 0);
|
||||
|
||||
for (t = 0; t < retModel->numMaterials; t++)
|
||||
{
|
||||
retModel->materials[t].ambient[0] = 0.3686f;
|
||||
retModel->materials[t].ambient[1] = 0.3684f;
|
||||
retModel->materials[t].ambient[2] = 0.3684f;
|
||||
retModel->materials[t].ambient[3] = 1.0f;
|
||||
retModel->materials[t].diffuse[0] = 0.8863f;
|
||||
retModel->materials[t].diffuse[1] = 0.8850f;
|
||||
retModel->materials[t].diffuse[2] = 0.8850f;
|
||||
retModel->materials[t].diffuse[3] = 1.0f;
|
||||
retModel->materials[t].emissive[0] = 0.0f;
|
||||
retModel->materials[t].emissive[1] = 0.0f;
|
||||
retModel->materials[t].emissive[2] = 0.0f;
|
||||
retModel->materials[t].emissive[3] = 1.0f;
|
||||
retModel->materials[t].specular[0] = 0.4902f;
|
||||
retModel->materials[t].specular[1] = 0.4887f;
|
||||
retModel->materials[t].specular[2] = 0.4887f;
|
||||
retModel->materials[t].specular[3] = 1.0f;
|
||||
retModel->materials[t].shininess = 25.0f;
|
||||
retModel->materials[t].spheremap = false;
|
||||
}
|
||||
|
||||
retModel->meshes = (mesh_t*)Z_Calloc(sizeof(mesh_t)*retModel->numMeshes, ztag, 0);
|
||||
|
||||
matCount = 0;
|
||||
for (i = 0, surfEnd = 0; i < mdh->numSurfaces; i++)
|
||||
{
|
||||
int j;
|
||||
md3Shader *mdShader;
|
||||
md3Surface *mdS = (md3Surface*)&buffer[mdh->offsetSurfaces + surfEnd];
|
||||
surfEnd += mdS->offsetEnd;
|
||||
|
||||
mdShader = (md3Shader*)((char*)mdS + mdS->offsetShaders);
|
||||
|
||||
for (j = 0; j < mdS->numShaders; j++, matCount++)
|
||||
{
|
||||
size_t len = strlen(mdShader[j].name);
|
||||
mdShader[j].name[len-1] = 'z';
|
||||
mdShader[j].name[len-2] = 'u';
|
||||
mdShader[j].name[len-3] = 'b';
|
||||
|
||||
// Load material
|
||||
/* retModel->materials[matCount].texture = Texture::ReadTexture(mdShader[j].name, ZT_TEXTURE);
|
||||
|
||||
if (!systemSucks)
|
||||
{
|
||||
// Check for a normal map...??
|
||||
char openfilename[1024];
|
||||
char normalMapName[1024];
|
||||
strcpy(normalMapName, mdShader[j].name);
|
||||
len = strlen(normalMapName);
|
||||
char *ptr = &normalMapName[len];
|
||||
ptr--; // z
|
||||
ptr--; // u
|
||||
ptr--; // b
|
||||
ptr--; // .
|
||||
*ptr++ = '_';
|
||||
*ptr++ = 'n';
|
||||
*ptr++ = '.';
|
||||
*ptr++ = 'b';
|
||||
*ptr++ = 'u';
|
||||
*ptr++ = 'z';
|
||||
*ptr++ = '\0';
|
||||
|
||||
sprintf(openfilename, "%s/%s", "textures", normalMapName);
|
||||
// Convert backslashes to forward slashes
|
||||
for (int k = 0; k < 1024; k++)
|
||||
{
|
||||
if (openfilename[k] == '\0')
|
||||
break;
|
||||
|
||||
if (openfilename[k] == '\\')
|
||||
openfilename[k] = '/';
|
||||
}
|
||||
|
||||
Resource::resource_t *res = Resource::Open(openfilename);
|
||||
if (res)
|
||||
{
|
||||
Resource::Close(res);
|
||||
retModel->materials[matCount].lightmap = Texture::ReadTexture(normalMapName, ZT_TEXTURE);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
retModel->meshes[i].numFrames = mdS->numFrames;
|
||||
retModel->meshes[i].numTriangles = mdS->numTriangles;
|
||||
|
||||
if (!useFloat) // 'tinyframe' mode with indices
|
||||
{
|
||||
float tempNormal[3];
|
||||
float *uvptr;
|
||||
md3TexCoord *mdST;
|
||||
unsigned short *indexptr;
|
||||
md3Triangle *mdT;
|
||||
|
||||
retModel->meshes[i].tinyframes = (tinyframe_t*)Z_Calloc(sizeof(tinyframe_t)*mdS->numFrames, ztag, 0);
|
||||
retModel->meshes[i].numVertices = mdS->numVerts;
|
||||
retModel->meshes[i].uvs = (float*)Z_Malloc(sizeof(float)*2*mdS->numVerts, ztag, 0);
|
||||
for (j = 0; j < mdS->numFrames; j++)
|
||||
{
|
||||
short *vertptr;
|
||||
char *normptr;
|
||||
// char *tanptr;
|
||||
int k;
|
||||
md3Vertex *mdV = (md3Vertex*)((char*)mdS + mdS->offsetXYZNormal + (mdS->numVerts*j*sizeof(md3Vertex)));
|
||||
retModel->meshes[i].tinyframes[j].vertices = (short*)Z_Malloc(sizeof(short)*3*mdS->numVerts, ztag, 0);
|
||||
retModel->meshes[i].tinyframes[j].normals = (char*)Z_Malloc(sizeof(char)*3*mdS->numVerts, ztag, 0);
|
||||
|
||||
// if (retModel->materials[0].lightmap)
|
||||
// retModel->meshes[i].tinyframes[j].tangents = (char*)malloc(sizeof(char));//(char*)Z_Malloc(sizeof(char)*3*mdS->numVerts, ztag);
|
||||
retModel->meshes[i].indices = (unsigned short*)Z_Malloc(sizeof(unsigned short) * 3 * mdS->numTriangles, ztag, 0);
|
||||
vertptr = retModel->meshes[i].tinyframes[j].vertices;
|
||||
normptr = retModel->meshes[i].tinyframes[j].normals;
|
||||
|
||||
// tanptr = retModel->meshes[i].tinyframes[j].tangents;
|
||||
retModel->meshes[i].tinyframes[j].material = &retModel->materials[i];
|
||||
|
||||
for (k = 0; k < mdS->numVerts; k++)
|
||||
{
|
||||
// Vertex
|
||||
*vertptr = mdV[k].x;
|
||||
vertptr++;
|
||||
*vertptr = mdV[k].z;
|
||||
vertptr++;
|
||||
*vertptr = 1.0f - mdV[k].y;
|
||||
vertptr++;
|
||||
|
||||
// Normal
|
||||
GetNormalFromLatLong(mdV[k].n, tempNormal);
|
||||
*normptr = (char)(tempNormal[0] * 127);
|
||||
normptr++;
|
||||
*normptr = (char)(tempNormal[2] * 127);
|
||||
normptr++;
|
||||
*normptr = (char)(tempNormal[1] * 127);
|
||||
normptr++;
|
||||
}
|
||||
}
|
||||
|
||||
uvptr = (float*)retModel->meshes[i].uvs;
|
||||
mdST = (md3TexCoord*)((char*)mdS + mdS->offsetST);
|
||||
for (j = 0; j < mdS->numVerts; j++)
|
||||
{
|
||||
*uvptr = mdST[j].st[0];
|
||||
uvptr++;
|
||||
*uvptr = mdST[j].st[1];
|
||||
uvptr++;
|
||||
}
|
||||
|
||||
indexptr = retModel->meshes[i].indices;
|
||||
mdT = (md3Triangle*)((char*)mdS + mdS->offsetTriangles);
|
||||
for (j = 0; j < mdS->numTriangles; j++, mdT++)
|
||||
{
|
||||
// Indices
|
||||
*indexptr = (unsigned short)mdT->index[0];
|
||||
indexptr++;
|
||||
*indexptr = (unsigned short)mdT->index[1];
|
||||
indexptr++;
|
||||
*indexptr = (unsigned short)mdT->index[2];
|
||||
indexptr++;
|
||||
}
|
||||
}
|
||||
else // Traditional full-float loading method
|
||||
{
|
||||
float dataScale = 0.015624f * WUNITS;
|
||||
float tempNormal[3];
|
||||
md3TexCoord *mdST;
|
||||
md3Triangle *mdT;
|
||||
float *uvptr;
|
||||
int k;
|
||||
|
||||
retModel->meshes[i].numVertices = mdS->numTriangles * 3;//mdS->numVerts;
|
||||
retModel->meshes[i].frames = (mdlframe_t*)Z_Calloc(sizeof(mdlframe_t)*mdS->numFrames, ztag, 0);
|
||||
retModel->meshes[i].uvs = (float*)Z_Malloc(sizeof(float)*2*mdS->numTriangles*3, ztag, 0);
|
||||
|
||||
for (j = 0; j < mdS->numFrames; j++)
|
||||
{
|
||||
float *vertptr;
|
||||
float *normptr;
|
||||
md3Vertex *mdV = (md3Vertex*)((char*)mdS + mdS->offsetXYZNormal + (mdS->numVerts*j*sizeof(md3Vertex)));
|
||||
retModel->meshes[i].frames[j].vertices = (float*)Z_Malloc(sizeof(float)*3*mdS->numTriangles*3, ztag, 0);
|
||||
retModel->meshes[i].frames[j].normals = (float*)Z_Malloc(sizeof(float)*3*mdS->numTriangles*3, ztag, 0);
|
||||
// if (retModel->materials[i].lightmap)
|
||||
// retModel->meshes[i].frames[j].tangents = (float*)malloc(sizeof(float));//(float*)Z_Malloc(sizeof(float)*3*mdS->numTriangles*3, ztag);
|
||||
vertptr = retModel->meshes[i].frames[j].vertices;
|
||||
normptr = retModel->meshes[i].frames[j].normals;
|
||||
retModel->meshes[i].frames[j].material = &retModel->materials[i];
|
||||
|
||||
mdT = (md3Triangle*)((char*)mdS + mdS->offsetTriangles);
|
||||
|
||||
for (k = 0; k < mdS->numTriangles; k++)
|
||||
{
|
||||
// Vertex 1
|
||||
*vertptr = mdV[mdT->index[0]].x * dataScale;
|
||||
vertptr++;
|
||||
*vertptr = mdV[mdT->index[0]].z * dataScale;
|
||||
vertptr++;
|
||||
*vertptr = 1.0f - mdV[mdT->index[0]].y * dataScale;
|
||||
vertptr++;
|
||||
|
||||
GetNormalFromLatLong(mdV[mdT->index[0]].n, tempNormal);
|
||||
*normptr = tempNormal[0];
|
||||
normptr++;
|
||||
*normptr = tempNormal[2];
|
||||
normptr++;
|
||||
*normptr = tempNormal[1];
|
||||
normptr++;
|
||||
|
||||
// Vertex 2
|
||||
*vertptr = mdV[mdT->index[1]].x * dataScale;
|
||||
vertptr++;
|
||||
*vertptr = mdV[mdT->index[1]].z * dataScale;
|
||||
vertptr++;
|
||||
*vertptr = 1.0f - mdV[mdT->index[1]].y * dataScale;
|
||||
vertptr++;
|
||||
|
||||
GetNormalFromLatLong(mdV[mdT->index[1]].n, tempNormal);
|
||||
*normptr = tempNormal[0];
|
||||
normptr++;
|
||||
*normptr = tempNormal[2];
|
||||
normptr++;
|
||||
*normptr = tempNormal[1];
|
||||
normptr++;
|
||||
|
||||
// Vertex 3
|
||||
*vertptr = mdV[mdT->index[2]].x * dataScale;
|
||||
vertptr++;
|
||||
*vertptr = mdV[mdT->index[2]].z * dataScale;
|
||||
vertptr++;
|
||||
*vertptr = 1.0f - mdV[mdT->index[2]].y * dataScale;
|
||||
vertptr++;
|
||||
|
||||
GetNormalFromLatLong(mdV[mdT->index[2]].n, tempNormal);
|
||||
*normptr = tempNormal[0];
|
||||
normptr++;
|
||||
*normptr = tempNormal[2];
|
||||
normptr++;
|
||||
*normptr = tempNormal[1];
|
||||
normptr++;
|
||||
|
||||
mdT++; // Advance to next triangle
|
||||
}
|
||||
}
|
||||
|
||||
mdST = (md3TexCoord*)((char*)mdS + mdS->offsetST);
|
||||
uvptr = (float*)retModel->meshes[i].uvs;
|
||||
mdT = (md3Triangle*)((char*)mdS + mdS->offsetTriangles);
|
||||
|
||||
for (k = 0; k < mdS->numTriangles; k++)
|
||||
{
|
||||
*uvptr = mdST[mdT->index[0]].st[0];
|
||||
uvptr++;
|
||||
*uvptr = mdST[mdT->index[0]].st[1];
|
||||
uvptr++;
|
||||
|
||||
*uvptr = mdST[mdT->index[1]].st[0];
|
||||
uvptr++;
|
||||
*uvptr = mdST[mdT->index[1]].st[1];
|
||||
uvptr++;
|
||||
|
||||
*uvptr = mdST[mdT->index[2]].st[0];
|
||||
uvptr++;
|
||||
*uvptr = mdST[mdT->index[2]].st[1];
|
||||
uvptr++;
|
||||
|
||||
mdT++; // Advance to next triangle
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
// Tags?
|
||||
retModel->numTags = mdh->numTags;
|
||||
retModel->maxNumFrames = mdh->numFrames;
|
||||
retModel->tags = (tag_t*)Z_Calloc(sizeof(tag_t) * retModel->numTags * mdh->numFrames, ztag);
|
||||
md3Tag *mdTag = (md3Tag*)&buffer[mdh->offsetTags];
|
||||
tag_t *curTag = retModel->tags;
|
||||
for (i = 0; i < mdh->numFrames; i++)
|
||||
{
|
||||
int j;
|
||||
for (j = 0; j < retModel->numTags; j++, mdTag++)
|
||||
{
|
||||
strcpys(curTag->name, mdTag->name, sizeof(curTag->name) / sizeof(char));
|
||||
curTag->transform.m[0][0] = mdTag->axis[0];
|
||||
curTag->transform.m[0][1] = mdTag->axis[1];
|
||||
curTag->transform.m[0][2] = mdTag->axis[2];
|
||||
curTag->transform.m[1][0] = mdTag->axis[3];
|
||||
curTag->transform.m[1][1] = mdTag->axis[4];
|
||||
curTag->transform.m[1][2] = mdTag->axis[5];
|
||||
curTag->transform.m[2][0] = mdTag->axis[6];
|
||||
curTag->transform.m[2][1] = mdTag->axis[7];
|
||||
curTag->transform.m[2][2] = mdTag->axis[8];
|
||||
curTag->transform.m[3][0] = mdTag->origin[0] * WUNITS;
|
||||
curTag->transform.m[3][1] = mdTag->origin[1] * WUNITS;
|
||||
curTag->transform.m[3][2] = mdTag->origin[2] * WUNITS;
|
||||
curTag->transform.m[3][3] = 1.0f;
|
||||
|
||||
Matrix::Rotate(&curTag->transform, 90.0f, &Vector::Xaxis);
|
||||
curTag++;
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
free(buffer);
|
||||
|
||||
return retModel;
|
||||
}
|
19
src/hardware/hw_md3load.h
Normal file
19
src/hardware/hw_md3load.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
|
||||
An experimental work-in-progress.
|
||||
|
||||
Donated to Sonic Team Junior and adapted to work with
|
||||
Sonic Robo Blast 2. The license of this code matches whatever
|
||||
the licensing is for Sonic Robo Blast 2.
|
||||
*/
|
||||
|
||||
#ifndef _HW_MD3LOAD_H_
|
||||
#define _HW_MD3LOAD_H_
|
||||
|
||||
#include "hw_model.h"
|
||||
#include "../doomtype.h"
|
||||
|
||||
// Load the Model
|
||||
model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat);
|
||||
|
||||
#endif
|
593
src/hardware/hw_model.c
Normal file
593
src/hardware/hw_model.c
Normal file
|
@ -0,0 +1,593 @@
|
|||
/*
|
||||
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
|
||||
An experimental work-in-progress.
|
||||
|
||||
Donated to Sonic Team Junior and adapted to work with
|
||||
Sonic Robo Blast 2. The license of this code matches whatever
|
||||
the licensing is for Sonic Robo Blast 2.
|
||||
*/
|
||||
|
||||
#include "../z_zone.h"
|
||||
#include "../doomdef.h"
|
||||
#include "hw_model.h"
|
||||
#include "hw_md2load.h"
|
||||
#include "hw_md3load.h"
|
||||
#include "u_list.h"
|
||||
#include <string.h>
|
||||
|
||||
static float PI = (3.1415926535897932384626433832795f);
|
||||
static float U_Deg2Rad(float deg)
|
||||
{
|
||||
return deg * ((float)PI / 180.0f);
|
||||
}
|
||||
|
||||
vector_t vectorXaxis = { 1.0f, 0.0f, 0.0f };
|
||||
vector_t vectorYaxis = { 0.0f, 1.0f, 0.0f };
|
||||
vector_t vectorZaxis = { 0.0f, 0.0f, 1.0f };
|
||||
|
||||
void VectorRotate(vector_t *rotVec, const vector_t *axisVec, float angle)
|
||||
{
|
||||
float ux, uy, uz, vx, vy, vz, wx, wy, wz, sa, ca;
|
||||
|
||||
angle = U_Deg2Rad(angle);
|
||||
|
||||
// Rotate the point (x,y,z) around the vector (u,v,w)
|
||||
ux = axisVec->x * rotVec->x;
|
||||
uy = axisVec->x * rotVec->y;
|
||||
uz = axisVec->x * rotVec->z;
|
||||
vx = axisVec->y * rotVec->x;
|
||||
vy = axisVec->y * rotVec->y;
|
||||
vz = axisVec->y * rotVec->z;
|
||||
wx = axisVec->z * rotVec->x;
|
||||
wy = axisVec->z * rotVec->y;
|
||||
wz = axisVec->z * rotVec->z;
|
||||
sa = sinf(angle);
|
||||
ca = cosf(angle);
|
||||
|
||||
rotVec->x = axisVec->x*(ux + vy + wz) + (rotVec->x*(axisVec->y*axisVec->y + axisVec->z*axisVec->z) - axisVec->x*(vy + wz))*ca + (-wy + vz)*sa;
|
||||
rotVec->y = axisVec->y*(ux + vy + wz) + (rotVec->y*(axisVec->x*axisVec->x + axisVec->z*axisVec->z) - axisVec->y*(ux + wz))*ca + (wx - uz)*sa;
|
||||
rotVec->z = axisVec->z*(ux + vy + wz) + (rotVec->z*(axisVec->x*axisVec->x + axisVec->y*axisVec->y) - axisVec->z*(ux + vy))*ca + (-vx + uy)*sa;
|
||||
}
|
||||
|
||||
void UnloadModel(model_t *model)
|
||||
{
|
||||
// Wouldn't it be great if C just had destructors?
|
||||
int i;
|
||||
for (i = 0; i < model->numMeshes; i++)
|
||||
{
|
||||
mesh_t *mesh = &model->meshes[i];
|
||||
|
||||
if (mesh->frames)
|
||||
{
|
||||
int j;
|
||||
for (j = 0; j < mesh->numFrames; j++)
|
||||
{
|
||||
if (mesh->frames[j].normals)
|
||||
Z_Free(mesh->frames[j].normals);
|
||||
|
||||
if (mesh->frames[j].tangents)
|
||||
Z_Free(mesh->frames[j].tangents);
|
||||
|
||||
if (mesh->frames[j].vertices)
|
||||
Z_Free(mesh->frames[j].vertices);
|
||||
|
||||
if (mesh->frames[j].colors)
|
||||
Z_Free(mesh->frames[j].colors);
|
||||
}
|
||||
|
||||
Z_Free(mesh->frames);
|
||||
}
|
||||
else if (mesh->tinyframes)
|
||||
{
|
||||
int j;
|
||||
for (j = 0; j < mesh->numFrames; j++)
|
||||
{
|
||||
if (mesh->tinyframes[j].normals)
|
||||
Z_Free(mesh->tinyframes[j].normals);
|
||||
|
||||
if (mesh->tinyframes[j].tangents)
|
||||
Z_Free(mesh->tinyframes[j].tangents);
|
||||
|
||||
if (mesh->tinyframes[j].vertices)
|
||||
Z_Free(mesh->tinyframes[j].vertices);
|
||||
}
|
||||
|
||||
if (mesh->indices)
|
||||
Z_Free(mesh->indices);
|
||||
|
||||
Z_Free(mesh->tinyframes);
|
||||
}
|
||||
|
||||
if (mesh->uvs)
|
||||
Z_Free(mesh->uvs);
|
||||
|
||||
if (mesh->lightuvs)
|
||||
Z_Free(mesh->lightuvs);
|
||||
}
|
||||
|
||||
if (model->meshes)
|
||||
Z_Free(model->meshes);
|
||||
|
||||
if (model->tags)
|
||||
Z_Free(model->tags);
|
||||
|
||||
if (model->materials)
|
||||
Z_Free(model->materials);
|
||||
|
||||
DeleteVBOs(model);
|
||||
Z_Free(model);
|
||||
}
|
||||
|
||||
tag_t *GetTagByName(model_t *model, char *name, int frame)
|
||||
{
|
||||
if (frame < model->maxNumFrames)
|
||||
{
|
||||
tag_t *iterator = &model->tags[frame * model->numTags];
|
||||
|
||||
int i;
|
||||
for (i = 0; i < model->numTags; i++)
|
||||
{
|
||||
if (!stricmp(iterator[i].name, name))
|
||||
return &iterator[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// LoadModel
|
||||
//
|
||||
// Load a model and
|
||||
// convert it to the
|
||||
// internal format.
|
||||
//
|
||||
model_t *LoadModel(const char *filename, int ztag)
|
||||
{
|
||||
model_t *model;
|
||||
|
||||
// What type of file?
|
||||
const char *extension = NULL;
|
||||
int i;
|
||||
for (i = (int)strlen(filename)-1; i >= 0; i--)
|
||||
{
|
||||
if (filename[i] != '.')
|
||||
continue;
|
||||
|
||||
extension = &filename[i];
|
||||
break;
|
||||
}
|
||||
|
||||
if (!extension)
|
||||
{
|
||||
CONS_Printf("Model %s is lacking a file extension, unable to determine type!\n", filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!strcmp(extension, ".md3"))
|
||||
{
|
||||
if (!(model = MD3_LoadModel(filename, ztag, false)))
|
||||
return NULL;
|
||||
}
|
||||
else if (!strcmp(extension, ".md3s")) // MD3 that will be converted in memory to use full floats
|
||||
{
|
||||
if (!(model = MD3_LoadModel(filename, ztag, true)))
|
||||
return NULL;
|
||||
}
|
||||
else if (!strcmp(extension, ".md2"))
|
||||
{
|
||||
if (!(model = MD2_LoadModel(filename, ztag, false)))
|
||||
return NULL;
|
||||
}
|
||||
else if (!strcmp(extension, ".md2s"))
|
||||
{
|
||||
if (!(model = MD2_LoadModel(filename, ztag, true)))
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Printf("Unknown model format: %s\n", extension);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
model->mdlFilename = (char*)Z_Malloc(strlen(filename)+1, ztag, 0);
|
||||
strcpy(model->mdlFilename, filename);
|
||||
|
||||
Optimize(model);
|
||||
GeneratePolygonNormals(model, ztag);
|
||||
|
||||
// Default material properties
|
||||
for (i = 0 ; i < model->numMaterials; i++)
|
||||
{
|
||||
material_t *material = &model->materials[i];
|
||||
material->ambient[0] = 0.7686f;
|
||||
material->ambient[1] = 0.7686f;
|
||||
material->ambient[2] = 0.7686f;
|
||||
material->ambient[3] = 1.0f;
|
||||
material->diffuse[0] = 0.5863f;
|
||||
material->diffuse[1] = 0.5863f;
|
||||
material->diffuse[2] = 0.5863f;
|
||||
material->diffuse[3] = 1.0f;
|
||||
material->specular[0] = 0.4902f;
|
||||
material->specular[1] = 0.4902f;
|
||||
material->specular[2] = 0.4902f;
|
||||
material->specular[3] = 1.0f;
|
||||
material->shininess = 25.0f;
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
//
|
||||
// GenerateVertexNormals
|
||||
//
|
||||
// Creates a new normal for a vertex using the average of all of the polygons it belongs to.
|
||||
//
|
||||
void GenerateVertexNormals(model_t *model)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < model->numMeshes; i++)
|
||||
{
|
||||
int j;
|
||||
|
||||
mesh_t *mesh = &model->meshes[i];
|
||||
|
||||
if (!mesh->frames)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < mesh->numFrames; j++)
|
||||
{
|
||||
mdlframe_t *frame = &mesh->frames[j];
|
||||
int memTag = PU_STATIC;
|
||||
float *newNormals = (float*)Z_Malloc(sizeof(float)*3*mesh->numTriangles*3, memTag, 0);
|
||||
int k;
|
||||
float *vertPtr = frame->vertices;
|
||||
float *oldNormals;
|
||||
|
||||
M_Memcpy(newNormals, frame->normals, sizeof(float)*3*mesh->numTriangles*3);
|
||||
|
||||
/* if (!systemSucks)
|
||||
{
|
||||
memTag = Z_GetTag(frame->tangents);
|
||||
float *newTangents = (float*)Z_Malloc(sizeof(float)*3*mesh->numTriangles*3, memTag);
|
||||
M_Memcpy(newTangents, frame->tangents, sizeof(float)*3*mesh->numTriangles*3);
|
||||
}*/
|
||||
|
||||
for (k = 0; k < mesh->numVertices; k++)
|
||||
{
|
||||
float x, y, z;
|
||||
int vCount = 0;
|
||||
vector_t normal;
|
||||
int l;
|
||||
float *testPtr = frame->vertices;
|
||||
|
||||
x = *vertPtr++;
|
||||
y = *vertPtr++;
|
||||
z = *vertPtr++;
|
||||
|
||||
normal.x = normal.y = normal.z = 0;
|
||||
|
||||
for (l = 0; l < mesh->numVertices; l++)
|
||||
{
|
||||
float testX, testY, testZ;
|
||||
testX = *testPtr++;
|
||||
testY = *testPtr++;
|
||||
testZ = *testPtr++;
|
||||
|
||||
if (fabsf(x - testX) > FLT_EPSILON
|
||||
|| fabsf(y - testY) > FLT_EPSILON
|
||||
|| fabsf(z - testZ) > FLT_EPSILON)
|
||||
continue;
|
||||
|
||||
// Found a vertex match! Add it...
|
||||
normal.x += frame->normals[3 * l + 0];
|
||||
normal.y += frame->normals[3 * l + 1];
|
||||
normal.z += frame->normals[3 * l + 2];
|
||||
vCount++;
|
||||
}
|
||||
|
||||
if (vCount > 1)
|
||||
{
|
||||
// Vector::Normalize(&normal);
|
||||
newNormals[3 * k + 0] = (float)normal.x;
|
||||
newNormals[3 * k + 1] = (float)normal.y;
|
||||
newNormals[3 * k + 2] = (float)normal.z;
|
||||
|
||||
/* if (!systemSucks)
|
||||
{
|
||||
Vector::vector_t tangent;
|
||||
Vector::Tangent(&normal, &tangent);
|
||||
newTangents[3 * k + 0] = tangent.x;
|
||||
newTangents[3 * k + 1] = tangent.y;
|
||||
newTangents[3 * k + 2] = tangent.z;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
oldNormals = frame->normals;
|
||||
frame->normals = newNormals;
|
||||
Z_Free(oldNormals);
|
||||
|
||||
/* if (!systemSucks)
|
||||
{
|
||||
float *oldTangents = frame->tangents;
|
||||
frame->tangents = newTangents;
|
||||
Z_Free(oldTangents);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct materiallist_s
|
||||
{
|
||||
struct materiallist_s *next;
|
||||
struct materiallist_s *prev;
|
||||
material_t *material;
|
||||
} materiallist_t;
|
||||
|
||||
static boolean AddMaterialToList(materiallist_t **head, material_t *material)
|
||||
{
|
||||
materiallist_t *node, *newMatNode;
|
||||
for (node = *head; node; node = node->next)
|
||||
{
|
||||
if (node->material == material)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Didn't find it, so add to the list
|
||||
newMatNode = (materiallist_t*)Z_Malloc(sizeof(materiallist_t), PU_CACHE, 0);
|
||||
newMatNode->material = material;
|
||||
ListAdd(newMatNode, (listitem_t**)head);
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// Optimize
|
||||
//
|
||||
// Groups triangles from meshes in the model
|
||||
// Only works for models with 1 frame
|
||||
//
|
||||
void Optimize(model_t *model)
|
||||
{
|
||||
int numMeshes = 0;
|
||||
int i;
|
||||
materiallist_t *matListHead = NULL;
|
||||
int memTag;
|
||||
mesh_t *newMeshes;
|
||||
materiallist_t *node;
|
||||
|
||||
if (model->numMeshes <= 1)
|
||||
return; // No need
|
||||
|
||||
for (i = 0; i < model->numMeshes; i++)
|
||||
{
|
||||
mesh_t *curMesh = &model->meshes[i];
|
||||
|
||||
if (curMesh->numFrames > 1)
|
||||
return; // Can't optimize models with > 1 frame
|
||||
|
||||
if (!curMesh->frames)
|
||||
return; // Don't optimize tinyframe models (no need)
|
||||
|
||||
// We are condensing to 1 mesh per material, so
|
||||
// the # of materials we use will be the new
|
||||
// # of meshes
|
||||
if (AddMaterialToList(&matListHead, curMesh->frames[0].material))
|
||||
numMeshes++;
|
||||
}
|
||||
|
||||
memTag = PU_STATIC;
|
||||
newMeshes = (mesh_t*)Z_Calloc(sizeof(mesh_t) * numMeshes, memTag, 0);
|
||||
|
||||
i = 0;
|
||||
for (node = matListHead; node; node = node->next)
|
||||
{
|
||||
material_t *curMat = node->material;
|
||||
mesh_t *newMesh = &newMeshes[i];
|
||||
mdlframe_t *curFrame;
|
||||
int uvCount;
|
||||
int vertCount;
|
||||
int colorCount;
|
||||
|
||||
// Find all triangles with this material and count them
|
||||
int numTriangles = 0;
|
||||
int j;
|
||||
for (j = 0; j < model->numMeshes; j++)
|
||||
{
|
||||
mesh_t *curMesh = &model->meshes[j];
|
||||
|
||||
if (curMesh->frames[0].material == curMat)
|
||||
numTriangles += curMesh->numTriangles;
|
||||
}
|
||||
|
||||
newMesh->numFrames = 1;
|
||||
newMesh->numTriangles = numTriangles;
|
||||
newMesh->numVertices = numTriangles * 3;
|
||||
newMesh->uvs = (float*)Z_Malloc(sizeof(float)*2*numTriangles*3, memTag, 0);
|
||||
// if (node->material->lightmap)
|
||||
// newMesh->lightuvs = (float*)Z_Malloc(sizeof(float)*2*numTriangles*3, memTag, 0);
|
||||
newMesh->frames = (mdlframe_t*)Z_Calloc(sizeof(mdlframe_t), memTag, 0);
|
||||
curFrame = &newMesh->frames[0];
|
||||
|
||||
curFrame->material = curMat;
|
||||
curFrame->normals = (float*)Z_Malloc(sizeof(float)*3*numTriangles*3, memTag, 0);
|
||||
// if (!systemSucks)
|
||||
// curFrame->tangents = (float*)Z_Malloc(sizeof(float)*3*numTriangles*3, memTag, 0);
|
||||
curFrame->vertices = (float*)Z_Malloc(sizeof(float)*3*numTriangles*3, memTag, 0);
|
||||
curFrame->colors = (char*)Z_Malloc(sizeof(char)*4*numTriangles*3, memTag, 0);
|
||||
|
||||
// Now traverse the meshes of the model, adding in
|
||||
// vertices/normals/uvs that match the current material
|
||||
uvCount = 0;
|
||||
vertCount = 0;
|
||||
colorCount = 0;
|
||||
for (j = 0; j < model->numMeshes; j++)
|
||||
{
|
||||
mesh_t *curMesh = &model->meshes[j];
|
||||
|
||||
if (curMesh->frames[0].material == curMat)
|
||||
{
|
||||
float *dest;
|
||||
float *src;
|
||||
char *destByte;
|
||||
char *srcByte;
|
||||
|
||||
M_Memcpy(&newMesh->uvs[uvCount],
|
||||
curMesh->uvs,
|
||||
sizeof(float)*2*curMesh->numTriangles*3);
|
||||
|
||||
/* if (node->material->lightmap)
|
||||
{
|
||||
M_Memcpy(&newMesh->lightuvs[uvCount],
|
||||
curMesh->lightuvs,
|
||||
sizeof(float)*2*curMesh->numTriangles*3);
|
||||
}*/
|
||||
uvCount += 2*curMesh->numTriangles*3;
|
||||
|
||||
dest = (float*)newMesh->frames[0].vertices;
|
||||
src = (float*)curMesh->frames[0].vertices;
|
||||
M_Memcpy(&dest[vertCount],
|
||||
src,
|
||||
sizeof(float)*3*curMesh->numTriangles*3);
|
||||
|
||||
dest = (float*)newMesh->frames[0].normals;
|
||||
src = (float*)curMesh->frames[0].normals;
|
||||
M_Memcpy(&dest[vertCount],
|
||||
src,
|
||||
sizeof(float)*3*curMesh->numTriangles*3);
|
||||
|
||||
/* if (!systemSucks)
|
||||
{
|
||||
dest = (float*)newMesh->frames[0].tangents;
|
||||
src = (float*)curMesh->frames[0].tangents;
|
||||
M_Memcpy(&dest[vertCount],
|
||||
src,
|
||||
sizeof(float)*3*curMesh->numTriangles*3);
|
||||
}*/
|
||||
|
||||
vertCount += 3 * curMesh->numTriangles * 3;
|
||||
|
||||
destByte = (char*)newMesh->frames[0].colors;
|
||||
srcByte = (char*)curMesh->frames[0].colors;
|
||||
|
||||
if (srcByte)
|
||||
{
|
||||
M_Memcpy(&destByte[colorCount],
|
||||
srcByte,
|
||||
sizeof(char)*4*curMesh->numTriangles*3);
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(&destByte[colorCount],
|
||||
255,
|
||||
sizeof(char)*4*curMesh->numTriangles*3);
|
||||
}
|
||||
|
||||
colorCount += 4 * curMesh->numTriangles * 3;
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
CONS_Printf("Model::Optimize(): Model reduced from %d to %d meshes.\n", model->numMeshes, numMeshes);
|
||||
model->meshes = newMeshes;
|
||||
model->numMeshes = numMeshes;
|
||||
}
|
||||
|
||||
void GeneratePolygonNormals(model_t *model, int ztag)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < model->numMeshes; i++)
|
||||
{
|
||||
int j;
|
||||
mesh_t *mesh = &model->meshes[i];
|
||||
|
||||
if (!mesh->frames)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < mesh->numFrames; j++)
|
||||
{
|
||||
int k;
|
||||
mdlframe_t *frame = &mesh->frames[j];
|
||||
const float *vertices = frame->vertices;
|
||||
vector_t *polyNormals;
|
||||
|
||||
frame->polyNormals = (vector_t*)Z_Malloc(sizeof(vector_t) * mesh->numTriangles, ztag, 0);
|
||||
|
||||
polyNormals = frame->polyNormals;
|
||||
|
||||
for (k = 0; k < mesh->numTriangles; k++)
|
||||
{
|
||||
// Vector::Normal(vertices, polyNormals);
|
||||
vertices += 3 * 3;
|
||||
polyNormals++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Reload
|
||||
//
|
||||
// Reload VBOs
|
||||
//
|
||||
#if 0
|
||||
static void Reload(void)
|
||||
{
|
||||
/* model_t *node;
|
||||
for (node = modelHead; node; node = node->next)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < node->numMeshes; i++)
|
||||
{
|
||||
mesh_t *mesh = &node->meshes[i];
|
||||
|
||||
if (mesh->frames)
|
||||
{
|
||||
int j;
|
||||
for (j = 0; j < mesh->numFrames; j++)
|
||||
CreateVBO(mesh, &mesh->frames[j]);
|
||||
}
|
||||
else if (mesh->tinyframes)
|
||||
{
|
||||
int j;
|
||||
for (j = 0; j < mesh->numFrames; j++)
|
||||
CreateVBO(mesh, &mesh->tinyframes[j]);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
#endif
|
||||
|
||||
void DeleteVBOs(model_t *model)
|
||||
{
|
||||
(void)model;
|
||||
/* for (int i = 0; i < model->numMeshes; i++)
|
||||
{
|
||||
mesh_t *mesh = &model->meshes[i];
|
||||
|
||||
if (mesh->frames)
|
||||
{
|
||||
for (int j = 0; j < mesh->numFrames; j++)
|
||||
{
|
||||
mdlframe_t *frame = &mesh->frames[j];
|
||||
if (!frame->vboID)
|
||||
continue;
|
||||
bglDeleteBuffers(1, &frame->vboID);
|
||||
frame->vboID = 0;
|
||||
}
|
||||
}
|
||||
else if (mesh->tinyframes)
|
||||
{
|
||||
for (int j = 0; j < mesh->numFrames; j++)
|
||||
{
|
||||
tinyframe_t *frame = &mesh->tinyframes[j];
|
||||
if (!frame->vboID)
|
||||
continue;
|
||||
bglDeleteBuffers(1, &frame->vboID);
|
||||
frame->vboID = 0;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
104
src/hardware/hw_model.h
Normal file
104
src/hardware/hw_model.h
Normal file
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
|
||||
An experimental work-in-progress.
|
||||
|
||||
Donated to Sonic Team Junior and adapted to work with
|
||||
Sonic Robo Blast 2. The license of this code matches whatever
|
||||
the licensing is for Sonic Robo Blast 2.
|
||||
*/
|
||||
|
||||
#ifndef _HW_MODEL_H_
|
||||
#define _HW_MODEL_H_
|
||||
|
||||
#include "../doomtype.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float x, y, z;
|
||||
} vector_t;
|
||||
|
||||
extern vector_t vectorXaxis;
|
||||
extern vector_t vectorYaxis;
|
||||
extern vector_t vectorZaxis;
|
||||
|
||||
void VectorRotate(vector_t *rotVec, const vector_t *axisVec, float angle);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float ambient[4], diffuse[4], specular[4], emissive[4];
|
||||
float shininess;
|
||||
boolean spheremap;
|
||||
// Texture::texture_t *texture;
|
||||
// Texture::texture_t *lightmap;
|
||||
} material_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
material_t *material; // Pointer to the allocated 'materials' list in model_t
|
||||
float *vertices;
|
||||
float *normals;
|
||||
float *tangents;
|
||||
char *colors;
|
||||
unsigned int vboID;
|
||||
vector_t *polyNormals;
|
||||
} mdlframe_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
material_t *material;
|
||||
short *vertices;
|
||||
char *normals;
|
||||
char *tangents;
|
||||
unsigned int vboID;
|
||||
} tinyframe_t;
|
||||
|
||||
// Equivalent to MD3's many 'surfaces'
|
||||
typedef struct mesh_s
|
||||
{
|
||||
int numVertices;
|
||||
int numTriangles;
|
||||
|
||||
float *uvs;
|
||||
float *lightuvs;
|
||||
|
||||
int numFrames;
|
||||
mdlframe_t *frames;
|
||||
tinyframe_t *tinyframes;
|
||||
unsigned short *indices;
|
||||
} mesh_t;
|
||||
|
||||
typedef struct tag_s
|
||||
{
|
||||
char name[64];
|
||||
// matrix_t transform;
|
||||
} tag_t;
|
||||
|
||||
typedef struct model_s
|
||||
{
|
||||
int maxNumFrames;
|
||||
|
||||
int numMaterials;
|
||||
material_t *materials;
|
||||
int numMeshes;
|
||||
mesh_t *meshes;
|
||||
int numTags;
|
||||
tag_t *tags;
|
||||
|
||||
char *mdlFilename;
|
||||
boolean unloaded;
|
||||
} model_t;
|
||||
|
||||
extern int numModels;
|
||||
extern model_t *modelHead;
|
||||
|
||||
tag_t *GetTagByName(model_t *model, char *name, int frame);
|
||||
model_t *LoadModel(const char *filename, int ztag);
|
||||
void UnloadModel(model_t *model);
|
||||
void Optimize(model_t *model);
|
||||
void GenerateVertexNormals(model_t *model);
|
||||
void GeneratePolygonNormals(model_t *model, int ztag);
|
||||
void CreateVBOTiny(mesh_t *mesh, tinyframe_t *frame);
|
||||
void CreateVBO(mesh_t *mesh, mdlframe_t *frame);
|
||||
void DeleteVBOs(model_t *model);
|
||||
|
||||
#endif
|
|
@ -347,13 +347,6 @@ static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode)
|
|||
if (strstr(renderer, "810")) oglflags |= GLF_NOZBUFREAD;
|
||||
DBG_Printf("oglflags : 0x%X\n", oglflags);
|
||||
|
||||
#ifdef USE_PALETTED_TEXTURE
|
||||
if (isExtAvailable("GL_EXT_paletted_texture",gl_extensions))
|
||||
glColorTableEXT = GetGLFunc("glColorTableEXT");
|
||||
else
|
||||
glColorTableEXT = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef USE_WGL_SWAP
|
||||
if (isExtAvailable("WGL_EXT_swap_control",gl_extensions))
|
||||
wglSwapIntervalEXT = GetGLFunc("wglSwapIntervalEXT");
|
||||
|
@ -582,19 +575,8 @@ EXPORT void HWRAPI(SetPalette) (RGBA_t *pal, RGBA_t *gamma)
|
|||
myPaletteData[i].s.blue = (UINT8)MIN((pal[i].s.blue*gamma->s.blue)/127, 255);
|
||||
myPaletteData[i].s.alpha = pal[i].s.alpha;
|
||||
}
|
||||
#ifdef USE_PALETTED_TEXTURE
|
||||
if (glColorTableEXT)
|
||||
{
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
palette_tex[3*i+0] = pal[i].s.red;
|
||||
palette_tex[3*i+1] = pal[i].s.green;
|
||||
palette_tex[3*i+2] = pal[i].s.blue;
|
||||
}
|
||||
glColorTableEXT(GL_TEXTURE_2D, GL_RGB8, 256, GL_RGB, GL_UNSIGNED_BYTE, palette_tex);
|
||||
}
|
||||
#endif
|
||||
// on a chang<6E> de palette, il faut recharger toutes les textures
|
||||
|
||||
// on a palette change, you have to reload all of the textures
|
||||
Flush();
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -37,13 +37,11 @@
|
|||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
|
||||
#ifndef MINI_GL_COMPATIBILITY
|
||||
#ifdef STATIC_OPENGL // Because of the 1.3 functions, you'll need GLext to compile it if static
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
#include <GL/glext.h>
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define _CREATE_DLL_ // necessary for Unix AND Windows
|
||||
#include "../../doomdef.h"
|
||||
|
@ -73,7 +71,6 @@ extern FILE *gllogstream;
|
|||
#endif
|
||||
|
||||
#ifndef DRIVER_STRING
|
||||
// #define USE_PALETTED_TEXTURE
|
||||
#define DRIVER_STRING "HWRAPI Init(): SRB2Kart OpenGL renderer" // Tails
|
||||
#endif
|
||||
|
||||
|
@ -91,10 +88,6 @@ int SetupPixelFormat(INT32 WantColorBits, INT32 WantStencilBits, INT32 WantDepth
|
|||
void SetModelView(GLint w, GLint h);
|
||||
void SetStates(void);
|
||||
FUNCMATH float byteasfloat(UINT8 fbyte);
|
||||
#ifdef USE_PALETTED_TEXTURE
|
||||
extern PFNGLCOLORTABLEEXTPROC glColorTableEXT;
|
||||
extern GLubyte palette_tex[256*3];
|
||||
#endif
|
||||
|
||||
#ifndef GL_EXT_texture_filter_anisotropic
|
||||
#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
|
||||
|
@ -120,6 +113,10 @@ typedef void (APIENTRY * PFNglGetIntegerv) (GLenum pname, GLint *params);
|
|||
extern PFNglGetIntegerv pglGetIntegerv;
|
||||
typedef const GLubyte* (APIENTRY * PFNglGetString) (GLenum name);
|
||||
extern PFNglGetString pglGetString;
|
||||
#if 0
|
||||
typedef void (APIENTRY * PFNglEnableClientState) (GLenum cap); // redefined in r_opengl.c
|
||||
static PFNglEnableClientState pglEnableClientState;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// ==========================================================================
|
||||
|
|
52
src/hardware/r_opengl/r_vbo.h
Normal file
52
src/hardware/r_opengl/r_vbo.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
|
||||
An experimental work-in-progress.
|
||||
|
||||
Donated to Sonic Team Junior and adapted to work with
|
||||
Sonic Robo Blast 2. The license of this code matches whatever
|
||||
the licensing is for Sonic Robo Blast 2.
|
||||
*/
|
||||
#ifndef _R_VBO_H_
|
||||
#define _R_VBO_H_
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float x, y, z; // Vertex
|
||||
float nx, ny, nz; // Normal
|
||||
float s0, t0; // Texcoord0
|
||||
} vbo32_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float x, y, z; // Vertex
|
||||
float s0, t0; // Texcoord0
|
||||
unsigned char r, g, b, a; // Color
|
||||
float pad[2]; // Pad
|
||||
} vbo2d32_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float x, y; // Vertex
|
||||
float s0, t0; // Texcoord0
|
||||
} vbofont_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short x, y, z; // Vertex
|
||||
char nx, ny, nz; // Normal
|
||||
char tanx, tany, tanz; // Tangent
|
||||
float s0, t0; // Texcoord0
|
||||
} vbotiny_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float x, y, z; // Vertex
|
||||
float nx, ny, nz; // Normal
|
||||
float s0, t0; // Texcoord0
|
||||
float s1, t1; // Texcoord1
|
||||
float s2, t2; // Texcoord2
|
||||
float tan0, tan1, tan2; // Tangent
|
||||
unsigned char r, g, b, a; // Color
|
||||
} vbo64_t;
|
||||
|
||||
#endif
|
230
src/hardware/u_list.c
Normal file
230
src/hardware/u_list.c
Normal file
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
|
||||
An experimental work-in-progress.
|
||||
|
||||
Donated to Sonic Team Junior and adapted to work with
|
||||
Sonic Robo Blast 2. The license of this code matches whatever
|
||||
the licensing is for Sonic Robo Blast 2.
|
||||
*/
|
||||
|
||||
#include "u_list.h"
|
||||
#include "../z_zone.h"
|
||||
|
||||
// Utility for managing
|
||||
// structures in a linked
|
||||
// list.
|
||||
//
|
||||
// Struct must have "next" and "prev" pointers
|
||||
// as its first two variables.
|
||||
//
|
||||
|
||||
//
|
||||
// ListAdd
|
||||
//
|
||||
// Adds an item to the list
|
||||
//
|
||||
void ListAdd(void *pItem, listitem_t **itemHead)
|
||||
{
|
||||
listitem_t *item = (listitem_t*)pItem;
|
||||
|
||||
if (*itemHead == NULL)
|
||||
{
|
||||
*itemHead = item;
|
||||
(*itemHead)->prev = (*itemHead)->next = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
listitem_t *tail;
|
||||
tail = *itemHead;
|
||||
|
||||
while (tail->next != NULL)
|
||||
tail = tail->next;
|
||||
|
||||
tail->next = item;
|
||||
|
||||
tail->next->prev = tail;
|
||||
|
||||
item->next = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// ListAddFront
|
||||
//
|
||||
// Adds an item to the front of the list
|
||||
// (This is much faster)
|
||||
//
|
||||
void ListAddFront(void *pItem, listitem_t **itemHead)
|
||||
{
|
||||
listitem_t *item = (listitem_t*)pItem;
|
||||
|
||||
if (*itemHead == NULL)
|
||||
{
|
||||
*itemHead = item;
|
||||
(*itemHead)->prev = (*itemHead)->next = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*itemHead)->prev = item;
|
||||
item->next = (*itemHead);
|
||||
item->prev = NULL;
|
||||
*itemHead = item;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// ListAddBefore
|
||||
//
|
||||
// Adds an item before the item specified in the list
|
||||
//
|
||||
void ListAddBefore(void *pItem, void *pSpot, listitem_t **itemHead)
|
||||
{
|
||||
listitem_t *item = (listitem_t*)pItem;
|
||||
listitem_t *spot = (listitem_t*)pSpot;
|
||||
|
||||
listitem_t *prev = spot->prev;
|
||||
|
||||
if (!prev)
|
||||
ListAddFront(pItem, itemHead);
|
||||
else
|
||||
{
|
||||
item->next = spot;
|
||||
spot->prev = item;
|
||||
item->prev = prev;
|
||||
prev->next = item;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// ListAddAfter
|
||||
//
|
||||
// Adds an item after the item specified in the list
|
||||
//
|
||||
void ListAddAfter(void *pItem, void *pSpot, listitem_t **itemHead)
|
||||
{
|
||||
listitem_t *item = (listitem_t*)pItem;
|
||||
listitem_t *spot = (listitem_t*)pSpot;
|
||||
|
||||
listitem_t *next = spot->next;
|
||||
|
||||
if (!next)
|
||||
ListAdd(pItem, itemHead);
|
||||
else
|
||||
{
|
||||
item->prev = spot;
|
||||
spot->next = item;
|
||||
item->next = next;
|
||||
next->prev = item;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// ListRemove
|
||||
//
|
||||
// Take an item out of the list and free its memory.
|
||||
//
|
||||
void ListRemove(void *pItem, listitem_t **itemHead)
|
||||
{
|
||||
listitem_t *item = (listitem_t*)pItem;
|
||||
|
||||
if (item == *itemHead) // Start of list
|
||||
{
|
||||
*itemHead = item->next;
|
||||
|
||||
if (*itemHead)
|
||||
(*itemHead)->prev = NULL;
|
||||
}
|
||||
else if (item->next == NULL) // end of list
|
||||
{
|
||||
item->prev->next = NULL;
|
||||
}
|
||||
else // Somewhere in between
|
||||
{
|
||||
item->prev->next = item->next;
|
||||
item->next->prev = item->prev;
|
||||
}
|
||||
|
||||
Z_Free (item);
|
||||
}
|
||||
|
||||
//
|
||||
// ListRemoveAll
|
||||
//
|
||||
// Removes all items from the list, freeing their memory.
|
||||
//
|
||||
void ListRemoveAll(listitem_t **itemHead)
|
||||
{
|
||||
listitem_t *item;
|
||||
listitem_t *next;
|
||||
for (item = *itemHead; item; item = next)
|
||||
{
|
||||
next = item->next;
|
||||
ListRemove(item, itemHead);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// ListRemoveNoFree
|
||||
//
|
||||
// Take an item out of the list, but don't free its memory.
|
||||
//
|
||||
void ListRemoveNoFree(void *pItem, listitem_t **itemHead)
|
||||
{
|
||||
listitem_t *item = (listitem_t*)pItem;
|
||||
|
||||
if (item == *itemHead) // Start of list
|
||||
{
|
||||
*itemHead = item->next;
|
||||
|
||||
if (*itemHead)
|
||||
(*itemHead)->prev = NULL;
|
||||
}
|
||||
else if (item->next == NULL) // end of list
|
||||
{
|
||||
item->prev->next = NULL;
|
||||
}
|
||||
else // Somewhere in between
|
||||
{
|
||||
item->prev->next = item->next;
|
||||
item->next->prev = item->prev;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// ListGetCount
|
||||
//
|
||||
// Counts the # of items in a list
|
||||
// Should not be used in performance-minded code
|
||||
//
|
||||
unsigned int ListGetCount(void *itemHead)
|
||||
{
|
||||
listitem_t *item = (listitem_t*)itemHead;
|
||||
|
||||
unsigned int count = 0;
|
||||
for (; item; item = item->next)
|
||||
count++;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
//
|
||||
// ListGetByIndex
|
||||
//
|
||||
// Gets an item in the list by its index
|
||||
// Should not be used in performance-minded code
|
||||
//
|
||||
listitem_t *ListGetByIndex(void *itemHead, unsigned int index)
|
||||
{
|
||||
listitem_t *head = (listitem_t*)itemHead;
|
||||
unsigned int count = 0;
|
||||
listitem_t *node;
|
||||
for (node = head; node; node = node->next)
|
||||
{
|
||||
if (count == index)
|
||||
return node;
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
29
src/hardware/u_list.h
Normal file
29
src/hardware/u_list.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
|
||||
An experimental work-in-progress.
|
||||
|
||||
Donated to Sonic Team Junior and adapted to work with
|
||||
Sonic Robo Blast 2. The license of this code matches whatever
|
||||
the licensing is for Sonic Robo Blast 2.
|
||||
*/
|
||||
|
||||
#ifndef _U_LIST_H_
|
||||
#define _U_LIST_H_
|
||||
|
||||
typedef struct listitem_s
|
||||
{
|
||||
struct listitem_s *next;
|
||||
struct listitem_s *prev;
|
||||
} listitem_t;
|
||||
|
||||
void ListAdd(void *pItem, listitem_t **itemHead);
|
||||
void ListAddFront(void *pItem, listitem_t **itemHead);
|
||||
void ListAddBefore(void *pItem, void *pSpot, listitem_t **itemHead);
|
||||
void ListAddAfter(void *pItem, void *pSpot, listitem_t **itemHead);
|
||||
void ListRemove(void *pItem, listitem_t **itemHead);
|
||||
void ListRemoveAll(listitem_t **itemHead);
|
||||
void ListRemoveNoFree(void *pItem, listitem_t **itemHead);
|
||||
unsigned int ListGetCount(void *itemHead);
|
||||
listitem_t *ListGetByIndex(void *itemHead, unsigned int index);
|
||||
|
||||
#endif
|
|
@ -146,6 +146,18 @@ boolean I_SongPaused(void);
|
|||
|
||||
boolean I_SetSongSpeed(float speed);
|
||||
|
||||
/// ------------------------
|
||||
// MUSIC SEEKING
|
||||
/// ------------------------
|
||||
|
||||
UINT32 I_GetSongLength(void);
|
||||
|
||||
boolean I_SetSongLoopPoint(UINT32 looppoint);
|
||||
UINT32 I_GetSongLoopPoint(void);
|
||||
|
||||
boolean I_SetSongPosition(UINT32 position);
|
||||
UINT32 I_GetSongPosition(void);
|
||||
|
||||
/// ------------------------
|
||||
// MUSIC PLAYBACK
|
||||
/// ------------------------
|
||||
|
@ -216,6 +228,17 @@ void I_SetMusicVolume(UINT8 volume);
|
|||
|
||||
boolean I_SetSongTrack(INT32 track);
|
||||
|
||||
/// ------------------------
|
||||
/// MUSIC FADING
|
||||
/// ------------------------
|
||||
|
||||
void I_SetInternalMusicVolume(UINT8 volume);
|
||||
void I_StopFadingSong(void);
|
||||
boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void));
|
||||
boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void));
|
||||
boolean I_FadeOutStopSong(UINT32 ms);
|
||||
boolean I_FadeInPlaySong(UINT32 ms, boolean looping);
|
||||
|
||||
/// ------------------------
|
||||
// CD MUSIC I/O
|
||||
/// ------------------------
|
||||
|
|
34
src/i_tcp.c
34
src/i_tcp.c
|
@ -813,6 +813,8 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
|
|||
#endif
|
||||
#endif
|
||||
mysockaddr_t straddr;
|
||||
struct sockaddr_in sin;
|
||||
socklen_t len = sizeof(sin);
|
||||
|
||||
if (s == (SOCKET_TYPE)ERRSOCKET)
|
||||
return (SOCKET_TYPE)ERRSOCKET;
|
||||
|
@ -906,12 +908,16 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
|
|||
CONS_Printf(M_GetText("Network system buffer set to: %dKb\n"), opt>>10);
|
||||
}
|
||||
|
||||
if (getsockname(s, (struct sockaddr *)&sin, &len) == -1)
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Failed to get port number\n"));
|
||||
else
|
||||
current_port = (UINT16)ntohs(sin.sin_port);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static boolean UDP_Socket(void)
|
||||
{
|
||||
const char *sock_port = NULL;
|
||||
size_t s;
|
||||
struct my_addrinfo *ai, *runp, hints;
|
||||
int gaie;
|
||||
|
@ -933,20 +939,11 @@ static boolean UDP_Socket(void)
|
|||
hints.ai_socktype = SOCK_DGRAM;
|
||||
hints.ai_protocol = IPPROTO_UDP;
|
||||
|
||||
if (M_CheckParm("-clientport"))
|
||||
{
|
||||
if (!M_IsNextParm())
|
||||
I_Error("syntax: -clientport <portnum>");
|
||||
sock_port = M_GetNextParm();
|
||||
}
|
||||
else
|
||||
sock_port = port_name;
|
||||
|
||||
if (M_CheckParm("-bindaddr"))
|
||||
{
|
||||
while (M_IsNextParm())
|
||||
{
|
||||
gaie = I_getaddrinfo(M_GetNextParm(), sock_port, &hints, &ai);
|
||||
gaie = I_getaddrinfo(M_GetNextParm(), port_name, &hints, &ai);
|
||||
if (gaie == 0)
|
||||
{
|
||||
runp = ai;
|
||||
|
@ -967,7 +964,7 @@ static boolean UDP_Socket(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
gaie = I_getaddrinfo("0.0.0.0", sock_port, &hints, &ai);
|
||||
gaie = I_getaddrinfo("0.0.0.0", port_name, &hints, &ai);
|
||||
if (gaie == 0)
|
||||
{
|
||||
runp = ai;
|
||||
|
@ -982,8 +979,8 @@ static boolean UDP_Socket(void)
|
|||
#ifdef HAVE_MINIUPNPC
|
||||
if (UPNP_support)
|
||||
{
|
||||
I_UPnP_rem(sock_port, "UDP");
|
||||
I_UPnP_add(NULL, sock_port, "UDP");
|
||||
I_UPnP_rem(port_name, "UDP");
|
||||
I_UPnP_add(NULL, port_name, "UDP");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -1000,7 +997,7 @@ static boolean UDP_Socket(void)
|
|||
{
|
||||
while (M_IsNextParm())
|
||||
{
|
||||
gaie = I_getaddrinfo(M_GetNextParm(), sock_port, &hints, &ai);
|
||||
gaie = I_getaddrinfo(M_GetNextParm(), port_name, &hints, &ai);
|
||||
if (gaie == 0)
|
||||
{
|
||||
runp = ai;
|
||||
|
@ -1021,7 +1018,7 @@ static boolean UDP_Socket(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
gaie = I_getaddrinfo("::", sock_port, &hints, &ai);
|
||||
gaie = I_getaddrinfo("::", port_name, &hints, &ai);
|
||||
if (gaie == 0)
|
||||
{
|
||||
runp = ai;
|
||||
|
@ -1478,14 +1475,15 @@ boolean I_InitTcpNetwork(void)
|
|||
if (!I_InitTcpDriver())
|
||||
return false;
|
||||
|
||||
if (M_CheckParm("-udpport"))
|
||||
if (M_CheckParm("-port"))
|
||||
// Combined -udpport and -clientport into -port
|
||||
// As it was really redundant having two seperate parms that does the same thing
|
||||
{
|
||||
if (M_IsNextParm())
|
||||
strcpy(port_name, M_GetNextParm());
|
||||
else
|
||||
strcpy(port_name, "0");
|
||||
}
|
||||
current_port = (UINT16)atoi(port_name);
|
||||
|
||||
// parse network game options,
|
||||
if (M_CheckParm("-server") || dedicated)
|
||||
|
|
|
@ -219,6 +219,7 @@ const UINT8 KartColor_Opposite[MAXSKINCOLORS*2] =
|
|||
SKINCOLOR_SUNSET,10, // SKINCOLOR_MOONSLAM
|
||||
SKINCOLOR_MAUVE,10, // SKINCOLOR_ULTRAVIOLET
|
||||
SKINCOLOR_DAWN,6, // SKINCOLOR_DUSK
|
||||
SKINCOLOR_POPCORN,12, // SKINCOLOR_BUBBLEGUM
|
||||
SKINCOLOR_EMERALD,8, // SKINCOLOR_PURPLE
|
||||
SKINCOLOR_PASTEL,11, // SKINCOLOR_FUCHSIA
|
||||
SKINCOLOR_MAROON,8, // SKINCOLOR_TOXIC
|
||||
|
|
|
@ -769,7 +769,8 @@ static int lib_pRestoreMusic(lua_State *L)
|
|||
NOHUD
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
P_RestoreMusic(player);
|
||||
if (P_IsLocalPlayer(player))
|
||||
P_RestoreMusic(player);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1836,7 +1837,7 @@ static int lib_sChangeMusic(lua_State *L)
|
|||
{
|
||||
#ifdef MUSICSLOT_COMPATIBILITY
|
||||
const char *music_name;
|
||||
UINT32 music_num;
|
||||
UINT32 music_num, position, prefadems, fadeinms;
|
||||
char music_compat_name[7];
|
||||
|
||||
boolean looping;
|
||||
|
@ -1864,7 +1865,6 @@ static int lib_sChangeMusic(lua_State *L)
|
|||
music_name = luaL_checkstring(L, 1);
|
||||
}
|
||||
|
||||
|
||||
looping = (boolean)lua_opttrueboolean(L, 2);
|
||||
|
||||
#else
|
||||
|
@ -1889,8 +1889,12 @@ static int lib_sChangeMusic(lua_State *L)
|
|||
#endif
|
||||
music_flags = (UINT16)luaL_optinteger(L, 4, 0);
|
||||
|
||||
position = (UINT32)luaL_optinteger(L, 5, 0);
|
||||
prefadems = (UINT32)luaL_optinteger(L, 6, 0);
|
||||
fadeinms = (UINT32)luaL_optinteger(L, 7, 0);
|
||||
|
||||
if (!player || P_IsLocalPlayer(player))
|
||||
S_ChangeMusic(music_name, music_flags, looping);
|
||||
S_ChangeMusicEx(music_name, music_flags, looping, position, prefadems, fadeinms);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1907,10 +1911,8 @@ static int lib_sSpeedMusic(lua_State *L)
|
|||
return LUA_ErrInvalid(L, "player_t");
|
||||
}
|
||||
if (!player || P_IsLocalPlayer(player))
|
||||
lua_pushboolean(L, S_SpeedMusic(speed));
|
||||
else
|
||||
lua_pushboolean(L, false);
|
||||
return 1;
|
||||
S_SpeedMusic(speed);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_sStopMusic(lua_State *L)
|
||||
|
@ -1928,6 +1930,110 @@ static int lib_sStopMusic(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int lib_sSetInternalMusicVolume(lua_State *L)
|
||||
{
|
||||
UINT32 volume = (UINT32)luaL_checkinteger(L, 1);
|
||||
player_t *player = NULL;
|
||||
NOHUD
|
||||
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
|
||||
{
|
||||
player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
}
|
||||
if (!player || P_IsLocalPlayer(player))
|
||||
{
|
||||
S_SetInternalMusicVolume(volume);
|
||||
lua_pushboolean(L, true);
|
||||
}
|
||||
else
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_sStopFadingMusic(lua_State *L)
|
||||
{
|
||||
player_t *player = NULL;
|
||||
NOHUD
|
||||
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
|
||||
{
|
||||
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
}
|
||||
if (!player || P_IsLocalPlayer(player))
|
||||
{
|
||||
S_StopFadingMusic();
|
||||
lua_pushboolean(L, true);
|
||||
}
|
||||
else
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_sFadeMusic(lua_State *L)
|
||||
{
|
||||
UINT32 target_volume = (UINT32)luaL_checkinteger(L, 1);
|
||||
UINT32 ms;
|
||||
INT32 source_volume;
|
||||
player_t *player = NULL;
|
||||
NOHUD
|
||||
if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
|
||||
{
|
||||
player = *((player_t **)luaL_checkudata(L, 3, META_PLAYER));
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
ms = (UINT32)luaL_checkinteger(L, 2);
|
||||
source_volume = -1;
|
||||
}
|
||||
else if (!lua_isnone(L, 4) && lua_isuserdata(L, 4))
|
||||
{
|
||||
player = *((player_t **)luaL_checkudata(L, 4, META_PLAYER));
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
source_volume = (INT32)luaL_checkinteger(L, 2);
|
||||
ms = (UINT32)luaL_checkinteger(L, 3);
|
||||
}
|
||||
else if (luaL_optinteger(L, 3, INT32_MAX) == INT32_MAX)
|
||||
{
|
||||
ms = (UINT32)luaL_checkinteger(L, 2);
|
||||
source_volume = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
source_volume = (INT32)luaL_checkinteger(L, 2);
|
||||
ms = (UINT32)luaL_checkinteger(L, 3);
|
||||
}
|
||||
|
||||
NOHUD
|
||||
|
||||
if (!player || P_IsLocalPlayer(player))
|
||||
lua_pushboolean(L, S_FadeMusicFromVolume(target_volume, source_volume, ms));
|
||||
else
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_sFadeOutStopMusic(lua_State *L)
|
||||
{
|
||||
UINT32 ms = (UINT32)luaL_checkinteger(L, 1);
|
||||
player_t *player = NULL;
|
||||
NOHUD
|
||||
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
|
||||
{
|
||||
player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
}
|
||||
if (!player || P_IsLocalPlayer(player))
|
||||
{
|
||||
lua_pushboolean(L, S_FadeOutStopMusic(ms));
|
||||
}
|
||||
else
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_sOriginPlaying(lua_State *L)
|
||||
{
|
||||
void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
|
||||
|
@ -2727,6 +2833,10 @@ static luaL_Reg lib[] = {
|
|||
{"S_ChangeMusic",lib_sChangeMusic},
|
||||
{"S_SpeedMusic",lib_sSpeedMusic},
|
||||
{"S_StopMusic",lib_sStopMusic},
|
||||
{"S_SetInternalMusicVolume", lib_sSetInternalMusicVolume},
|
||||
{"S_StopFadingMusic",lib_sStopFadingMusic},
|
||||
{"S_FadeMusic",lib_sFadeMusic},
|
||||
{"S_FadeOutStopMusic",lib_sFadeOutStopMusic},
|
||||
{"S_OriginPlaying",lib_sOriginPlaying},
|
||||
{"S_IdPlaying",lib_sIdPlaying},
|
||||
{"S_SoundPlaying",lib_sSoundPlaying},
|
||||
|
@ -2752,7 +2862,7 @@ static luaL_Reg lib[] = {
|
|||
// k_kart
|
||||
{"K_PlayAttackTaunt", lib_kAttackSound},
|
||||
{"K_PlayBoostTaunt", lib_kBoostSound},
|
||||
{"K_PlayPowerGloatSund", lib_kGloatSound},
|
||||
{"K_PlayPowerGloatSound", lib_kGloatSound},
|
||||
{"K_PlayOvertakeSound", lib_kOvertakeSound},
|
||||
{"K_PlayLossSound", lib_kLossSound},
|
||||
{"K_PlayHitEmSound", lib_kHitEmSound},
|
||||
|
|
|
@ -51,6 +51,7 @@ enum hook {
|
|||
hook_PlayerExplode, //SRB2KART
|
||||
hook_PlayerSquish, //SRB2KART
|
||||
hook_PlayerCmd, //SRB2KART
|
||||
hook_IntermissionThinker, //SRB2KART
|
||||
|
||||
hook_MAX // last hook
|
||||
};
|
||||
|
@ -99,4 +100,6 @@ boolean LUAh_PlayerSquish(player_t *player, mobj_t *inflictor, mobj_t *source);
|
|||
|
||||
boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd); // Allows to write to player cmd before the game does anything with them.
|
||||
|
||||
void LUAh_IntermissionThinker(void); // Hook for Y_Ticker
|
||||
|
||||
#endif
|
||||
|
|
|
@ -62,6 +62,7 @@ const char *const hookNames[hook_MAX+1] = {
|
|||
"PlayerExplode",
|
||||
"PlayerSquish",
|
||||
"PlayerCmd",
|
||||
"IntermissionThinker",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -420,6 +421,28 @@ void LUAh_ThinkFrame(void)
|
|||
}
|
||||
}
|
||||
|
||||
// Hook for Y_Ticker
|
||||
void LUAh_IntermissionThinker(void)
|
||||
{
|
||||
hook_p hookp;
|
||||
if (!gL || !(hooksAvailable[hook_IntermissionThinker/8] & (1<<(hook_IntermissionThinker%8))))
|
||||
return;
|
||||
|
||||
for (hookp = roothook; hookp; hookp = hookp->next)
|
||||
if (hookp->type == hook_IntermissionThinker)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Hook for mobj collisions
|
||||
UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which)
|
||||
{
|
||||
|
|
|
@ -1477,6 +1477,12 @@ static int mapheaderinfo_get(lua_State *L)
|
|||
lua_pushstring(L, header->musname);
|
||||
else if (fastcmp(field,"mustrack"))
|
||||
lua_pushinteger(L, header->mustrack);
|
||||
else if (fastcmp(field,"muspos"))
|
||||
lua_pushinteger(L, header->muspos);
|
||||
else if (fastcmp(field,"musinterfadeout"))
|
||||
lua_pushinteger(L, header->musinterfadeout);
|
||||
else if (fastcmp(field,"musintername"))
|
||||
lua_pushstring(L, header->musintername);
|
||||
else if (fastcmp(field,"forcecharacter"))
|
||||
lua_pushstring(L, header->forcecharacter);
|
||||
else if (fastcmp(field,"weather"))
|
||||
|
|
239
src/m_fixed.c
239
src/m_fixed.c
|
@ -56,7 +56,7 @@ fixed_t FixedDiv2(fixed_t a, fixed_t b)
|
|||
if (b == 0)
|
||||
I_Error("FixedDiv: divide by zero");
|
||||
|
||||
ret = (((INT64)a * FRACUNIT) ) / b;
|
||||
ret = (((INT64)a * FRACUNIT)) / b;
|
||||
|
||||
if ((ret > INT32_MAX) || (ret < INT32_MIN))
|
||||
I_Error("FixedDiv: divide by zero");
|
||||
|
@ -117,7 +117,7 @@ fixed_t FixedHypot(fixed_t x, fixed_t y)
|
|||
yx = FixedDiv(y, x); // (x/y)
|
||||
}
|
||||
yx2 = FixedMul(yx, yx); // (x/y)^2
|
||||
yx1 = FixedSqrt(1*FRACUNIT + yx2); // (1 + (x/y)^2)^1/2
|
||||
yx1 = FixedSqrt(1 * FRACUNIT + yx2); // (1 + (x/y)^2)^1/2
|
||||
return FixedMul(ax, yx1); // |x|*((1 + (x/y)^2)^1/2)
|
||||
}
|
||||
|
||||
|
@ -191,8 +191,8 @@ vector2_t *FV2_Divide(vector2_t *a_i, fixed_t a_c)
|
|||
// Vector Complex Math
|
||||
vector2_t *FV2_Midpoint(const vector2_t *a_1, const vector2_t *a_2, vector2_t *a_o)
|
||||
{
|
||||
a_o->x = FixedDiv(a_2->x - a_1->x, 2*FRACUNIT);
|
||||
a_o->y = FixedDiv(a_2->y - a_1->y, 2*FRACUNIT);
|
||||
a_o->x = FixedDiv(a_2->x - a_1->x, 2 * FRACUNIT);
|
||||
a_o->y = FixedDiv(a_2->y - a_1->y, 2 * FRACUNIT);
|
||||
a_o->x = a_1->x + a_o->x;
|
||||
a_o->y = a_1->y + a_o->y;
|
||||
return a_o;
|
||||
|
@ -200,16 +200,16 @@ vector2_t *FV2_Midpoint(const vector2_t *a_1, const vector2_t *a_2, vector2_t *a
|
|||
|
||||
fixed_t FV2_Distance(const vector2_t *p1, const vector2_t *p2)
|
||||
{
|
||||
fixed_t xs = FixedMul(p2->x-p1->x,p2->x-p1->x);
|
||||
fixed_t ys = FixedMul(p2->y-p1->y,p2->y-p1->y);
|
||||
return FixedSqrt(xs+ys);
|
||||
fixed_t xs = FixedMul(p2->x - p1->x, p2->x - p1->x);
|
||||
fixed_t ys = FixedMul(p2->y - p1->y, p2->y - p1->y);
|
||||
return FixedSqrt(xs + ys);
|
||||
}
|
||||
|
||||
fixed_t FV2_Magnitude(const vector2_t *a_normal)
|
||||
{
|
||||
fixed_t xs = FixedMul(a_normal->x,a_normal->x);
|
||||
fixed_t ys = FixedMul(a_normal->y,a_normal->y);
|
||||
return FixedSqrt(xs+ys);
|
||||
fixed_t xs = FixedMul(a_normal->x, a_normal->x);
|
||||
fixed_t ys = FixedMul(a_normal->y, a_normal->y);
|
||||
return FixedSqrt(xs + ys);
|
||||
}
|
||||
|
||||
// Also returns the magnitude
|
||||
|
@ -240,7 +240,7 @@ vector2_t *FV2_Negate(vector2_t *a_1)
|
|||
|
||||
boolean FV2_Equal(const vector2_t *a_1, const vector2_t *a_2)
|
||||
{
|
||||
fixed_t Epsilon = FRACUNIT/FRACUNIT;
|
||||
fixed_t Epsilon = FRACUNIT / FRACUNIT;
|
||||
|
||||
if ((abs(a_2->x - a_1->x) > Epsilon) ||
|
||||
(abs(a_2->y - a_1->y) > Epsilon))
|
||||
|
@ -261,7 +261,7 @@ fixed_t FV2_Dot(const vector2_t *a_1, const vector2_t *a_2)
|
|||
//
|
||||
// Given two points, create a vector between them.
|
||||
//
|
||||
vector2_t *FV2_Point2Vec (const vector2_t *point1, const vector2_t *point2, vector2_t *a_o)
|
||||
vector2_t *FV2_Point2Vec(const vector2_t *point1, const vector2_t *point2, vector2_t *a_o)
|
||||
{
|
||||
a_o->x = point1->x - point2->x;
|
||||
a_o->y = point1->y - point2->y;
|
||||
|
@ -344,9 +344,9 @@ vector3_t *FV3_Divide(vector3_t *a_i, fixed_t a_c)
|
|||
// Vector Complex Math
|
||||
vector3_t *FV3_Midpoint(const vector3_t *a_1, const vector3_t *a_2, vector3_t *a_o)
|
||||
{
|
||||
a_o->x = FixedDiv(a_2->x - a_1->x, 2*FRACUNIT);
|
||||
a_o->y = FixedDiv(a_2->y - a_1->y, 2*FRACUNIT);
|
||||
a_o->z = FixedDiv(a_2->z - a_1->z, 2*FRACUNIT);
|
||||
a_o->x = FixedDiv(a_2->x - a_1->x, 2 * FRACUNIT);
|
||||
a_o->y = FixedDiv(a_2->y - a_1->y, 2 * FRACUNIT);
|
||||
a_o->z = FixedDiv(a_2->z - a_1->z, 2 * FRACUNIT);
|
||||
a_o->x = a_1->x + a_o->x;
|
||||
a_o->y = a_1->y + a_o->y;
|
||||
a_o->z = a_1->z + a_o->z;
|
||||
|
@ -355,18 +355,18 @@ vector3_t *FV3_Midpoint(const vector3_t *a_1, const vector3_t *a_2, vector3_t *a
|
|||
|
||||
fixed_t FV3_Distance(const vector3_t *p1, const vector3_t *p2)
|
||||
{
|
||||
fixed_t xs = FixedMul(p2->x-p1->x,p2->x-p1->x);
|
||||
fixed_t ys = FixedMul(p2->y-p1->y,p2->y-p1->y);
|
||||
fixed_t zs = FixedMul(p2->z-p1->z,p2->z-p1->z);
|
||||
return FixedSqrt(xs+ys+zs);
|
||||
fixed_t xs = FixedMul(p2->x - p1->x, p2->x - p1->x);
|
||||
fixed_t ys = FixedMul(p2->y - p1->y, p2->y - p1->y);
|
||||
fixed_t zs = FixedMul(p2->z - p1->z, p2->z - p1->z);
|
||||
return FixedSqrt(xs + ys + zs);
|
||||
}
|
||||
|
||||
fixed_t FV3_Magnitude(const vector3_t *a_normal)
|
||||
{
|
||||
fixed_t xs = FixedMul(a_normal->x,a_normal->x);
|
||||
fixed_t ys = FixedMul(a_normal->y,a_normal->y);
|
||||
fixed_t zs = FixedMul(a_normal->z,a_normal->z);
|
||||
return FixedSqrt(xs+ys+zs);
|
||||
fixed_t xs = FixedMul(a_normal->x, a_normal->x);
|
||||
fixed_t ys = FixedMul(a_normal->y, a_normal->y);
|
||||
fixed_t zs = FixedMul(a_normal->z, a_normal->z);
|
||||
return FixedSqrt(xs + ys + zs);
|
||||
}
|
||||
|
||||
// Also returns the magnitude
|
||||
|
@ -399,7 +399,7 @@ vector3_t *FV3_Negate(vector3_t *a_1)
|
|||
|
||||
boolean FV3_Equal(const vector3_t *a_1, const vector3_t *a_2)
|
||||
{
|
||||
fixed_t Epsilon = FRACUNIT/FRACUNIT;
|
||||
fixed_t Epsilon = FRACUNIT / FRACUNIT;
|
||||
|
||||
if ((abs(a_2->x - a_1->x) > Epsilon) ||
|
||||
(abs(a_2->y - a_1->y) > Epsilon) ||
|
||||
|
@ -458,6 +458,20 @@ vector3_t *FV3_ClosestPointOnLine(const vector3_t *Line, const vector3_t *p, vec
|
|||
return FV3_AddEx(&Line[0], &V, out);
|
||||
}
|
||||
|
||||
//
|
||||
// ClosestPointOnVector
|
||||
//
|
||||
// Similar to ClosestPointOnLine, but uses a vector instead of two points.
|
||||
//
|
||||
void FV3_ClosestPointOnVector(const vector3_t *dir, const vector3_t *p, vector3_t *out)
|
||||
{
|
||||
fixed_t t = FV3_Dot(dir, p);
|
||||
|
||||
// Return the point on the line closest
|
||||
FV3_MulEx(dir, t, out);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// ClosestPointOnTriangle
|
||||
//
|
||||
|
@ -465,7 +479,7 @@ vector3_t *FV3_ClosestPointOnLine(const vector3_t *Line, const vector3_t *p, vec
|
|||
// the closest point on the edge of
|
||||
// the triangle is returned.
|
||||
//
|
||||
void FV3_ClosestPointOnTriangle (const vector3_t *tri, const vector3_t *point, vector3_t *result)
|
||||
void FV3_ClosestPointOnTriangle(const vector3_t *tri, const vector3_t *point, vector3_t *result)
|
||||
{
|
||||
UINT8 i;
|
||||
fixed_t dist, closestdist;
|
||||
|
@ -506,7 +520,7 @@ void FV3_ClosestPointOnTriangle (const vector3_t *tri, const vector3_t *point, v
|
|||
//
|
||||
// Given two points, create a vector between them.
|
||||
//
|
||||
vector3_t *FV3_Point2Vec (const vector3_t *point1, const vector3_t *point2, vector3_t *a_o)
|
||||
vector3_t *FV3_Point2Vec(const vector3_t *point1, const vector3_t *point2, vector3_t *a_o)
|
||||
{
|
||||
a_o->x = point1->x - point2->x;
|
||||
a_o->y = point1->y - point2->y;
|
||||
|
@ -519,7 +533,7 @@ vector3_t *FV3_Point2Vec (const vector3_t *point1, const vector3_t *point2, vect
|
|||
//
|
||||
// Calculates the normal of a polygon.
|
||||
//
|
||||
void FV3_Normal (const vector3_t *a_triangle, vector3_t *a_normal)
|
||||
fixed_t FV3_Normal(const vector3_t *a_triangle, vector3_t *a_normal)
|
||||
{
|
||||
vector3_t a_1;
|
||||
vector3_t a_2;
|
||||
|
@ -529,7 +543,28 @@ void FV3_Normal (const vector3_t *a_triangle, vector3_t *a_normal)
|
|||
|
||||
FV3_Cross(&a_1, &a_2, a_normal);
|
||||
|
||||
FV3_NormalizeEx(a_normal, a_normal);
|
||||
return FV3_NormalizeEx(a_normal, a_normal);
|
||||
}
|
||||
|
||||
//
|
||||
// Strength
|
||||
//
|
||||
// Measures the 'strength' of a vector in a particular direction.
|
||||
//
|
||||
fixed_t FV3_Strength(const vector3_t *a_1, const vector3_t *dir)
|
||||
{
|
||||
vector3_t normal;
|
||||
fixed_t dist = FV3_NormalizeEx(a_1, &normal);
|
||||
fixed_t dot = FV3_Dot(&normal, dir);
|
||||
|
||||
FV3_ClosestPointOnVector(dir, a_1, &normal);
|
||||
|
||||
dist = FV3_Magnitude(&normal);
|
||||
|
||||
if (dot < 0) // Not facing same direction, so negate result.
|
||||
dist = -dist;
|
||||
|
||||
return dist;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -550,11 +585,11 @@ boolean FV3_IntersectedPlane(const vector3_t *a_triangle, const vector3_t *a_lin
|
|||
|
||||
*originDistance = FV3_PlaneDistance(a_normal, &a_triangle[0]);
|
||||
|
||||
distance1 = (FixedMul(a_normal->x, a_line[0].x) + FixedMul(a_normal->y, a_line[0].y)
|
||||
+ FixedMul(a_normal->z, a_line[0].z)) + *originDistance;
|
||||
distance1 = (FixedMul(a_normal->x, a_line[0].x) + FixedMul(a_normal->y, a_line[0].y)
|
||||
+ FixedMul(a_normal->z, a_line[0].z)) + *originDistance;
|
||||
|
||||
distance2 = (FixedMul(a_normal->x, a_line[1].x) + FixedMul(a_normal->y, a_line[1].y)
|
||||
+ FixedMul(a_normal->z, a_line[1].z)) + *originDistance;
|
||||
distance2 = (FixedMul(a_normal->x, a_line[1].x) + FixedMul(a_normal->y, a_line[1].y)
|
||||
+ FixedMul(a_normal->z, a_line[1].z)) + *originDistance;
|
||||
|
||||
// Positive or zero number means no intersection
|
||||
if (FixedMul(distance1, distance2) >= 0)
|
||||
|
@ -575,8 +610,8 @@ boolean FV3_IntersectedPlane(const vector3_t *a_triangle, const vector3_t *a_lin
|
|||
fixed_t FV3_PlaneIntersection(const vector3_t *pOrigin, const vector3_t *pNormal, const vector3_t *rOrigin, const vector3_t *rVector)
|
||||
{
|
||||
fixed_t d = -(FV3_Dot(pNormal, pOrigin));
|
||||
fixed_t number = FV3_Dot(pNormal,rOrigin) + d;
|
||||
fixed_t denom = FV3_Dot(pNormal,rVector);
|
||||
fixed_t number = FV3_Dot(pNormal, rOrigin) + d;
|
||||
fixed_t denom = FV3_Dot(pNormal, rVector);
|
||||
return -FixedDiv(number, denom);
|
||||
}
|
||||
|
||||
|
@ -597,11 +632,11 @@ fixed_t FV3_IntersectRaySphere(const vector3_t *rO, const vector3_t *rV, const v
|
|||
|
||||
c = FV3_Magnitude(&Q);
|
||||
v = FV3_Dot(&Q, rV);
|
||||
d = FixedMul(sR, sR) - (FixedMul(c,c) - FixedMul(v,v));
|
||||
d = FixedMul(sR, sR) - (FixedMul(c, c) - FixedMul(v, v));
|
||||
|
||||
// If there was no intersection, return -1
|
||||
if (d < 0*FRACUNIT)
|
||||
return (-1*FRACUNIT);
|
||||
if (d < 0 * FRACUNIT)
|
||||
return (-1 * FRACUNIT);
|
||||
|
||||
// Return the distance to the [first] intersecting point
|
||||
return (v - FixedSqrt(d));
|
||||
|
@ -629,9 +664,9 @@ vector3_t *FV3_IntersectionPoint(const vector3_t *vNormal, const vector3_t *vLin
|
|||
// Here I just chose a arbitrary point as the point to find that distance. You notice we negate that
|
||||
// distance. We negate the distance because we want to eventually go BACKWARDS from our point to the plane.
|
||||
// By doing this is will basically bring us back to the plane to find our intersection point.
|
||||
Numerator = - (FixedMul(vNormal->x, vLine[0].x) + // Use the plane equation with the normal and the line
|
||||
FixedMul(vNormal->y, vLine[0].y) +
|
||||
FixedMul(vNormal->z, vLine[0].z) + distance);
|
||||
Numerator = -(FixedMul(vNormal->x, vLine[0].x) + // Use the plane equation with the normal and the line
|
||||
FixedMul(vNormal->y, vLine[0].y) +
|
||||
FixedMul(vNormal->z, vLine[0].z) + distance);
|
||||
|
||||
// 3) If we take the dot product between our line vector and the normal of the polygon,
|
||||
// this will give us the cosine of the angle between the 2 (since they are both normalized - length 1).
|
||||
|
@ -643,7 +678,7 @@ vector3_t *FV3_IntersectionPoint(const vector3_t *vNormal, const vector3_t *vLin
|
|||
// on the plane (the normal is perpendicular to the line - (Normal.Vector = 0)).
|
||||
// In this case, we should just return any point on the line.
|
||||
|
||||
if( Denominator == 0*FRACUNIT) // Check so we don't divide by zero
|
||||
if (Denominator == 0 * FRACUNIT) // Check so we don't divide by zero
|
||||
{
|
||||
ReturnVec->x = vLine[0].x;
|
||||
ReturnVec->y = vLine[0].y;
|
||||
|
@ -686,8 +721,8 @@ vector3_t *FV3_IntersectionPoint(const vector3_t *vNormal, const vector3_t *vLin
|
|||
//
|
||||
UINT8 FV3_PointOnLineSide(const vector3_t *point, const vector3_t *line)
|
||||
{
|
||||
fixed_t s1 = FixedMul((point->y - line[0].y),(line[1].x - line[0].x));
|
||||
fixed_t s2 = FixedMul((point->x - line[0].x),(line[1].y - line[0].y));
|
||||
fixed_t s1 = FixedMul((point->y - line[0].y), (line[1].x - line[0].x));
|
||||
fixed_t s2 = FixedMul((point->x - line[0].x), (line[1].y - line[0].y));
|
||||
return (UINT8)(s1 - s2 < 0);
|
||||
}
|
||||
|
||||
|
@ -752,7 +787,7 @@ void FM_CreateObjectMatrix(matrix_t *matrix, fixed_t x, fixed_t y, fixed_t z, fi
|
|||
matrix->m[0] = upcross.x;
|
||||
matrix->m[1] = upcross.y;
|
||||
matrix->m[2] = upcross.z;
|
||||
matrix->m[3] = 0*FRACUNIT;
|
||||
matrix->m[3] = 0 * FRACUNIT;
|
||||
|
||||
matrix->m[4] = upx;
|
||||
matrix->m[5] = upy;
|
||||
|
@ -764,9 +799,9 @@ void FM_CreateObjectMatrix(matrix_t *matrix, fixed_t x, fixed_t y, fixed_t z, fi
|
|||
matrix->m[10] = anglez;
|
||||
matrix->m[11] = 0;
|
||||
|
||||
matrix->m[12] = x - FixedMul(upx,radius);
|
||||
matrix->m[13] = y - FixedMul(upy,radius);
|
||||
matrix->m[14] = z - FixedMul(upz,radius);
|
||||
matrix->m[12] = x - FixedMul(upx, radius);
|
||||
matrix->m[13] = y - FixedMul(upy, radius);
|
||||
matrix->m[14] = z - FixedMul(upz, radius);
|
||||
matrix->m[15] = FRACUNIT;
|
||||
}
|
||||
|
||||
|
@ -778,20 +813,20 @@ void FM_CreateObjectMatrix(matrix_t *matrix, fixed_t x, fixed_t y, fixed_t z, fi
|
|||
void FM_MultMatrixVec3(const matrix_t *matrix, const vector3_t *vec, vector3_t *out)
|
||||
{
|
||||
#define M(row,col) matrix->m[col * 4 + row]
|
||||
out->x = FixedMul(vec->x,M(0, 0))
|
||||
+ FixedMul(vec->y,M(0, 1))
|
||||
+ FixedMul(vec->z,M(0, 2))
|
||||
+ M(0, 3);
|
||||
out->x = FixedMul(vec->x, M(0, 0))
|
||||
+ FixedMul(vec->y, M(0, 1))
|
||||
+ FixedMul(vec->z, M(0, 2))
|
||||
+ M(0, 3);
|
||||
|
||||
out->y = FixedMul(vec->x,M(1, 0))
|
||||
+ FixedMul(vec->y,M(1, 1))
|
||||
+ FixedMul(vec->z,M(1, 2))
|
||||
+ M(1, 3);
|
||||
out->y = FixedMul(vec->x, M(1, 0))
|
||||
+ FixedMul(vec->y, M(1, 1))
|
||||
+ FixedMul(vec->z, M(1, 2))
|
||||
+ M(1, 3);
|
||||
|
||||
out->z = FixedMul(vec->x,M(2, 0))
|
||||
+ FixedMul(vec->y,M(2, 1))
|
||||
+ FixedMul(vec->z,M(2, 2))
|
||||
+ M(2, 3);
|
||||
out->z = FixedMul(vec->x, M(2, 0))
|
||||
+ FixedMul(vec->y, M(2, 1))
|
||||
+ FixedMul(vec->z, M(2, 2))
|
||||
+ M(2, 3);
|
||||
#undef M
|
||||
}
|
||||
|
||||
|
@ -811,7 +846,7 @@ void FM_MultMatrix(matrix_t *dest, const matrix_t *multme)
|
|||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
for (j = 0; j < 4; j++)
|
||||
R(i, j) = FixedMul(D(i, 0),M(0, j)) + FixedMul(D(i, 1),M(1, j)) + FixedMul(D(i, 2),M(2, j)) + FixedMul(D(i, 3),M(3, j));
|
||||
R(i, j) = FixedMul(D(i, 0), M(0, j)) + FixedMul(D(i, 1), M(1, j)) + FixedMul(D(i, 2), M(2, j)) + FixedMul(D(i, 3), M(3, j));
|
||||
}
|
||||
|
||||
M_Memcpy(dest, &result, sizeof(matrix_t));
|
||||
|
@ -869,8 +904,8 @@ void FM_Scale(matrix_t *dest, fixed_t x, fixed_t y, fixed_t z)
|
|||
|
||||
static inline void M_print(INT64 a)
|
||||
{
|
||||
const fixed_t w = (a>>FRACBITS);
|
||||
fixed_t f = a%FRACUNIT;
|
||||
const fixed_t w = (a >> FRACBITS);
|
||||
fixed_t f = a % FRACUNIT;
|
||||
fixed_t d = FRACUNIT;
|
||||
|
||||
if (f == 0)
|
||||
|
@ -878,7 +913,7 @@ static inline void M_print(INT64 a)
|
|||
printf("%d", (fixed_t)w);
|
||||
return;
|
||||
}
|
||||
else while (f != 1 && f/2 == f>>1)
|
||||
else while (f != 1 && f / 2 == f >> 1)
|
||||
{
|
||||
d /= 2;
|
||||
f /= 2;
|
||||
|
@ -892,7 +927,7 @@ static inline void M_print(INT64 a)
|
|||
|
||||
FUNCMATH FUNCINLINE static inline fixed_t FixedMulC(fixed_t a, fixed_t b)
|
||||
{
|
||||
return (fixed_t)((((INT64)a * b) ) / FRACUNIT);
|
||||
return (fixed_t)((((INT64)a * b)) / FRACUNIT);
|
||||
}
|
||||
|
||||
FUNCMATH FUNCINLINE static inline fixed_t FixedDivC2(fixed_t a, fixed_t b)
|
||||
|
@ -902,7 +937,7 @@ FUNCMATH FUNCINLINE static inline fixed_t FixedDivC2(fixed_t a, fixed_t b)
|
|||
if (b == 0)
|
||||
I_Error("FixedDiv: divide by zero");
|
||||
|
||||
ret = (((INT64)a * FRACUNIT) ) / b;
|
||||
ret = (((INT64)a * FRACUNIT)) / b;
|
||||
|
||||
if ((ret > INT32_MAX) || (ret < INT32_MIN))
|
||||
I_Error("FixedDiv: divide by zero");
|
||||
|
@ -911,7 +946,7 @@ FUNCMATH FUNCINLINE static inline fixed_t FixedDivC2(fixed_t a, fixed_t b)
|
|||
|
||||
FUNCMATH FUNCINLINE static inline fixed_t FixedDivC(fixed_t a, fixed_t b)
|
||||
{
|
||||
if ((abs(a) >> (FRACBITS-2)) >= abs(b))
|
||||
if ((abs(a) >> (FRACBITS - 2)) >= abs(b))
|
||||
return (a^b) < 0 ? INT32_MIN : INT32_MAX;
|
||||
|
||||
return FixedDivC2(a, b);
|
||||
|
@ -938,43 +973,43 @@ int main(int argc, char** argv)
|
|||
|
||||
#ifdef MULDIV_TEST
|
||||
for (a = 1; a <= INT32_MAX; a += FRACUNIT)
|
||||
for (b = 0; b <= INT32_MAX; b += FRACUNIT)
|
||||
{
|
||||
c = FixedMul(a, b);
|
||||
d = FixedMulC(a, b);
|
||||
if (c != d)
|
||||
for (b = 0; b <= INT32_MAX; b += FRACUNIT)
|
||||
{
|
||||
printf("(");
|
||||
M_print(a);
|
||||
printf(") * (");
|
||||
M_print(b);
|
||||
printf(") = (");
|
||||
M_print(c);
|
||||
printf(") != (");
|
||||
M_print(d);
|
||||
printf(") \n");
|
||||
n--;
|
||||
printf("%d != %d\n", c, d);
|
||||
c = FixedMul(a, b);
|
||||
d = FixedMulC(a, b);
|
||||
if (c != d)
|
||||
{
|
||||
printf("(");
|
||||
M_print(a);
|
||||
printf(") * (");
|
||||
M_print(b);
|
||||
printf(") = (");
|
||||
M_print(c);
|
||||
printf(") != (");
|
||||
M_print(d);
|
||||
printf(") \n");
|
||||
n--;
|
||||
printf("%d != %d\n", c, d);
|
||||
}
|
||||
c = FixedDiv(a, b);
|
||||
d = FixedDivC(a, b);
|
||||
if (c != d)
|
||||
{
|
||||
printf("(");
|
||||
M_print(a);
|
||||
printf(") / (");
|
||||
M_print(b);
|
||||
printf(") = (");
|
||||
M_print(c);
|
||||
printf(") != (");
|
||||
M_print(d);
|
||||
printf(")\n");
|
||||
n--;
|
||||
printf("%d != %d\n", c, d);
|
||||
}
|
||||
if (n <= 0)
|
||||
exit(-1);
|
||||
}
|
||||
c = FixedDiv(a, b);
|
||||
d = FixedDivC(a, b);
|
||||
if (c != d)
|
||||
{
|
||||
printf("(");
|
||||
M_print(a);
|
||||
printf(") / (");
|
||||
M_print(b);
|
||||
printf(") = (");
|
||||
M_print(c);
|
||||
printf(") != (");
|
||||
M_print(d);
|
||||
printf(")\n");
|
||||
n--;
|
||||
printf("%d != %d\n", c, d);
|
||||
}
|
||||
if (n <= 0)
|
||||
exit(-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SQRT_TEST
|
||||
|
@ -982,7 +1017,7 @@ int main(int argc, char** argv)
|
|||
{
|
||||
c = FixedSqrt(a);
|
||||
d = FixedSqrtC(a);
|
||||
b = abs(c-d);
|
||||
b = abs(c - d);
|
||||
if (b > 1)
|
||||
{
|
||||
printf("sqrt(");
|
||||
|
|
|
@ -394,9 +394,11 @@ boolean FV3_Equal(const vector3_t *a_1, const vector3_t *a_2);
|
|||
fixed_t FV3_Dot(const vector3_t *a_1, const vector3_t *a_2);
|
||||
vector3_t *FV3_Cross(const vector3_t *a_1, const vector3_t *a_2, vector3_t *a_o);
|
||||
vector3_t *FV3_ClosestPointOnLine(const vector3_t *Line, const vector3_t *p, vector3_t *out);
|
||||
void FV3_ClosestPointOnVector(const vector3_t *dir, const vector3_t *p, vector3_t *out);
|
||||
void FV3_ClosestPointOnTriangle(const vector3_t *tri, const vector3_t *point, vector3_t *result);
|
||||
vector3_t *FV3_Point2Vec(const vector3_t *point1, const vector3_t *point2, vector3_t *a_o);
|
||||
void FV3_Normal(const vector3_t *a_triangle, vector3_t *a_normal);
|
||||
fixed_t FV3_Normal(const vector3_t *a_triangle, vector3_t *a_normal);
|
||||
fixed_t FV3_Strength(const vector3_t *a_1, const vector3_t *dir);
|
||||
fixed_t FV3_PlaneDistance(const vector3_t *a_normal, const vector3_t *a_point);
|
||||
boolean FV3_IntersectedPlane(const vector3_t *a_triangle, const vector3_t *a_line, vector3_t *a_normal, fixed_t *originDistance);
|
||||
fixed_t FV3_PlaneIntersection(const vector3_t *pOrigin, const vector3_t *pNormal, const vector3_t *rOrigin, const vector3_t *rVector);
|
||||
|
|
136
src/m_menu.c
136
src/m_menu.c
|
@ -121,41 +121,8 @@ typedef enum
|
|||
const char *quitmsg[NUM_QUITMESSAGES];
|
||||
|
||||
// Stuff for customizing the player select screen Tails 09-22-2003
|
||||
description_t description[32] =
|
||||
{
|
||||
{"\x82Sonic\x80\n\x82Speed:\x80 7\n\x82Weight:\x80 3", "", "sonic"},
|
||||
{"???", "", ""},
|
||||
{"???", "", ""},
|
||||
{"???", "", ""},
|
||||
{"???", "", ""},
|
||||
{"???", "", ""},
|
||||
{"???", "", ""},
|
||||
{"???", "", ""},
|
||||
{"???", "", ""},
|
||||
{"???", "", ""},
|
||||
{"???", "", ""},
|
||||
{"???", "", ""},
|
||||
{"???", "", ""},
|
||||
{"???", "", ""},
|
||||
{"???", "", ""},
|
||||
{"???", "", ""},
|
||||
{"???", "", ""},
|
||||
{"???", "", ""},
|
||||
{"???", "", ""},
|
||||
{"???", "", ""},
|
||||
{"???", "", ""},
|
||||
{"???", "", ""},
|
||||
{"???", "", ""},
|
||||
{"???", "", ""},
|
||||
{"???", "", ""},
|
||||
{"???", "", ""},
|
||||
{"???", "", ""},
|
||||
{"???", "", ""},
|
||||
{"???", "", ""},
|
||||
{"???", "", ""},
|
||||
{"???", "", ""},
|
||||
{"???", "", ""}
|
||||
};
|
||||
description_t description[MAXSKINS];
|
||||
|
||||
//static char *char_notes = NULL;
|
||||
//static fixed_t char_scroll = 0;
|
||||
|
||||
|
@ -413,27 +380,9 @@ static CV_PossibleValue_t skins_cons_t[MAXSKINS+1] = {{1, DEFAULTSKIN}};
|
|||
consvar_t cv_chooseskin = {"chooseskin", DEFAULTSKIN, CV_HIDEN|CV_CALL, skins_cons_t, Nextmap_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
// This gametype list is integral for many different reasons.
|
||||
// When you add gametypes here, don't forget to update them in CV_AddValue!
|
||||
CV_PossibleValue_t gametype_cons_t[] =
|
||||
{
|
||||
{GT_RACE, "Race"}, {GT_MATCH, "Battle"},
|
||||
// When you add gametypes here, don't forget to update them in dehacked.c and doomstat.h!
|
||||
CV_PossibleValue_t gametype_cons_t[NUMGAMETYPES+1];
|
||||
|
||||
/* // SRB2kart
|
||||
{GT_COOP, "Co-op"},
|
||||
|
||||
{GT_COMPETITION, "Competition"},
|
||||
{GT_RACE, "Race"},
|
||||
|
||||
{GT_MATCH, "Match"},
|
||||
{GT_TEAMMATCH, "Team Match"},
|
||||
|
||||
{GT_TAG, "Tag"},
|
||||
{GT_HIDEANDSEEK, "Hide and Seek"},
|
||||
|
||||
{GT_CTF, "CTF"},
|
||||
*/
|
||||
{0, NULL}
|
||||
};
|
||||
consvar_t cv_newgametype = {"newgametype", "Race", CV_HIDEN|CV_CALL, gametype_cons_t, Newgametype_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
static CV_PossibleValue_t serversort_cons_t[] = {
|
||||
|
@ -1219,7 +1168,7 @@ static menuitem_t OP_VideoOptionsMenu[] =
|
|||
{IT_STRING | IT_CVAR, NULL, "Vertical Sync", &cv_vidwait, 90},
|
||||
|
||||
#ifdef HWRENDER
|
||||
{IT_STRING | IT_CVAR, NULL, "3D models", &cv_grmd2, 105},
|
||||
{IT_STRING | IT_CVAR, NULL, "3D models", &cv_grmdls, 105},
|
||||
{IT_SUBMENU|IT_STRING, NULL, "OpenGL Options...", &OP_OpenGLOptionsDef, 115},
|
||||
#endif
|
||||
};
|
||||
|
@ -2333,10 +2282,8 @@ static void M_ChangeCvar(INT32 choice)
|
|||
choice *= (TICRATE/7);
|
||||
else if (cv == &cv_maxsend)
|
||||
choice *= 512;
|
||||
#ifdef NEWPING
|
||||
else if (cv == &cv_maxping)
|
||||
choice *= 50;
|
||||
#endif
|
||||
#endif
|
||||
CV_AddValue(cv,choice);
|
||||
}
|
||||
|
@ -3254,6 +3201,55 @@ void M_Init(void)
|
|||
CV_RegisterVar(&cv_allcaps);
|
||||
}
|
||||
|
||||
void M_InitCharacterTables(void)
|
||||
{
|
||||
UINT8 i;
|
||||
|
||||
// Setup PlayerMenu table
|
||||
for (i = 0; i < MAXSKINS; i++)
|
||||
{
|
||||
PlayerMenu[i].status = (i < 4 ? IT_CALL : IT_DISABLED);
|
||||
PlayerMenu[i].patch = PlayerMenu[i].text = NULL;
|
||||
PlayerMenu[i].itemaction = M_ChoosePlayer;
|
||||
PlayerMenu[i].alphaKey = 0;
|
||||
}
|
||||
|
||||
// Setup description table
|
||||
for (i = 0; i < MAXSKINS; i++)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
strcpy(description[i].notes, "\x82Sonic\x80 is the fastest of the three, but also the hardest to control. Beginners beware, but experts will find Sonic very powerful.\n\n\x82""Ability:\x80 Speed Thok\nDouble jump to zoom forward with a huge burst of speed.\n\n\x82Tip:\x80 Simply letting go of forward does not slow down in SRB2. To slow down, hold the opposite direction.");
|
||||
strcpy(description[i].picname, "");
|
||||
strcpy(description[i].skinname, "sonic");
|
||||
}
|
||||
else if (i == 1)
|
||||
{
|
||||
strcpy(description[i].notes, "\x82Tails\x80 is the most mobile of the three, but has the slowest speed. Because of his mobility, he's well-\nsuited to beginners.\n\n\x82""Ability:\x80 Fly\nDouble jump to start flying for a limited time. Repetitively hit the jump button to ascend.\n\n\x82Tip:\x80 To quickly descend while flying, hit the spin button.");
|
||||
strcpy(description[i].picname, "");
|
||||
strcpy(description[i].skinname, "tails");
|
||||
}
|
||||
else if (i == 2)
|
||||
{
|
||||
strcpy(description[i].notes, "\x82Knuckles\x80 is well-\nrounded and can destroy breakable walls simply by touching them, but he can't jump as high as the other two.\n\n\x82""Ability:\x80 Glide & Climb\nDouble jump to glide in the air as long as jump is held. Glide into a wall to climb it.\n\n\x82Tip:\x80 Press spin while climbing to jump off the wall; press jump instead to jump off\nand face away from\nthe wall.");
|
||||
strcpy(description[i].picname, "");
|
||||
strcpy(description[i].skinname, "knuckles");
|
||||
}
|
||||
else if (i == 3)
|
||||
{
|
||||
strcpy(description[i].notes, "\x82Sonic & Tails\x80 team up to take on Dr. Eggman!\nControl Sonic while Tails desperately struggles to keep up.\n\nPlayer 2 can control Tails directly by setting the controls in the options menu.\nTails's directional controls are relative to Player 1's camera.\n\nTails can pick up Sonic while flying and carry him around.");
|
||||
strcpy(description[i].picname, "CHRS&T");
|
||||
strcpy(description[i].skinname, "sonic&tails");
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(description[i].notes, "???");
|
||||
strcpy(description[i].picname, "");
|
||||
strcpy(description[i].skinname, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
// SPECIAL MENU OPTION DRAW ROUTINES GO HERE
|
||||
// ==========================================================================
|
||||
|
@ -7283,7 +7279,7 @@ static void M_DrawRoomMenu(void)
|
|||
|
||||
static void M_DrawConnectMenu(void)
|
||||
{
|
||||
UINT16 i, j;
|
||||
UINT16 i;
|
||||
const char *gt = "Unknown";
|
||||
const char *spd = "";
|
||||
INT32 numPages = (serverlistcount+(SERVERS_PER_PAGE-1))/SERVERS_PER_PAGE;
|
||||
|
@ -7330,11 +7326,8 @@ static void M_DrawConnectMenu(void)
|
|||
va("Ping: %u", (UINT32)LONG(serverlist[slindex].info.time)));
|
||||
|
||||
gt = "Unknown";
|
||||
for (j = 0; gametype_cons_t[j].strvalue; j++)
|
||||
{
|
||||
if (gametype_cons_t[j].value == serverlist[slindex].info.gametype)
|
||||
gt = gametype_cons_t[j].strvalue;
|
||||
}
|
||||
if (serverlist[slindex].info.gametype < NUMGAMETYPES)
|
||||
gt = Gametype_Names[serverlist[slindex].info.gametype];
|
||||
|
||||
V_DrawSmallString(currentMenu->x+46,S_LINEY(i)+8, globalflags,
|
||||
va("Players: %02d/%02d", serverlist[slindex].info.numberofplayer, serverlist[slindex].info.maxplayer));
|
||||
|
@ -7460,7 +7453,10 @@ static void M_ConnectMenu(INT32 choice)
|
|||
|
||||
// first page of servers
|
||||
serverlistpage = 0;
|
||||
M_SetupNextMenu(&MP_ConnectDef);
|
||||
if (ms_RoomId < 0)
|
||||
M_RoomMenu(0); // Select a room instead of staring at an empty list
|
||||
else
|
||||
M_SetupNextMenu(&MP_ConnectDef);
|
||||
itemOn = 0;
|
||||
M_Refresh(0);
|
||||
}
|
||||
|
@ -7533,7 +7529,15 @@ static void M_ChooseRoom(INT32 choice)
|
|||
}
|
||||
|
||||
serverlistpage = 0;
|
||||
M_SetupNextMenu(currentMenu->prevMenu);
|
||||
/*
|
||||
We were on the Multiplayer menu? That means that we must have been trying to
|
||||
view the server browser, but we hadn't selected a room yet. So we need to go
|
||||
to the browser next, not back there.
|
||||
*/
|
||||
if (currentMenu->prevMenu == &MP_MainDef)
|
||||
M_SetupNextMenu(&MP_ConnectDef);
|
||||
else
|
||||
M_SetupNextMenu(currentMenu->prevMenu);
|
||||
if (currentMenu == &MP_ConnectDef)
|
||||
M_Refresh(0);
|
||||
}
|
||||
|
|
|
@ -38,6 +38,9 @@ void M_Drawer(void);
|
|||
// Called by D_SRB2Main, loads the config file.
|
||||
void M_Init(void);
|
||||
|
||||
// Called by D_SRB2Main also, sets up the playermenu and description tables.
|
||||
void M_InitCharacterTables(void);
|
||||
|
||||
// Called by intro code to force menu up upon a keypress,
|
||||
// does nothing if menu is already up.
|
||||
void M_StartControlPanel(void);
|
||||
|
@ -210,7 +213,7 @@ typedef struct
|
|||
UINT8 netgame;
|
||||
} saveinfo_t;
|
||||
|
||||
extern description_t description[32];
|
||||
extern description_t description[MAXSKINS];
|
||||
|
||||
extern consvar_t cv_showfocuslost;
|
||||
extern consvar_t cv_newgametype, cv_nextmap, cv_chooseskin, cv_serversort;
|
||||
|
|
50
src/mserv.c
50
src/mserv.c
|
@ -661,11 +661,19 @@ FUNCMATH static const char *int2str(INT32 n)
|
|||
#ifndef NONET
|
||||
static INT32 ConnectionFailed(void)
|
||||
{
|
||||
time(&MSLastPing);
|
||||
con_state = MSCS_FAILED;
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Connection to Master Server failed\n"));
|
||||
CloseConnection();
|
||||
return MS_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
static INT32 ConnectionFailedwerrno(int no)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Master Server socket error: %s\n"),
|
||||
strerror(no));
|
||||
return ConnectionFailed();
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Tries to register the local game server on the master server.
|
||||
|
@ -682,44 +690,43 @@ static INT32 AddToMasterServer(boolean firstadd)
|
|||
msg_server_t *info = (msg_server_t *)msg.buffer;
|
||||
INT32 room = -1;
|
||||
fd_set tset;
|
||||
time_t timestamp = time(NULL);
|
||||
UINT32 signature, tmp;
|
||||
const char *insname;
|
||||
|
||||
if (socket_fd == (SOCKET_TYPE)ERRSOCKET)/* Woah, our socket was closed! */
|
||||
{
|
||||
if (MS_Connect(GetMasterServerIP(), GetMasterServerPort(), 0))
|
||||
return ConnectionFailedwerrno(errno);
|
||||
}
|
||||
|
||||
M_Memcpy(&tset, &wset, sizeof (tset));
|
||||
res = select(255, NULL, &tset, NULL, &select_timeout);
|
||||
if (res != ERRSOCKET && !res)
|
||||
if (res == ERRSOCKET)
|
||||
return ConnectionFailedwerrno(errno);
|
||||
if (res == 0)/* nothing selected */
|
||||
{
|
||||
if (retry++ > 30) // an about 30 second timeout
|
||||
/*
|
||||
Timeout next call because SendPingToMasterServer
|
||||
(our calling function) already calls this once
|
||||
every two minutes.
|
||||
*/
|
||||
if (retry++ == 1)
|
||||
{
|
||||
retry = 0;
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Master Server timed out\n"));
|
||||
MSLastPing = timestamp;
|
||||
return ConnectionFailed();
|
||||
}
|
||||
return MS_CONNECT_ERROR;
|
||||
}
|
||||
retry = 0;
|
||||
if (res == ERRSOCKET)
|
||||
{
|
||||
if (MS_Connect(GetMasterServerIP(), GetMasterServerPort(), 0))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Master Server socket error #%u: %s\n"), errno, strerror(errno));
|
||||
MSLastPing = timestamp;
|
||||
return ConnectionFailed();
|
||||
}
|
||||
}
|
||||
|
||||
// so, the socket is writable, but what does that mean, that the connection is
|
||||
// ok, or bad... let see that!
|
||||
j = (socklen_t)sizeof (i);
|
||||
getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, (char *)&i, &j);
|
||||
if (getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, (char *)&i, &j) == ERRSOCKET)
|
||||
return ConnectionFailedwerrno(errno);
|
||||
if (i) // it was bad
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Master Server socket error #%u: %s\n"), errno, strerror(errno));
|
||||
MSLastPing = timestamp;
|
||||
return ConnectionFailed();
|
||||
}
|
||||
return ConnectionFailedwerrno(i);
|
||||
|
||||
#ifdef PARANOIA
|
||||
if (ms_RoomId <= 0)
|
||||
|
@ -752,15 +759,12 @@ static INT32 AddToMasterServer(boolean firstadd)
|
|||
msg.length = (UINT32)sizeof (msg_server_t);
|
||||
msg.room = 0;
|
||||
if (MS_Write(&msg) < 0)
|
||||
{
|
||||
MSLastPing = timestamp;
|
||||
return ConnectionFailed();
|
||||
}
|
||||
|
||||
if(con_state != MSCS_REGISTERED)
|
||||
CONS_Printf(M_GetText("Master Server update successful.\n"));
|
||||
|
||||
MSLastPing = timestamp;
|
||||
time(&MSLastPing);
|
||||
con_state = MSCS_REGISTERED;
|
||||
CloseConnection();
|
||||
#endif
|
||||
|
|
|
@ -1837,6 +1837,9 @@ void P_CheckTimeLimit(void)
|
|||
}
|
||||
}
|
||||
|
||||
if (playercount > MAXPLAYERS)
|
||||
playercount = MAXPLAYERS;
|
||||
|
||||
//Sort 'em.
|
||||
for (i = 1; i < playercount; i++)
|
||||
{
|
||||
|
|
|
@ -193,6 +193,12 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
|
|||
mapheaderinfo[num]->musname[6] = 0;
|
||||
DEH_WriteUndoline("MUSICTRACK", va("%d", mapheaderinfo[num]->mustrack), UNDO_NONE);
|
||||
mapheaderinfo[num]->mustrack = 0;
|
||||
DEH_WriteUndoline("MUSICPOS", va("%d", mapheaderinfo[num]->muspos), UNDO_NONE);
|
||||
mapheaderinfo[num]->muspos = 0;
|
||||
DEH_WriteUndoline("MUSICINTERFADEOUT", va("%d", mapheaderinfo[num]->musinterfadeout), UNDO_NONE);
|
||||
mapheaderinfo[num]->musinterfadeout = 0;
|
||||
DEH_WriteUndoline("MUSICINTER", mapheaderinfo[num]->musintername, UNDO_NONE);
|
||||
mapheaderinfo[num]->musintername[0] = '\0';
|
||||
DEH_WriteUndoline("FORCECHARACTER", va("%d", mapheaderinfo[num]->forcecharacter), UNDO_NONE);
|
||||
mapheaderinfo[num]->forcecharacter[0] = '\0';
|
||||
DEH_WriteUndoline("WEATHER", va("%d", mapheaderinfo[num]->weather), UNDO_NONE);
|
||||
|
@ -1544,19 +1550,33 @@ static void P_LoadRawSideDefs2(void *data)
|
|||
{
|
||||
M_Memcpy(process,msd->bottomtexture,8);
|
||||
process[8] = '\0';
|
||||
sd->bottomtexture = get_number(process)-1;
|
||||
sd->bottomtexture = get_number(process);
|
||||
}
|
||||
M_Memcpy(process,msd->toptexture,8);
|
||||
process[8] = '\0';
|
||||
sd->text = Z_Malloc(7, PU_LEVEL, NULL);
|
||||
|
||||
// If they type in O_ or D_ and their music name, just shrug,
|
||||
// then copy the rest instead.
|
||||
if ((process[0] == 'O' || process[0] == 'D') && process[7])
|
||||
M_Memcpy(sd->text, process+2, 6);
|
||||
else // Assume it's a proper music name.
|
||||
M_Memcpy(sd->text, process, 6);
|
||||
sd->text[6] = 0;
|
||||
if (!(msd->midtexture[0] == '-' && msd->midtexture[1] == '\0') || msd->midtexture[1] != '\0')
|
||||
{
|
||||
M_Memcpy(process,msd->midtexture,8);
|
||||
process[8] = '\0';
|
||||
sd->midtexture = get_number(process);
|
||||
}
|
||||
|
||||
// always process if back sidedef, because we need that - symbol
|
||||
sd->text = Z_Malloc(7, PU_LEVEL, NULL);
|
||||
if (i == 1 || msd->toptexture[0] != '-' || msd->toptexture[1] != '\0')
|
||||
{
|
||||
M_Memcpy(process,msd->toptexture,8);
|
||||
process[8] = '\0';
|
||||
|
||||
// If they type in O_ or D_ and their music name, just shrug,
|
||||
// then copy the rest instead.
|
||||
if ((process[0] == 'O' || process[0] == 'D') && process[7])
|
||||
M_Memcpy(sd->text, process+2, 6);
|
||||
else // Assume it's a proper music name.
|
||||
M_Memcpy(sd->text, process, 6);
|
||||
sd->text[6] = 0;
|
||||
}
|
||||
else
|
||||
sd->text[0] = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -264,7 +264,7 @@ void P_SpawnSlope_Line(int linenum)
|
|||
|
||||
if(!line->frontsector || !line->backsector)
|
||||
{
|
||||
CONS_Printf("P_SpawnSlope_Line used on a line without two sides.\n");
|
||||
CONS_Debug(DBG_SETUP, "P_SpawnSlope_Line used on a line without two sides. (line number %i)\n", linenum);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
71
src/p_spec.c
71
src/p_spec.c
|
@ -2440,18 +2440,71 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
|
|||
// console player only unless NOCLIMB is set
|
||||
if ((line->flags & ML_NOCLIMB) || (mo && mo->player && P_IsLocalPlayer(mo->player)))
|
||||
{
|
||||
UINT16 tracknum = (UINT16)sides[line->sidenum[0]].bottomtexture;
|
||||
boolean musicsame = (!sides[line->sidenum[0]].text[0] || !strnicmp(sides[line->sidenum[0]].text, S_MusicName(), 7));
|
||||
UINT16 tracknum = (UINT16)max(sides[line->sidenum[0]].bottomtexture, 0);
|
||||
INT32 position = (INT32)max(sides[line->sidenum[0]].midtexture, 0);
|
||||
UINT32 prefadems = (UINT32)max(sides[line->sidenum[0]].textureoffset >> FRACBITS, 0);
|
||||
UINT32 postfadems = (UINT32)max(sides[line->sidenum[0]].rowoffset >> FRACBITS, 0);
|
||||
UINT8 fadetarget = (UINT8)max((line->sidenum[1] != 0xffff) ? sides[line->sidenum[1]].textureoffset >> FRACBITS : 0, 0);
|
||||
INT16 fadesource = (INT16)max((line->sidenum[1] != 0xffff) ? sides[line->sidenum[1]].rowoffset >> FRACBITS : -1, -1);
|
||||
|
||||
strncpy(mapmusname, sides[line->sidenum[0]].text, 7);
|
||||
mapmusname[6] = 0;
|
||||
// Seek offset from current song position
|
||||
if (line->flags & ML_EFFECT1)
|
||||
{
|
||||
// adjust for loop point if subtracting
|
||||
if (position < 0 && S_GetMusicLength() &&
|
||||
S_GetMusicPosition() > S_GetMusicLoopPoint() &&
|
||||
S_GetMusicPosition() + position < S_GetMusicLoopPoint())
|
||||
position = max(S_GetMusicLength() - (S_GetMusicLoopPoint() - (S_GetMusicPosition() + position)), 0);
|
||||
else
|
||||
position = max(S_GetMusicPosition() + position, 0);
|
||||
}
|
||||
|
||||
mapmusflags = tracknum & MUSIC_TRACKMASK;
|
||||
if (!(line->flags & ML_BLOCKMONSTERS))
|
||||
mapmusflags |= MUSIC_RELOADRESET;
|
||||
// Fade current music to target volume (if music won't be changed)
|
||||
if ((line->flags & ML_EFFECT2) && fadetarget && musicsame)
|
||||
{
|
||||
// 0 fadesource means fade from current volume.
|
||||
// meaning that we can't specify volume 0 as the source volume -- this starts at 1.
|
||||
if (!fadesource)
|
||||
fadesource = -1;
|
||||
|
||||
S_ChangeMusic(mapmusname, mapmusflags, !(line->flags & ML_EFFECT4));
|
||||
if (!(line->flags & ML_EFFECT3))
|
||||
S_ShowMusicCredit();
|
||||
if (!postfadems)
|
||||
S_SetInternalMusicVolume(fadetarget);
|
||||
else
|
||||
S_FadeMusicFromVolume(fadetarget, fadesource, postfadems);
|
||||
|
||||
if (!(line->flags & ML_EFFECT3))
|
||||
S_ShowMusicCredit();
|
||||
|
||||
if (position)
|
||||
S_SetMusicPosition(position);
|
||||
}
|
||||
// Change the music and apply position/fade operations
|
||||
else
|
||||
{
|
||||
strncpy(mapmusname, sides[line->sidenum[0]].text, 7);
|
||||
mapmusname[6] = 0;
|
||||
|
||||
mapmusflags = tracknum & MUSIC_TRACKMASK;
|
||||
if (!(line->flags & ML_BLOCKMONSTERS))
|
||||
mapmusflags |= MUSIC_RELOADRESET;
|
||||
if (line->flags & ML_BOUNCY)
|
||||
mapmusflags |= MUSIC_FORCERESET;
|
||||
|
||||
mapmusposition = position;
|
||||
|
||||
S_ChangeMusicEx(mapmusname, mapmusflags, !(line->flags & ML_EFFECT4), position,
|
||||
!(line->flags & ML_EFFECT2) ? prefadems : 0,
|
||||
!(line->flags & ML_EFFECT2) ? postfadems : 0);
|
||||
|
||||
if ((line->flags & ML_EFFECT2) && fadetarget)
|
||||
{
|
||||
if (!postfadems)
|
||||
S_SetInternalMusicVolume(fadetarget);
|
||||
else
|
||||
S_FadeMusicFromVolume(fadetarget, fadesource, postfadems);
|
||||
}
|
||||
}
|
||||
|
||||
// Except, you can use the ML_BLOCKMONSTERS flag to change this behavior.
|
||||
// if (mapmusflags & MUSIC_RELOADRESET) then it will reset the music in G_PlayerReborn.
|
||||
|
|
|
@ -1283,7 +1283,7 @@ void P_RestoreMusic(player_t *player)
|
|||
if (G_RaceGametype() && player->laps >= (UINT8)(cv_numlaps.value - 1))
|
||||
S_SpeedMusic(1.2f);
|
||||
#endif
|
||||
S_ChangeMusic(mapmusname, mapmusflags, true);
|
||||
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8879,8 +8879,11 @@ void P_PlayerThink(player_t *player)
|
|||
|
||||
if (player->bot)
|
||||
{
|
||||
if (player->playerstate == PST_LIVE && B_CheckRespawn(player))
|
||||
player->playerstate = PST_REBORN;
|
||||
if (player->playerstate == PST_LIVE || player->playerstate == PST_DEAD)
|
||||
{
|
||||
if (B_CheckRespawn(player))
|
||||
player->playerstate = PST_REBORN;
|
||||
}
|
||||
if (player->playerstate == PST_REBORN)
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1561,7 +1561,6 @@ void R_RegisterEngineStuff(void)
|
|||
CV_RegisterVar(&cv_grgammared);
|
||||
CV_RegisterVar(&cv_grfovchange);
|
||||
CV_RegisterVar(&cv_grfog);
|
||||
CV_RegisterVar(&cv_voodoocompatibility);
|
||||
CV_RegisterVar(&cv_grfogcolor);
|
||||
CV_RegisterVar(&cv_grsoftwarefog);
|
||||
#ifdef ALAM_LIGHTING
|
||||
|
@ -1570,7 +1569,8 @@ void R_RegisterEngineStuff(void)
|
|||
CV_RegisterVar(&cv_grcoronas);
|
||||
CV_RegisterVar(&cv_grcoronasize);
|
||||
#endif
|
||||
CV_RegisterVar(&cv_grmd2);
|
||||
CV_RegisterVar(&cv_grmdls);
|
||||
CV_RegisterVar(&cv_grspritebillboarding);
|
||||
#endif
|
||||
|
||||
#ifdef HWRENDER
|
||||
|
|
|
@ -862,8 +862,8 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
|||
if (leftheight > pfloorleft && rightheight > pfloorright && i+1 < dc_numlights)
|
||||
{
|
||||
lightlist_t *nextlight = &frontsector->lightlist[i+1];
|
||||
if (nextlight->slope ? P_GetZAt(nextlight->slope, ds->leftpos.x, ds->leftpos.y) : nextlight->height > pfloorleft
|
||||
&& nextlight->slope ? P_GetZAt(nextlight->slope, ds->rightpos.x, ds->rightpos.y) : nextlight->height > pfloorright)
|
||||
if ((nextlight->slope ? P_GetZAt(nextlight->slope, ds->leftpos.x, ds->leftpos.y) : nextlight->height) > pfloorleft
|
||||
&& (nextlight->slope ? P_GetZAt(nextlight->slope, ds->rightpos.x, ds->rightpos.y) : nextlight->height) > pfloorright)
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,8 @@ int snprintf(char *str, size_t n, const char *fmt, ...);
|
|||
//int vsnprintf(char *str, size_t n, const char *fmt, va_list ap);
|
||||
#endif
|
||||
|
||||
CV_PossibleValue_t Forceskin_cons_t[MAXSKINS+2];
|
||||
|
||||
static void R_InitSkins(void);
|
||||
|
||||
#define MINZ (FRACUNIT*4)
|
||||
|
@ -1796,7 +1798,7 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel, UINT8 viewnumber)
|
|||
}
|
||||
}
|
||||
|
||||
// Someone seriously wants infinite draw distance for precipitation?
|
||||
// no, no infinite draw distance for precipitation. this option at zero is supposed to turn it off
|
||||
if ((limit_dist = (fixed_t)cv_drawdist_precip.value << FRACBITS))
|
||||
{
|
||||
for (precipthing = sec->preciplist; precipthing; precipthing = precipthing->snext)
|
||||
|
@ -1812,13 +1814,6 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel, UINT8 viewnumber)
|
|||
R_ProjectPrecipitationSprite(precipthing);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Draw everything in sector, no checks
|
||||
for (precipthing = sec->preciplist; precipthing; precipthing = precipthing->snext)
|
||||
if (!(precipthing->precipflags & PCF_INVISIBLE))
|
||||
R_ProjectPrecipitationSprite(precipthing);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -2593,6 +2588,10 @@ void R_InitSkins(void)
|
|||
skin->spritedef.spriteframes = sprites[SPR_PLAY].spriteframes;
|
||||
ST_LoadFaceGraphics(skin->facerank, skin->facewant, skin->facemmap, 0);
|
||||
|
||||
// Set values for Sonic skin
|
||||
Forceskin_cons_t[1].value = 0;
|
||||
Forceskin_cons_t[1].strvalue = skin->name;
|
||||
|
||||
//MD2 for sonic doesn't want to load in Linux.
|
||||
#ifdef HWRENDER
|
||||
if (rendermode == render_opengl)
|
||||
|
@ -3043,6 +3042,10 @@ next_token:
|
|||
skin_cons_t[numskins].strvalue = skin->name;
|
||||
#endif
|
||||
|
||||
// Update the forceskin possiblevalues
|
||||
Forceskin_cons_t[numskins+1].value = numskins;
|
||||
Forceskin_cons_t[numskins+1].strvalue = skins[numskins].name;
|
||||
|
||||
// add face graphics
|
||||
ST_LoadFaceGraphics(skin->facerank, skin->facewant, skin->facemmap, numskins);
|
||||
|
||||
|
|
|
@ -97,6 +97,7 @@ typedef struct
|
|||
sfxenum_t soundsid[NUMSKINSOUNDS]; // sound # in S_sfx table
|
||||
} skin_t;
|
||||
|
||||
extern CV_PossibleValue_t Forceskin_cons_t[];
|
||||
//
|
||||
// for followers.
|
||||
//
|
||||
|
|
177
src/s_sound.c
177
src/s_sound.c
|
@ -38,6 +38,10 @@ extern INT32 msg_id;
|
|||
#include "p_local.h" // camera info
|
||||
#include "m_misc.h" // for tunes command
|
||||
|
||||
#if defined(HAVE_BLUA) && defined(HAVE_LUA_MUSICPLUS)
|
||||
#include "lua_hook.h" // MusicChange hook
|
||||
#endif
|
||||
|
||||
#ifdef HW3SOUND
|
||||
// 3D Sound Interface
|
||||
#include "hardware/hw3sound.h"
|
||||
|
@ -1550,6 +1554,12 @@ static void *music_data;
|
|||
static UINT16 music_flags;
|
||||
static boolean music_looping;
|
||||
|
||||
static char queue_name[7];
|
||||
static UINT16 queue_flags;
|
||||
static boolean queue_looping;
|
||||
static UINT32 queue_position;
|
||||
static UINT32 queue_fadeinms;
|
||||
|
||||
/// ------------------------
|
||||
/// Music Definitions
|
||||
/// ------------------------
|
||||
|
@ -1788,6 +1798,11 @@ musictype_t S_MusicType(void)
|
|||
return I_SongType();
|
||||
}
|
||||
|
||||
const char *S_MusicName(void)
|
||||
{
|
||||
return music_name;
|
||||
}
|
||||
|
||||
boolean S_MusicInfo(char *mname, UINT16 *mflags, boolean *looping)
|
||||
{
|
||||
if (!I_SongPlaying())
|
||||
|
@ -1818,6 +1833,35 @@ boolean S_SpeedMusic(float speed)
|
|||
return I_SetSongSpeed(speed);
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
/// Music Seeking
|
||||
/// ------------------------
|
||||
|
||||
UINT32 S_GetMusicLength(void)
|
||||
{
|
||||
return I_GetSongLength();
|
||||
}
|
||||
|
||||
boolean S_SetMusicLoopPoint(UINT32 looppoint)
|
||||
{
|
||||
return I_SetSongLoopPoint(looppoint);
|
||||
}
|
||||
|
||||
UINT32 S_GetMusicLoopPoint(void)
|
||||
{
|
||||
return I_GetSongLoopPoint();
|
||||
}
|
||||
|
||||
boolean S_SetMusicPosition(UINT32 position)
|
||||
{
|
||||
return I_SetSongPosition(position);
|
||||
}
|
||||
|
||||
UINT32 S_GetMusicPosition(void)
|
||||
{
|
||||
return I_GetSongPosition();
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
/// Music Playback
|
||||
/// ------------------------
|
||||
|
@ -1894,12 +1938,13 @@ static void S_UnloadMusic(void)
|
|||
music_looping = false;
|
||||
}
|
||||
|
||||
static boolean S_PlayMusic(boolean looping)
|
||||
static boolean S_PlayMusic(boolean looping, UINT32 fadeinms)
|
||||
{
|
||||
if (S_MusicDisabled())
|
||||
return false;
|
||||
|
||||
if (!I_PlaySong(looping))
|
||||
if ((!fadeinms && !I_PlaySong(looping)) ||
|
||||
(fadeinms && !I_FadeInPlaySong(fadeinms, looping)))
|
||||
{
|
||||
S_UnloadMusic();
|
||||
return false;
|
||||
|
@ -1913,8 +1958,30 @@ static boolean S_PlayMusic(boolean looping)
|
|||
return true;
|
||||
}
|
||||
|
||||
void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping)
|
||||
static void S_QueueMusic(const char *mmusic, UINT16 mflags, boolean looping, UINT32 position, UINT32 fadeinms)
|
||||
{
|
||||
strncpy(queue_name, mmusic, 7);
|
||||
queue_flags = mflags;
|
||||
queue_looping = looping;
|
||||
queue_position = position;
|
||||
queue_fadeinms = fadeinms;
|
||||
}
|
||||
|
||||
static void S_ClearQueue(void)
|
||||
{
|
||||
queue_name[0] = queue_flags = queue_looping = queue_position = queue_fadeinms = 0;
|
||||
}
|
||||
|
||||
static void S_ChangeMusicToQueue(void)
|
||||
{
|
||||
S_ChangeMusicEx(queue_name, queue_flags, queue_looping, queue_position, 0, queue_fadeinms);
|
||||
S_ClearQueue();
|
||||
}
|
||||
|
||||
void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 position, UINT32 prefadems, UINT32 fadeinms)
|
||||
{
|
||||
char newmusic[7];
|
||||
|
||||
#if defined (DC) || defined (_WIN32_WCE) || defined (PSP) || defined(GP2X)
|
||||
S_ClearSfx();
|
||||
#endif
|
||||
|
@ -1923,33 +1990,66 @@ void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping)
|
|||
|| titledemo) // SRB2Kart: Demos don't interrupt title screen music
|
||||
return;
|
||||
|
||||
// No Music (empty string)
|
||||
if (mmusic[0] == 0)
|
||||
{
|
||||
S_StopMusic();
|
||||
strncpy(newmusic, mmusic, 7);
|
||||
#if defined(HAVE_BLUA) && defined(HAVE_LUA_MUSICPLUS)
|
||||
if(LUAh_MusicChange(music_name, newmusic, &mflags, &looping, &position, &prefadems, &fadeinms))
|
||||
return;
|
||||
#endif
|
||||
newmusic[6] = 0;
|
||||
|
||||
// No Music (empty string)
|
||||
if (newmusic[0] == 0)
|
||||
{
|
||||
if (prefadems)
|
||||
I_FadeSong(0, prefadems, &S_StopMusic);
|
||||
else
|
||||
S_StopMusic();
|
||||
return;
|
||||
}
|
||||
|
||||
if (strnicmp(music_name, mmusic, 6))
|
||||
if (prefadems && S_MusicPlaying()) // queue music change for after fade // allow even if the music is the same
|
||||
{
|
||||
S_StopMusic(); // shutdown old music
|
||||
CONS_Debug(DBG_DETAILED, "Now fading out song %s\n", music_name);
|
||||
S_QueueMusic(newmusic, mflags, looping, position, fadeinms);
|
||||
I_FadeSong(0, prefadems, S_ChangeMusicToQueue);
|
||||
return;
|
||||
}
|
||||
else if (strnicmp(music_name, newmusic, 6) || (mflags & MUSIC_FORCERESET))
|
||||
{
|
||||
CONS_Debug(DBG_DETAILED, "Now playing song %s\n", newmusic);
|
||||
|
||||
if (!S_LoadMusic(mmusic))
|
||||
S_StopMusic();
|
||||
|
||||
if (!S_LoadMusic(newmusic))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "Music %.6s could not be loaded!\n", mmusic);
|
||||
CONS_Alert(CONS_ERROR, "Music %.6s could not be loaded!\n", newmusic);
|
||||
return;
|
||||
}
|
||||
|
||||
music_flags = mflags;
|
||||
music_looping = looping;
|
||||
|
||||
if (!S_PlayMusic(looping))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "Music %.6s could not be played!\n", mmusic);
|
||||
if (!S_PlayMusic(looping, fadeinms))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "Music %.6s could not be played!\n", newmusic);
|
||||
return;
|
||||
}
|
||||
|
||||
if (position)
|
||||
I_SetSongPosition(position);
|
||||
|
||||
I_SetSongTrack(mflags & MUSIC_TRACKMASK);
|
||||
}
|
||||
else if (fadeinms) // let fades happen with same music
|
||||
{
|
||||
I_SetSongPosition(position);
|
||||
I_FadeSong(100, fadeinms, NULL);
|
||||
}
|
||||
else // reset volume to 100 with same music
|
||||
{
|
||||
I_StopFadingSong();
|
||||
I_FadeSong(100, 500, NULL);
|
||||
}
|
||||
I_SetSongTrack(mflags & MUSIC_TRACKMASK);
|
||||
}
|
||||
|
||||
void S_StopMusic(void)
|
||||
|
@ -2055,6 +2155,32 @@ void S_SetMusicVolume(INT32 digvolume, INT32 seqvolume)
|
|||
}
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
/// Music Fading
|
||||
/// ------------------------
|
||||
|
||||
void S_SetInternalMusicVolume(INT32 volume)
|
||||
{
|
||||
I_SetInternalMusicVolume(min(max(volume, 0), 100));
|
||||
}
|
||||
|
||||
void S_StopFadingMusic(void)
|
||||
{
|
||||
I_StopFadingSong();
|
||||
}
|
||||
|
||||
boolean S_FadeMusicFromVolume(UINT8 target_volume, INT16 source_volume, UINT32 ms)
|
||||
{
|
||||
if (source_volume < 0)
|
||||
return I_FadeSong(target_volume, ms, NULL);
|
||||
else
|
||||
return I_FadeSongFromVolume(target_volume, source_volume, ms, NULL);
|
||||
}
|
||||
|
||||
boolean S_FadeOutStopMusic(UINT32 ms)
|
||||
{
|
||||
return I_FadeSong(0, ms, &S_StopMusic);
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
/// Init & Others
|
||||
|
@ -2072,26 +2198,28 @@ void S_Start(void)
|
|||
strncpy(mapmusname, mapheaderinfo[gamemap-1]->musname, 7);
|
||||
mapmusname[6] = 0;
|
||||
mapmusflags = (mapheaderinfo[gamemap-1]->mustrack & MUSIC_TRACKMASK);
|
||||
mapmusposition = mapheaderinfo[gamemap-1]->muspos;
|
||||
}
|
||||
|
||||
//if (cv_resetmusic.value) // Starting ambience should always be restarted
|
||||
S_StopMusic();
|
||||
|
||||
if (leveltime < (starttime + (TICRATE/2))) // SRB2Kart
|
||||
S_ChangeMusic((encoremode ? "estart" : "kstart"), 0, false);
|
||||
S_ChangeMusicEx((encoremode ? "estart" : "kstart"), 0, false, mapmusposition, 0, 0);
|
||||
else
|
||||
S_ChangeMusic(mapmusname, mapmusflags, true);
|
||||
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
|
||||
}
|
||||
|
||||
static void Command_Tunes_f(void)
|
||||
{
|
||||
const char *tunearg;
|
||||
UINT16 tunenum, track = 0;
|
||||
UINT32 position = 0;
|
||||
const size_t argc = COM_Argc();
|
||||
|
||||
if (argc < 2) //tunes slot ...
|
||||
{
|
||||
CONS_Printf("tunes <name/num> [track] [speed] / <-show> / <-default> / <-none>:\n");
|
||||
CONS_Printf("tunes <name/num> [track] [speed] [position] / <-show> / <-default> / <-none>:\n");
|
||||
CONS_Printf(M_GetText("Play an arbitrary music lump. If a map number is used, 'MAP##M' is played.\n"));
|
||||
CONS_Printf(M_GetText("If the format supports multiple songs, you can specify which one to play.\n\n"));
|
||||
CONS_Printf(M_GetText("* With \"-show\", shows the currently playing tune and track.\n"));
|
||||
|
@ -2138,10 +2266,15 @@ static void Command_Tunes_f(void)
|
|||
snprintf(mapmusname, 7, "%sM", G_BuildMapName(tunenum));
|
||||
else
|
||||
strncpy(mapmusname, tunearg, 7);
|
||||
|
||||
if (argc > 4)
|
||||
position = (UINT32)atoi(COM_Argv(4));
|
||||
|
||||
mapmusname[6] = 0;
|
||||
mapmusflags = (track & MUSIC_TRACKMASK);
|
||||
mapmusposition = position;
|
||||
|
||||
S_ChangeMusic(mapmusname, mapmusflags, true);
|
||||
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
|
||||
|
||||
if (argc > 3)
|
||||
{
|
||||
|
@ -2182,7 +2315,7 @@ static void Command_RestartAudio_f(void)
|
|||
|
||||
void GameSounds_OnChange(void)
|
||||
{
|
||||
if (M_CheckParm("-nosound"))
|
||||
if (M_CheckParm("-nosound") || M_CheckParm("-noaudio"))
|
||||
return;
|
||||
|
||||
if (sound_disabled)
|
||||
|
@ -2196,7 +2329,7 @@ void GameSounds_OnChange(void)
|
|||
|
||||
void GameDigiMusic_OnChange(void)
|
||||
{
|
||||
if (M_CheckParm("-nomusic"))
|
||||
if (M_CheckParm("-nomusic") || M_CheckParm("-noaudio"))
|
||||
return;
|
||||
else if (M_CheckParm("-nodigmusic"))
|
||||
return;
|
||||
|
@ -2239,7 +2372,7 @@ void GameDigiMusic_OnChange(void)
|
|||
#ifndef NO_MIDI
|
||||
void GameMIDIMusic_OnChange(void)
|
||||
{
|
||||
if (M_CheckParm("-nomusic"))
|
||||
if (M_CheckParm("-nomusic") || M_CheckParm("-noaudio"))
|
||||
return;
|
||||
else if (M_CheckParm("-nomidimusic"))
|
||||
return;
|
||||
|
|
|
@ -117,14 +117,14 @@ boolean S_MusicDisabled(void);
|
|||
boolean S_MusicPlaying(void);
|
||||
boolean S_MusicPaused(void);
|
||||
musictype_t S_MusicType(void);
|
||||
const char *S_MusicName(void);
|
||||
boolean S_MusicInfo(char *mname, UINT16 *mflags, boolean *looping);
|
||||
boolean S_MusicExists(const char *mname, boolean checkMIDI, boolean checkDigi);
|
||||
#define S_DigExists(a) S_MusicExists(a, false, true)
|
||||
#define S_MIDIExists(a) S_MusicExists(a, true, false)
|
||||
|
||||
|
||||
//
|
||||
// Music Properties
|
||||
// Music Effects
|
||||
//
|
||||
|
||||
// Set Speed of Music
|
||||
|
@ -154,15 +154,35 @@ void S_InitMusicDefs(void);
|
|||
void S_ShowMusicCredit(void);
|
||||
|
||||
//
|
||||
// Music Routines
|
||||
// Music Seeking
|
||||
//
|
||||
|
||||
// Get Length of Music
|
||||
UINT32 S_GetMusicLength(void);
|
||||
|
||||
// Set LoopPoint of Music
|
||||
boolean S_SetMusicLoopPoint(UINT32 looppoint);
|
||||
|
||||
// Get LoopPoint of Music
|
||||
UINT32 S_GetMusicLoopPoint(void);
|
||||
|
||||
// Set Position of Music
|
||||
boolean S_SetMusicPosition(UINT32 position);
|
||||
|
||||
// Get Position of Music
|
||||
UINT32 S_GetMusicPosition(void);
|
||||
|
||||
//
|
||||
// Music Playback
|
||||
//
|
||||
|
||||
// Start music track, arbitrary, given its name, and set whether looping
|
||||
// note: music flags 12 bits for tracknum (gme, other formats with more than one track)
|
||||
// 13-15 aren't used yet
|
||||
// and the last bit we ignore (internal game flag for resetting music on reload)
|
||||
#define S_ChangeMusicInternal(a,b) S_ChangeMusic(a,0,b)
|
||||
void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping);
|
||||
void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 position, UINT32 prefadems, UINT32 fadeinms);
|
||||
#define S_ChangeMusicInternal(a,b) S_ChangeMusicEx(a,0,b,0,0,0)
|
||||
#define S_ChangeMusic(a,b,c) S_ChangeMusicEx(a,b,c,0,0,0)
|
||||
|
||||
// Stops the music.
|
||||
void S_StopMusic(void);
|
||||
|
@ -175,6 +195,17 @@ void S_ResumeAudio(void);
|
|||
void S_EnableSound(void);
|
||||
void S_DisableSound(void);
|
||||
|
||||
//
|
||||
// Music Fading
|
||||
//
|
||||
|
||||
void S_SetInternalMusicVolume(INT32 volume);
|
||||
void S_StopFadingMusic(void);
|
||||
boolean S_FadeMusicFromVolume(UINT8 target_volume, INT16 source_volume, UINT32 ms);
|
||||
#define S_FadeMusic(a, b) S_FadeMusicFromVolume(a, -1, b)
|
||||
#define S_FadeInChangeMusic(a,b,c,d) S_ChangeMusicEx(a,b,c,0,0,d)
|
||||
boolean S_FadeOutStopMusic(UINT32 ms);
|
||||
|
||||
//
|
||||
// Updates music & sounds
|
||||
//
|
||||
|
|
|
@ -227,6 +227,10 @@
|
|||
<ClInclude Include="..\hardware\hw_light.h" />
|
||||
<ClInclude Include="..\hardware\hw_main.h" />
|
||||
<ClInclude Include="..\hardware\hw_md2.h" />
|
||||
<ClInclude Include="..\hardware\hw_md2load.h" />
|
||||
<ClInclude Include="..\hardware\hw_md3load.h" />
|
||||
<ClInclude Include="..\hardware\hw_model.h" />
|
||||
<ClInclude Include="..\hardware\u_list.h" />
|
||||
<ClInclude Include="..\hu_stuff.h" />
|
||||
<ClInclude Include="..\info.h" />
|
||||
<ClInclude Include="..\i_addrinfo.h" />
|
||||
|
@ -366,8 +370,12 @@
|
|||
<ClCompile Include="..\hardware\hw_light.c" />
|
||||
<ClCompile Include="..\hardware\hw_main.c" />
|
||||
<ClCompile Include="..\hardware\hw_md2.c" />
|
||||
<ClCompile Include="..\hardware\hw_md2load.c" />
|
||||
<ClCompile Include="..\hardware\hw_md3load.c" />
|
||||
<ClCompile Include="..\hardware\hw_model.c" />
|
||||
<ClCompile Include="..\hardware\hw_trick.c" />
|
||||
<ClCompile Include="..\hardware\r_opengl\r_opengl.c" />
|
||||
<ClCompile Include="..\hardware\u_list.c" />
|
||||
<ClCompile Include="..\hu_stuff.c" />
|
||||
<ClCompile Include="..\info.c" />
|
||||
<ClCompile Include="..\i_addrinfo.c">
|
||||
|
|
|
@ -246,6 +246,18 @@
|
|||
<ClInclude Include="..\hardware\hw_md2.h">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\hardware\hw_md2load.h">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\hardware\hw_md3load.h">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\hardware\hw_model.h">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\hardware\u_list.h">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\byteptr.h">
|
||||
<Filter>I_Interface</Filter>
|
||||
</ClInclude>
|
||||
|
@ -627,9 +639,21 @@
|
|||
<ClCompile Include="..\hardware\hw_md2.c">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\hardware\hw_md2load.c">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\hardware\hw_md3load.c">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\hardware\hw_model.c">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\hardware\hw_trick.c">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\hardware\u_list.c">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\filesrch.c">
|
||||
<Filter>I_Interface</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
@ -87,13 +87,11 @@ void *hwSym(const char *funcName,void *handle)
|
|||
GETFUNC(ClearMipMapCache);
|
||||
GETFUNC(SetSpecialState);
|
||||
GETFUNC(GetTextureUsed);
|
||||
GETFUNC(DrawMD2);
|
||||
GETFUNC(DrawMD2i);
|
||||
GETFUNC(DrawModel);
|
||||
GETFUNC(CreateModelVBOs);
|
||||
GETFUNC(SetTransform);
|
||||
GETFUNC(GetRenderVersion);
|
||||
#ifdef SHUFFLE
|
||||
GETFUNC(PostImgRedraw);
|
||||
#endif //SHUFFLE
|
||||
GETFUNC(FlushScreenTextures);
|
||||
GETFUNC(StartScreenWipe);
|
||||
GETFUNC(EndScreenWipe);
|
||||
|
|
|
@ -359,6 +359,14 @@ static INT32 Impl_SDL_Scancode_To_Keycode(SDL_Scancode code)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void SDLdoGrabMouse(void)
|
||||
{
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
SDL_SetWindowGrab(window, SDL_TRUE);
|
||||
if (SDL_SetRelativeMouseMode(SDL_TRUE) == 0) // already warps mouse if successful
|
||||
wrapmouseok = SDL_TRUE; // TODO: is wrapmouseok or HalfWarpMouse needed anymore?
|
||||
}
|
||||
|
||||
static void SDLdoUngrabMouse(void)
|
||||
{
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
|
@ -629,6 +637,9 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt)
|
|||
//else firsttimeonmouse = SDL_FALSE;
|
||||
|
||||
capslock = !!( SDL_GetModState() & KMOD_CAPS );// in case CL changes
|
||||
|
||||
if (USE_MOUSEINPUT)
|
||||
SDLdoGrabMouse();
|
||||
}
|
||||
else if (!mousefocus && !kbfocus)
|
||||
{
|
||||
|
@ -708,9 +719,7 @@ static void Impl_HandleMouseMotionEvent(SDL_MouseMotionEvent evt)
|
|||
// -- Monster Iestyn
|
||||
if (SDL_GetMouseFocus() == window && SDL_GetKeyboardFocus() == window)
|
||||
{
|
||||
SDL_SetWindowGrab(window, SDL_TRUE);
|
||||
if (SDL_SetRelativeMouseMode(SDL_TRUE) == 0) // already warps mouse if successful
|
||||
wrapmouseok = SDL_TRUE; // TODO: is wrapmouseok or HalfWarpMouse needed anymore?
|
||||
SDLdoGrabMouse();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1277,7 +1286,7 @@ void I_StartupMouse(void)
|
|||
else
|
||||
firsttimeonmouse = SDL_FALSE;
|
||||
if (cv_usemouse.value)
|
||||
return;
|
||||
SDLdoGrabMouse();
|
||||
else
|
||||
SDLdoUngrabMouse();
|
||||
}
|
||||
|
@ -1845,13 +1854,11 @@ void I_StartupGraphics(void)
|
|||
HWD.pfnSetSpecialState = hwSym("SetSpecialState",NULL);
|
||||
HWD.pfnSetPalette = hwSym("SetPalette",NULL);
|
||||
HWD.pfnGetTextureUsed = hwSym("GetTextureUsed",NULL);
|
||||
HWD.pfnDrawMD2 = hwSym("DrawMD2",NULL);
|
||||
HWD.pfnDrawMD2i = hwSym("DrawMD2i",NULL);
|
||||
HWD.pfnDrawModel = hwSym("DrawModel",NULL);
|
||||
HWD.pfnCreateModelVBOs = hwSym("CreateModelVBOs",NULL);
|
||||
HWD.pfnSetTransform = hwSym("SetTransform",NULL);
|
||||
HWD.pfnGetRenderVersion = hwSym("GetRenderVersion",NULL);
|
||||
#ifdef SHUFFLE
|
||||
HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL);
|
||||
#endif
|
||||
HWD.pfnFlushScreenTextures=hwSym("FlushScreenTextures",NULL);
|
||||
HWD.pfnStartScreenWipe = hwSym("StartScreenWipe",NULL);
|
||||
HWD.pfnEndScreenWipe = hwSym("EndScreenWipe",NULL);
|
||||
|
|
|
@ -75,15 +75,41 @@
|
|||
UINT8 sound_started = false;
|
||||
|
||||
static Mix_Music *music;
|
||||
static UINT8 music_volume, sfx_volume;
|
||||
static UINT8 music_volume, sfx_volume, internal_volume;
|
||||
static float loop_point;
|
||||
static float song_length; // length in seconds
|
||||
static boolean songpaused;
|
||||
static UINT32 music_bytes;
|
||||
static boolean is_looping;
|
||||
|
||||
// fading
|
||||
static boolean is_fading;
|
||||
static UINT8 fading_source;
|
||||
static UINT8 fading_target;
|
||||
static UINT32 fading_timer;
|
||||
static UINT32 fading_duration;
|
||||
static INT32 fading_id;
|
||||
static void (*fading_callback)(void);
|
||||
|
||||
#ifdef HAVE_LIBGME
|
||||
static Music_Emu *gme;
|
||||
static INT32 current_track;
|
||||
#endif
|
||||
|
||||
static void var_cleanup(void)
|
||||
{
|
||||
loop_point = song_length =\
|
||||
music_bytes = fading_source = fading_target =\
|
||||
fading_timer = fading_duration = 0;
|
||||
|
||||
songpaused = is_looping =\
|
||||
is_fading = false;
|
||||
|
||||
fading_callback = NULL;
|
||||
|
||||
internal_volume = 100;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
/// Audio System
|
||||
/// ------------------------
|
||||
|
@ -111,6 +137,8 @@ void I_StartupSound(void)
|
|||
return;
|
||||
}
|
||||
|
||||
var_cleanup();
|
||||
|
||||
music = NULL;
|
||||
music_volume = sfx_volume = 0;
|
||||
|
||||
|
@ -336,6 +364,7 @@ void *I_GetSfx(sfxinfo_t *sfx)
|
|||
len = (info->play_length * 441 / 10) << 2;
|
||||
mem = malloc(len);
|
||||
gme_play(emu, len >> 1, mem);
|
||||
gme_free_info(info);
|
||||
gme_delete(emu);
|
||||
|
||||
return Mix_QuickLoad_RAW((Uint8 *)mem, len);
|
||||
|
@ -408,6 +437,7 @@ void *I_GetSfx(sfxinfo_t *sfx)
|
|||
len = (info->play_length * 441 / 10) << 2;
|
||||
mem = malloc(len);
|
||||
gme_play(emu, len >> 1, mem);
|
||||
gme_free_info(info);
|
||||
gme_delete(emu);
|
||||
|
||||
return Mix_QuickLoad_RAW((Uint8 *)mem, len);
|
||||
|
@ -482,14 +512,102 @@ void I_SetSfxVolume(UINT8 volume)
|
|||
sfx_volume = volume;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
/// Music Utilities
|
||||
/// ------------------------
|
||||
|
||||
static UINT32 get_real_volume(UINT8 volume)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (I_SongType() == MU_MID)
|
||||
// HACK: Until we stop using native MIDI,
|
||||
// disable volume changes
|
||||
return ((UINT32)31*128/31); // volume = 31
|
||||
else
|
||||
#endif
|
||||
// convert volume to mixer's 128 scale
|
||||
// then apply internal_volume as a percentage
|
||||
return ((UINT32)volume*128/31) * (UINT32)internal_volume / 100;
|
||||
}
|
||||
|
||||
static UINT32 get_adjusted_position(UINT32 position)
|
||||
{
|
||||
// all in milliseconds
|
||||
UINT32 length = I_GetSongLength();
|
||||
UINT32 looppoint = I_GetSongLoopPoint();
|
||||
if (length)
|
||||
return position >= length ? (position % (length-looppoint)) : position;
|
||||
else
|
||||
return position;
|
||||
}
|
||||
|
||||
static void do_fading_callback(void)
|
||||
{
|
||||
if (fading_callback)
|
||||
(*fading_callback)();
|
||||
fading_callback = NULL;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
/// Music Hooks
|
||||
/// ------------------------
|
||||
|
||||
static void count_music_bytes(int chan, void *stream, int len, void *udata)
|
||||
{
|
||||
(void)chan;
|
||||
(void)stream;
|
||||
(void)udata;
|
||||
|
||||
if (!music || I_SongType() == MU_GME || I_SongType() == MU_MOD || I_SongType() == MU_MID)
|
||||
return;
|
||||
music_bytes += len;
|
||||
}
|
||||
|
||||
static void music_loop(void)
|
||||
{
|
||||
Mix_PlayMusic(music, 0);
|
||||
Mix_SetMusicPosition(loop_point);
|
||||
if (is_looping)
|
||||
{
|
||||
Mix_PlayMusic(music, 0);
|
||||
Mix_SetMusicPosition(loop_point);
|
||||
music_bytes = loop_point*44100.0L*4; //assume 44.1khz, 4-byte length (see I_GetSongPosition)
|
||||
}
|
||||
else
|
||||
I_StopSong();
|
||||
}
|
||||
|
||||
static UINT32 music_fade(UINT32 interval, void *param)
|
||||
{
|
||||
(void)param;
|
||||
|
||||
if (!is_fading ||
|
||||
internal_volume == fading_target ||
|
||||
fading_duration == 0)
|
||||
{
|
||||
I_StopFadingSong();
|
||||
do_fading_callback();
|
||||
return 0;
|
||||
}
|
||||
else if (songpaused) // don't decrement timer
|
||||
return interval;
|
||||
else if ((fading_timer -= 10) <= 0)
|
||||
{
|
||||
internal_volume = fading_target;
|
||||
Mix_VolumeMusic(get_real_volume(music_volume));
|
||||
I_StopFadingSong();
|
||||
do_fading_callback();
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
UINT8 delta = abs(fading_target - fading_source);
|
||||
fixed_t factor = FixedDiv(fading_duration - fading_timer, fading_duration);
|
||||
if (fading_target < fading_source)
|
||||
internal_volume = max(min(internal_volume, fading_source - FixedMul(delta, factor)), fading_target);
|
||||
else if (fading_target > fading_source)
|
||||
internal_volume = min(max(internal_volume, fading_source + FixedMul(delta, factor)), fading_target);
|
||||
Mix_VolumeMusic(get_real_volume(music_volume));
|
||||
return interval;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBGME
|
||||
|
@ -509,7 +627,7 @@ static void mix_gme(void *udata, Uint8 *stream, int len)
|
|||
|
||||
// apply volume to stream
|
||||
for (i = 0, p = (short *)stream; i < len/2; i++, p++)
|
||||
*p = ((INT32)*p) * music_volume*2 / 42;
|
||||
*p = ((INT32)*p) * (music_volume*internal_volume/100)*2 / 42;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -586,6 +704,194 @@ boolean I_SetSongSpeed(float speed)
|
|||
return false;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
/// MUSIC SEEKING
|
||||
/// ------------------------
|
||||
|
||||
UINT32 I_GetSongLength(void)
|
||||
{
|
||||
INT32 length;
|
||||
|
||||
#ifdef HAVE_LIBGME
|
||||
if (gme)
|
||||
{
|
||||
gme_info_t *info;
|
||||
gme_err_t gme_e = gme_track_info(gme, &info, current_track);
|
||||
|
||||
if (gme_e != NULL)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e);
|
||||
length = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// reconstruct info->play_length, from GME source
|
||||
// we only want intro + 1 loop, not 2
|
||||
length = info->length;
|
||||
if (length <= 0)
|
||||
{
|
||||
length = info->intro_length + info->loop_length; // intro + 1 loop
|
||||
if (length <= 0)
|
||||
length = 150 * 1000; // 2.5 minutes
|
||||
}
|
||||
}
|
||||
|
||||
gme_free_info(info);
|
||||
return max(length, 0);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (!music || I_SongType() == MU_MOD || I_SongType() == MU_MID)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
// VERY IMPORTANT to set your LENGTHMS= in your song files, folks!
|
||||
// SDL mixer can't read music length itself.
|
||||
length = (UINT32)(song_length*1000);
|
||||
if (!length)
|
||||
CONS_Debug(DBG_DETAILED, "Getting music length: music is missing LENGTHMS= tag. Needed for seeking.\n");
|
||||
return length;
|
||||
}
|
||||
}
|
||||
|
||||
boolean I_SetSongLoopPoint(UINT32 looppoint)
|
||||
{
|
||||
if (!music || I_SongType() == MU_GME || I_SongType() == MU_MOD || I_SongType() == MU_MID || !is_looping)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
UINT32 length = I_GetSongLength();
|
||||
|
||||
if (length > 0)
|
||||
looppoint %= length;
|
||||
|
||||
loop_point = max((float)(looppoint / 1000.0L), 0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
UINT32 I_GetSongLoopPoint(void)
|
||||
{
|
||||
#ifdef HAVE_LIBGME
|
||||
if (gme)
|
||||
{
|
||||
INT32 looppoint;
|
||||
gme_info_t *info;
|
||||
gme_err_t gme_e = gme_track_info(gme, &info, current_track);
|
||||
|
||||
if (gme_e != NULL)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e);
|
||||
looppoint = 0;
|
||||
}
|
||||
else
|
||||
looppoint = info->intro_length > 0 ? info->intro_length : 0;
|
||||
|
||||
gme_free_info(info);
|
||||
return max(looppoint, 0);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (!music || I_SongType() == MU_MOD || I_SongType() == MU_MID)
|
||||
return 0;
|
||||
else
|
||||
return (UINT32)(loop_point * 1000);
|
||||
}
|
||||
|
||||
boolean I_SetSongPosition(UINT32 position)
|
||||
{
|
||||
UINT32 length;
|
||||
#ifdef HAVE_LIBGME
|
||||
if (gme)
|
||||
{
|
||||
// this is unstable, so fail silently
|
||||
return true;
|
||||
// this isn't required technically, but GME thread-locks for a second
|
||||
// if you seek too high from the counter
|
||||
// length = I_GetSongLength();
|
||||
// if (length)
|
||||
// position = get_adjusted_position(position);
|
||||
|
||||
// SDL_LockAudio();
|
||||
// gme_err_t gme_e = gme_seek(gme, position);
|
||||
// SDL_UnlockAudio();
|
||||
|
||||
// if (gme_e != NULL)
|
||||
// {
|
||||
// CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e);
|
||||
// return false;
|
||||
// }
|
||||
// else
|
||||
// return true;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (!music || I_SongType() == MU_MID)
|
||||
return false;
|
||||
else if (I_SongType() == MU_MOD)
|
||||
return Mix_SetMusicPosition(position); // Goes by channels
|
||||
else
|
||||
{
|
||||
// Because SDL mixer can't identify song length, if you have
|
||||
// a position input greater than the real length, then
|
||||
// music_bytes becomes inaccurate.
|
||||
|
||||
length = I_GetSongLength(); // get it in MS
|
||||
if (length)
|
||||
position = get_adjusted_position(position);
|
||||
|
||||
Mix_RewindMusic(); // needed for mp3
|
||||
if(Mix_SetMusicPosition((float)(position/1000.0L)) == 0)
|
||||
music_bytes = position/1000.0L*44100.0L*4; //assume 44.1khz, 4-byte length (see I_GetSongPosition)
|
||||
else
|
||||
// NOTE: This block fires on incorrect song format,
|
||||
// NOT if position input is greater than song length.
|
||||
music_bytes = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
UINT32 I_GetSongPosition(void)
|
||||
{
|
||||
#ifdef HAVE_LIBGME
|
||||
if (gme)
|
||||
{
|
||||
INT32 position = gme_tell(gme);
|
||||
|
||||
gme_info_t *info;
|
||||
gme_err_t gme_e = gme_track_info(gme, &info, current_track);
|
||||
|
||||
if (gme_e != NULL)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e);
|
||||
return position;
|
||||
}
|
||||
else
|
||||
{
|
||||
// adjust position, since GME's counter keeps going past loop
|
||||
if (info->length > 0)
|
||||
position %= info->length;
|
||||
else if (info->intro_length + info->loop_length > 0)
|
||||
position = position >= (info->intro_length + info->loop_length) ? (position % info->loop_length) : position;
|
||||
else
|
||||
position %= 150 * 1000; // 2.5 minutes
|
||||
}
|
||||
|
||||
gme_free_info(info);
|
||||
return max(position, 0);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (!music || I_SongType() == MU_MID)
|
||||
return 0;
|
||||
else
|
||||
return music_bytes/44100.0L*1000.0L/4; //assume 44.1khz
|
||||
// 4 = byte length for 16-bit samples (AUDIO_S16SYS), stereo (2-channel)
|
||||
// This is hardcoded in I_StartupSound. Other formats for factor:
|
||||
// 8M: 1 | 8S: 2 | 16M: 2 | 16S: 4
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
/// Music Playback
|
||||
/// ------------------------
|
||||
|
@ -598,6 +904,7 @@ boolean I_LoadSong(char *data, size_t len)
|
|||
const size_t key1len = strlen(key1);
|
||||
const size_t key2len = strlen(key2);
|
||||
const size_t key3len = strlen(key3);
|
||||
|
||||
char *p = data;
|
||||
SDL_RWops *rw;
|
||||
|
||||
|
@ -608,6 +915,9 @@ boolean I_LoadSong(char *data, size_t len)
|
|||
)
|
||||
I_UnloadSong();
|
||||
|
||||
// always do this whether or not a music already exists
|
||||
var_cleanup();
|
||||
|
||||
#ifdef HAVE_LIBGME
|
||||
if ((UINT8)data[0] == 0x1F
|
||||
&& (UINT8)data[1] == 0x8B)
|
||||
|
@ -717,30 +1027,35 @@ boolean I_LoadSong(char *data, size_t len)
|
|||
|
||||
// Find the OGG loop point.
|
||||
loop_point = 0.0f;
|
||||
song_length = 0.0f;
|
||||
|
||||
while ((UINT32)(p - data) < len)
|
||||
{
|
||||
if (strncmp(p++, key1, key1len))
|
||||
continue;
|
||||
p += key1len-1; // skip OOP (the L was skipped in strncmp)
|
||||
if (!strncmp(p, key2, key2len)) // is it LOOPPOINT=?
|
||||
if (fpclassify(loop_point) == FP_ZERO && !strncmp(p, key1, key1len))
|
||||
{
|
||||
p += key2len; // skip POINT=
|
||||
loop_point = (float)((44.1L+atoi(p)) / 44100.0L); // LOOPPOINT works by sample count.
|
||||
// because SDL_Mixer is USELESS and can't even tell us
|
||||
// something simple like the frequency of the streaming music,
|
||||
// we are unfortunately forced to assume that ALL MUSIC is 44100hz.
|
||||
// This means a lot of tracks that are only 22050hz for a reasonable downloadable file size will loop VERY badly.
|
||||
p += key1len; // skip LOOP
|
||||
if (!strncmp(p, key2, key2len)) // is it LOOPPOINT=?
|
||||
{
|
||||
p += key2len; // skip POINT=
|
||||
loop_point = (float)((44.1L+atoi(p)) / 44100.0L); // LOOPPOINT works by sample count.
|
||||
// because SDL_Mixer is USELESS and can't even tell us
|
||||
// something simple like the frequency of the streaming music,
|
||||
// we are unfortunately forced to assume that ALL MUSIC is 44100hz.
|
||||
// This means a lot of tracks that are only 22050hz for a reasonable downloadable file size will loop VERY badly.
|
||||
}
|
||||
else if (!strncmp(p, key3, key3len)) // is it LOOPMS=?
|
||||
{
|
||||
p += key3len; // skip MS=
|
||||
loop_point = (float)(atoi(p) / 1000.0L); // LOOPMS works by real time, as miliseconds.
|
||||
// Everything that uses LOOPMS will work perfectly with SDL_Mixer.
|
||||
}
|
||||
}
|
||||
else if (!strncmp(p, key3, key3len)) // is it LOOPMS=?
|
||||
{
|
||||
p += key3len; // skip MS=
|
||||
loop_point = (float)(atoi(p) / 1000.0L); // LOOPMS works by real time, as miliseconds.
|
||||
// Everything that uses LOOPMS will work perfectly with SDL_Mixer.
|
||||
}
|
||||
// Neither?! Continue searching.
|
||||
}
|
||||
|
||||
if (fpclassify(loop_point) != FP_ZERO) // Got what we needed
|
||||
break;
|
||||
else // continue searching
|
||||
p++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -764,7 +1079,6 @@ void I_UnloadSong(void)
|
|||
|
||||
boolean I_PlaySong(boolean looping)
|
||||
{
|
||||
boolean lpz = fpclassify(loop_point) == FP_ZERO;
|
||||
#ifdef HAVE_LIBGME
|
||||
if (gme)
|
||||
{
|
||||
|
@ -778,21 +1092,37 @@ boolean I_PlaySong(boolean looping)
|
|||
if (!music)
|
||||
return false;
|
||||
|
||||
if (fpclassify(song_length) == FP_ZERO && (I_SongType() == MU_OGG || I_SongType() == MU_MP3 || I_SongType() == MU_FLAC))
|
||||
CONS_Debug(DBG_DETAILED, "This song is missing a LENGTHMS= tag! Required to make seeking work properly.\n");
|
||||
|
||||
if (Mix_PlayMusic(music, looping && lpz ? -1 : 0) == -1)
|
||||
if (I_SongType() != MU_MOD && I_SongType() != MU_MID && Mix_PlayMusic(music, 0) == -1)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "Mix_PlayMusic: %s\n", Mix_GetError());
|
||||
return false;
|
||||
}
|
||||
else if ((I_SongType() == MU_MOD || I_SongType() == MU_MID) && Mix_PlayMusic(music, looping ? -1 : 0) == -1) // if MOD, loop forever
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "Mix_PlayMusic: %s\n", Mix_GetError());
|
||||
return false;
|
||||
}
|
||||
Mix_VolumeMusic((UINT32)music_volume*128/31);
|
||||
|
||||
if (!lpz)
|
||||
Mix_HookMusicFinished(music_loop);
|
||||
is_looping = looping;
|
||||
|
||||
I_SetMusicVolume(music_volume);
|
||||
|
||||
if (I_SongType() != MU_MOD && I_SongType() != MU_MID)
|
||||
Mix_HookMusicFinished(music_loop); // don't bother counting if MOD
|
||||
|
||||
if(I_SongType() != MU_MOD && I_SongType() != MU_MID && !Mix_RegisterEffect(MIX_CHANNEL_POST, count_music_bytes, NULL, NULL))
|
||||
CONS_Alert(CONS_WARNING, "Error registering SDL music position counter: %s\n", Mix_GetError());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void I_StopSong(void)
|
||||
{
|
||||
I_StopFadingSong();
|
||||
|
||||
#ifdef HAVE_LIBGME
|
||||
if (gme)
|
||||
{
|
||||
|
@ -802,19 +1132,40 @@ void I_StopSong(void)
|
|||
#endif
|
||||
if (music)
|
||||
{
|
||||
Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes);
|
||||
Mix_HookMusicFinished(NULL);
|
||||
Mix_HaltMusic();
|
||||
}
|
||||
|
||||
var_cleanup();
|
||||
}
|
||||
|
||||
void I_PauseSong(void)
|
||||
{
|
||||
if(I_SongType() == MU_MID) // really, SDL Mixer? why can't you pause MIDI???
|
||||
return;
|
||||
|
||||
if(I_SongType() != MU_GME && I_SongType() != MU_MOD && I_SongType() != MU_MID)
|
||||
Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes);
|
||||
|
||||
Mix_PauseMusic();
|
||||
songpaused = true;
|
||||
}
|
||||
|
||||
void I_ResumeSong(void)
|
||||
{
|
||||
if (I_SongType() == MU_MID)
|
||||
return;
|
||||
|
||||
if (I_SongType() != MU_GME && I_SongType() != MU_MOD && I_SongType() != MU_MID)
|
||||
{
|
||||
while(Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes) != 0) { }
|
||||
// HACK: fixes issue of multiple effect callbacks being registered
|
||||
|
||||
if(music && I_SongType() != MU_MOD && I_SongType() != MU_MID && !Mix_RegisterEffect(MIX_CHANNEL_POST, count_music_bytes, NULL, NULL))
|
||||
CONS_Alert(CONS_WARNING, "Error registering SDL music position counter: %s\n", Mix_GetError());
|
||||
}
|
||||
|
||||
Mix_ResumeMusic();
|
||||
songpaused = false;
|
||||
}
|
||||
|
@ -833,7 +1184,7 @@ void I_SetMusicVolume(UINT8 volume)
|
|||
#endif
|
||||
music_volume = volume;
|
||||
|
||||
Mix_VolumeMusic((UINT32)music_volume*128/31);
|
||||
Mix_VolumeMusic(get_real_volume(music_volume));
|
||||
}
|
||||
|
||||
boolean I_SetSongTrack(int track)
|
||||
|
@ -862,9 +1213,100 @@ boolean I_SetSongTrack(int track)
|
|||
SDL_UnlockAudio();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (I_SongType() == MU_MOD)
|
||||
return !Mix_SetMusicPosition(track);
|
||||
(void)track;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
/// MUSIC FADING
|
||||
/// ------------------------
|
||||
|
||||
void I_SetInternalMusicVolume(UINT8 volume)
|
||||
{
|
||||
internal_volume = volume;
|
||||
if (!I_SongPlaying())
|
||||
return;
|
||||
Mix_VolumeMusic(get_real_volume(music_volume));
|
||||
}
|
||||
|
||||
void I_StopFadingSong(void)
|
||||
{
|
||||
if (fading_id)
|
||||
SDL_RemoveTimer(fading_id);
|
||||
is_fading = false;
|
||||
fading_source = fading_target = fading_timer = fading_duration = fading_id = 0;
|
||||
}
|
||||
|
||||
boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void))
|
||||
{
|
||||
INT16 volume_delta;
|
||||
|
||||
source_volume = min(source_volume, 100);
|
||||
volume_delta = (INT16)(target_volume - source_volume);
|
||||
|
||||
I_StopFadingSong();
|
||||
|
||||
if (!ms && volume_delta)
|
||||
{
|
||||
I_SetInternalMusicVolume(target_volume);
|
||||
if (callback)
|
||||
(*callback)();
|
||||
return true;
|
||||
|
||||
}
|
||||
else if (!volume_delta)
|
||||
{
|
||||
if (callback)
|
||||
(*callback)();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Round MS to nearest 10
|
||||
// If n - lower > higher - n, then round up
|
||||
ms = (ms - ((ms / 10) * 10) > (((ms / 10) * 10) + 10) - ms) ?
|
||||
(((ms / 10) * 10) + 10) // higher
|
||||
: ((ms / 10) * 10); // lower
|
||||
|
||||
if (!ms)
|
||||
I_SetInternalMusicVolume(target_volume);
|
||||
else if (source_volume != target_volume)
|
||||
{
|
||||
fading_id = SDL_AddTimer(10, music_fade, NULL);
|
||||
if (fading_id)
|
||||
{
|
||||
is_fading = true;
|
||||
fading_timer = fading_duration = ms;
|
||||
fading_source = source_volume;
|
||||
fading_target = target_volume;
|
||||
fading_callback = callback;
|
||||
|
||||
if (internal_volume != source_volume)
|
||||
I_SetInternalMusicVolume(source_volume);
|
||||
}
|
||||
}
|
||||
|
||||
return is_fading;
|
||||
}
|
||||
|
||||
boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void))
|
||||
{
|
||||
return I_FadeSongFromVolume(target_volume, internal_volume, ms, callback);
|
||||
}
|
||||
|
||||
boolean I_FadeOutStopSong(UINT32 ms)
|
||||
{
|
||||
return I_FadeSongFromVolume(0, internal_volume, ms, &I_StopSong);
|
||||
}
|
||||
|
||||
boolean I_FadeInPlaySong(UINT32 ms, boolean looping)
|
||||
{
|
||||
if (I_PlaySong(looping))
|
||||
return I_FadeSongFromVolume(100, 0, ms, NULL);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1375,6 +1375,37 @@ boolean I_SetSongSpeed(float speed)
|
|||
return false;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
// MUSIC SEEKING
|
||||
/// ------------------------
|
||||
|
||||
UINT32 I_GetSongLength(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean I_SetSongLoopPoint(UINT32 looppoint)
|
||||
{
|
||||
(void)looppoint;
|
||||
return false;
|
||||
}
|
||||
|
||||
UINT32 I_GetSongLoopPoint(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean I_SetSongPosition(UINT32 position)
|
||||
{
|
||||
(void)position;
|
||||
return false;
|
||||
}
|
||||
|
||||
UINT32 I_GetSongPosition(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
// MUSIC PLAYBACK
|
||||
/// ------------------------
|
||||
|
@ -1443,6 +1474,47 @@ boolean I_SetSongTrack(int track)
|
|||
return false;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
/// MUSIC FADING
|
||||
/// ------------------------
|
||||
|
||||
void I_SetInternalMusicVolume(UINT8 volume)
|
||||
{
|
||||
(void)volume;
|
||||
}
|
||||
|
||||
void I_StopFadingSong(void)
|
||||
{
|
||||
}
|
||||
|
||||
boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void))
|
||||
{
|
||||
(void)target_volume;
|
||||
(void)source_volume;
|
||||
(void)ms;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void))
|
||||
{
|
||||
(void)target_volume;
|
||||
(void)ms;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean I_FadeOutStopSong(UINT32 ms)
|
||||
{
|
||||
(void)ms;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean I_FadeInPlaySong(UINT32 ms, boolean looping)
|
||||
{
|
||||
(void)ms;
|
||||
(void)looping;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
// MUSIC LOADING AND CLEANUP
|
||||
// \todo Split logic between loading and playing,
|
||||
|
|
|
@ -755,6 +755,36 @@
|
|||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\hardware\hw_md2load.c">
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\hardware\hw_md3load.c">
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\hardware\hw_model.c">
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\hardware\hw_trick.c">
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
|
@ -765,6 +795,16 @@
|
|||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\hardware\u_list.c">
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\i_tcp.c">
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
|
@ -1340,7 +1380,11 @@
|
|||
<ClInclude Include="..\hardware\hw_light.h" />
|
||||
<ClInclude Include="..\hardware\hw_main.h" />
|
||||
<ClInclude Include="..\hardware\hw_md2.h" />
|
||||
<ClInclude Include="..\hardware\hw_md2load.h" />
|
||||
<ClInclude Include="..\hardware\hw_md3load.h" />
|
||||
<ClInclude Include="..\hardware\hw_model.h" />
|
||||
<ClInclude Include="..\hardware\hws_data.h" />
|
||||
<ClInclude Include="..\hardware\u_list.h" />
|
||||
<ClInclude Include="..\byteptr.h" />
|
||||
<ClInclude Include="..\i_joy.h" />
|
||||
<ClInclude Include="..\i_net.h" />
|
||||
|
|
|
@ -60,7 +60,6 @@ static void CV_Gammaxxx_ONChange(void);
|
|||
static CV_PossibleValue_t grgamma_cons_t[] = {{1, "MIN"}, {255, "MAX"}, {0, NULL}};
|
||||
static CV_PossibleValue_t grsoftwarefog_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "LightPlanes"}, {0, NULL}};
|
||||
|
||||
consvar_t cv_voodoocompatibility = {"gr_voodoocompatibility", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_grfovchange = {"gr_fovchange", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_grfog = {"gr_fog", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_grfogcolor = {"gr_fogcolor", "AAAAAA", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
@ -80,7 +79,8 @@ consvar_t cv_grcoronasize = {"gr_coronasize", "1", CV_SAVE| CV_FLOAT, 0, NULL, 0
|
|||
|
||||
//static CV_PossibleValue_t CV_MD2[] = {{0, "Off"}, {1, "On"}, {2, "Old"}, {0, NULL}};
|
||||
// console variables in development
|
||||
consvar_t cv_grmd2 = {"gr_md2", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_grmdls = {"gr_mdls", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_grspritebillboarding = {"gr_spritebillboarding", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
#endif
|
||||
|
||||
const UINT8 gammatable[5][256] =
|
||||
|
|
|
@ -24,8 +24,10 @@ ifndef NOASM
|
|||
USEASM=1
|
||||
endif
|
||||
|
||||
ifndef NONET
|
||||
ifndef MINGW64 #miniupnc is broken with MINGW64
|
||||
HAVE_MINIUPNPC=1
|
||||
endif
|
||||
endif
|
||||
|
||||
OPTS=-DSTDC_HEADERS
|
||||
|
|
|
@ -230,7 +230,11 @@
|
|||
<ClCompile Include="..\hardware\hw_light.c" />
|
||||
<ClCompile Include="..\hardware\hw_main.c" />
|
||||
<ClCompile Include="..\hardware\hw_md2.c" />
|
||||
<ClCompile Include="..\hardware\hw_md2load.c" />
|
||||
<ClCompile Include="..\hardware\hw_md3load.c" />
|
||||
<ClCompile Include="..\hardware\hw_model.c" />
|
||||
<ClCompile Include="..\hardware\hw_trick.c" />
|
||||
<ClCompile Include="..\hardware\u_list.c" />
|
||||
<ClCompile Include="..\hu_stuff.c" />
|
||||
<ClCompile Include="..\info.c" />
|
||||
<ClCompile Include="..\i_addrinfo.c">
|
||||
|
@ -394,6 +398,10 @@
|
|||
<ClInclude Include="..\hardware\hw_light.h" />
|
||||
<ClInclude Include="..\hardware\hw_main.h" />
|
||||
<ClInclude Include="..\hardware\hw_md2.h" />
|
||||
<ClInclude Include="..\hardware\hw_md2load.h" />
|
||||
<ClInclude Include="..\hardware\hw_md3load.h" />
|
||||
<ClInclude Include="..\hardware\hw_model.h" />
|
||||
<ClInclude Include="..\hardware\u_list.h" />
|
||||
<ClInclude Include="..\hu_stuff.h" />
|
||||
<ClInclude Include="..\info.h" />
|
||||
<ClInclude Include="..\i_addrinfo.h" />
|
||||
|
|
|
@ -453,6 +453,10 @@
|
|||
<ClCompile Include="..\string.c">
|
||||
<Filter>M_Misc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\hardware\hw_md2load.c" />
|
||||
<ClCompile Include="..\hardware\hw_md3load.c" />
|
||||
<ClCompile Include="..\hardware\hw_model.c" />
|
||||
<ClCompile Include="..\hardware\u_list.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="afxres.h">
|
||||
|
@ -506,6 +510,15 @@
|
|||
<ClInclude Include="..\hardware\hw_md2.h">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\hardware\hw_md2load.h">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\hardware\hw_md3load.h">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\hardware\hw_model.h">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\hardware\hw3dsdrv.h">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClInclude>
|
||||
|
@ -515,6 +528,9 @@
|
|||
<ClInclude Include="..\hardware\hws_data.h">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\hardware\u_list.h">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\blua\lapi.h">
|
||||
<Filter>BLUA</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
@ -109,8 +109,7 @@ static loadfunc_t hwdFuncTable[] = {
|
|||
{"GClipRect@20", &hwdriver.pfnGClipRect},
|
||||
{"ClearMipMapCache@0", &hwdriver.pfnClearMipMapCache},
|
||||
{"SetSpecialState@8", &hwdriver.pfnSetSpecialState},
|
||||
{"DrawMD2@16", &hwdriver.pfnDrawMD2},
|
||||
{"DrawMD2i@36", &hwdriver.pfnDrawMD2i},
|
||||
{"DrawModel@16", &hwdriver.pfnDrawModel},
|
||||
{"SetTransform@4", &hwdriver.pfnSetTransform},
|
||||
{"GetTextureUsed@0", &hwdriver.pfnGetTextureUsed},
|
||||
{"GetRenderVersion@0", &hwdriver.pfnGetRenderVersion},
|
||||
|
@ -140,8 +139,7 @@ static loadfunc_t hwdFuncTable[] = {
|
|||
{"GClipRect", &hwdriver.pfnGClipRect},
|
||||
{"ClearMipMapCache", &hwdriver.pfnClearMipMapCache},
|
||||
{"SetSpecialState", &hwdriver.pfnSetSpecialState},
|
||||
{"DrawMD2", &hwdriver.pfnDrawMD2},
|
||||
{"DrawMD2i", &hwdriver.pfnDrawMD2i},
|
||||
{"DrawModel", &hwdriver.pfnDrawModel},
|
||||
{"SetTransform", &hwdriver.pfnSetTransform},
|
||||
{"GetTextureUsed", &hwdriver.pfnGetTextureUsed},
|
||||
{"GetRenderVersion", &hwdriver.pfnGetRenderVersion},
|
||||
|
|
|
@ -815,6 +815,60 @@ void I_SetMusicVolume(UINT8 volume)
|
|||
FMR_MUSIC(FMOD_Channel_SetVolume(music_channel, music_volume / 31.0));
|
||||
}
|
||||
|
||||
UINT32 I_GetSongLength(void)
|
||||
{
|
||||
UINT32 length;
|
||||
if (I_SongType() == MU_MID)
|
||||
return 0;
|
||||
FMR_MUSIC(FMOD_Sound_GetLength(music_stream, &length, FMOD_TIMEUNIT_MS));
|
||||
return length;
|
||||
}
|
||||
|
||||
boolean I_SetSongLoopPoint(UINT32 looppoint)
|
||||
{
|
||||
(void)looppoint;
|
||||
return false;
|
||||
}
|
||||
|
||||
UINT32 I_GetSongLoopPoint(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean I_SetSongPosition(UINT32 position)
|
||||
{
|
||||
FMOD_RESULT e;
|
||||
if(I_SongType() == MU_MID)
|
||||
// Dummy out; this works for some MIDI, but not others.
|
||||
// SDL does not support this for any MIDI.
|
||||
return false;
|
||||
e = FMOD_Channel_SetPosition(music_channel, position, FMOD_TIMEUNIT_MS);
|
||||
if (e == FMOD_OK)
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
UINT32 I_GetSongPosition(void)
|
||||
{
|
||||
FMOD_RESULT e;
|
||||
unsigned int fmposition = 0;
|
||||
if(I_SongType() == MU_MID)
|
||||
// Dummy out because unsupported, even though FMOD does this correctly.
|
||||
return 0;
|
||||
e = FMOD_Channel_GetPosition(music_channel, &fmposition, FMOD_TIMEUNIT_MS);
|
||||
if (e == FMOD_OK)
|
||||
return (UINT32)fmposition;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean I_SetSongTrack(INT32 track)
|
||||
{
|
||||
if (track != current_track) // If the track's already playing, then why bother?
|
||||
|
@ -859,3 +913,46 @@ boolean I_SetSongTrack(INT32 track)
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
/// MUSIC FADING
|
||||
/// ------------------------
|
||||
|
||||
void I_SetInternalMusicVolume(UINT8 volume)
|
||||
{
|
||||
(void)volume;
|
||||
}
|
||||
|
||||
void I_StopFadingSong(void)
|
||||
{
|
||||
}
|
||||
|
||||
boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void))
|
||||
{
|
||||
(void)target_volume;
|
||||
(void)source_volume;
|
||||
(void)ms;
|
||||
(void)callback;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void))
|
||||
{
|
||||
(void)target_volume;
|
||||
(void)ms;
|
||||
(void)callback;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean I_FadeOutStopSong(UINT32 ms)
|
||||
{
|
||||
(void)ms;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean I_FadeInPlaySong(UINT32 ms, boolean looping)
|
||||
{
|
||||
(void)ms;
|
||||
(void)looping;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "g_input.h" // PLAYER1INPUTDOWN
|
||||
#include "k_kart.h" // colortranslations
|
||||
#include "console.h" // cons_menuhighlight
|
||||
#include "lua_hook.h" // IntermissionThinker hook
|
||||
|
||||
#ifdef HWRENDER
|
||||
#include "hardware/hw_main.h"
|
||||
|
@ -574,6 +575,10 @@ void Y_Ticker(void)
|
|||
if (paused || P_AutoPause())
|
||||
return;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
LUAh_IntermissionThinker();
|
||||
#endif
|
||||
|
||||
intertic++;
|
||||
|
||||
// Team scramble code for team match and CTF.
|
||||
|
@ -1505,11 +1510,11 @@ void Y_EndVote(void)
|
|||
//
|
||||
static void Y_UnloadVoteData(void)
|
||||
{
|
||||
voteclient.loaded = false;
|
||||
|
||||
if (rendermode != render_soft)
|
||||
return;
|
||||
|
||||
voteclient.loaded = false;
|
||||
|
||||
UNLOAD(widebgpatch);
|
||||
UNLOAD(bgpatch);
|
||||
UNLOAD(cursor);
|
||||
|
|
Loading…
Reference in a new issue