19 May 2008

This commit is contained in:
g-cont 2008-05-19 00:00:00 +04:00 committed by Alibek Omarov
parent 3271793934
commit 1fe636b994
33 changed files with 231 additions and 2666 deletions

View File

@ -50,7 +50,7 @@ void InitPlatform ( uint funcname, int argc, char **argv )
{
case COMP_BSPLIB:
if(!FS_GetParmFromCmdLine("-game", gamedir ))
strncpy(gamedir, "xash", sizeof(gamedir));
strncpy(gamedir, "tmpQuArK", sizeof(gamedir));
if(!FS_GetParmFromCmdLine("+map", source ))
strncpy(source, "newmap", sizeof(source));
if(FS_CheckParm("-vis")) bspflags |= BSP_ONLYVIS;

View File

@ -131,6 +131,57 @@ bool Com_ValidScript( int scripttype )
return true;
};
void Com_CheckToken( const char *match )
{
Com_GetToken( true );
if( Com_MatchToken( match ))
{
Sys_Break( "\"%s\" not found\n" );
}
}
void Com_Parse1DMatrix( int x, vec_t *m )
{
int i;
Com_CheckToken( "(" );
for( i = 0; i < x; i++ )
{
Com_GetToken( false );
m[i] = com.atof( com_token );
}
Com_CheckToken( ")" );
}
void Com_Parse2DMatrix( int y, int x, vec_t *m )
{
int i;
Com_CheckToken( "(" );
for( i = 0; i < y; i++ )
{
Com_Parse1DMatrix( x, m+i*x );
}
Com_CheckToken( ")" );
}
void Com_Parse3DMatrix( int z, int y, int x, vec_t *m )
{
int i;
Com_CheckToken( "(" );
for( i = 0; i < z; i++ )
{
Com_Parse2DMatrix( y, x, m+i*x*y );
}
Com_CheckToken( ")" );
}
/*
========================================================================

View File

@ -71,9 +71,10 @@ void Profile_Time( void ); // total profile time
extern stdlib_api_t com;
extern imglib_exp_t *Image;
#define Sys_Error com.error
#define Malloc(size) Mem_Alloc(basepool, size)
#define Z_Malloc(size) Mem_Alloc(zonepool, size)
#define Sys_Error com.error
#define Malloc(size) Mem_Alloc(basepool, size)
#define BSP_Realloc(ptr, size) Mem_Realloc(basepool, ptr, size)
#define Z_Malloc(size) Mem_Alloc(zonepool, size)
extern string gs_filename;
extern char gs_basedir[ MAX_SYSPATH ];
@ -91,6 +92,10 @@ enum
};
bool Com_ValidScript( int scripttype );
void Com_CheckToken( const char *match );
void Com_Parse1DMatrix( int x, vec_t *m );
void Com_Parse2DMatrix( int y, int x, vec_t *m );
void Com_Parse3DMatrix( int z, int y, int x, vec_t *m );
// get rid of this
byte *ReadBMP (char *filename, byte **palette, int *width, int *height);

View File

@ -63,5 +63,5 @@ if exist viewer\viewer.plg del /f /q viewer\viewer.plg
echo Build succeeded!
echo Please wait. Xash is now loading
cd D:\Xash3D\
xash.exe +map qctest -log -debug -dev 3
xash.exe -log -game tmpQuArK -debug -dev 3 +map qctest
:done

View File

@ -603,7 +603,8 @@ void CL_AddPacketEntities (frame_t *frame)
ent.alpha = s1->alpha;
ent.body = s1->body;
ent.sequence = s1->sequence;
ent.animtime = s1->animtime;
if (renderfx & (RF_FRAMELERP|RF_BEAM))
{
// step origin discretely, because the frames

View File

@ -1638,6 +1638,7 @@ void CL_Init (void)
SCR_Init();
CL_InitLocal();
S_ClearLoopingSounds( true );
}

View File

@ -33,6 +33,7 @@ char *svc_strings[256] =
"svc_disconnect",
"svc_reconnect",
"svc_sound",
"svc_ambientsound",
"svc_print",
"svc_stufftext",
"svc_serverdata",
@ -577,6 +578,20 @@ void CL_ParseStartSoundPacket(void)
S_StartSound (pos, ent, channel, cl.sound_precache[sound_num]);
}
void CL_ParseAmbientSound( void )
{
sound_t loopSoundHandle;
int entityNum, soundNum;
vec3_t ambient_org;
entityNum = MSG_ReadShort (&net_message);
soundNum = MSG_ReadShort (&net_message);
MSG_ReadPos32 (&net_message, ambient_org);
loopSoundHandle = S_RegisterSound( cl.configstrings[CS_SOUNDS + soundNum] );
// add ambient looping sound
S_AddRealLoopingSound( entityNum, ambient_org, vec3_origin, loopSoundHandle );
}
void SHOWNET(char *s)
{
@ -672,6 +687,10 @@ void CL_ParseServerMessage (void)
CL_ParseStartSoundPacket();
break;
case svc_ambientsound:
CL_ParseAmbientSound();
break;
case svc_spawnbaseline:
CL_ParseBaseline ();
break;

View File

@ -5,7 +5,6 @@
#include "client.h"
bool scr_initialized; // ready to draw
vrect_t scr_vrect; // position of render window on screen
cvar_t *scr_viewsize;
@ -354,7 +353,4 @@ void SCR_Init (void)
Cmd_AddCommand( "loading", SCR_Loading_f, "prepare client to a loading new map" );
Cmd_AddCommand( "skyname", CL_SetSky_f, "set new skybox by basename" );
Cmd_AddCommand( "setfont", CL_SetFont_f, "set new system font" );
scr_initialized = true;
}

View File

@ -1148,7 +1148,7 @@ void S_ClearLoopingSounds( bool killall )
for ( i = 0; i < MAX_MAP_ENTITIES; i++)
{
if (killall || loopSounds[i].kill == true || (loopSounds[i].sfx && loopSounds[i].sfx->soundLength == 0))
if( killall || loopSounds[i].kill == true || (loopSounds[i].sfx && loopSounds[i].sfx->soundLength == 0))
{
loopSounds[i].kill = false;
S_StopLoopingSound( i );
@ -1271,10 +1271,9 @@ void S_AddLoopSounds (void)
float time;
numLoopChannels = 0;
time = Sys_DoubleTime();
loopFrame++;
for ( i = 0; i < MAX_MAP_ENTITIES; i++)
{
loop = &loopSounds[i];

View File

@ -38,8 +38,6 @@ cvar_t *cl_testblend;
cvar_t *cl_stats;
extern bool scr_initialized;
int r_numdlights;
dlight_t r_dlights[MAX_DLIGHTS];
@ -521,8 +519,8 @@ V_PreRender
*/
bool V_PreRender( void )
{
if(!scr_initialized)
return false;
// too early
if(!re) return false;
re->BeginFrame();

View File

@ -176,7 +176,7 @@ aborts the current host frame and goes on with the next one
*/
void Host_AbortCurrentFrame( void )
{
longjmp(host.abortframe, 1);
longjmp( host.abortframe, 1 );
}
/*
@ -400,7 +400,7 @@ void Host_Print( const char *txt )
*host.rd.buffer = 0;
}
}
strcat (host.rd.buffer, txt);
com.strcat (host.rd.buffer, txt);
return;
}
Con_Print( txt ); // echo to client console
@ -434,7 +434,7 @@ void Host_Error( const char *error, ... )
}
recursive = true;
sprintf( host.finalmsg, "Server crashed: %s\n", hosterror1 );
com.sprintf( host.finalmsg, "Server crashed: %s\n", hosterror1 );
com.strncpy( host.finalmsg, "Server shutdown\n", MAX_STRING );
SV_Shutdown( false );

View File

@ -198,11 +198,6 @@ void _MSG_WriteDeltaEntity (entity_state_t *from, entity_state_t *to, sizebuf_t
if (to->skin < 256) bits |= U_SKIN8;
else bits |= U_SKIN16;
}
if ( to->frame != from->frame )
{
if (to->frame < 256) bits |= U_FRAME8;
else bits |= U_FRAME16;
}
if ( to->effects != from->effects )
{
if (to->effects < 256) bits |= U_EFFECTS8;
@ -215,7 +210,8 @@ void _MSG_WriteDeltaEntity (entity_state_t *from, entity_state_t *to, sizebuf_t
else if (to->renderfx < 32768) bits |= U_RENDERFX16;
else bits |= U_RENDERFX8 | U_RENDERFX16;
}
if ( to->frame != from->frame ) bits |= U_FRAME;
if ( to->solid != from->solid ) bits |= U_SOLID;
if ( to->event ) bits |= U_EVENT; // event is not delta compressed, just 0 compressed
@ -225,8 +221,9 @@ void _MSG_WriteDeltaEntity (entity_state_t *from, entity_state_t *to, sizebuf_t
if ( to->sequence != from->sequence ) bits |= U_SEQUENCE;
if ( to->soundindex != from->soundindex ) bits |= U_SOUNDIDX;
if (newentity || (to->renderfx & RF_BEAM)) bits |= U_OLDORIGIN;
if( to->alpha != from->alpha ) bits |= U_ALPHA;
if ( to->alpha != from->alpha ) bits |= U_ALPHA;
if ( to->animtime != from->animtime ) bits |= U_ANIMTIME;
// write the message
if (!bits && !force) return; // nothing to send!
@ -262,9 +259,7 @@ void _MSG_WriteDeltaEntity (entity_state_t *from, entity_state_t *to, sizebuf_t
if (bits & U_MODEL) MSG_WriteShort (msg, to->modelindex );
if (bits & U_WEAPONMODEL) _MSG_WriteShort (msg, to->weaponmodel, filename, fileline);
if (bits & U_FRAME8) _MSG_WriteByte (msg, to->frame, filename, fileline);
if (bits & U_FRAME16) MSG_WriteShort (msg, to->frame );
if (bits & U_FRAME ) _MSG_WriteFloat (msg, to->frame, filename, fileline);
if (bits & U_SKIN8 ) _MSG_WriteByte (msg, to->skin, filename, fileline);
if (bits & U_SKIN16)
{
@ -303,6 +298,7 @@ void _MSG_WriteDeltaEntity (entity_state_t *from, entity_state_t *to, sizebuf_t
if (bits & U_EVENT) _MSG_WriteByte (msg, to->event, filename, fileline);
if (bits & U_SOUNDIDX) _MSG_WriteByte (msg, to->soundindex, filename, fileline);
if (bits & U_BODY) _MSG_WriteByte (msg, to->body, filename, fileline);
if (bits & U_ANIMTIME) _MSG_WriteFloat (msg, to->animtime, filename, fileline);
}
/*
@ -512,9 +508,7 @@ void MSG_ReadDeltaEntity(entity_state_t *from, entity_state_t *to, int number, i
if (bits & U_MODEL) to->modelindex = MSG_ReadShort (&net_message);
if (bits & U_WEAPONMODEL) to->weaponmodel = MSG_ReadShort (&net_message);
if (bits & U_FRAME8 ) to->frame = MSG_ReadByte (&net_message);
if (bits & U_FRAME16) to->frame = MSG_ReadShort (&net_message);
if (bits & U_FRAME ) to->frame = MSG_ReadFloat (&net_message);
if (bits & U_SKIN8 ) to->skin = MSG_ReadByte(&net_message);
if (bits & U_SKIN16) to->skin = MSG_ReadShort(&net_message);
@ -545,6 +539,7 @@ void MSG_ReadDeltaEntity(entity_state_t *from, entity_state_t *to, int number, i
else to->event = 0;
if (bits & U_BODY) to->body = MSG_ReadByte (&net_message);
if (bits & U_ANIMTIME) to->animtime = MSG_ReadFloat (&net_message);
}
void MSG_ReadData (sizebuf_t *msg_read, void *data, int len)

View File

@ -20,6 +20,7 @@ enum svc_ops_e
svc_disconnect,
svc_reconnect,
svc_sound, // <see code>
svc_ambientsound, // ambient looping sound
svc_print, // [byte] id [string] null terminated string
svc_stufftext, // [string] stuffed into client's console buffer, should be \n terminated
svc_serverdata, // [long] protocol ...
@ -134,7 +135,7 @@ enum player_stats
#define U_ORIGIN2 (1<<1)
#define U_ANGLE2 (1<<2)
#define U_ANGLE3 (1<<3)
#define U_FRAME8 (1<<4) // frame is a byte
#define U_FRAME (1<<4) // sv. interpolated value
#define U_SKIN8 (1<<5)
#define U_REMOVE (1<<6) // REMOVE this entity, don't add it
#define U_MOREBITS1 (1<<7) // read one additional byte
@ -150,7 +151,7 @@ enum player_stats
// third byte
#define U_SKIN16 (1<<16)
#define U_FRAME16 (1<<17) // frame is a short
#define U_ANIMTIME (1<<17) // auto-animating time
#define U_RENDERFX16 (1<<18) // 8 + 16 = 32
#define U_EFFECTS16 (1<<19) // 8 + 16 = 32
#define U_WEAPONMODEL (1<<20) // weapons, flags, etc
@ -179,7 +180,7 @@ typedef struct entity_state_s
int weaponmodel;
short skin; // skin for studiomodels
short frame; // % playback position in animation sequences (0..512)
float frame; // % playback position in animation sequences (0..512)
byte body; // sub-model selection for studiomodels
byte sequence; // animation sequence (0 - 255)
uint effects; // PGM - we're filling it, so it needs to be unsigned
@ -191,6 +192,7 @@ typedef struct entity_state_s
// events only go out for a single frame, they
// are automatically cleared each frame
float alpha; // alpha value
float animtime; // auto-animating time
} entity_state_t;

View File

@ -200,11 +200,6 @@ typedef struct
float last_heartbeat;
challenge_t challenges[MAX_CHALLENGES]; // to prevent invalid IPs from connecting
// serverrecord values
file_t *demofile;
sizebuf_t demo_multicast;
byte demo_multicast_buf[MAX_MSGLEN];
} server_static_t;
//=============================================================================
@ -285,6 +280,7 @@ void SV_FlushRedirect (int sv_redirected, char *outputbuf);
void SV_DemoCompleted (void);
void SV_SendClientMessages (void);
void SV_AmbientSound( edict_t *entity, int soundindex, float volume, float attenuation );
void SV_StartSound (vec3_t origin, edict_t *entity, int channel, int index, float vol, float attn, float timeofs);
void SV_ClientPrintf (client_state_t *cl, int level, char *fmt, ...);
void SV_BroadcastPrintf (int level, char *fmt, ...);

View File

@ -174,7 +174,7 @@ void SV_Demo_f( void )
==================
SV_Movie_f
Playing a roq video with specified name
Playing a Darkplaces video with specified name
==================
*/
void SV_Movie_f( void )

View File

@ -138,6 +138,7 @@ typedef struct sv_entvars_s
float frame;
float sequence;
float renderfx;
float animtime;
float effects;
float skin;
float body;
@ -283,6 +284,6 @@ static fields_t sv_reqfields[] =
{217, 1, "oldmodel"}
};
#define PROG_CRC_SERVER 6477
#define PROG_CRC_SERVER 406
#endif//SV_EDICT_H

View File

@ -44,12 +44,13 @@ void SV_UpdateEntityState( edict_t *ent)
ent->priv.sv->s.skin = (short)ent->progs.sv->skin; // studio model skin
ent->priv.sv->s.body = (byte)ent->progs.sv->body; // studio model submodel
ent->priv.sv->s.frame = (short)ent->progs.sv->frame; // any model current frame
ent->priv.sv->s.frame = ent->progs.sv->frame; // any model current frame
ent->priv.sv->s.sequence = (byte)ent->progs.sv->sequence; // studio model sequence
ent->priv.sv->s.effects = (uint)ent->progs.sv->effects; // shared client and render flags
ent->priv.sv->s.renderfx = (int)ent->progs.sv->renderfx; // renderer flags
ent->priv.sv->s.alpha = ent->progs.sv->alpha; // alpha value
ent->priv.sv->s.soundindex = SV_SoundIndex(PRVM_GetString(ent->progs.sv->noise3));
ent->priv.sv->s.animtime = ent->progs.sv->animtime; // auto-animating time
ent->priv.sv->s.soundindex = (int)ent->progs.sv->sounds;
}
/*
@ -484,59 +485,4 @@ void SV_BuildClientFrame (client_state_t *client)
svs.next_client_entities++;
frame->num_entities++;
}
}
/*
==================
SV_RecordDemoMessage
Save everything in the world out without deltas.
Used for recording footage for merged or assembled demos
==================
*/
void SV_RecordDemoMessage (void)
{
int e;
edict_t *ent;
entity_state_t nostate;
sizebuf_t buf;
byte buf_data[32768];
int len;
if (!svs.demofile) return;
memset (&nostate, 0, sizeof(nostate));
SZ_Init (&buf, buf_data, sizeof(buf_data));
// write a frame message that doesn't contain a player_state_t
MSG_WriteByte (&buf, svc_frame);
MSG_WriteLong (&buf, sv.framenum);
MSG_WriteByte (&buf, svc_packetentities);
e = 1;
ent = PRVM_EDICT_NUM(e);
while (e < prog->num_edicts)
{
// ignore ents without visible models unless they have an effect
if (!ent->priv.sv->free && ent->priv.sv->serialnumber && (ent->priv.sv->s.modelindex || ent->progs.sv->effects || ent->progs.sv->noise3 || ent->priv.sv->event))
{
SV_UpdateEntityState( ent );
MSG_WriteDeltaEntity (&nostate, &ent->priv.sv->s, &buf, false, true);
}
e++;
ent = PRVM_EDICT_NUM(e);
}
MSG_WriteShort (&buf, 0); // end of packetentities
// now add the accumulated multicast information
SZ_Write (&buf, svs.demo_multicast.data, svs.demo_multicast.cursize);
SZ_Clear (&svs.demo_multicast);
// now write the entire message to the file, prefixed by the length
len = LittleLong (buf.cursize);
FS_Write (svs.demofile, &len, 4);
FS_Write (svs.demofile, buf.data, buf.cursize);
}
}

View File

@ -224,8 +224,12 @@ void SV_SpawnServer (char *server, char *savename, sv_state_t serverstate )
// check for a savegame
SV_CheckForSavegame( savename );
if(sv.loadgame) SV_ReadLevelFile( savename );
else SV_SpawnEntities ( sv.name, pe->GetEntityString());
if( serverstate == ss_game )
{
// ignore ents for demo or cinematic servers
if(sv.loadgame) SV_ReadLevelFile( savename );
else SV_SpawnEntities ( sv.name, pe->GetEntityString());
}
// run two frames to allow everything to settle
SV_RunFrame();

View File

@ -1,22 +1,7 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//=======================================================================
// Copyright XashXT Group 2007 ©
// sv_utils.c - server vm utils
//=======================================================================
#include "engine.h"
#include "server.h"
@ -796,9 +781,6 @@ void SV_Frame (float time)
// send messages back to the clients that had packets read this frame
SV_SendClientMessages ();
// save the entire world state if recording a serverdemo
SV_RecordDemoMessage ();
// send a heartbeat to the master if needed
Master_Heartbeat ();
@ -1056,7 +1038,6 @@ void SV_Shutdown( bool reconnect )
// free server static data
if (svs.clients) Z_Free (svs.clients);
if (svs.client_entities) Z_Free (svs.client_entities);
if (svs.demofile) FS_Close (svs.demofile);
memset (&svs, 0, sizeof(svs));
}

View File

@ -174,9 +174,6 @@ void _MSG_Send (msgtype_t to, vec3_t origin, edict_t *ent, const char *filename,
else Msg("MSG_Send: origin == NULL (called at %s:%i)\n", filename, fileline);
return;
}*/
// if doing a serverrecord, store everything
if (svs.demofile) SZ_Write (&svs.demo_multicast, sv.multicast.data, sv.multicast.cursize);
switch (to)
{
@ -373,6 +370,32 @@ void SV_StartSound (vec3_t origin, edict_t *entity, int channel, int soundindex,
}
}
void SV_AmbientSound( edict_t *entity, int soundindex, float volume, float attenuation )
{
vec3_t origin_v;
int i;
if(entity->progs.sv->solid == SOLID_BSP)
{
for(i = 0; i < 3; i++)
{
origin_v[i] = entity->progs.sv->origin[i]+0.5*(entity->progs.sv->mins[i]+entity->progs.sv->maxs[i]);
}
}
else
{
VectorCopy( entity->progs.sv->origin, origin_v );
}
if( sv.state != ss_loading )
{
MSG_Begin( svc_ambientsound );
MSG_WriteWord(&sv.multicast, entity->priv.sv->serialnumber);
MSG_WriteWord(&sv.multicast, soundindex);
MSG_WritePos32(&sv.multicast, origin_v );
MSG_Send (MSG_ALL_R, origin_v, NULL);
}
}
/*
===============================================================================

View File

@ -482,7 +482,7 @@ PF_ambientsound
void ambientsound( entity e, string sample)
=================
*/
void PF_ambientsound (void)
void PF_ambientsound( void )
{
const char *samp;
edict_t *soundent;
@ -490,8 +490,7 @@ void PF_ambientsound (void)
soundent = PRVM_G_EDICT(OFS_PARM0);
samp = PRVM_G_STRING(OFS_PARM1);
// check to see if samp was properly precached
soundent->progs.sv->noise3 = SV_SoundIndex( samp );
if( soundent ) SV_AmbientSound( soundent, SV_SoundIndex( samp ), 0.0f, 0.0f ); // unused parms
}
/*
@ -658,8 +657,15 @@ void PF_create( void )
VM_create();
}
void PF_modelframes (void)
void PF_modelframes( void )
{
cmodel_t *mod;
float framecount = 0.0f;
mod = pe->RegisterModel( sv.configstrings[CS_MODELS + (int)PRVM_G_FLOAT(OFS_PARM0)] );
if( mod ) framecount = ( float )mod->numframes;
PRVM_G_FLOAT(OFS_RETURN) = framecount;
}
void PF_changelevel (void)

View File

@ -103,8 +103,8 @@ worldsector_t *SV_CreateWorldSector( int depth, vec3_t mins, vec3_t maxs )
VectorCopy(maxs, maxs2);
maxs1[anode->axis] = mins2[anode->axis] = anode->dist;
anode->children[0] = SV_CreateWorldSector( depth+1, mins2, maxs2);
anode->children[1] = SV_CreateWorldSector( depth+1, mins1, maxs1);
anode->children[0] = SV_CreateWorldSector( depth + 1, mins2, maxs2);
anode->children[1] = SV_CreateWorldSector( depth + 1, mins1, maxs1);
return anode;
}

View File

@ -1,853 +0,0 @@
//=======================================================================
// Copyright XashXT Group 2007 ©
// image_save.c - saving textures
//=======================================================================
#include "launch.h"
#include "image.h"
#include "mathlib.h"
#define Sum(c) ((c)->r + (c)->g + (c)->b)
/*
===============
GetImageSize
calculate buffer size for current miplevel
===============
*/
uint GetImageSize( int block, int width, int height, int depth, int bpp, int rgbcount )
{
uint BlockSize = 0;
if(block == 0) BlockSize = width * height * bpp;
else if(block > 0) BlockSize = ((width + 3)/4) * ((height + 3)/4) * depth * block;
else if(block < 0 && rgbcount > 0) BlockSize = width * height * depth * rgbcount;
else BlockSize = width * height * abs(block);
return BlockSize;
}
bool dds_write_header( vfile_t *f, rgbdata_t *pix, uint cubemap_flags, uint savetype )
{
uint dwFourCC, dwFlags1 = 0, dwFlags2 = 0, dwCaps1 = 0;
uint dwLinearSize, dwBlockSize, dwCaps2 = 0;
uint dwIdent = DDSHEADER, dwSize = 124, dwSize2 = 32;
uint dwWidth, dwHeight, dwDepth, dwMipCount = 1;
if(!pix || !pix->buffer )
return false;
// setup flags
dwFlags1 |= DDS_LINEARSIZE | DDS_WIDTH | DDS_HEIGHT | DDS_CAPS | DDS_PIXELFORMAT;
dwFlags2 |= DDS_FOURCC;
if( pix->numLayers > 1) dwFlags1 |= DDS_DEPTH;
switch( savetype )
{
case PF_DXT1:
dwFourCC = TYPE_DXT1;
break;
case PF_DXT2:
dwFourCC = TYPE_DXT2;
break;
case PF_DXT3:
dwFourCC = TYPE_DXT3;
break;
case PF_DXT4:
dwFourCC = TYPE_DXT4;
break;
case PF_DXT5:
dwFourCC = TYPE_DXT5;
break;
case PF_ATI1N:
dwFourCC = TYPE_ATI1;
break;
case PF_ATI2N:
dwFourCC = TYPE_ATI2;
break;
case PF_RXGB:
dwFourCC = TYPE_RXGB;
break;
default:
MsgDev( D_ERROR, "dds_write_header: unsupported type %s\n", PFDesc[pix->type].name );
return false;
}
dwWidth = pix->width;
dwHeight = pix->height;
VFS_Write(f, &dwIdent, sizeof(uint));
VFS_Write(f, &dwSize, sizeof(uint));
VFS_Write(f, &dwFlags1, sizeof(uint));
VFS_Write(f, &dwHeight, sizeof(uint));
VFS_Write(f, &dwWidth, sizeof(uint));
dwBlockSize = PFDesc[savetype].block;
dwLinearSize = GetImageSize(PFDesc[savetype].block, pix->width, pix->height, pix->numLayers, PFDesc[savetype].bpp, pix->bitsCount / 8 );
//dwLinearSize = (((pix->width + 3)/4) * ((pix->height + 3)/4)) * dwBlockSize * pix->numLayers;
VFS_Write(f, &dwLinearSize, sizeof(uint)); // TODO: use dds_get_linear_size
if (pix->numLayers > 1)
{
dwDepth = pix->numLayers;
VFS_Write(f, &dwDepth, sizeof(uint));
dwCaps2 |= DDS_VOLUME;
}
else VFS_Write(f, 0, sizeof(uint));
VFS_Write(f, &dwMipCount, sizeof(uint));
VFS_Write(f, 0, sizeof(uint));
VFS_Write(f, pix->color, sizeof(vec3_t));
VFS_Write(f, &pix->bump_scale, sizeof(float));
VFS_Write(f, 0, sizeof(uint) * 6 ); // reserved fields
VFS_Write(f, &dwSize2, sizeof(uint));
VFS_Write(f, &dwFlags2, sizeof(uint));
VFS_Write(f, &dwFourCC, sizeof(uint));
VFS_Write(f, 0, sizeof(uint) * 5 ); // bit masks
dwCaps1 |= DDS_TEXTURE;
if( pix->numMips > 1 ) dwCaps1 |= DDS_MIPMAP | DDS_COMPLEX;
if( cubemap_flags )
{
dwCaps1 |= DDS_COMPLEX;
dwCaps2 |= cubemap_flags;
}
VFS_Write(f, &dwCaps1, sizeof(uint));
VFS_Write(f, &dwCaps2, sizeof(uint));
VFS_Write(f, 0, sizeof(uint) * 3 ); // other caps and TextureStage
return true;
}
void ShortToColor565(word Pixel, color16 *Colour)
{
Colour->r = (Pixel & 0xF800) >> 11;
Colour->g = (Pixel & 0x07E0) >> 5;
Colour->b = (Pixel & 0x001F);
return;
}
void ShortToColor888(word Pixel, color24 *Colour)
{
Colour->r = ((Pixel & 0xF800) >> 11) << 3;
Colour->g = ((Pixel & 0x07E0) >> 5) << 2;
Colour->b = ((Pixel & 0x001F)) << 3;
return;
}
word Color565ToShort(color16 *Colour)
{
return (Colour->r << 11) | (Colour->g << 5) | (Colour->b);
}
word Color888ToShort(color24 *Colour)
{
return ((Colour->r >> 3) << 11) | ((Colour->g >> 2) << 5) | (Colour->b >> 3);
}
void ChooseEndpoints(word *Block, word *ex0, word *ex1)
{
uint i;
color24 Colours[16];
int Lowest=0, Highest=0;
for (i = 0; i < 16; i++)
{
ShortToColor888(Block[i], &Colours[i]);
if(Sum(&Colours[i]) < Sum(&Colours[Lowest])) Lowest = i;
if(Sum(&Colours[i]) > Sum(&Colours[Highest])) Highest = i;
}
*ex0 = Block[Highest];
*ex1 = Block[Lowest];
}
void CorrectEndDXT1( word *ex0, word *ex1, bool HasAlpha )
{
word Temp;
if( HasAlpha )
{
if(*ex0 > *ex1)
{
Temp = *ex0;
*ex0 = *ex1;
*ex1 = Temp;
}
}
else
{
if (*ex0 < *ex1)
{
Temp = *ex0;
*ex0 = *ex1;
*ex1 = Temp;
}
}
return;
}
void PreMult(word *Data, byte *Alpha)
{
color24 Colour;
uint i;
for (i = 0; i < 16; i++)
{
ShortToColor888(Data[i], &Colour);
Colour.r = (byte)(((uint)Colour.r * Alpha[i]) >> 8);
Colour.g = (byte)(((uint)Colour.g * Alpha[i]) >> 8);
Colour.b = (byte)(((uint)Colour.b * Alpha[i]) >> 8);
Data[i] = Color888ToShort(&Colour);
ShortToColor888(Data[i], &Colour);
}
return;
}
void ChooseAlphaEndpoints( byte *Block, byte *a0, byte *a1)
{
uint i, Lowest = 0xFF, Highest = 0;
for (i = 0; i < 16; i++)
{
if( Block[i] < Lowest ) Lowest = Block[i];
if( Block[i] > Highest) Highest = Block[i];
}
*a0 = Lowest;
*a1 = Highest;
}
// Assumed to be 16-bit (5:6:5).
bool GetBlock( word *Block, word *Data, rgbdata_t *pix, uint XPos, uint YPos)
{
uint x, y, i = 0, Offset = YPos * pix->width + XPos;
for( y = 0; y < 4; y++)
{
for (x = 0; x < 4; x++)
{
if(x < pix->width && y < pix->height)
Block[i++] = Data[Offset + x];
else Block[i++] = Data[Offset];
}
Offset += pix->width;
}
return true;
}
bool GetAlphaBlock( byte *Block, byte *Data, rgbdata_t *pix, uint XPos, uint YPos)
{
uint x, y, i = 0, Offset = YPos * pix->width + XPos;
for (y = 0; y < 4; y++)
{
for (x = 0; x < 4; x++)
{
if (x < pix->width && y < pix->height)
Block[i++] = Data[Offset + x];
else Block[i++] = Data[Offset];
}
Offset += pix->width;
}
return true;
}
bool Get3DcBlock( byte *Block, byte *Data, rgbdata_t *pix, uint XPos, uint YPos, int channel )
{
uint x, y, i = 0, Offset = 2*(YPos * pix->width + XPos) + channel;
for (y = 0; y < 4; y++)
{
for (x = 0; x < 4; x++)
{
if(x < pix->width && y < pix->height)
Block[i++] = Data[Offset + 2 * x];
else Block[i++] = Data[Offset];
}
Offset += 2 * pix->width;
}
return true;
}
byte* GetAlpha( rgbdata_t *pix )
{
byte *Alpha;
uint i, j, Bpc, Size, AlphaOff;
Bpc = PFDesc[pix->type].bpc;
if( Bpc == 0 ) return NULL;
Size = pix->width * pix->height * pix->numLayers * PFDesc[pix->type].bpp;
Alpha = (byte*)Mem_Alloc( Sys.imagepool, Size / PFDesc[pix->type].bpp * Bpc);
if( pix->type == PF_LUMINANCE_ALPHA )
AlphaOff = 2;
else AlphaOff = 4;
for (i = AlphaOff - 1, j = 0; i < Size; i += AlphaOff, j++ )
Alpha[j] = pix->buffer[i];
return Alpha;
}
uint RMSAlpha( byte *Orig, byte *Test )
{
uint RMS = 0, i;
int d;
for (i = 0; i < 16; i++)
{
d = Orig[i] - Test[i];
RMS += d*d;
}
return RMS;
}
uint Distance(color24 *c1, color24 *c2)
{
return (c1->r - c2->r) * (c1->r - c2->r) + (c1->g - c2->g) * (c1->g - c2->g) + (c1->b - c2->b) * (c1->b - c2->b);
}
uint GenBitMask( word ex0, word ex1, uint NumCols, word *In, byte *Alpha, color24 *OutCol )
{
uint i, j, Closest, Dist, BitMask = 0;
byte Mask[16];
color24 c, Colours[4];
ShortToColor888(ex0, &Colours[0]);
ShortToColor888(ex1, &Colours[1]);
if (NumCols == 3)
{
Colours[2].r = (Colours[0].r + Colours[1].r) / 2;
Colours[2].g = (Colours[0].g + Colours[1].g) / 2;
Colours[2].b = (Colours[0].b + Colours[1].b) / 2;
Colours[3].r = (Colours[0].r + Colours[1].r) / 2;
Colours[3].g = (Colours[0].g + Colours[1].g) / 2;
Colours[3].b = (Colours[0].b + Colours[1].b) / 2;
}
else
{ // NumCols == 4
Colours[2].r = (2 * Colours[0].r + Colours[1].r + 1) / 3;
Colours[2].g = (2 * Colours[0].g + Colours[1].g + 1) / 3;
Colours[2].b = (2 * Colours[0].b + Colours[1].b + 1) / 3;
Colours[3].r = (Colours[0].r + 2 * Colours[1].r + 1) / 3;
Colours[3].g = (Colours[0].g + 2 * Colours[1].g + 1) / 3;
Colours[3].b = (Colours[0].b + 2 * Colours[1].b + 1) / 3;
}
for (i = 0; i < 16; i++)
{
if (Alpha)
{
// Test to see if we have 1-bit transparency
if (Alpha[i] < 128)
{
Mask[i] = 3; // Transparent
if (OutCol)
{
OutCol[i].r = Colours[3].r;
OutCol[i].g = Colours[3].g;
OutCol[i].b = Colours[3].b;
}
continue;
}
}
// if no transparency, try to find which colour is the closest.
Closest = UINT_MAX;
ShortToColor888(In[i], &c);
for (j = 0; j < NumCols; j++)
{
Dist = Distance(&c, &Colours[j]);
if( Dist < Closest )
{
Closest = Dist;
Mask[i] = j;
if( OutCol )
{
OutCol[i].r = Colours[j].r;
OutCol[i].g = Colours[j].g;
OutCol[i].b = Colours[j].b;
}
}
}
}
for( i = 0; i < 16; i++ )
{
BitMask |= (Mask[i] << (i*2));
}
return BitMask;
}
void GenAlphaBitMask( byte a0, byte a1, byte *In, byte *Mask, byte *Out )
{
byte Alphas[8], M[16];
uint i, j, Closest, Dist;
Alphas[0] = a0;
Alphas[1] = a1;
// 8-alpha or 6-alpha block?
if (a0 > a1)
{
// 8-alpha block: derive the other six alphas.
// Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated.
Alphas[2] = (6 * Alphas[0] + 1 * Alphas[1] + 3) / 7; // bit code 010
Alphas[3] = (5 * Alphas[0] + 2 * Alphas[1] + 3) / 7; // bit code 011
Alphas[4] = (4 * Alphas[0] + 3 * Alphas[1] + 3) / 7; // bit code 100
Alphas[5] = (3 * Alphas[0] + 4 * Alphas[1] + 3) / 7; // bit code 101
Alphas[6] = (2 * Alphas[0] + 5 * Alphas[1] + 3) / 7; // bit code 110
Alphas[7] = (1 * Alphas[0] + 6 * Alphas[1] + 3) / 7; // bit code 111
}
else
{
// 6-alpha block.
// Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated.
Alphas[2] = (4 * Alphas[0] + 1 * Alphas[1] + 2) / 5; // Bit code 010
Alphas[3] = (3 * Alphas[0] + 2 * Alphas[1] + 2) / 5; // Bit code 011
Alphas[4] = (2 * Alphas[0] + 3 * Alphas[1] + 2) / 5; // Bit code 100
Alphas[5] = (1 * Alphas[0] + 4 * Alphas[1] + 2) / 5; // Bit code 101
Alphas[6] = 0x00; // Bit code 110
Alphas[7] = 0xFF; // Bit code 111
}
for (i = 0; i < 16; i++)
{
Closest = UINT_MAX;
for (j = 0; j < 8; j++)
{
Dist = abs((int)In[i] - (int)Alphas[j]);
if (Dist < Closest)
{
Closest = Dist;
M[i] = j;
}
}
}
if( Out )
{
for (i = 0; i < 16; i++)
{
Out[i] = Alphas[M[i]];
}
}
// First three bytes.
Mask[0] = (M[0]) | (M[1] << 3) | ((M[2] & 0x03) << 6);
Mask[1] = ((M[2] & 0x04) >> 2) | (M[3] << 1) | (M[4] << 4) | ((M[5] & 0x01) << 7);
Mask[2] = ((M[5] & 0x06) >> 1) | (M[6] << 2) | (M[7] << 5);
// Second three bytes.
Mask[3] = (M[8]) | (M[9] << 3) | ((M[10] & 0x03) << 6);
Mask[4] = ((M[10] & 0x04) >> 2) | (M[11] << 1) | (M[12] << 4) | ((M[13] & 0x01) << 7);
Mask[5] = ((M[13] & 0x06) >> 1) | (M[14] << 2) | (M[15] << 5);
return;
}
word *dds_compress_565( rgbdata_t *pix )
{
word *Data;
uint i, j;
Data = (word*)Mem_Alloc( Sys.imagepool, pix->width * pix->height * 2 * pix->numLayers );
switch ( pix->type )
{
case PF_RGB_24:
for (i = 0, j = 0; i < pix->size; i += 3, j++)
{
Data[j] = (pix->buffer[i+0] >> 3) << 11;
Data[j] |= (pix->buffer[i+1] >> 2) << 5;
Data[j] |= pix->buffer[i+2] >> 3;
}
break;
case PF_RGBA_32:
for( i = 0, j = 0; i < pix->size; i += 4, j++ )
{
Data[j] |= (pix->buffer[i+0]>>3)<<11;
Data[j] |= (pix->buffer[i+1]>>2)<<5;
Data[j] |= (pix->buffer[i+2]>>3);
}
break;
case PF_RGB_24_FLIP:
for (i = 0, j = 0; i < pix->size; i += 3, j++)
{
Data[j] = (pix->buffer[i+2] >> 3) << 11;
Data[j] |= (pix->buffer[i+1] >> 2) << 5;
Data[j] |= pix->buffer[i+0] >> 3;
}
break;
case PF_LUMINANCE:
for (i = 0, j = 0; i < pix->size; i++, j++)
{
Data[j] = (pix->buffer[i] >> 3) << 11;
Data[j] |= (pix->buffer[i] >> 2) << 5;
Data[j] |= pix->buffer[i] >> 3;
}
break;
case PF_LUMINANCE_ALPHA:
for (i = 0, j = 0; i < pix->size; i += 2, j++)
{
Data[j] = (pix->buffer[i] >> 3) << 11;
Data[j] |= (pix->buffer[i] >> 2) << 5;
Data[j] |= pix->buffer[i] >> 3;
}
break;
}
return Data;
}
byte *dds_compress_88( rgbdata_t *pix )
{
byte *Data;
uint i, j;
Data = (byte*)Mem_Alloc(Sys.imagepool, pix->width * pix->height * 2 * pix->numLayers );
switch( pix->type )
{
case PF_RGB_24:
for (i = 0, j = 0; i < pix->size; i += 3, j += 2)
{
Data[j+0] = pix->buffer[i+1];
Data[j+1] = pix->buffer[i+0];
}
break;
case PF_RGBA_32:
for (i = 0, j = 0; i < pix->size; i += 4, j += 2)
{
Data[j+0] = pix->buffer[i+1];
Data[j+1] = pix->buffer[i+0];
}
break;
case PF_RGB_24_FLIP:
for (i = 0, j = 0; i < pix->size; i += 3, j += 2)
{
Data[j ] = pix->buffer[i+1];
Data[j+1] = pix->buffer[i+2];
}
break;
case PF_LUMINANCE:
case PF_LUMINANCE_ALPHA:
for (i = 0, j = 0; i < pix->size; i++, j += 2)
{
Data[j] = Data[j+1] = 0; //??? Luminance is no normal map format...
}
break;
}
return Data;
}
void dds_compress_RXGB(rgbdata_t *pix, word **xgb, byte **r )
{
uint i, j;
word *Data;
byte *Alpha;
*xgb = NULL;
*r = NULL;
*xgb = (word*)Mem_Alloc( Sys.imagepool, pix->width * pix->height * 2 * pix->numLayers );
*r = Mem_Alloc( Sys.imagepool, pix->width * pix->height * pix->numLayers);
//alias pointers to be able to use copy'n'pasted code :)
Data = *xgb;
Alpha = *r;
switch( pix->type )
{
case PF_RGB_24:
for (i = 0, j = 0; i < pix->size; i += 3, j++)
{
Alpha[j] = pix->buffer[i+0];
Data[j] = (pix->buffer[i+1] >> 2) << 5;
Data[j] |= pix->buffer[i+2] >> 3;
}
break;
case PF_RGBA_32:
for (i = 0, j = 0; i < pix->size; i += 4, j++)
{
Alpha[j] = pix->buffer[i+0];
Data[j] = (pix->buffer[i+1] >> 2) << 5;
Data[j] |= pix->buffer[i+2] >> 3;
}
break;
case PF_RGB_24_FLIP:
for (i = 0, j = 0; i < pix->size; i += 3, j++)
{
Alpha[j] = pix->buffer[i+2];
Data[j] = (pix->buffer[i+1] >> 2) << 5;
Data[j] |= pix->buffer[i+0] >> 3;
}
break;
case PF_LUMINANCE:
for (i = 0, j = 0; i < pix->size; i++, j++)
{
Alpha[j] = pix->buffer[i];
Data[j] = (pix->buffer[i] >> 2) << 5;
Data[j] |= pix->buffer[i] >> 3;
}
break;
case PF_LUMINANCE_ALPHA:
for (i = 0, j = 0; i < pix->size; i += 2, j++)
{
Alpha[j] = pix->buffer[i];
Data[j] = (pix->buffer[i] >> 2) << 5;
Data[j] |= pix->buffer[i] >> 3;
}
break;
}
}
uint dds_compress_dxt( vfile_t *f, int saveformat, rgbdata_t *pix )
{
word *Data, Block[16], ex0, ex1, *Runner16, t0, t1;
byte *Alpha, AlphaBlock[16], AlphaBitMask[6], a0, a1;
uint x, y, z, i, BitMask;
byte *Data3Dc, *Runner8;
bool HasAlpha;
uint Count = 0;
if(!pix || !pix->buffer )
return 0;
if( saveformat == PF_ATI2N)
{
Data3Dc = dds_compress_88( pix );
if(!Data3Dc) return 0;
Runner8 = Data3Dc;
for (z = 0; z < pix->numLayers; z++)
{
for (y = 0; y < pix->height; y += 4)
{
for (x = 0; x < pix->width; x += 4)
{
Get3DcBlock( AlphaBlock, Runner8, pix, x, y, 0);
ChooseAlphaEndpoints(AlphaBlock, &a0, &a1);
GenAlphaBitMask(a0, a1, AlphaBlock, AlphaBitMask, NULL);
VFS_Write(f, &a0, sizeof(byte));
VFS_Write(f, &a1, sizeof(byte));
VFS_Write(f, &AlphaBitMask, sizeof(byte) * 6 );
Get3DcBlock(AlphaBlock, Runner8, pix, x, y, 1);
ChooseAlphaEndpoints(AlphaBlock, &a0, &a1);
GenAlphaBitMask(a0, a1, AlphaBlock, AlphaBitMask, NULL);
VFS_Write(f, &a0, sizeof(byte));
VFS_Write(f, &a1, sizeof(byte));
VFS_Write(f, &AlphaBitMask, sizeof(byte) * 6 );
Count += 16;
}
}
Runner8 += pix->width * pix->height * 2;
}
Mem_Free( Data3Dc );
}
else if( saveformat == PF_ATI1N )
{
rgbdata_t *lum = NULL;
if (PFDesc[pix->type].bpp != 1)
{
//FIXME: lum = Image_Convert( pix, PF_LUMINANCE );
if(!lum) return 0;
}
else lum = pix;
Runner8 = lum->buffer;
for (z = 0; z < pix->numLayers; z++)
{
for (y = 0; y < pix->height; y += 4)
{
for (x = 0; x < pix->width; x += 4)
{
GetAlphaBlock(AlphaBlock, Runner8, pix, x, y);
ChooseAlphaEndpoints(AlphaBlock, &a0, &a1);
GenAlphaBitMask(a0, a1, AlphaBlock, AlphaBitMask, NULL);
VFS_Write(f, &a0, sizeof(byte));
VFS_Write(f, &a1, sizeof(byte));
VFS_Write(f, &AlphaBitMask, sizeof(byte) * 6 );
Count += 8;
}
}
Runner8 += pix->width * pix->height;
}
if(lum != pix) FS_FreeImage( lum );
}
else
{
if( saveformat != PF_RXGB )
{
Data = dds_compress_565( pix );
if(!Data) return 0;
Alpha = GetAlpha( pix );
if(!Alpha)
{
Mem_Free(Data);
return 0;
}
}
else
{
dds_compress_RXGB(pix, &Data, &Alpha);
if (!Data || !Alpha)
{
if( Data ) Mem_Free( Data );
if( Alpha) Mem_Free( Alpha);
return 0;
}
}
Runner8 = Alpha;
Runner16 = Data;
switch( saveformat )
{
case PF_DXT1:
for (z = 0; z < pix->numLayers; z++)
{
for (y = 0; y < pix->height; y += 4)
{
for (x = 0; x < pix->width; x += 4)
{
GetAlphaBlock(AlphaBlock, Runner8, pix, x, y);
HasAlpha = false;
for (i = 0; i < 16; i++)
{
if(AlphaBlock[i] < 128)
{
HasAlpha = true;
break;
}
}
GetBlock(Block, Runner16, pix, x, y);
ChooseEndpoints(Block, &ex0, &ex1);
CorrectEndDXT1(&ex0, &ex1, HasAlpha);
VFS_Write(f, &ex0, sizeof(word));
VFS_Write(f, &ex1, sizeof(word));
if (HasAlpha) BitMask = GenBitMask(ex0, ex1, 3, Block, AlphaBlock, NULL);
else BitMask = GenBitMask(ex0, ex1, 4, Block, NULL, NULL);
VFS_Write(f, AlphaBitMask, sizeof(uint));
Count += 8;
}
}
Runner16 += pix->width * pix->height;
Runner8 += pix->width * pix->height;
}
break;
case PF_DXT2:
for (y = 0; y < pix->height; y += 4)
{
for (x = 0; x < pix->width; x += 4)
{
GetAlphaBlock(AlphaBlock, Runner8, pix, x, y);
for (i = 0; i < 16; i += 2)
{
byte tempBlock = ((AlphaBlock[i]>>4)<<4) | (AlphaBlock[i+1]>>4);
VFS_Write(f, &tempBlock, 1 );
}
GetBlock(Block, Runner16, pix, x, y);
PreMult(Block, AlphaBlock);
ChooseEndpoints(Block, &ex0, &ex1);
VFS_Write(f, &ex0, sizeof(word));
VFS_Write(f, &ex1, sizeof(word));
BitMask = GenBitMask(ex0, ex1, 4, Block, NULL, NULL);
VFS_Write(f, &AlphaBitMask, sizeof(uint));
Count += 16;
}
}
break;
case PF_DXT3:
for (z = 0; z < pix->numLayers; z++)
{
for (y = 0; y < pix->height; y += 4)
{
for (x = 0; x < pix->width; x += 4)
{
GetAlphaBlock(AlphaBlock, Runner8, pix, x, y);
for (i = 0; i < 16; i += 2)
{
byte tempBlock = ((AlphaBlock[i]>>4)<<4) | (AlphaBlock[i+1]>>4);
VFS_Write(f, &tempBlock, 1 );
}
GetBlock(Block, Runner16, pix, x, y);
ChooseEndpoints(Block, &t0, &t1);
ex0 = max(t0, t1);
ex1 = min(t0, t1);
CorrectEndDXT1(&ex0, &ex1, 0);
VFS_Write(f, &ex0, sizeof(word));
VFS_Write(f, &ex1, sizeof(word));
BitMask = GenBitMask(ex0, ex1, 4, Block, NULL, NULL);
VFS_Write(f, AlphaBitMask, sizeof(uint));
Count += 16;
}
}
Runner16 += pix->width * pix->height;
Runner8 += pix->width * pix->height;
}
break;
case PF_RXGB:
case PF_DXT5:
for (z = 0; z < pix->numLayers; z++)
{
for (y = 0; y < pix->height; y += 4)
{
for (x = 0; x < pix->width; x += 4)
{
GetAlphaBlock(AlphaBlock, Runner8, pix, x, y);
ChooseAlphaEndpoints(AlphaBlock, &a0, &a1);
GenAlphaBitMask(a0, a1, AlphaBlock, AlphaBitMask, NULL/*AlphaOut*/);
VFS_Write(f, &a0, sizeof(byte));
VFS_Write(f, &a1, sizeof(byte));
VFS_Write(f, &AlphaBitMask, sizeof(byte) * 6 );
GetBlock(Block, Runner16, pix, x, y);
ChooseEndpoints(Block, &t0, &t1);
ex0 = max(t0, t1);
ex1 = min(t0, t1);
CorrectEndDXT1(&ex0, &ex1, 0);
VFS_Write(f, &ex0, sizeof(word));
VFS_Write(f, &ex1, sizeof(word));
BitMask = GenBitMask(ex0, ex1, 4, Block, NULL, NULL);
VFS_Write(f, &BitMask, sizeof(uint));
Count += 16;
}
}
Runner16 += pix->width * pix->height;
Runner8 += pix->width * pix->height;
}
break;
}
Mem_Free( Data );
Mem_Free( Alpha);
}
return Count;
}
bool dds_save_image( const char *name, rgbdata_t *pix, int saveformat )
{
file_t *file;
vfile_t *vhandle;
file = FS_Open( name, "wb" ); // create real file
vhandle = VFS_Open( file, "w" ); // create virtual file
dds_write_header( vhandle, pix, 0, saveformat );
if(!dds_compress_dxt( vhandle, saveformat, pix ))
{
Msg("dds_save_image: can't create dds file\n");
return false;
}
file = VFS_Close( vhandle ); // write buffer into hdd
FS_Close( file );
return true;
}

File diff suppressed because it is too large Load Diff

View File

@ -1356,7 +1356,7 @@ void FS_CreateGameInfo( const char *filename )
char *buffer = Malloc( MAX_SYSPATH );
// make simply gameinfo.txt
com_strncat(buffer, "// generated by Xash3D\r\r\nbasedir\t\t\"xash\"\n", MAX_SYSPATH ); // add new string
com_strncat(buffer, "// generated by Xash3D\r\r\nbasedir\t\t\"\"\n", MAX_SYSPATH ); // add new string
com_strncat(buffer, va("gamedir\t\t\"%s\"\n", gs_basedir ), MAX_SYSPATH);
com_strncat(buffer, va("title\t\t\"New Game\"\rversion\t\t\"%g\"\rviewmode\t\"firstperson\"\r", XASH_VERSION), MAX_SYSPATH );
com_strncat(buffer, va("gamemode\t\t\"singleplayer\"\rgamekey\t\t\"%s\"", GI.key), MAX_SYSPATH );
@ -1466,16 +1466,16 @@ void FS_Init( void )
if(!FS_GetParmFromCmdLine("-game", gs_basedir ))
{
if( Sys.app_name == COMP_BSPLIB )
com_strcpy( gs_basedir, "xash" );
com_strcpy( gs_basedir, "tmpQuArK" );
else if(GetModuleFileName( NULL, szTemp, MAX_SYSPATH ))
FS_FileBase( szTemp, gs_basedir );
else com_strcpy( gs_basedir, "xash" ); // default dir
else com_strcpy( gs_basedir, "tmpQuArK" ); // default dir
}
// checked nasty path: "bin" it's a reserved word
if(FS_CheckNastyPath( gs_basedir, true ) || !com_stricmp("bin", gs_basedir ))
{
MsgWarn("FS_Init: invalid game directory \"%s\"\n", gs_basedir );
com_strcpy(gs_basedir, "xash" ); // default dir
com_strcpy(gs_basedir, "tmpQuArK" ); // default dir
}
// validate directories
@ -1488,7 +1488,7 @@ void FS_Init( void )
if(i == dirs.numstrings)
{
MsgWarn("FS_Init: game directory \"%s\" not exist\n", gs_basedir );
com_strcpy(gs_basedir, "xash" ); // default dir
com_strcpy(gs_basedir, "tmpQuArK" ); // default dir
}
stringlistfreecontents(&dirs);
}

View File

@ -830,6 +830,7 @@ cmodel_t *CM_BeginRegistration( const char *name, bool clientload, uint *checksu
if(!com.strlen(name))
{
CM_FreeWorld(); // release old map
// cinematic servers won't have anything at all
cm.numleafs = cm.numclusters = cm.numareas = 1;
*checksum = 0;
@ -1261,7 +1262,6 @@ bool CM_StudioModel( byte *buffer, uint filesize )
return false;
}
loadmodel->numframes = 0;
loadmodel->numbodies = 0;
loadmodel->type = mod_studio;
@ -1269,6 +1269,8 @@ bool CM_StudioModel( byte *buffer, uint filesize )
pseqdesc = (mstudioseqdesc_t *)((byte *)phdr + phdr->seqindex);
VectorCopy( pseqdesc[0].bbmin, loadmodel->mins );
VectorCopy( pseqdesc[0].bbmax, loadmodel->maxs );
loadmodel->numframes = pseqdesc[0].numframes; // FIXME: get numframes from current sequence (not first)
CM_CreateMeshBuffer( buffer ); // newton collision mesh
return true;

View File

@ -97,7 +97,6 @@ BRUSH MODELS
#define IDBSPMODHEADER (('P'<<24)+('S'<<16)+('B'<<8)+'I') // little-endian "IBSP"
// 32 bit limits
#define MAX_MAP_SIZE 0x40000 // -/+ 131072
#define MAX_KEY 128
#define MAX_VALUE 512
#define MAX_MAP_AREAS 0x100 // don't increase this
@ -123,7 +122,12 @@ BRUSH MODELS
#define MAX_MAP_COLLISION 0x800000
#define MAX_MAP_STRINGDATA 0x40000
#define MAX_MAP_NUMSTRINGS 0x10000
// game limits
#define MAX_MODELS MAX_MAP_MODELS>>1 // brushmodels and other models
#define MAX_WORLD_COORD ( 128 * 1024 )
#define MIN_WORLD_COORD (-128 * 1024 )
#define WORLD_SIZE ( MAX_WORLD_COORD - MIN_WORLD_COORD )
// lump offset
#define LUMP_ENTITIES 0

View File

@ -1512,6 +1512,41 @@ typedef struct rgbdata_s
/*
========================================================================
wavefile in memory representation
using with darkplaces video encoder-decoder
========================================================================
*/
typedef struct wavefile_s
{
file_t *file; // file this is reading from
uint info_format; // these settings are read directly from the wave format (1 is uncompressed PCM)
uint info_rate; // how many samples per second
uint info_channels; // how many channels (1 = mono, 2 = stereo, 6 = 5.1 audio?)
uint info_bits; // how many bits per channel (8 or 16)
// these settings are generated from the wave format
// how many bytes in a sample (which may be one or two channels,
// thus 1 or 2 or 2 or 4, depending on info_bytesperchannel)
uint info_bytespersample;
// how many bytes in channel (1 for 8bit, or 2 for 16bit)
uint info_bytesperchannel;
uint length; // how many samples in the wave file
uint datalength; // how large the data chunk is
uint dataposition; // beginning of data in data chunk
uint position; // current position in stream (in samples)
uint bufferlength; // these are private to the wave file functions, just used for processing size of *buffer
void *buffer; // buffer is reallocated if caller asks for more than fits
} wavefile_t;
/*
========================================================================
internal physic data
hold linear and angular velocity, current position stored too

View File

@ -63,5 +63,5 @@ if exist viewer\viewer.plg del /f /q viewer\viewer.plg
echo Build succeeded!
echo Please wait. Xash is now loading
cd D:\Xash3D\
xash.exe +map qctest -dev 3 -debug -log
xash.exe -game tmpQuArK +map start -dev 3 -debug -log
:done

View File

@ -1118,7 +1118,7 @@ void R_DrawWorld (void)
// auto cycle the world frame for texture animation
memset (&ent, 0, sizeof(ent));
ent.frame = (int)(r_newrefdef.time);
ent.frame = (int)(r_newrefdef.time * 6.0f);
currententity = &ent;
gl_state.currenttextures[0] = gl_state.currenttextures[1] = -1;

View File

@ -216,8 +216,8 @@ void EmitWaterPolys (msurface_t *fa)
if (fa->texinfo->flags & SURF_FLOWING)
scroll = -64 * ( (r_newrefdef.time * 0.5) - (int)(r_newrefdef.time * 0.5));
else
scroll = 0;
else scroll = 0;
for (bp = fa->polys; bp; bp = bp->next)
{
p = bp;

View File

@ -87,7 +87,7 @@ image_t *R_StudioLoadTexture( model_t *mod, mstudiotexture_t *ptexture, byte *pi
r_skin.buffer = pin + ptexture->index; // texdata
r_skin.size = ptexture->width * ptexture->height * 3; // for bounds cheking
//load studio texture and bind it
// load studio texture and bind it
image = R_LoadImage(ptexture->name, &r_skin, it_skin );
if(!image)
{

View File

@ -10,6 +10,24 @@ SprExplorer
fopen завешивает приложение, при попытке создать файл в несуществующей директории. Ну вылетал бы чтоли, или ошибку
возвращал.
Глобальные задачи:
1. вернуть обратно roq video OK
2. исправить проигрывание movie после загрузки карты
3. физика игрока на ньютоне
1. переписать сервер
Alt+Enter для fullscreen
// global todo list
| module | todo num | description |
@IMGLIB 1 переписать сохранение dxtc |