Example #1
0
void* WAV_MemoryLoad(const byte* data, size_t datalength, int* bits, int* rate, int* samples)
{
    const byte* end = data + datalength;
    byte* sampledata = NULL;
    chunk_hdr_t riff_chunk;
    wav_format_t wave_format;

    LOG_AS("WAV_MemoryLoad");

    if(!WAV_CheckFormat((const char*)data))
    {
        LOG_RES_WARNING("Not WAV format data");
        return NULL;
    }

    // Read the RIFF header.
    data += sizeof(riff_hdr_t);
    data += 4; // "WAVE" already verified above

#ifdef _DEBUG
    assert(sizeof(wave_format) == 16);
    assert(sizeof(riff_chunk) == 8);
#endif

    // Start readin' the chunks, baby!
    while(data < end)
    {
        // Read next chunk header.
        WReadAndAdvance(data, &riff_chunk, sizeof(riff_chunk));

        // Correct endianness.
        riff_chunk.len = DD_ULONG(riff_chunk.len);

        // What have we got here?
        if(!strncmp(riff_chunk.id, "fmt ", 4))
        {
            // Read format chunk.
            WReadAndAdvance(data, &wave_format, sizeof(wave_format));

            // Correct endianness.
            wave_format.wFormatTag       = DD_USHORT(wave_format.wFormatTag      );
            wave_format.wChannels        = DD_USHORT(wave_format.wChannels       );
            wave_format.dwSamplesPerSec  = DD_ULONG (wave_format.dwSamplesPerSec );
            wave_format.dwAvgBytesPerSec = DD_ULONG (wave_format.dwAvgBytesPerSec);
            wave_format.wBlockAlign      = DD_USHORT(wave_format.wBlockAlign     );
            wave_format.wBitsPerSample   = DD_USHORT(wave_format.wBitsPerSample  );

            assert(wave_format.wFormatTag == WAVE_FORMAT_PCM); // linear PCM

            // Check that it's a format we know how to read.
            if(wave_format.wFormatTag != WAVE_FORMAT_PCM)
            {
                LOG_RES_WARNING("Unsupported format (%i)") << wave_format.wFormatTag;
                return NULL;
            }
            if(wave_format.wChannels != 1)
            {
                LOG_RES_WARNING("Too many channels (only mono supported)");
                return NULL;
            }
            // Read the extra format information.
            //WReadAndAdvance(&data, &wave_format2, sizeof(*wave_format2));
            /*if(wave_format->wBitsPerSample == 0)
               {
               // We'll have to guess...
               *bits = 8*wave_format->dwAvgBytesPerSec/
               wave_format->dwSamplesPerSec;
               }
               else
               { */
            if(wave_format.wBitsPerSample != 8 &&
               wave_format.wBitsPerSample != 16)
            {
                LOG_RES_WARNING("Must have 8 or 16 bits per sample");
                return NULL;
            }
            // Now we know some information about the sample.
            *bits = wave_format.wBitsPerSample;
            *rate = wave_format.dwSamplesPerSec;
        }
        else if(!strncmp(riff_chunk.id, "data", 4))
        {
            if(!wave_format.wFormatTag)
            {
                LOG_RES_WARNING("Malformed WAV data");
                return NULL;
            }
            // Read data chunk.
            *samples = riff_chunk.len / wave_format.wBlockAlign;
            // Allocate the sample buffer.
            sampledata = (byte *) Z_Malloc(riff_chunk.len, PU_APPSTATIC, 0);
            memcpy(sampledata, data, riff_chunk.len);
#ifdef __BIG_ENDIAN__
            // Correct endianness.
            /*if(wave_format->wBitsPerSample == 16)
            {
                ushort* sample = sampledata;
                for(; sample < ((short*)sampledata) + *samples; ++sample)
                    *sample = DD_USHORT(*sample);
            }*/
#endif
            // We're satisfied with this! Let's get out of here.
            break;
        }
        else
        {
            // Unknown chunk, just skip it.
            data += riff_chunk.len;
        }
    }

    return sampledata;
}
Example #2
0
void NetUpdate(void)
{
  static int lastmadetic;
  if (isExtraDDisplay)
    return;
  if (server) { // Receive network packets
    size_t recvlen;
    packet_header_t *packet = Z_Malloc(10000, PU_STATIC, NULL);
    while ((recvlen = I_GetPacket(packet, 10000))) {
      switch(packet->type) {
      case PKT_TICS:
  {
    byte *p = (void*)(packet+1);
    int tics = *p++;
    unsigned long ptic = doom_ntohl(packet->tic);
    if (ptic > (unsigned)remotetic) { // Missed some
      packet_set(packet, PKT_RETRANS, remotetic);
      *(byte*)(packet+1) = consoleplayer;
      I_SendPacket(packet, sizeof(*packet)+1);
    } else {
      if (ptic + tics <= (unsigned)remotetic) break; // Will not improve things
      remotetic = ptic;
      while (tics--) {
        int players = *p++;
        while (players--) {
            int n = *p++;
            RawToTic(&netcmds[n][remotetic%BACKUPTICS], p);
            p += sizeof(ticcmd_t);
        }
        remotetic++;
      }
    }
  }
  break;
      case PKT_RETRANS: // Resend request
          remotesend = doom_ntohl(packet->tic);
          break;
      case PKT_DOWN: // Server downed
  {
    int j;
    for (j=0; j<MAXPLAYERS; j++)
      if (j != consoleplayer) playeringame[j] = false;
    server = false;
    doom_printf("Server is down\nAll other players are no longer in the game\n");
    jni_info_msg("Server is down\nAll other players are no longer in the game!", TT_LONG_DELAY | TT_COLOR_RED);
  }
  break;
      case PKT_EXTRA: // Misc stuff
      case PKT_QUIT: // Player quit
  // Queue packet to be processed when its tic time is reached
  queuedpacket = Z_Realloc(queuedpacket, ++numqueuedpackets * sizeof *queuedpacket,
         PU_STATIC, NULL);
  queuedpacket[numqueuedpackets-1] = Z_Malloc(recvlen, PU_STATIC, NULL);
  memcpy(queuedpacket[numqueuedpackets-1], packet, recvlen);
  break;
      case PKT_BACKOFF:
        /* cph 2003-09-18 -
	 * The server sends this when we have got ahead of the other clients. We should
	 * stall the input side on this client, to allow other clients to catch up.
	 */
        lastmadetic++;
	break;
      default: // Other packet, unrecognised or redundant
  break;
      }
    }
    Z_Free(packet);
  }
  { // Build new ticcmds
    int newtics = I_GetTime() - lastmadetic;
    newtics = (newtics > 0 ? newtics : 0);
    lastmadetic += newtics;
    if (ffmap) newtics++;
    while (newtics--) {
      I_StartTic();
      if (maketic - gametic > BACKUPTICS/2) break;
      G_BuildTiccmd(&localcmds[maketic%BACKUPTICS]);
      maketic++;
    }
    if (server && maketic > remotesend) { // Send the tics to the server
      int sendtics;
      remotesend -= xtratics;
      if (remotesend < 0) remotesend = 0;
      sendtics = maketic - remotesend;
      {
  size_t pkt_size = sizeof(packet_header_t) + 2 + sendtics * sizeof(ticcmd_t);
  packet_header_t *packet = Z_Malloc(pkt_size, PU_STATIC, NULL);

  packet_set(packet, PKT_TICC, maketic - sendtics);
  *(byte*)(packet+1) = sendtics;
  *(((byte*)(packet+1))+1) = consoleplayer;
  {
    void *tic = ((byte*)(packet+1)) +2;
    while (sendtics--) {
      TicToRaw(tic, &localcmds[remotesend++%BACKUPTICS]);
      tic = (byte *)tic + sizeof(ticcmd_t);
    }
  }
  I_SendPacket(packet, pkt_size);
  Z_Free(packet);
      }
    }
  }
}
Example #3
0
bool LoadTGAPalletteImage ( const char *name, byte **pic, int *width, int *height)
{
	int		columns, rows, numPixels;
	byte	*buf_p;
	byte	*buffer;
	TargaHeader	targa_header;
	byte	*dataStart;

	*pic = NULL;

	//
	// load the file
	//
	ri->FS_ReadFile ( ( char * ) name, (void **)&buffer);
	if (!buffer) {
		return false;
	}

	buf_p = buffer;

	targa_header.id_length = *buf_p++;
	targa_header.colormap_type = *buf_p++;
	targa_header.image_type = *buf_p++;
	
	targa_header.colormap_index = LittleShort ( *(short *)buf_p );
	buf_p += 2;
	targa_header.colormap_length = LittleShort ( *(short *)buf_p );
	buf_p += 2;
	targa_header.colormap_size = *buf_p++;
	targa_header.x_origin = LittleShort ( *(short *)buf_p );
	buf_p += 2;
	targa_header.y_origin = LittleShort ( *(short *)buf_p );
	buf_p += 2;
	targa_header.width = LittleShort ( *(short *)buf_p );
	buf_p += 2;
	targa_header.height = LittleShort ( *(short *)buf_p );
	buf_p += 2;
	targa_header.pixel_size = *buf_p++;
	targa_header.attributes = *buf_p++;

	if (targa_header.image_type!=1 )
	{
		Com_Error (ERR_DROP, "LoadTGAPalletteImage: Only type 1 (uncompressed pallettised) TGA images supported\n");
	}

	if ( targa_header.colormap_type == 0 )
	{
		Com_Error( ERR_DROP, "LoadTGAPalletteImage: colormaps ONLY supported\n" );
	}

	columns = targa_header.width;
	rows = targa_header.height;
	numPixels = columns * rows;

	if (width)
		*width = columns;
	if (height)
		*height = rows;

	*pic = (unsigned char *) Z_Malloc (numPixels, TAG_TEMP_WORKSPACE, qfalse );
	if (targa_header.id_length != 0)
	{
		buf_p += targa_header.id_length;  // skip TARGA image comment
	}
	dataStart = buf_p + (targa_header.colormap_length * (targa_header.colormap_size / 4));
	memcpy(*pic, dataStart, numPixels);
	ri->FS_FreeFile (buffer);

	return true;
}
Example #4
0
int
EV_DoDoor
( line_t*	line,
  vldoor_e	type )
{
    int		secnum,rtn;
    sector_t*	sec;
    vldoor_t*	door;
	
    secnum = -1;
    rtn = 0;
    
    while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
    {
	sec = &sectors[secnum];
	if (sec->specialdata)
	    continue;
		
	
	// new door thinker
	rtn = 1;
	door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
	P_AddThinker (&door->thinker);
	sec->specialdata = door;

	door->thinker.function.acp1 = (actionf_p1) T_VerticalDoor;
	door->sector = sec;
	door->type = type;
	door->topwait = VDOORWAIT;
	door->speed = VDOORSPEED;
		
	switch(type)
	{
	  case vld_blazeClose:
	    door->topheight = P_FindLowestCeilingSurrounding(sec);
	    door->topheight -= 4*FRACUNIT;
	    door->direction = -1;
	    door->speed = VDOORSPEED * 4;
	    S_StartSound(&door->sector->soundorg, sfx_bdcls);
	    break;
	    
	  case vld_close:
	    door->topheight = P_FindLowestCeilingSurrounding(sec);
	    door->topheight -= 4*FRACUNIT;
	    door->direction = -1;
	    S_StartSound(&door->sector->soundorg, sfx_dorcls);
	    break;
	    
	  case vld_close30ThenOpen:
	    door->topheight = sec->ceilingheight;
	    door->direction = -1;
	    S_StartSound(&door->sector->soundorg, sfx_dorcls);
	    break;
	    
	  case vld_blazeRaise:
	  case vld_blazeOpen:
	    door->direction = 1;
	    door->topheight = P_FindLowestCeilingSurrounding(sec);
	    door->topheight -= 4*FRACUNIT;
	    door->speed = VDOORSPEED * 4;
	    if (door->topheight != sec->ceilingheight)
		S_StartSound(&door->sector->soundorg, sfx_bdopn);
	    break;
	    
	  case vld_normal:
	  case vld_open:
	    door->direction = 1;
	    door->topheight = P_FindLowestCeilingSurrounding(sec);
	    door->topheight -= 4*FRACUNIT;
	    if (door->topheight != sec->ceilingheight)
		S_StartSound(&door->sector->soundorg, sfx_doropn);
	    break;
	    
	  default:
	    break;
	}
		
    }
    return rtn;
}
Example #5
0
static void ExpandSoundData_SDL(byte *data, int samplerate, uint32_t length, Mix_Chunk *destination)
{
    SDL_AudioCVT convertor;
    uint32_t expanded_length;

    // Calculate the length of the expanded version of the sample.

    expanded_length = (uint32_t)(((uint64_t)length * mixer_freq) / samplerate);

    // Double up twice: 8 -> 16 bit and mono -> stereo

    expanded_length *= 4;
    destination->alen = expanded_length;
    destination->abuf
        = (Uint8 *)Z_Malloc(expanded_length, PU_STATIC, (void **)&destination->abuf);

    // If we can, use the standard / optimized SDL conversion routines.

    if (samplerate <= mixer_freq
        && ConvertibleRatio(samplerate, mixer_freq)
        && SDL_BuildAudioCVT(&convertor,
                             AUDIO_U8, 1, samplerate,
                             mixer_format, mixer_channels, mixer_freq))
    {
        convertor.buf = destination->abuf;
        convertor.len = length;
        memcpy(convertor.buf, data, length);

        SDL_ConvertAudio(&convertor);
    }
    else
    {
        Sint16 *expanded = (Sint16 *)destination->abuf;
        int expanded_length;
        int expand_ratio;
        int i;

        // Generic expansion if conversion does not work:
        //
        // SDL's audio conversion only works for rate conversions that are
        // powers of 2; if the two formats are not in a direct power of 2
        // ratio, do this naive conversion instead.

        // number of samples in the converted sound

        expanded_length = ((uint64_t)length * mixer_freq) / samplerate;
        expand_ratio = (length << 8) / expanded_length;

        for (i = 0; i < expanded_length; ++i)
        {
            Sint16 sample;
            int src;

            src = (i * expand_ratio) >> 8;

            sample = data[src] | (data[src] << 8);
            sample -= 32768;

            // expand 8->16 bits, mono->stereo

            expanded[i * 2] = expanded[i * 2 + 1] = sample;
        }

        {
            float rc, dt, alpha;

            // Low-pass filter for cutoff frequency f:
            //
            // For sampling rate r, dt = 1 / r
            // rc = 1 / 2*pi*f
            // alpha = dt / (rc + dt)

            // Filter to the half sample rate of the original sound effect
            // (maximum frequency, by nyquist)

            dt = 1.0f / mixer_freq;
            rc = 1.0f / (float)(2 * M_PI * samplerate);
            alpha = dt / (rc + dt);

            // Both channels are processed in parallel, hence [i - 2]:

            for (i = 2; i < expanded_length * 2; ++i)
            {
                expanded[i] = (Sint16)(alpha * expanded[i]
                              + (1 - alpha) * expanded[i - 2]);
            }
        }
    }
}
Example #6
0
/**
 * @brief Change sv_maxclients and move real clients slots when a demo is playing or stopped
 */
void SV_DemoChangeMaxClients(void)
{
    int      oldMaxClients, oldDemoClients;
    int      i, j, k;
    client_t *oldClients = NULL;
    int      count;
    //qboolean firstTime = svs.clients == NULL;

    // == Checking the prerequisites
    // Note: we check  here that we have enough slots to fit all clients, and that it doesn't overflow the MAX_CLIENTS the engine can support. Also, we save the oldMaxClients and oldDemoClients values.

    // -- Get the highest client number in use
    count = 0;
    for (i = 0 ; i < sv_maxclients->integer ; i++)
    {
        if (svs.clients[i].state >= CS_CONNECTED)
        {
            if (i > count)
            {
                count = i;
            }
        }
    }
    count++;

    // -- Save the previous oldMaxClients and oldDemoClients values, and update

    // Save the previous sv_maxclients value before updating it
    oldMaxClients = sv_maxclients->integer;
    // update the cvars
    Cvar_Get("sv_maxclients", "8", 0);
    Cvar_Get("sv_democlients", "0", 0);   // unnecessary now that sv_democlients is not latched anymore?
    // Save the previous sv_democlients (since it's updated instantly, we cannot get it directly), we use a trick by computing the difference between the new and previous sv_maxclients (the difference should indeed be the exact value of sv_democlients)
    oldDemoClients = (oldMaxClients - sv_maxclients->integer);
    if (oldDemoClients < 0) // if the difference is negative, this means that before it was set to 0 (because the newer sv_maxclients is greater than the old)
    {
        oldDemoClients = 0;
    }

    // -- Check limits
    // never go below the highest client number in use (make sure we have enough room for all players)
    SV_BoundMaxClients(count);

    // -- Change check: if still the same, we just quit, there's nothing to do
    if (sv_maxclients->integer == oldMaxClients)
    {
        return;
    }

    // == Memorizing clients
    // Note: we save in a temporary variables the clients, because after we will wipe completely the svs.clients struct

    // copy the clients to hunk memory
    oldClients = Hunk_AllocateTempMemory((sv_maxclients->integer - sv_democlients->integer) * sizeof(client_t));   // we allocate just enough memory for the real clients (not counting in the democlients)
    // For all previous clients slots, we copy the entire client into a temporary var
    for (i = 0, j = 0, k = sv_privateClients->integer ; i < oldMaxClients ; i++)     // for all the previously connected clients, we copy them to a temporary var
    {   // If there is a real client in this slot
        if (svs.clients[i].state >= CS_CONNECTED)
        {
            // if the client is in a privateClient reserved slot, we move him on the reserved slots
            if (i >= oldDemoClients && i < oldDemoClients + sv_privateClients->integer)
            {
                oldClients[j++] = svs.clients[i];
                // else the client is not a privateClient, and we move him to the first available slot after the privateClients slots
            }
            else
            {
                oldClients[k++] = svs.clients[i];
            }
        }
    }

    // Fill in the remaining clients slots with empty clients (else the engine crash when copying into memory svs.clients)
    for (i = j; i < sv_privateClients->integer; i++)   // Fill the privateClients empty slots
    {
        Com_Memset(&oldClients[i], 0, sizeof(client_t));
    }
    for (i = k; i < (sv_maxclients->integer - sv_democlients->integer); i++)   // Fill the other normal clients slots
    {
        Com_Memset(&oldClients[i], 0, sizeof(client_t));
    }

    // free old clients arrays
    Z_Free(svs.clients);

    // == Allocating the new svs.clients and moving the saved clients over from the temporary var

    // allocate new svs.clients
    svs.clients = Z_Malloc(sv_maxclients->integer * sizeof(client_t));
    Com_Memset(svs.clients, 0, sv_maxclients->integer * sizeof(client_t));

    // copy the clients over (and move them depending on sv_democlients: if >0, move them upwards, if == 0, move them to their original slots)
    Com_Memcpy(svs.clients + sv_democlients->integer, oldClients, (sv_maxclients->integer - sv_democlients->integer) * sizeof(client_t));

    // free the old clients on the hunk
    Hunk_FreeTempMemory(oldClients);

    // == Allocating snapshot entities

    // allocate new snapshot entities
    if (com_dedicated->integer)
    {
        svs.numSnapshotEntities = sv_maxclients->integer * PACKET_BACKUP * 64;
    }
    else
    {
        // we don't need nearly as many when playing locally
        svs.numSnapshotEntities = sv_maxclients->integer * 4 * 64;
    }

    // == Server-side demos management

    // set demostate to none if it was just waiting to set maxclients and move real clients slots
    if (sv.demoState == DS_WAITINGSTOP)
    {
        sv.demoState = DS_NONE;
        Cvar_SetValue("sv_demoState", DS_NONE);
    }
}
Example #7
0
{
   int       groupid = groupcount;
   pgroup_t  *group;
   
   if(from->groupid != R_NOGROUP)
      return from->groupid;
      
   if(groupcount == grouplimit)
   {
      grouplimit = grouplimit ? (grouplimit << 1) : 8;
      groups = erealloc(pgroup_t **, groups, sizeof(pgroup_t **) * grouplimit);
   }
   groupcount++;   
   
   
   group = groups[groupid] = (pgroup_t *)(Z_Malloc(sizeof(pgroup_t), PU_LEVEL, 0));
      
   group->seclist = NULL;
   group->listsize = 0;
  
   P_GatherSectors(from, groupid);
   return groupid;
}

//
// P_GatherSectors
//
// The function will run through the sector's lines list, and add 
// attached sectors to the group's sector list. As each sector is added the 
// currently forming group's id is assigned to that sector. This will continue
// until every attached sector has been added to the list, thus defining a 
Example #8
0
//
// R_GenerateTexture
//
// Allocate space for full size texture, either single patch or 'composite'
// Build the full textures from patches.
// The texture caching system is a little more hungry of memory, but has
// been simplified for the sake of highcolor, dynamic ligthing, & speed.
//
// This is not optimised, but it's supposed to be executed only once
// per level, when enough memory is available.
//
static UINT8 *R_GenerateTexture(size_t texnum)
{
	UINT8 *block;
	UINT8 *blocktex;
	texture_t *texture;
	texpatch_t *patch;
	patch_t *realpatch;
	int x, x1, x2, i;
	size_t blocksize;
	column_t *patchcol;
	UINT32 *colofs;

	I_Assert(texnum <= (size_t)numtextures);
	texture = textures[texnum];
	I_Assert(texture != NULL);

	// allocate texture column offset lookup

	// single-patch textures can have holes in them and may be used on
	// 2sided lines so they need to be kept in 'packed' format
	// BUT this is wrong for skies and walls with over 255 pixels,
	// so check if there's holes and if not strip the posts.
	if (texture->patchcount == 1)
	{
		boolean holey = false;
		patch = texture->patches;
		realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE);

		// Check the patch for holes.
		if (texture->width > SHORT(realpatch->width) || texture->height > SHORT(realpatch->height))
			holey = true;
		colofs = (UINT32 *)realpatch->columnofs;
		for (x = 0; x < texture->width && !holey; x++)
		{
			column_t *col = (column_t *)((UINT8 *)realpatch + LONG(colofs[x]));
			INT32 topdelta, prevdelta = -1, y = 0;
			while (col->topdelta != 0xff)
			{
				topdelta = col->topdelta;
				if (topdelta <= prevdelta)
					topdelta += prevdelta;
				prevdelta = topdelta;
				if (topdelta > y)
					break;
				y = topdelta + col->length + 1;
				col = (column_t *)((UINT8 *)col + col->length + 4);
			}
			if (y < texture->height)
				holey = true; // this texture is HOLEy! D:
		}

		// If the patch uses transparency, we have to save it this way.
		if (holey)
		{
			texture->holes = true;
			blocksize = W_LumpLengthPwad(patch->wad, patch->lump);
			block = Z_Calloc(blocksize, PU_STATIC, // will change tag at end of this function
				&texturecache[texnum]);
			M_Memcpy(block, realpatch, blocksize);
			texturememory += blocksize;

			// use the patch's column lookup
			colofs = (UINT32 *)(void *)(block + 8);
			texturecolumnofs[texnum] = colofs;
			blocktex = block;
			for (x = 0; x < texture->width; x++)
				colofs[x] = LONG(LONG(colofs[x]) + 3);
			goto done;
		}

		// Otherwise, do multipatch format.
	}

	// multi-patch textures (or 'composite')
	texture->holes = false;
	blocksize = (texture->width * 4) + (texture->width * texture->height);
	texturememory += blocksize;
	block = Z_Malloc(blocksize+1, PU_STATIC, &texturecache[texnum]);

	memset(block, 0xF7, blocksize+1); // Transparency hack

	// columns lookup table
	colofs = (UINT32 *)(void *)block;
	texturecolumnofs[texnum] = colofs;

	// texture data after the lookup table
	blocktex = block + (texture->width*4);

	// Composite the columns together.
	for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++)
	{
		realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE);
		x1 = patch->originx;
		x2 = x1 + SHORT(realpatch->width);

		if (x1 < 0)
			x = 0;
		else
			x = x1;

		if (x2 > texture->width)
			x2 = texture->width;

		for (; x < x2; x++)
		{
			patchcol = (column_t *)((UINT8 *)realpatch + LONG(realpatch->columnofs[x-x1]));

			// generate column ofset lookup
			colofs[x] = LONG((x * texture->height) + (texture->width*4));
			R_DrawColumnInCache(patchcol, block + LONG(colofs[x]), patch->originy, texture->height);
		}
	}

done:
	// Now that the texture has been built in column cache, it is purgable from zone memory.
	Z_ChangeTag(block, PU_CACHE);
	return blocktex;
}
Example #9
0
void R_LoadTextures(void)
{
	INT32 i, k, w;
	UINT16 j;
	UINT16 texstart, texend, texturesLumpPos;
	patch_t *patchlump;
	texpatch_t *patch;
	texture_t *texture;

	// Free previous memory before numtextures change.
	if (numtextures)
	{
		for (i = 0; i < numtextures; i++)
		{
			Z_Free(textures[i]);
			Z_Free(texturecache[i]);
		}
		Z_Free(texturetranslation);
		Z_Free(textures);
	}

	// Load patches and textures.

	// Get the number of textures to check.
	// NOTE: Make SURE the system does not process
	// the markers.
	// This system will allocate memory for all duplicate/patched textures even if it never uses them,
	// but the alternative is to spend a ton of time checking and re-checking all previous entries just to skip any potentially patched textures.
	for (w = 0, numtextures = 0; w < numwadfiles; w++)
	{
		texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0) + 1;
		texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0);
		texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0);

		if (texturesLumpPos != INT16_MAX)
		{
			numtextures += R_CountTexturesInTEXTURESLump((UINT16)w);
		}

		// Add all the textures between TX_START and TX_END
		if (texstart != INT16_MAX && texend != INT16_MAX)
		{
			numtextures += (UINT32)(texend - texstart);
		}

		// If no textures found by this point, bomb out
		if (!numtextures && w == (numwadfiles - 1))
		{
			I_Error("No textures detected in any WADs!\n");
		}
	}

	// Allocate memory and initialize to 0 for all the textures we are initialising.
	// There are actually 5 buffers allocated in one for convenience.
	textures = Z_Calloc((numtextures * sizeof(void *)) * 5, PU_STATIC, NULL);

	// Allocate texture column offset table.
	texturecolumnofs = (void *)((UINT8 *)textures + (numtextures * sizeof(void *)));
	// Allocate texture referencing cache.
	texturecache     = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 2));
	// Allocate texture width mask table.
	texturewidthmask = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 3));
	// Allocate texture height mask table.
	textureheight    = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 4));
	// Create translation table for global animation.
	texturetranslation = Z_Malloc((numtextures + 1) * sizeof(*texturetranslation), PU_STATIC, NULL);

	for (i = 0; i < numtextures; i++)
		texturetranslation[i] = i;

	for (i = 0, w = 0; w < numwadfiles; w++)
	{
		// Get the lump numbers for the markers in the WAD, if they exist.
		texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0) + 1;
		texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0);
		texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0);

		if (texturesLumpPos != INT16_MAX)
			R_ParseTEXTURESLump(w,&i);

		if (texstart == INT16_MAX || texend == INT16_MAX)
			continue;

		// Work through each lump between the markers in the WAD.
		for (j = 0; j < (texend - texstart); i++, j++)
		{
			patchlump = W_CacheLumpNumPwad((UINT16)w, texstart + j, PU_CACHE);

			// Then, check the lump directly to see if it's a texture SOC,
			// and if it is, load it using dehacked instead.
			if (strstr((const char *)patchlump, "TEXTURE"))
			{
				CONS_Alert(CONS_WARNING, "%s is a Texture SOC.\n", W_CheckNameForNumPwad((UINT16)w,texstart+j));
				Z_Unlock(patchlump);
				DEH_LoadDehackedLumpPwad((UINT16)w, texstart + j);
			}
			else
			{
				UINT16 patchcount = 1;
				//CONS_Printf("\n\"%s\" is a single patch, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),patchlump->width, patchlump->height);
				if (SHORT(patchlump->width) == 64
				&& SHORT(patchlump->height) == 64)
				{ // 64x64 patch
					const column_t *column;
					for (k = 0; k < SHORT(patchlump->width); k++)
					{ // Find use of transparency.
						column = (const column_t *)((const UINT8 *)patchlump + LONG(patchlump->columnofs[k]));
						if (column->length != SHORT(patchlump->height))
							break;
					}
					if (k == SHORT(patchlump->width))
						patchcount = 2; // No transparency? 64x128 texture.
				}
				texture = textures[i] = Z_Calloc(sizeof(texture_t) + (sizeof(texpatch_t) * patchcount), PU_STATIC, NULL);

				// Set texture properties.
				M_Memcpy(texture->name, W_CheckNameForNumPwad((UINT16)w, texstart + j), sizeof(texture->name));
				texture->width = SHORT(patchlump->width);
				texture->height = SHORT(patchlump->height)*patchcount;
				texture->patchcount = patchcount;
				texture->holes = false;

				// Allocate information for the texture's patches.
				for (k = 0; k < patchcount; k++)
				{
					patch = &texture->patches[k];

					patch->originx = 0;
					patch->originy = (INT16)(k*patchlump->height);
					patch->wad = (UINT16)w;
					patch->lump = texstart + j;
				}

				Z_Unlock(patchlump);

				k = 1;
				while (k << 1 <= texture->width)
					k <<= 1;

				texturewidthmask[i] = k - 1;
				textureheight[i] = texture->height << FRACBITS;
			}
		}
	}
}
Example #10
0
/*
================
SV_SpawnServer

Change the server to a new map, taking all connected
clients along with it.
================
*/
void SV_SpawnServer( char *server, ForceReload_e eForceReload, qboolean bAllowScreenDissolve )
{
	int			i;
	int			checksum;

	RE_RegisterMedia_LevelLoadBegin( server, eForceReload, bAllowScreenDissolve );


	Cvar_SetValue( "cl_paused", 0 );
	Cvar_Set( "timescale", "1" );//jic we were skipping

	// shut down the existing game if it is running
	SV_ShutdownGameProgs();

	Com_Printf ("------ Server Initialization ------\n%s\n", com_version->string);
	Com_Printf ("Server: %s\n",server);	

	// init client structures and svs.numSnapshotEntities 
	if ( !Cvar_VariableIntegerValue("sv_running") ) {
		SV_Startup();
	}		

	// don't let sound stutter and dump all stuff on the hunk
	CL_MapLoading();

	Hunk_Clear();
 	// clear out those shaders, images and Models
	R_InitImages();
	R_InitShaders();
	R_ModelInit();

	// create a heap for Ghoul2 to use for game side model vertex transforms used in collision detection
	if (!G2VertSpaceServer)
	{
		static const int MiniHeapSize=128 * 1024; // maxsize of ghoul2 miniheap
		G2VertSpaceServer	= new CMiniHeap(MiniHeapSize);
	}

	if (svs.snapshotEntities)
	{
		Z_Free(svs.snapshotEntities);
	}
	// allocate the snapshot entities 
	svs.snapshotEntities = (entityState_t *) Z_Malloc (sizeof(entityState_t)*svs.numSnapshotEntities, TAG_CLIENTS, qtrue );

	Music_SetLevelName(server);

	// toggle the server bit so clients can detect that a
	// server has changed
//[email protected]	svs.snapFlagServerBit ^= SNAPFLAG_SERVERCOUNT;

	// set nextmap to the same map, but it may be overriden
	// by the game startup or another console command
	Cvar_Set( "nextmap", va("map %s", server) );

	// wipe the entire per-level structure
	for ( i = 0 ; i < MAX_CONFIGSTRINGS ; i++ ) {
		if ( sv.configstrings[i] ) {
			Z_Free( sv.configstrings[i] );
		}
	}

	memset (&sv, 0, sizeof(sv));


	for ( i = 0 ; i < MAX_CONFIGSTRINGS ; i++ ) {
		sv.configstrings[i] = CopyString("");
	}

	sv.time = 1000;
	G2API_SetTime(sv.time,G2T_SV_TIME);

	CM_LoadMap( va("maps/%s.bsp", server), qfalse, &checksum );

	// set serverinfo visible name
	Cvar_Set( "mapname", server );

	Cvar_Set( "sv_mapChecksum", va("%i",checksum) );

	// serverid should be different each time
	sv.serverId = com_frameTime;
	Cvar_Set( "sv_serverid", va("%i", sv.serverId ) );

	// clear physics interaction links
	SV_ClearWorld ();
	
	// media configstring setting should be done during
	// the loading stage, so connected clients don't have
	// to load during actual gameplay
	sv.state = SS_LOADING;

	// load and spawn all other entities
	SV_InitGameProgs();

	// run a few frames to allow everything to settle
	for ( i = 0 ;i < 3 ; i++ ) {
		ge->RunFrame( sv.time );
		sv.time += 100;
		G2API_SetTime(sv.time,G2T_SV_TIME);
	}

	// create a baseline for more efficient communications
	SV_CreateBaseline ();

	for (i=0 ; i<1 ; i++) {
		// clear all time counters, because we have reset sv.time
		svs.clients[i].lastPacketTime = 0;
		svs.clients[i].lastConnectTime = 0;
		svs.clients[i].nextSnapshotTime = 0;

		// send the new gamestate to all connected clients
		if (svs.clients[i].state >= CS_CONNECTED) {
			char	*denied;

			// connect the client again
			denied = ge->ClientConnect( i, qfalse, eNO/*qfalse*/ );	// firstTime = qfalse, qbFromSavedGame
			if ( denied ) {
				// this generally shouldn't happen, because the client
				// was connected before the level change
				SV_DropClient( &svs.clients[i], denied );
			} else {
				svs.clients[i].state = CS_CONNECTED;
				// when we get the next packet from a connected client,
				// the new gamestate will be sent
			}
		}
	}	

	// run another frame to allow things to look at all connected clients
	ge->RunFrame( sv.time );
	sv.time += 100;
	G2API_SetTime(sv.time,G2T_SV_TIME);


	// save systeminfo and serverinfo strings
	SV_SetConfigstring( CS_SYSTEMINFO, Cvar_InfoString( CVAR_SYSTEMINFO ) );
	cvar_modifiedFlags &= ~CVAR_SYSTEMINFO;

	SV_SetConfigstring( CS_SERVERINFO, Cvar_InfoString( CVAR_SERVERINFO ) );
	cvar_modifiedFlags &= ~CVAR_SERVERINFO;

	// any media configstring setting now should issue a warning
	// and any configstring changes should be reliably transmitted
	// to all clients
	sv.state = SS_GAME;
	
	// send a heartbeat now so the master will get up to date info
	svs.nextHeartbeatTime = -9999999;

	Hunk_SetMark();
	
	Com_Printf ("-----------------------------------\n");
}
Example #11
0
//
// EV_VerticalDoor : open a door manually, no tag value
//
void EV_VerticalDoor(line_t *line, mobj_t *thing)
{
	player_t *player;
	int     secnum;
	sector_t *sec;
	vldoor_t *door;
	int     side;

	side = 0;					// only front sides can be used

	//  Check for locks
	player = thing->player;

	switch (line->special)
	{
	case 26:					// Blue Lock
	case 32:
		if(!player)
			return;

		if(!player->cards[it_bluecard] && !player->cards[it_blueskull])
		{
			P_SetMessage(player, PD_BLUEK);
			S_StartSound(sfx_oof, player->plr->mo);
			return;
		}
		break;

	case 27:					// Yellow Lock
	case 34:
		if(!player)
			return;

		if(!player->cards[it_yellowcard] && !player->cards[it_yellowskull])
		{
			P_SetMessage(player, PD_YELLOWK);
			S_StartSound(sfx_oof, player->plr->mo);
			return;
		}
		break;

	case 28:					// Red Lock
	case 33:
		if(!player)
			return;

		if(!player->cards[it_redcard] && !player->cards[it_redskull])
		{
			P_SetMessage(player, PD_REDK);
			S_StartSound(sfx_oof, player->plr->mo);
			return;
		}
		break;
	}

	// if the sector has an active thinker, use it
	sec = sides[line->sidenum[side ^ 1]].sector;
	secnum = sec - sectors;

	if(sec->specialdata)
	{
		door = sec->specialdata;
		switch (line->special)
		{
		case 1:				// ONLY FOR "RAISE" DOORS, NOT "OPEN"s
		case 26:
		case 27:
		case 28:
		case 117:
			if(door->direction == -1)
				door->direction = 1;	// go back up
			else
			{
				if(!thing->player)
					return;		// JDC: bad guys never close doors

				door->direction = -1;	// start going down immediately
			}
			return;
		}
	}

	// for proper sound
	switch (line->special)
	{
	case 117:					// BLAZING DOOR RAISE
	case 118:					// BLAZING DOOR OPEN
		S_SectorSound(sec, sfx_bdopn);
		break;

	case 1:					// NORMAL DOOR SOUND
	case 31:
		S_SectorSound(sec, sfx_doropn);
		break;

	default:					// LOCKED DOOR SOUND
		S_SectorSound(sec, sfx_doropn);
		break;
	}

	// new door thinker
	door = Z_Malloc(sizeof(*door), PU_LEVSPEC, 0);
	P_AddThinker(&door->thinker);
	sec->specialdata = door;
	door->thinker.function = T_VerticalDoor;
	door->sector = sec;
	door->direction = 1;
	door->speed = VDOORSPEED;
	door->topwait = VDOORWAIT;

	switch (line->special)
	{
	case 1:
	case 26:
	case 27:
	case 28:
		door->type = normal;
		break;

	case 31:
	case 32:
	case 33:
	case 34:
		door->type = open;
		line->special = 0;
		break;

	case 117:					// blazing door raise
		door->type = blazeRaise;
		door->speed = VDOORSPEED * 4;
		break;
	case 118:					// blazing door open
		door->type = blazeOpen;
		line->special = 0;
		door->speed = VDOORSPEED * 4;
		break;
	}

	// find the top and bottom of the movement range
	door->topheight = P_FindLowestCeilingSurrounding(sec);
	door->topheight -= 4 * FRACUNIT;
}
Example #12
0
//
// Do Platforms
//  "amount" is only used for SOME platforms.
//
int EV_DoPlat(line_t *line, plattype_e type, int amount)
{
    plat_t	*plat;
    int		secnum;
    int		rtn;
    sector_t	*sec;

    secnum = -1;
    rtn = 0;

    //	Activate all <type> plats that are in_stasis
    switch(type)
    {
      case perpetualRaise:
	P_ActivateInStasis(line->tag);
	break;

      default:
	break;
    }

    while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0)
    {
	sec = &sectors[secnum];

	if (sec->floordata)
	    continue;

	// Find lowest & highest floors around sector
	rtn = 1;
	plat = Z_Malloc(sizeof(*plat), PU_LEVSPEC, (void *)0);
	P_AddThinker(&plat->thinker);

	plat->type = type;
	plat->sector = sec;
	plat->sector->floordata = plat;
	plat->thinker.function.acp1 = (actionf_p1)T_PlatRaise;
	plat->crush = false;
	plat->tag = line->tag;

	switch(type)
	{
	  case raiseToNearestAndChange:
	    plat->speed = PLATSPEED / 2;
	    sec->floorpic = sides[line->sidenum[0]].sector->floorpic;
	    plat->high = P_FindNextHighestFloor(sec, sec->floorheight);
	    plat->wait = 0;
	    plat->status = up;
	    // NO MORE DAMAGE, IF APPLICABLE
	    sec->special = 0;

	    S_StartSound((mobj_t *)&sec->soundorg, sfx_stnmov);
	    break;

	  case raiseAndChange:
	    plat->speed = PLATSPEED / 2;
	    sec->floorpic = sides[line->sidenum[0]].sector->floorpic;
	    plat->high = sec->floorheight + amount * FRACUNIT;
	    plat->wait = 0;
	    plat->status = up;

	    S_StartSound((mobj_t *)&sec->soundorg, sfx_stnmov);
	    break;

	  case downWaitUpStay:
	    plat->speed = PLATSPEED * 4;
	    plat->low = P_FindLowestFloorSurrounding(sec);

	    if (plat->low > sec->floorheight)
		plat->low = sec->floorheight;

	    plat->high = sec->floorheight;
	    plat->wait = 35 * PLATWAIT;
	    plat->status = down;
	    S_StartSound((mobj_t *)&sec->soundorg, sfx_pstart);
	    break;

	  case blazeDWUS:
	    plat->speed = PLATSPEED * 8;
	    plat->low = P_FindLowestFloorSurrounding(sec);

	    if (plat->low > sec->floorheight)
		plat->low = sec->floorheight;

	    plat->high = sec->floorheight;
	    plat->wait = 35 * PLATWAIT;
	    plat->status = down;
	    S_StartSound((mobj_t *)&sec->soundorg, sfx_pstart);
	    break;

	  case perpetualRaise:
	    plat->speed = PLATSPEED;
	    plat->low = P_FindLowestFloorSurrounding(sec);

	    if (plat->low > sec->floorheight)
		plat->low = sec->floorheight;

	    plat->high = P_FindHighestFloorSurrounding(sec);

	    if (plat->high < sec->floorheight)
		plat->high = sec->floorheight;

	    plat->wait = 35 * PLATWAIT;
	    plat->status = P_Random() & 1;

	    S_StartSound((mobj_t *)&sec->soundorg, sfx_pstart);
	    break;
	}
	P_AddActivePlat(plat);
    }
    return rtn;
}
Example #13
0
//---------------------------------------------------------------------------
static void createTextureCompositePatch(int id) {
  rpatch_t *composite_patch;
  texture_t *texture;
  texpatch_t *texpatch;
  int patchNum;
  const patch_t *oldPatch;
  const column_t *oldColumn, *oldPrevColumn, *oldNextColumn;
  int i, x, y;
  int oy, count;
  int pixelDataSize;
  int columnsDataSize;
  int postsDataSize;
  int dataSize;
  int numPostsTotal;
  const unsigned char *oldColumnPixelData;
  int numPostsUsedSoFar;
  int edgeSlope;
  count_t *countsInColumn;

#ifdef RANGECHECK
  if (id >= numtextures)
    I_Error("createTextureCompositePatch: %i >= numtextures", id);
#endif

  composite_patch = &texture_composites[id];

  texture = textures[id];

  composite_patch->width = texture->width;
  composite_patch->height = texture->height;
  composite_patch->widthmask = texture->widthmask;
  composite_patch->leftoffset = 0;
  composite_patch->topoffset = 0;
  composite_patch->isNotTileable = 0;

  // work out how much memory we need to allocate for this patch's data
  pixelDataSize = (composite_patch->width * composite_patch->height + 4) & ~3;
  columnsDataSize = sizeof(rcolumn_t) * composite_patch->width;

  // count the number of posts in each column
  countsInColumn = (count_t *)calloc(sizeof(count_t), composite_patch->width);
  numPostsTotal = 0;

  for (i=0; i<texture->patchcount; i++) {
    texpatch = &texture->patches[i];
    patchNum = texpatch->patch;
    oldPatch = (const patch_t*)W_CacheLumpNum(patchNum);

    for (x=0; x<SHORT(oldPatch->width); x++) {
      int tx = texpatch->originx + x;

      if (tx < 0)
        continue;
      if (tx >= composite_patch->width)
        break;

      countsInColumn[tx].patches++;

      oldColumn = (const column_t *)((const byte *)oldPatch + LONG(oldPatch->columnofs[x]));
      while (oldColumn->topdelta != 0xff) {
        countsInColumn[tx].posts++;
        numPostsTotal++;
        oldColumn = (const column_t *)((const byte *)oldColumn + oldColumn->length + 4);
      }
    }

    W_UnlockLumpNum(patchNum);
  }

  postsDataSize = numPostsTotal * sizeof(rpost_t);

  // allocate our data chunk
  dataSize = pixelDataSize + columnsDataSize + postsDataSize;
  composite_patch->data = (unsigned char*)Z_Malloc(dataSize, PU_STATIC, (void **)&composite_patch->data);
  memset(composite_patch->data, 0, dataSize);

  // set out pixel, column, and post pointers into our data array
  composite_patch->pixels = composite_patch->data;
  composite_patch->columns = (rcolumn_t*)((unsigned char*)composite_patch->pixels + pixelDataSize);
  composite_patch->posts = (rpost_t*)((unsigned char*)composite_patch->columns + columnsDataSize);

  // sanity check that we've got all the memory allocated we need
  assert((((byte*)composite_patch->posts + numPostsTotal*sizeof(rpost_t)) - (byte*)composite_patch->data) == dataSize);

  memset(composite_patch->pixels, 0xff, (composite_patch->width*composite_patch->height));

  numPostsUsedSoFar = 0;

  for (x=0; x<texture->width; x++) {
      // setup the column's data
      composite_patch->columns[x].pixels = composite_patch->pixels + (x*composite_patch->height);
      composite_patch->columns[x].numPosts = countsInColumn[x].posts;
      composite_patch->columns[x].posts = composite_patch->posts + numPostsUsedSoFar;
      numPostsUsedSoFar += countsInColumn[x].posts;
  }

  // fill in the pixels, posts, and columns
  for (i=0; i<texture->patchcount; i++) {
    texpatch = &texture->patches[i];
    patchNum = texpatch->patch;
    oldPatch = (const patch_t*)W_CacheLumpNum(patchNum);

    for (x=0; x<SHORT(oldPatch->width); x++) {
      int tx = texpatch->originx + x;

      if (tx < 0)
        continue;
      if (tx >= composite_patch->width)
        break;

      oldColumn = (const column_t *)((const byte *)oldPatch + LONG(oldPatch->columnofs[x]));

      {
        // tiling
        int prevColumnIndex = x-1;
        int nextColumnIndex = x+1;
        while (prevColumnIndex < 0) prevColumnIndex += SHORT(oldPatch->width);
        while (nextColumnIndex >= SHORT(oldPatch->width)) nextColumnIndex -= SHORT(oldPatch->width);
        oldPrevColumn = (const column_t *)((const byte *)oldPatch + LONG(oldPatch->columnofs[prevColumnIndex]));
        oldNextColumn = (const column_t *)((const byte *)oldPatch + LONG(oldPatch->columnofs[nextColumnIndex]));
      }

      while (oldColumn->topdelta != 0xff) {
        rpost_t *post = &composite_patch->columns[tx].posts[countsInColumn[tx].posts_used];
        oldColumnPixelData = (const byte *)oldColumn + 3;
        oy = texpatch->originy;
        count = oldColumn->length;
        // the original renderer had several bugs which we reproduce here
        if (countsInColumn[tx].patches > 1) {
          // when there are multiple patches, then we need to handle the
          // column differently
          if (i == 0) {
            // draw first patch at original position, it will be partly
            // overdrawn below
            for (y=0; y<count; y++) {
              int ty = oy + oldColumn->topdelta + y;
              if (ty < 0)
                continue;
              if (ty >= composite_patch->height)
                break;
              composite_patch->pixels[tx * composite_patch->height + ty] = oldColumnPixelData[y];
            }
          }
          // do the buggy clipping
          if (oy < 0) {
            count += oy;
            oy = 0;
          }
        } else {
          // with a single patch only negative y origins are wrong
          oy = 0;
        }
        // set up the post's data
        post->topdelta = oldColumn->topdelta + oy;
        post->length = count;
        if ((post->topdelta + post->length) > composite_patch->height) {
          if ((post->topdelta) > composite_patch->height)
            post->length = 0;
          else
            post->length = composite_patch->height - post->topdelta;
        }
        if (post->topdelta < 0) {
          post->topdelta = 0;
          if ((post->topdelta + post->length) <= 0)
            post->length = 0;
          else
            post->length -= post->topdelta;
        }
        post->slope = 0;

        edgeSlope = getColumnEdgeSlope(oldPrevColumn, oldNextColumn, oldColumn->topdelta);
        if (edgeSlope == 1) post->slope |= RDRAW_EDGESLOPE_TOP_UP;
        else if (edgeSlope == -1) post->slope |= RDRAW_EDGESLOPE_TOP_DOWN;

        edgeSlope = getColumnEdgeSlope(oldPrevColumn, oldNextColumn, oldColumn->topdelta+count);
        if (edgeSlope == 1) post->slope |= RDRAW_EDGESLOPE_BOT_UP;
        else if (edgeSlope == -1) post->slope |= RDRAW_EDGESLOPE_BOT_DOWN;

        // fill in the post's pixels
        for (y=0; y<count; y++) {
          int ty = oy + oldColumn->topdelta + y;
          if (ty < 0)
            continue;
          if (ty >= composite_patch->height)
            break;
          composite_patch->pixels[tx * composite_patch->height + ty] = oldColumnPixelData[y];
        }

        oldColumn = (const column_t *)((const byte *)oldColumn + oldColumn->length + 4);
        countsInColumn[tx].posts_used++;
        assert(countsInColumn[tx].posts_used <= countsInColumn[tx].posts);
      }
    }

    W_UnlockLumpNum(patchNum);
  }

  for (x=0; x<texture->width; x++) {
    rcolumn_t *column;

    if (countsInColumn[x].patches <= 1)
      continue;

    // cleanup posts on multipatch columns
    column = &composite_patch->columns[x];

    i = 0;
    while (i<(column->numPosts-1)) {
      rpost_t *post1 = &column->posts[i];
      rpost_t *post2 = &column->posts[i+1];
      int length;

      if ((post2->topdelta - post1->topdelta) < 0)
        switchPosts(post1, post2);

      if ((post1->topdelta + post1->length) >= post2->topdelta) {
        length = (post1->length + post2->length) - ((post1->topdelta + post1->length) - post2->topdelta);
        if (post1->length < length) {
          post1->slope = post2->slope;
          post1->length = length;
        }
        removePostFromColumn(column, i+1);
        i = 0;
        continue;
      }
      i++;
    }
  }

  if (1 || composite_patch->isNotTileable) {
    const rcolumn_t *column, *prevColumn;

    // copy the patch image down and to the right where there are
    // holes to eliminate the black halo from bilinear filtering
    for (x=0; x<composite_patch->width; x++) {
      //oldColumn = (const column_t *)((const byte *)oldPatch + oldPatch->columnofs[x]);

      column = R_GetPatchColumnClamped(composite_patch, x);
      prevColumn = R_GetPatchColumnClamped(composite_patch, x-1);

      if (column->pixels[0] == 0xff) {
        // force the first pixel (which is a hole), to use
        // the color from the next solid spot in the column
        for (y=0; y<composite_patch->height; y++) {
          if (column->pixels[y] != 0xff) {
            column->pixels[0] = column->pixels[y];
            break;
          }
        }
      }

      // copy from above or to the left
      for (y=1; y<composite_patch->height; y++) {
        //if (getIsSolidAtSpot(oldColumn, y)) continue;
        if (column->pixels[y] != 0xff) continue;

        // this pixel is a hole

        if (x && prevColumn->pixels[y-1] != 0xff) {
          // copy the color from the left
          column->pixels[y] = prevColumn->pixels[y];
        }
        else {
          // copy the color from above
          column->pixels[y] = column->pixels[y-1];
        }
      }
    }

    // verify that the patch truly is non-rectangular since
    // this determines tiling later on
  }

  free(countsInColumn);
}
Example #14
0
//---------------------------------------------------------------------------
static void createPatch(int id) {
  rpatch_t *patch;
  const int patchNum = id;
  const patch_t *oldPatch = (const patch_t*)W_CacheLumpNum(patchNum);
  const column_t *oldColumn, *oldPrevColumn, *oldNextColumn;
  int x, y;
  int pixelDataSize;
  int columnsDataSize;
  int postsDataSize;
  int dataSize;
  int *numPostsInColumn;
  int numPostsTotal;
  const unsigned char *oldColumnPixelData;
  int numPostsUsedSoFar;
  int edgeSlope;

#ifdef RANGECHECK
  if (id >= numlumps)
    I_Error("createPatch: %i >= numlumps", id);
#endif

  patch = &patches[id];
  // proff - 2003-02-16 What about endianess?
  patch->width = SHORT(oldPatch->width);
  patch->widthmask = 0;
  patch->height = SHORT(oldPatch->height);
  patch->leftoffset = SHORT(oldPatch->leftoffset);
  patch->topoffset = SHORT(oldPatch->topoffset);
  patch->isNotTileable = getPatchIsNotTileable(oldPatch);

  // work out how much memory we need to allocate for this patch's data
  pixelDataSize = (patch->width * patch->height + 4) & ~3;
  columnsDataSize = sizeof(rcolumn_t) * patch->width;

  // count the number of posts in each column
  numPostsInColumn = (int*)malloc(sizeof(int) * patch->width);
  numPostsTotal = 0;

  for (x=0; x<patch->width; x++) {
    oldColumn = (const column_t *)((const byte *)oldPatch + LONG(oldPatch->columnofs[x]));
    numPostsInColumn[x] = 0;
    while (oldColumn->topdelta != 0xff) {
      numPostsInColumn[x]++;
      numPostsTotal++;
      oldColumn = (const column_t *)((const byte *)oldColumn + oldColumn->length + 4);
    }
  }

  postsDataSize = numPostsTotal * sizeof(rpost_t);

  // allocate our data chunk
  dataSize = pixelDataSize + columnsDataSize + postsDataSize;
  patch->data = (unsigned char*)Z_Malloc(dataSize, PU_CACHE, (void **)&patch->data);
  memset(patch->data, 0, dataSize);

  // set out pixel, column, and post pointers into our data array
  patch->pixels = patch->data;
  patch->columns = (rcolumn_t*)((unsigned char*)patch->pixels + pixelDataSize);
  patch->posts = (rpost_t*)((unsigned char*)patch->columns + columnsDataSize);

  // sanity check that we've got all the memory allocated we need
  assert((((byte*)patch->posts  + numPostsTotal*sizeof(rpost_t)) - (byte*)patch->data) == dataSize);

  memset(patch->pixels, 0xff, (patch->width*patch->height));

  // fill in the pixels, posts, and columns
  numPostsUsedSoFar = 0;
  for (x=0; x<patch->width; x++) {

    oldColumn = (const column_t *)((const byte *)oldPatch + LONG(oldPatch->columnofs[x]));

    if (patch->isNotTileable) {
      // non-tiling
      if (x == 0) oldPrevColumn = 0;
      else oldPrevColumn = (const column_t *)((const byte *)oldPatch + LONG(oldPatch->columnofs[x-1]));
      if (x == patch->width-1) oldNextColumn = 0;
      else oldNextColumn = (const column_t *)((const byte *)oldPatch + LONG(oldPatch->columnofs[x+1]));
    }
    else {
      // tiling
      int prevColumnIndex = x-1;
      int nextColumnIndex = x+1;
      while (prevColumnIndex < 0) prevColumnIndex += patch->width;
      while (nextColumnIndex >= patch->width) nextColumnIndex -= patch->width;
      oldPrevColumn = (const column_t *)((const byte *)oldPatch + LONG(oldPatch->columnofs[prevColumnIndex]));
      oldNextColumn = (const column_t *)((const byte *)oldPatch + LONG(oldPatch->columnofs[nextColumnIndex]));
    }

    // setup the column's data
    patch->columns[x].pixels = patch->pixels + (x*patch->height) + 0;
    patch->columns[x].numPosts = numPostsInColumn[x];
    patch->columns[x].posts = patch->posts + numPostsUsedSoFar;

    while (oldColumn->topdelta != 0xff) {
      // set up the post's data
      patch->posts[numPostsUsedSoFar].topdelta = oldColumn->topdelta;
      patch->posts[numPostsUsedSoFar].length = oldColumn->length;
      patch->posts[numPostsUsedSoFar].slope = 0;

      edgeSlope = getColumnEdgeSlope(oldPrevColumn, oldNextColumn, oldColumn->topdelta);
      if (edgeSlope == 1) patch->posts[numPostsUsedSoFar].slope |= RDRAW_EDGESLOPE_TOP_UP;
      else if (edgeSlope == -1) patch->posts[numPostsUsedSoFar].slope |= RDRAW_EDGESLOPE_TOP_DOWN;

      edgeSlope = getColumnEdgeSlope(oldPrevColumn, oldNextColumn, oldColumn->topdelta+oldColumn->length);
      if (edgeSlope == 1) patch->posts[numPostsUsedSoFar].slope |= RDRAW_EDGESLOPE_BOT_UP;
      else if (edgeSlope == -1) patch->posts[numPostsUsedSoFar].slope |= RDRAW_EDGESLOPE_BOT_DOWN;

      // fill in the post's pixels
      oldColumnPixelData = (const byte *)oldColumn + 3;
      for (y=0; y<oldColumn->length; y++) {
        patch->pixels[x * patch->height + oldColumn->topdelta + y] = oldColumnPixelData[y];
      }

      oldColumn = (const column_t *)((const byte *)oldColumn + oldColumn->length + 4);
      numPostsUsedSoFar++;
    }
  }

  if (1 || patch->isNotTileable) {
    const rcolumn_t *column, *prevColumn;

    // copy the patch image down and to the right where there are
    // holes to eliminate the black halo from bilinear filtering
    for (x=0; x<patch->width; x++) {
      //oldColumn = (const column_t *)((const byte *)oldPatch + oldPatch->columnofs[x]);

      column = R_GetPatchColumnClamped(patch, x);
      prevColumn = R_GetPatchColumnClamped(patch, x-1);

      if (column->pixels[0] == 0xff) {
        // force the first pixel (which is a hole), to use
        // the color from the next solid spot in the column
        for (y=0; y<patch->height; y++) {
          if (column->pixels[y] != 0xff) {
            column->pixels[0] = column->pixels[y];
            break;
          }
        }
      }

      // copy from above or to the left
      for (y=1; y<patch->height; y++) {
        //if (getIsSolidAtSpot(oldColumn, y)) continue;
        if (column->pixels[y] != 0xff) continue;

        // this pixel is a hole

        if (x && prevColumn->pixels[y-1] != 0xff) {
          // copy the color from the left
          column->pixels[y] = prevColumn->pixels[y];
        }
        else {
          // copy the color from above
          column->pixels[y] = column->pixels[y-1];
        }
      }
    }

    // verify that the patch truly is non-rectangular since
    // this determines tiling later on
  }

  W_UnlockLumpNum(patchNum);
  free(numPostsInColumn);
}
Example #15
0
/*
-----------------------------------------------------------------------------
 Function: LoadOggInfo -Load ogg file.
 
 Parameters: filename -[in] Name of wav file to load.
			 wav -[out] wav data.
			 info -[out] wav sound info.
 
 Returns: True if file loaded, otherwise false.
 
 Notes: Caller is responsible for freeing wav data by calling Z_Free.

-----------------------------------------------------------------------------
*/
PUBLIC _boolean LoadOggInfo( const char *filename, W8 **wav, soundInfo_t *info )
{
	W8	*data;
	int size;
	int dummy;
	char *newFilename;
	int len;
	OggVorbis_File	vorbisFile;
	vorbis_info		vorbisInfo;
	ov_callbacks	vorbisCallbacks = {ovc_read, ovc_seek, ovc_close, ovc_tell};
	int ret;
	
	newFilename = strdup( filename );
	
	len = strlen( newFilename );
	if ( len < 5 || strcmp( newFilename + len - 4, ".wav" ) ) {
		free( newFilename );
		return false;
	}
	
	newFilename[ len - 3 ] = 'o';
	newFilename[ len - 2 ] = 'g';
	newFilename[ len - 1 ] = 'g';
		
	fh = FS_OpenFile( newFilename, 0 );
	if( ! fh )
	{
		free( newFilename );
		return false;
	}

	if( (ret = ov_open_callbacks( fh, &vorbisFile, NULL, 0, vorbisCallbacks )) < 0 ) {
		free( newFilename );
		return false;
	}

	vorbisInfo = *ov_info( &vorbisFile, -1 );
	if( vorbisInfo.channels != 1 && vorbisInfo.channels != 2 )
	{
		Com_Printf( "Only mono and stereo OGG files supported (%s)\n", newFilename );
		free( newFilename );
		return false;
	}
	
	info->channels = vorbisInfo.channels;
	info->sample_rate = vorbisInfo.rate;
	info->sample_size = 2;

#define BUFFER_SIZE ( 128 * 1024 )
	
	data = (W8 *)malloc( BUFFER_SIZE );
	size = 0;
	
	while( size < BUFFER_SIZE )
	{
		int read = 0;
		read = ov_read( &vorbisFile, (char *)data + size, BUFFER_SIZE - size, &dummy );
		if( read == 0 )
		{
			break;
		}
		
		if( read <= 0 )
		{
			Com_Printf( "Only mono and stereo OGG files supported (%s)\n", newFilename );
			free( newFilename );
			return false;
		}
		
		size += read;
	}

	info->samples = size / ( info->channels * info->sample_size );

//	Com_Printf("Loaded %s: channels=%d, sample_rate=%d, sample_size=%d, samples=%d.  \n", newFilename, info->channels, info->sample_rate, info->sample_size, info->samples );
	free( newFilename );

	*wav = (W8 *)Z_Malloc( size );
	memcpy(*wav, data, size );
	free( data );

	
	FS_CloseFile( fh );

	return true;
}
Example #16
0
static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch)
{
	char *texturesToken;
	size_t texturesTokenLength;
	char *endPos;
	char *patchName = NULL;
	INT16 patchXPos;
	INT16 patchYPos;
	texpatch_t *resultPatch = NULL;
	lumpnum_t patchLumpNum;

	// Patch identifier
	texturesToken = M_GetToken(NULL);
	if (texturesToken == NULL)
	{
		I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch name should be");
	}
	texturesTokenLength = strlen(texturesToken);
	if (texturesTokenLength>8)
	{
		I_Error("Error parsing TEXTURES lump: Patch name \"%s\" exceeds 8 characters",texturesToken);
	}
	else
	{
		if (patchName != NULL)
		{
			Z_Free(patchName);
		}
		patchName = (char *)Z_Malloc((texturesTokenLength+1)*sizeof(char),PU_STATIC,NULL);
		M_Memcpy(patchName,texturesToken,texturesTokenLength*sizeof(char));
		patchName[texturesTokenLength] = '\0';
	}

	// Comma 1
	Z_Free(texturesToken);
	texturesToken = M_GetToken(NULL);
	if (texturesToken == NULL)
	{
		I_Error("Error parsing TEXTURES lump: Unexpected end of file where comma after \"%s\"'s patch name should be",patchName);
	}
	if (strcmp(texturesToken,",")!=0)
	{
		I_Error("Error parsing TEXTURES lump: Expected \",\" after %s's patch name, got \"%s\"",patchName,texturesToken);
	}

	// XPos
	Z_Free(texturesToken);
	texturesToken = M_GetToken(NULL);
	if (texturesToken == NULL)
	{
		I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch \"%s\"'s x coordinate should be",patchName);
	}
	endPos = NULL;
#ifndef AVOID_ERRNO
	errno = 0;
#endif
	patchXPos = strtol(texturesToken,&endPos,10);
	(void)patchXPos; //unused for now
	if (endPos == texturesToken // Empty string
		|| *endPos != '\0' // Not end of string
#ifndef AVOID_ERRNO
		|| errno == ERANGE // Number out-of-range
#endif
		)
	{
		I_Error("Error parsing TEXTURES lump: Expected an integer for patch \"%s\"'s x coordinate, got \"%s\"",patchName,texturesToken);
	}

	// Comma 2
	Z_Free(texturesToken);
	texturesToken = M_GetToken(NULL);
	if (texturesToken == NULL)
	{
		I_Error("Error parsing TEXTURES lump: Unexpected end of file where comma after patch \"%s\"'s x coordinate should be",patchName);
	}
	if (strcmp(texturesToken,",")!=0)
	{
		I_Error("Error parsing TEXTURES lump: Expected \",\" after patch \"%s\"'s x coordinate, got \"%s\"",patchName,texturesToken);
	}

	// YPos
	Z_Free(texturesToken);
	texturesToken = M_GetToken(NULL);
	if (texturesToken == NULL)
	{
		I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch \"%s\"'s y coordinate should be",patchName);
	}
	endPos = NULL;
#ifndef AVOID_ERRNO
	errno = 0;
#endif
	patchYPos = strtol(texturesToken,&endPos,10);
	(void)patchYPos; //unused for now
	if (endPos == texturesToken // Empty string
		|| *endPos != '\0' // Not end of string
#ifndef AVOID_ERRNO
		|| errno == ERANGE // Number out-of-range
#endif
		)
	{
		I_Error("Error parsing TEXTURES lump: Expected an integer for patch \"%s\"'s y coordinate, got \"%s\"",patchName,texturesToken);
	}
	Z_Free(texturesToken);

	if (actuallyLoadPatch == true)
	{
		// Check lump exists
		patchLumpNum = W_GetNumForName(patchName);
		// If so, allocate memory for texpatch_t and fill 'er up
		resultPatch = (texpatch_t *)Z_Malloc(sizeof(texpatch_t),PU_STATIC,NULL);
		resultPatch->originx = patchXPos;
		resultPatch->originy = patchYPos;
		resultPatch->lump = patchLumpNum & 65535;
		resultPatch->wad = patchLumpNum>>16;
		// Clean up a little after ourselves
		Z_Free(patchName);
		// Then return it
		return resultPatch;
	}
Example #17
0
/*
==================
SV_WriteDownloadToClient

Check to see if the client wants a file, open it if needed and start pumping the client
Fill up msg with data 
==================
*/
void SV_WriteDownloadToClient( client_t *cl , msg_t *msg )
{
	int curindex;
	int rate;
	int blockspersnap;
	int idPack, missionPack;
	char errorMessage[1024];

	if (!*cl->downloadName)
		return;	// Nothing being downloaded

	if (!cl->download) {
		// We open the file here

		Com_Printf( "clientDownload: %d : begining \"%s\"\n", cl - svs.clients, cl->downloadName );

		missionPack = FS_idPak(cl->downloadName, "missionpack");
		idPack = missionPack || FS_idPak(cl->downloadName, "base");

		if ( !sv_allowDownload->integer || idPack ||
			( cl->downloadSize = FS_SV_FOpenFileRead( cl->downloadName, &cl->download ) ) <= 0 ) {
			// cannot auto-download file
			if (idPack) {
				Com_Printf("clientDownload: %d : \"%s\" cannot download id pk3 files\n", cl - svs.clients, cl->downloadName);
				if (missionPack) {
					Com_sprintf(errorMessage, sizeof(errorMessage), "Cannot autodownload Team Arena file \"%s\"\n"
									"The Team Arena mission pack can be found in your local game store.", cl->downloadName);
				}
				else {
					Com_sprintf(errorMessage, sizeof(errorMessage), "Cannot autodownload id pk3 file \"%s\"", cl->downloadName);
				}
			} else if ( !sv_allowDownload->integer ) {
				Com_Printf("clientDownload: %d : \"%s\" download disabled", cl - svs.clients, cl->downloadName);
				if (sv_pure->integer) {
					Com_sprintf(errorMessage, sizeof(errorMessage), "Could not download \"%s\" because autodownloading is disabled on the server.\n\n"
										"You will need to get this file elsewhere before you "
										"can connect to this pure server.\n", cl->downloadName);
				} else {
					Com_sprintf(errorMessage, sizeof(errorMessage), "Could not download \"%s\" because autodownloading is disabled on the server.\n\n"
										"Set autodownload to No in your settings and you might be "
										"able to connect if you do have the file.\n", cl->downloadName);
				}
			} else {
				Com_Printf("clientDownload: %d : \"%s\" file not found on server\n", cl - svs.clients, cl->downloadName);
				Com_sprintf(errorMessage, sizeof(errorMessage), "File \"%s\" not found on server for autodownloading.\n", cl->downloadName);
			}
			MSG_WriteByte( msg, svc_download );
			MSG_WriteShort( msg, 0 ); // client is expecting block zero
			MSG_WriteLong( msg, -1 ); // illegal file size
			MSG_WriteString( msg, errorMessage );

			*cl->downloadName = 0;
			return;
		}
 
		// Init
		cl->downloadCurrentBlock = cl->downloadClientBlock = cl->downloadXmitBlock = 0;
		cl->downloadCount = 0;
		cl->downloadEOF = qfalse;
	}

	// Perform any reads that we need to
	while (cl->downloadCurrentBlock - cl->downloadClientBlock < MAX_DOWNLOAD_WINDOW &&
		cl->downloadSize != cl->downloadCount) {

		curindex = (cl->downloadCurrentBlock % MAX_DOWNLOAD_WINDOW);

		if (!cl->downloadBlocks[curindex])
			cl->downloadBlocks[curindex] = (unsigned char *)Z_Malloc( MAX_DOWNLOAD_BLKSIZE, TAG_DOWNLOAD, qtrue );

		cl->downloadBlockSize[curindex] = FS_Read( cl->downloadBlocks[curindex], MAX_DOWNLOAD_BLKSIZE, cl->download );

		if (cl->downloadBlockSize[curindex] < 0) {
			// EOF right now
			cl->downloadCount = cl->downloadSize;
			break;
		}

		cl->downloadCount += cl->downloadBlockSize[curindex];

		// Load in next block
		cl->downloadCurrentBlock++;
	}

	// Check to see if we have eof condition and add the EOF block
	if (cl->downloadCount == cl->downloadSize &&
		!cl->downloadEOF &&
		cl->downloadCurrentBlock - cl->downloadClientBlock < MAX_DOWNLOAD_WINDOW) {

		cl->downloadBlockSize[cl->downloadCurrentBlock % MAX_DOWNLOAD_WINDOW] = 0;
		cl->downloadCurrentBlock++;

		cl->downloadEOF = qtrue;  // We have added the EOF block
	}

	// Loop up to window size times based on how many blocks we can fit in the
	// client snapMsec and rate

	// based on the rate, how many bytes can we fit in the snapMsec time of the client
	// normal rate / snapshotMsec calculation
	rate = cl->rate;
	if ( sv_maxRate->integer ) {
		if ( sv_maxRate->integer < 1000 ) {
			Cvar_Set( "sv_MaxRate", "1000" );
		}
		if ( sv_maxRate->integer < rate ) {
			rate = sv_maxRate->integer;
		}
	}

	if (!rate) {
		blockspersnap = 1;
	} else {
		blockspersnap = ( (rate * cl->snapshotMsec) / 1000 + MAX_DOWNLOAD_BLKSIZE ) /
			MAX_DOWNLOAD_BLKSIZE;
	}

	if (blockspersnap < 0)
		blockspersnap = 1;

	while (blockspersnap--) {

		// Write out the next section of the file, if we have already reached our window,
		// automatically start retransmitting

		if (cl->downloadClientBlock == cl->downloadCurrentBlock)
			return; // Nothing to transmit

		if (cl->downloadXmitBlock == cl->downloadCurrentBlock) {
			// We have transmitted the complete window, should we start resending?

			//FIXME:  This uses a hardcoded one second timeout for lost blocks
			//the timeout should be based on client rate somehow
			if (svs.time - cl->downloadSendTime > 1000)
				cl->downloadXmitBlock = cl->downloadClientBlock;
			else
				return;
		}

		// Send current block
		curindex = (cl->downloadXmitBlock % MAX_DOWNLOAD_WINDOW);

		MSG_WriteByte( msg, svc_download );
		MSG_WriteShort( msg, cl->downloadXmitBlock );

		// block zero is special, contains file size
		if ( cl->downloadXmitBlock == 0 )
			MSG_WriteLong( msg, cl->downloadSize );
 
		MSG_WriteShort( msg, cl->downloadBlockSize[curindex] );

		// Write the block
		if ( cl->downloadBlockSize[curindex] ) {
			MSG_WriteData( msg, cl->downloadBlocks[curindex], cl->downloadBlockSize[curindex] );
		}

		Com_DPrintf( "clientDownload: %d : writing block %d\n", cl - svs.clients, cl->downloadXmitBlock );

		// Move on to the next block
		// It will get sent with next snap shot.  The rate will keep us in line.
		cl->downloadXmitBlock++;

		cl->downloadSendTime = svs.time;
	}
}
Example #18
0
/*
==============
S_LoadSound
==============
*/
sfxcache_t *S_LoadSound (sfx_t *s)
{
    char	namebuffer[MAX_QPATH];
	byte	*data;
	wavinfo_t	info;
	int		len;
	float	stepscale;
	sfxcache_t	*sc;
	int		size;
	char	*name;

	if (s->name[0] == '*')
		return NULL;

// see if still in memory
	sc = s->cache;
	if (sc)
		return sc;

//Com_Printf ("S_LoadSound: %x\n", (int)stackbuf);
// load it in
	if (s->truename)
		name = s->truename;
	else
		name = s->name;

	if (name[0] == '#')
		strcpy(namebuffer, &name[1]);
	else
		Com_sprintf (namebuffer, sizeof(namebuffer), "sound/%s", name);

//	Com_Printf ("loading %s\n",namebuffer);

	size = FS_LoadFile (namebuffer, (void **)&data);

	if (!data)
	{
		Com_DPrintf ("Couldn't load %s\n", namebuffer);
		return NULL;
	}

	info = GetWavinfo (s->name, data, size);
	if (info.channels != 1)
	{
		Com_Printf ("%s is a stereo sample\n",s->name);
		FS_FreeFile (data);
		return NULL;
	}

	stepscale = (float)info.rate / dma.speed;	
	len = info.samples / stepscale;

	len = len * info.width * info.channels;

	sc = s->cache = Z_Malloc (len + sizeof(sfxcache_t));
	if (!sc)
	{
		FS_FreeFile (data);
		return NULL;
	}
	
	sc->length = info.samples;
	sc->loopstart = info.loopstart;
	sc->speed = info.rate;
	sc->width = info.width;
	sc->stereo = info.channels;

	ResampleSfx (s, sc->speed, sc->width, data + info.dataofs);

	FS_FreeFile (data);

	return sc;
}
Example #19
0
//
// Special Stuff that can not be categorized
//
int EV_DoDonut(line_t*	line)
{
    sector_t*		s1;
    sector_t*		s2;
    sector_t*		s3;
    int			secnum;
    int			rtn;
    int			i;
    floormove_t*	floor;
	
    secnum = -1;
    rtn = 0;
    while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
    {
	s1 = &sectors[secnum];
		
	// ALREADY MOVING?  IF SO, KEEP GOING...
	if (s1->specialdata)
	    continue;
			
	rtn = 1;
	s2 = getNextSector(s1->lines[0],s1);
	for (i = 0;i < s2->linecount;i++)
	{
//	    if ((!s2->lines[i]->flags & ML_TWOSIDED) ||
	    if (((!s2->lines[i]->flags) & ML_TWOSIDED) || (s2->lines[i]->backsector == s1))
	    {
		continue;
	    }
	    s3 = s2->lines[i]->backsector;
	    
	    //	Spawn rising slime
	    floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
	    P_AddThinker (&floor->thinker);
	    s2->specialdata = floor;
	    floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor;
	    floor->type = donutRaise;
	    floor->crush = false;
	    floor->direction = 1;
	    floor->sector = s2;
	    floor->speed = FLOORSPEED / 2;
	    floor->texture = s3->floorpic;
	    floor->newspecial = 0;
	    floor->floordestheight = s3->floorheight;
	    
	    //	Spawn lowering donut-hole
	    floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
	    P_AddThinker (&floor->thinker);
	    s1->specialdata = floor;
	    floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor;
	    floor->type = lowerFloor;
	    floor->crush = false;
	    floor->direction = -1;
	    floor->sector = s1;
	    floor->speed = FLOORSPEED / 2;
	    floor->floordestheight = s3->floorheight;
	    break;
	}
    }
    return rtn;
}
Example #20
0
// JPG decompression now subroutinised so I can call it from the savegame stuff...
//
// (note, the param "byte* pJPGData" should be a malloc of 4K more than the JPG data because the decompressor will read 
//	up to 4K beyond what's actually presented during decompression).
//	
// This will Z_Malloc the output data buffer that gets fed back into "pic", so Z_Free it yourself later.
//
void Decompress_JPG( const char *filename, byte *pJPGData, unsigned char **pic, int *width, int *height ) 
{
	/* This struct contains the JPEG decompression parameters and pointers to
	* working space (which is allocated as needed by the JPEG library).
	*/
	struct jpeg_decompress_struct cinfo;
	/* We use our private extension JPEG error handler.
	* Note that this struct must live as long as the main JPEG parameter
	* struct, to avoid dangling-pointer problems.
	*/
	/* This struct represents a JPEG error handler.  It is declared separately
	* because applications often want to supply a specialized error handler
	* (see the second half of this file for an example).  But here we just
	* take the easy way out and use the standard error handler, which will
	* print a message on stderr and call exit() if compression fails.
	* Note that this struct must live as long as the main JPEG parameter
	* struct, to avoid dangling-pointer problems.
	*/
	struct jpeg_error_mgr jerr;
	/* More stuff */
	JSAMPARRAY buffer;		/* Output row buffer */
	int row_stride;		/* physical row width in output buffer */
	unsigned char *out;	
	byte  *bbuf;
	
	/* Step 1: allocate and initialize JPEG decompression object */
	
	/* We have to set up the error handler first, in case the initialization
	   * step fails.  (Unlikely, but it could happen if you are out of memory.)
	   * This routine fills in the contents of struct jerr, and returns jerr's
	   * address which we place into the link field in cinfo.
	   */
	cinfo.err = jpeg_std_error(&jerr);
	
	/* Now we can initialize the JPEG decompression object. */
	jpeg_create_decompress(&cinfo);
	
	/* Step 2: specify data source (eg, a file) */
	
	jpeg_stdio_src(&cinfo, pJPGData);
	
	/* Step 3: read file parameters with jpeg_read_header() */
	
	(void) jpeg_read_header(&cinfo, TRUE);
	/* We can ignore the return value from jpeg_read_header since
	   *   (a) suspension is not possible with the stdio data source, and
	   *   (b) we passed TRUE to reject a tables-only JPEG file as an error.
	   * See libjpeg.doc for more info.
	   */
	
	/* Step 4: set parameters for decompression */
	
	/* In this example, we don't need to change any of the defaults set by
	   * jpeg_read_header(), so we do nothing here.
	   */
	
	/* Step 5: Start decompressor */
	
	(void) jpeg_start_decompress(&cinfo);
	/* We can ignore the return value since suspension is not possible
	   * with the stdio data source.
	   */
	
	   /* We may need to do some setup of our own at this point before reading
	   * the data.  After jpeg_start_decompress() we have the correct scaled
	   * output image dimensions available, as well as the output colormap
	   * if we asked for color quantization.
	   * In this example, we need to make an output work buffer of the right size.
	   */ 
	/* JSAMPLEs per row in output buffer */
	row_stride = cinfo.output_width * cinfo.output_components;
	
	if (cinfo.output_components!=4 && cinfo.output_components!=1 ) {
		VID_Printf(PRINT_WARNING, "JPG %s is unsupported color depth (%d)\n", filename, cinfo.output_components);
	}
	out = (byte *)Z_Malloc(cinfo.output_width*cinfo.output_height*4, TAG_TEMP_JPG, qfalse );
	
	*pic = out;
	*width = cinfo.output_width;
	*height = cinfo.output_height;
	
	/* Step 6: while (scan lines remain to be read) */
	/*           jpeg_read_scanlines(...); */
	
	/* Here we use the library's state variable cinfo.output_scanline as the
	   * loop counter, so that we don't have to keep track ourselves.
	   */
	while (cinfo.output_scanline < cinfo.output_height) {
	/* jpeg_read_scanlines expects an array of pointers to scanlines.
	* Here the array is only one element long, but you could ask for
	* more than one scanline at a time if that's more convenient.
		*/
		bbuf = ((out+(row_stride*cinfo.output_scanline)));
		buffer = &bbuf;
		(void) jpeg_read_scanlines(&cinfo, buffer, 1);
	}
	
	// if we've just loaded a greyscale, then adjust it from 8-bit to 32bit by stretch-copying it over itself...
	//  (this also does the alpha stuff as well)
	//
	if (cinfo.output_components == 1)
	{
		byte *pbDest = (*pic + (cinfo.output_width * cinfo.output_height * 4))-1;
		byte *pbSrc  = (*pic + (cinfo.output_width * cinfo.output_height    ))-1;
		int  iPixels = cinfo.output_width * cinfo.output_height;
		
		for (int i=0; i<iPixels; i++)
		{
			byte b = *pbSrc--;
			*pbDest-- = 255;
			*pbDest-- = b;
			*pbDest-- = b;
			*pbDest-- = b;
		}
	}
	else	  
	{// clear all the alphas to 255
		int	i, j;
		byte	*buf;
		
		buf = *pic;
		
		j = cinfo.output_width * cinfo.output_height * 4;
		for ( i = 3 ; i < j ; i+=4 ) {
			buf[i] = 255;
		}
	}
	
	/* Step 7: Finish decompression */
	
	(void) jpeg_finish_decompress(&cinfo);
	/* We can ignore the return value since suspension is not possible
	   * with the stdio data source.
	   */
	
	/* Step 8: Release JPEG decompression object */
	
	/* This is an important step since it will release a good deal of memory. */
	jpeg_destroy_decompress(&cinfo);
	
	/* After finish_decompress, we can close the input file.
	* Here we postpone it until after no more JPEG errors are possible,
	* so as to simplify the setjmp error logic above.  (Actually, I don't
	* think that jpeg_destroy can do an error exit, but why assume anything...)
	*/
	
	/* At this point you may want to check to see whether any corrupt-data
	* warnings occurred (test whether jerr.pub.num_warnings is nonzero).
	*/
	
	/* And we're done! */
}
Example #21
0
// a file has been loaded in memory, see if we want to keep it as MP3, else as normal WAV...
//
// return = qtrue if keeping as MP3
//
// (note: the reason I pass in the unpacked size rather than working it out here is simply because I already have it)
//
qboolean MP3Stream_InitFromFile( sfx_t* sfx, byte *pbSrcData, int iSrcDatalen, const char *psSrcDataFilename, 
									int iMP3UnPackedSize, qboolean bStereoDesired /* = qfalse */
								)
{
	// first, make a decision based on size here as to whether or not it's worth it because of MP3 buffer space
	//	making small files much bigger (and therefore best left as WAV)...
	//
	
	if (cv_MP3overhead &&
			(
			//iSrcDatalen + sizeof(MP3STREAM) + FUZZY_AMOUNT < iMP3UnPackedSize
			iSrcDatalen + cv_MP3overhead->integer < iMP3UnPackedSize
			)
		)
	{
		// ok, let's keep it as MP3 then...
		//
		float fMaxVol = 128;	// seems to be a reasonable typical default for maxvol (for lip synch). Naturally there's no #define I can use instead...

		MP3_ReadSpecialTagInfo(pbSrcData, iSrcDatalen, NULL, NULL, &fMaxVol );	// try and read a read maxvol from MP3 header
	
		// fill in some sfx_t fields...
		//
//		Q_strncpyz( sfx->name, psSrcDataFilename, sizeof(sfx->name) );					
		sfx->eSoundCompressionMethod = ct_MP3;
		sfx->fVolRange = fMaxVol;
		//sfx->width  = 2;
		sfx->iSoundLengthInSamples = ((iMP3UnPackedSize / 2/*sfx->width*/) / (44100 / dma.speed)) / (bStereoDesired?2:1);
		//
		// alloc mem for data and store it (raw MP3 in this case)...
		//
		sfx->pSoundData = (short *) SND_malloc( iSrcDatalen, sfx );
		memcpy( sfx->pSoundData, pbSrcData, iSrcDatalen );
		
		// now init the low-level MP3 stuff...
		//
		MP3STREAM SFX_MP3Stream = {0};	// important to init to all zeroes!
		char *psError = C_MP3Stream_DecodeInit( &SFX_MP3Stream, /*sfx->data*/ /*sfx->soundData*/ pbSrcData, iSrcDatalen,
												dma.speed,//(s_khz->value == 44)?44100:(s_khz->value == 22)?22050:11025,
												2/*sfx->width*/ * 8,
												bStereoDesired
												);
		SFX_MP3Stream.pbSourceData = (byte *) sfx->pSoundData;
		if (psError)
		{
			// This should never happen, since any errors or problems with the MP3 file would have stopped us getting
			//	to this whole function, but just in case...
			//
			Com_Printf(va(S_COLOR_YELLOW"File \"%s\": %s\n",psSrcDataFilename,psError));

			// This will leave iSrcDatalen bytes on the hunk stack (since you can't dealloc that), but MP3 files are
			//	usually small, and like I say, it should never happen.
			//
			// Strictly speaking, I should do a Z_Malloc above, then I could do a Z_Free if failed, else do a Hunk_Alloc
			//	to copy the Z_Malloc data into, then Z_Free, but for something that shouldn't happen it seemed bad to
			//	penalise the rest of the game with extra alloc demands.
			//
			return qfalse;	
		}

		// success ( ...on a plate).
		//
		// make a copy of the filled-in stream struct and attach to the sfx_t struct...
		//
				sfx->pMP3StreamHeader = (MP3STREAM *) Z_Malloc( sizeof(MP3STREAM), TAG_SND_MP3STREAMHDR, qfalse );
		memcpy(	sfx->pMP3StreamHeader, &SFX_MP3Stream,		    sizeof(MP3STREAM) );
		//
		return qtrue;
	}

	return qfalse;
}
Example #22
0
// returns a Z_Malloc'd piece of mem that you should free up yourself
//
byte *Compress_JPG(int *pOutputSize, int quality, int image_width, int image_height, byte *image_buffer, qboolean bInvertDuringCompression)
{
  /* This struct contains the JPEG compression parameters and pointers to
   * working space (which is allocated as needed by the JPEG library).
   * It is possible to have several such structures, representing multiple
   * compression/decompression processes, in existence at once.  We refer
   * to any one struct (and its associated working data) as a "JPEG object".
   */
  struct jpeg_compress_struct cinfo;
  /* This struct represents a JPEG error handler.  It is declared separately
   * because applications often want to supply a specialized error handler
   * (see the second half of this file for an example).  But here we just
   * take the easy way out and use the standard error handler, which will
   * print a message on stderr and call exit() if compression fails.
   * Note that this struct must live as long as the main JPEG parameter
   * struct, to avoid dangling-pointer problems.
   */
  struct jpeg_error_mgr jerr;
  /* More stuff */
  JSAMPROW row_pointer[1];	/* pointer to JSAMPLE row[s] */
  int row_stride;		/* physical row width in image buffer */  

  /* Step 1: allocate and initialize JPEG compression object */

  /* We have to set up the error handler first, in case the initialization
   * step fails.  (Unlikely, but it could happen if you are out of memory.)
   * This routine fills in the contents of struct jerr, and returns jerr's
   * address which we place into the link field in cinfo.
   */
  cinfo.err = jpeg_std_error(&jerr);
  /* Now we can initialize the JPEG compression object. */
  jpeg_create_compress(&cinfo);

  /* Step 2: specify data destination (eg, a file) */
  /* Note: steps 2 and 3 can be done in either order. */

  /* Here we use the library-supplied code to send compressed data to a
   * stdio stream.  You can also write your own code to do something else.
   * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
   * requires it in order to write binary files.
   */
	byte *out =	//  (unsigned char *)ri.Hunk_AllocateTempMemory(image_width*image_height*4);
					(unsigned char *)Z_Malloc(image_width*image_height*4, TAG_TEMP_JPG, qfalse);  	

  jpegDest(&cinfo, out, image_width*image_height*4);

  /* Step 3: set parameters for compression */

  /* First we supply a description of the input image.
   * Four fields of the cinfo struct must be filled in:
   */
  cinfo.image_width = image_width; 	/* image width and height, in pixels */
  cinfo.image_height = image_height;
  cinfo.input_components = 4;		/* # of color components per pixel */
  cinfo.in_color_space = JCS_RGB; 	/* colorspace of input image */
  /* Now use the library's routine to set default compression parameters.
   * (You must set at least cinfo.in_color_space before calling this,
   * since the defaults depend on the source color space.)
   */
  jpeg_set_defaults(&cinfo);
  /* Now you can set any non-default parameters you wish to.
   * Here we just illustrate the use of quality (quantization table) scaling:
   */
  jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);

  /* Step 4: Start compressor */

  /* TRUE ensures that we will write a complete interchange-JPEG file.
   * Pass TRUE unless you are very sure of what you're doing.
   */
  jpeg_start_compress(&cinfo, TRUE);

  /* Step 5: while (scan lines remain to be written) */
  /*           jpeg_write_scanlines(...); */

  /* Here we use the library's state variable cinfo.next_scanline as the
   * loop counter, so that we don't have to keep track ourselves.
   * To keep things simple, we pass one scanline per call; you can pass
   * more if you wish, though.
   */
  row_stride = image_width * 4;	/* JSAMPLEs per row in image_buffer */

  while (cinfo.next_scanline < cinfo.image_height) {
    /* jpeg_write_scanlines expects an array of pointers to scanlines.
     * Here the array is only one element long, but you could pass
     * more than one scanline at a time if that's more convenient.
     */
	 if (bInvertDuringCompression)
	 { 
		row_pointer[0] = & image_buffer[((cinfo.image_height-1)*row_stride)-cinfo.next_scanline * row_stride];
	 }
	 else
	 {
		row_pointer[0] = & image_buffer[									cinfo.next_scanline * row_stride];		 
	 }

     jpeg_write_scanlines(&cinfo, row_pointer, 1);
  }

  /* Step 6: Finish compression */

  jpeg_finish_compress(&cinfo);
  
  /* Step 7: release JPEG compression object */

  /* This is an important step since it will release a good deal of memory. */
  jpeg_destroy_compress(&cinfo);

  /* And we're done! */

  *pOutputSize = hackSize;
  return out;
}
Example #23
0
//
// EV_VerticalDoor : open a door manually, no tag value
//
void
EV_VerticalDoor
( line_t*	line,
  mobj_t*	thing )
{
    player_t*	player;
    sector_t*	sec;
    vldoor_t*	door;
    int		side;
	
    side = 0;	// only front sides can be used

    //	Check for locks
    player = thing->player;
		
    switch(line->special)
    {
      case 26: // Blue Lock
      case 32:
	if ( !player )
	    return;
	
	if (!player->cards[it_bluecard] && !player->cards[it_blueskull])
	{
	    player->message = DEH_String(PD_BLUEK);
	    S_StartSound(NULL,sfx_oof);
	    return;
	}
	break;
	
      case 27: // Yellow Lock
      case 34:
	if ( !player )
	    return;
	
	if (!player->cards[it_yellowcard] &&
	    !player->cards[it_yellowskull])
	{
	    player->message = DEH_String(PD_YELLOWK);
	    S_StartSound(NULL,sfx_oof);
	    return;
	}
	break;
	
      case 28: // Red Lock
      case 33:
	if ( !player )
	    return;
	
	if (!player->cards[it_redcard] && !player->cards[it_redskull])
	{
	    player->message = DEH_String(PD_REDK);
	    S_StartSound(NULL,sfx_oof);
	    return;
	}
	break;
    }
	
    // if the sector has an active thinker, use it

    if (line->sidenum[side^1] == -1)
    {
        I_Error("EV_VerticalDoor: DR special type on 1-sided linedef");
    }

    sec = sides[ line->sidenum[side^1]] .sector;

    if (sec->specialdata)
    {
	door = sec->specialdata;
	switch(line->special)
	{
	  case	1: // ONLY FOR "RAISE" DOORS, NOT "OPEN"s
	  case	26:
	  case	27:
	  case	28:
	  case	117:
	    if (door->direction == -1)
		door->direction = 1;	// go back up
	    else
	    {
		if (!thing->player)
		    return;		// JDC: bad guys never close doors

                // When is a door not a door?
                // In Vanilla, door->direction is set, even though
                // "specialdata" might not actually point at a door.

                if (door->thinker.function.acp1 == (actionf_p1) T_VerticalDoor)
                {
                    door->direction = -1;	// start going down immediately
                }
                else if (door->thinker.function.acp1 == (actionf_p1) T_PlatRaise)
                {
                    // Erm, this is a plat, not a door.
                    // This notably causes a problem in ep1-0500.lmp where
                    // a plat and a door are cross-referenced; the door
                    // doesn't open on 64-bit.
                    // The direction field in vldoor_t corresponds to the wait
                    // field in plat_t.  Let's set that to -1 instead.

                    plat_t *plat;

                    plat = (plat_t *) door;
                    plat->wait = -1;
                }
                else
                {
                    // This isn't a door OR a plat.  Now we're in trouble.

                    fprintf(stderr, "EV_VerticalDoor: Tried to close "
                                    "something that wasn't a door.\n");

                    // Try closing it anyway. At least it will work on 32-bit
                    // machines.

                    door->direction = -1;
                }
	    }
	    return;
	}
    }
	
    // for proper sound
    switch(line->special)
    {
      case 117:	// BLAZING DOOR RAISE
      case 118:	// BLAZING DOOR OPEN
	S_StartSound(&sec->soundorg,sfx_bdopn);
	break;
	
      case 1:	// NORMAL DOOR SOUND
      case 31:
	S_StartSound(&sec->soundorg,sfx_doropn);
	break;
	
      default:	// LOCKED DOOR SOUND
	S_StartSound(&sec->soundorg,sfx_doropn);
	break;
    }
	
    
    // new door thinker
    door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
    P_AddThinker (&door->thinker);
    sec->specialdata = door;
    door->thinker.function.acp1 = (actionf_p1) T_VerticalDoor;
    door->sector = sec;
    door->direction = 1;
    door->speed = VDOORSPEED;
    door->topwait = VDOORWAIT;

    switch(line->special)
    {
      case 1:
      case 26:
      case 27:
      case 28:
	door->type = vld_normal;
	break;
	
      case 31:
      case 32:
      case 33:
      case 34:
	door->type = vld_open;
	line->special = 0;
	break;
	
      case 117:	// blazing door raise
	door->type = vld_blazeRaise;
	door->speed = VDOORSPEED*4;
	break;
      case 118:	// blazing door open
	door->type = vld_blazeOpen;
	line->special = 0;
	door->speed = VDOORSPEED*4;
	break;
    }
    
    // find the top and bottom of the movement range
    door->topheight = P_FindLowestCeilingSurrounding(sec);
    door->topheight -= 4*FRACUNIT;
}
Example #24
0
/*
==============
SV_InitGame

A brand new game has been started
==============
*/
void SV_InitGame (void)
{
	int		i;
	edict_t	*ent;
	char	idmaster[32];

	if (svs.initialized)
	{
		// cause any connected clients to reconnect
		SV_Shutdown ("Server restarted\n", true);
	}
	else
	{
		// make sure the client is down
		CL_Drop ();
		SCR_BeginLoadingPlaque ();
	}

	// get any latched variable changes (maxclients, etc)
	Cvar_GetLatchedVars ();

	svs.initialized = true;

	if (Cvar_VariableValue ("coop") && Cvar_VariableValue ("deathmatch"))
	{
		Com_Printf("Deathmatch and Coop both set, disabling Coop\n");
		Cvar_FullSet ("coop", "0",  CVAR_SERVERINFO | CVAR_LATCH);
	}

	// dedicated servers are can't be single player and are usually DM
	// so unless they explicity set coop, force it to deathmatch
	if (dedicated->value)
	{
		if (!Cvar_VariableValue ("coop"))
			Cvar_FullSet ("deathmatch", "1",  CVAR_SERVERINFO | CVAR_LATCH);
	}

	// init clients
	if (Cvar_VariableValue ("deathmatch"))
	{
		if (maxclients->value <= 1)
			Cvar_FullSet ("maxclients", "8", CVAR_SERVERINFO | CVAR_LATCH);
		else if (maxclients->value > MAX_CLIENTS)
			Cvar_FullSet ("maxclients", va("%i", MAX_CLIENTS), CVAR_SERVERINFO | CVAR_LATCH);
	}
	else if (Cvar_VariableValue ("coop"))
	{
		if (maxclients->value <= 1 || maxclients->value > 4)
			Cvar_FullSet ("maxclients", "4", CVAR_SERVERINFO | CVAR_LATCH);
	}
	else	// non-deathmatch, non-coop is one player
	{
		Cvar_FullSet ("maxclients", "1", CVAR_SERVERINFO | CVAR_LATCH);
	}

	svs.spawncount = rand();
	svs.clients = Z_Malloc (sizeof(client_t)*maxclients->value);
	svs.num_client_entities = maxclients->value*UPDATE_BACKUP*64;
	svs.client_entities = Z_Malloc (sizeof(entity_state_t)*svs.num_client_entities);

	// init network stuff
	NET_Config ( (maxclients->value > 1) );

	// heartbeats will always be sent to the id master
	svs.last_heartbeat = -99999;		// send immediately
	Com_sprintf(idmaster, sizeof(idmaster), "192.246.40.37:%i", PORT_MASTER);
	NET_StringToAdr (idmaster, &master_adr[0]);

	// init game
	SV_InitGameProgs ();
	for (i=0 ; i<maxclients->value ; i++)
	{
		ent = EDICT_NUM(i+1);
		ent->s.number = i+1;
		svs.clients[i].edict = ent;
		memset (&svs.clients[i].lastcmd, 0, sizeof(svs.clients[i].lastcmd));
	}
}
Example #25
0
boolean D_NetGetWad(const char* name)
{
#if defined(HAVE_WAIT_H)
  size_t psize = sizeof(packet_header_t) + strlen(name) + 500;
  packet_header_t *packet;
  boolean done = false;

  if (!server || strchr(name, '/')) return false; // If it contains path info, reject

  do {
    // Send WAD request to remote
    packet = Z_Malloc(psize, PU_STATIC, NULL);
    packet_set(packet, PKT_WAD, 0);
    *(byte*)(packet+1) = consoleplayer;
    strcpy(1+(byte*)(packet+1), name);
    I_SendPacket(packet, sizeof(packet_header_t) + strlen(name) + 2);

    I_uSleep(10000);
  } while (!I_GetPacket(packet, psize) || (packet->type != PKT_WAD));
  Z_Free(packet);

  if (!strcasecmp((void*)(packet+1), name)) {
    pid_t pid;
    int   rv;
    byte *p = (byte*)(packet+1) + strlen(name) + 1;

    /* Automatic wad file retrieval using wget (supports http and ftp, using URLs)
     * Unix systems have all these commands handy, this kind of thing is easy
     * Any windo$e port will have some awkward work replacing these.
     */
    /* cph - caution here. This is data from an untrusted source.
     * Don't pass it via a shell. */
    if ((pid = fork()) == -1)
      perror("fork");
    else if (!pid) {
      /* Child chains to wget, does the download */
      execlp("wget", "wget", p, NULL);
    }
    /* This is the parent, i.e. main LxDoom process */
    wait(&rv);
    if (!(done = !access(name, R_OK))) {
      if (!strcmp(p+strlen(p)-4, ".zip")) {
  p = strrchr(p, '/')+1;
  if ((pid = fork()) == -1)
    perror("fork");
  else if (!pid) {
    /* Child executes decompressor */
    execlp("unzip", "unzip", p, name, NULL);
  }
  /* Parent waits for the file */
  wait(&rv);
  done = !!access(name, R_OK);
      }
      /* Add more decompression protocols here as desired */
    }
    Z_Free(buffer);
  }
  return done;
#else /* HAVE_WAIT_H */
  return false;
#endif
}
Example #26
0
//
// R_GenerateComposite
// Using the texture definition,
//  the composite texture is created from the patches,
//  and each column is cached.
//
void R_GenerateComposite (int texnum)
{
    byte*               block;
    texture_t*          texture;
    texpatch_t*         patch;  
    patch_t*            realpatch;
    int                 x;
    int                 x1;
    int                 x2;
    int                 i;
    column_t*           patchcol;
    short*              collump;
    unsigned short*     colofs;
        
    texture = textures[texnum];

    block = Z_Malloc (texturecompositesize[texnum],
                      PU_STATIC, 
                      &texturecomposite[texnum]);       

    collump = texturecolumnlump[texnum];
    colofs = texturecolumnofs[texnum];
    
    // Composite the columns together.
    patch = texture->patches;
                
    for (i=0 , patch = texture->patches;
         i<texture->patchcount;
         i++, patch++)
    {
        realpatch = W_CacheLumpNum (patch->patch, PU_CACHE);
        x1 = patch->originx;
        x2 = x1 + SHORT(realpatch->width);

        if (x1<0)
            x = 0;
        else
            x = x1;
        
        if (x2 > texture->width)
            x2 = texture->width;

        for ( ; x<x2 ; x++)
        {
            // Column does not have multiple patches?
            if (collump[x] >= 0)
                continue;
            
            patchcol = (column_t *)((byte *)realpatch
                                    + LONG(realpatch->columnofs[x-x1]));
            R_DrawColumnInCache (patchcol,
                                 block + colofs[x],
                                 patch->originy,
                                 texture->height);
        }
                                                
    }

    // Now that the texture has been built in column cache,
    //  it is purgable from zone memory.
    Z_ChangeTag (block, PU_CACHE);
}
Example #27
0
void D_InitNetGame (void)
{
  int i;
  int numplayers = 1;

  i = M_CheckParm("-net");
  if (i && i < myargc-1) i++;

  if (!(netgame = server =  !!i)) {
    playeringame[consoleplayer = 0] = true;
    // e6y
    // for play, recording or playback using "single-player coop" mode.
    // Equivalent to using prboom_server with -N 1
    netgame = M_CheckParm("-solo-net");
  } else {
    // Get game info from server
    packet_header_t *packet = Z_Malloc(1000, PU_STATIC, NULL);
    struct setup_packet_s *sinfo = (void*)(packet+1);
  struct { packet_header_t head; short pn; } PACKEDATTR initpacket;

    I_InitNetwork();
  udp_socket = I_Socket(0);
  I_ConnectToServer(myargv[i]);

    do
    {
      do { 
	// Send init packet
	initpacket.pn = doom_htons(wanted_player_number);
	packet_set(&initpacket.head, PKT_INIT, 0);
	I_SendPacket(&initpacket.head, sizeof(initpacket));
	I_WaitForPacket(5000);
      } while (!I_GetPacket(packet, 1000));
      if (packet->type == PKT_DOWN) I_Error("Server aborted the game");
    } while (packet->type != PKT_SETUP);

    // Once we have been accepted by the server, we should tell it when we leave
    atexit(D_QuitNetGame);

    // Get info from the setup packet
    consoleplayer = sinfo->yourplayer;
    compatibility_level = sinfo->complevel;
    G_Compatibility();
    startskill = sinfo->skill;
    deathmatch = sinfo->deathmatch;
    startmap = sinfo->level;
    startepisode = sinfo->episode;
    ticdup = sinfo->ticdup;
    xtratics = sinfo->extratic;
    G_ReadOptions(sinfo->game_options);

    lprintf(LO_INFO, "\tjoined game as player %d/%d; %d WADs specified\n",
      consoleplayer+1, numplayers = sinfo->players, sinfo->numwads);
    {
      char *p = sinfo->wadnames;
      int i = sinfo->numwads;

      while (i--) {
#ifdef USE_ANDROID
    	  char tmp[80];
    	  strcpy(tmp, doomWADDir);
    	  strcat(tmp, "/");
    	  strcat(tmp, p);
  D_AddFile(tmp, source_net);
#else
  D_AddFile(p, source_net);
#endif
  p += strlen(p) + 1;
      }
    }
    Z_Free(packet);
  }
  localcmds = netcmds[displayplayer = consoleplayer];
  for (i=0; i<numplayers; i++)
    playeringame[i] = true;
  for (; i<MAXPLAYERS; i++)
    playeringame[i] = false;
  if (!playeringame[consoleplayer]) I_Error("D_InitNetGame: consoleplayer not in game");
}
Example #28
0
//
// R_InitTextures
// Initializes the texture list
//  with the textures from the world map.
//
void R_InitTextures (void)
{
    maptexture_t*       mtexture;
    texture_t*          texture;
    mappatch_t*         mpatch;
    texpatch_t*         patch;

    int                 i;
    int                 j;

    int*                maptex;
    int*                maptex2;
    int*                maptex1;
    
    char                name[9];
    char*               names;
    char*               name_p;
    
    int*                patchlookup;
    
    int                 totalwidth;
    int                 nummappatches;
    int                 offset;
    int                 maxoff;
    int                 maxoff2;
    int                 numtextures1;
    int                 numtextures2;

    int*                directory;
    
    int                 temp1;
    int                 temp2;
    int                 temp3;

    
    // Load the patch names from pnames.lmp.
    name[8] = 0;        
    names = W_CacheLumpName ("PNAMES", PU_STATIC);
    nummappatches = LONG ( *((int *)names) );
    name_p = names+4;
    patchlookup = alloca (nummappatches*sizeof(*patchlookup));
    
    for (i=0 ; i<nummappatches ; i++)
    {
        strncpy (name,name_p+i*8, 8);
        patchlookup[i] = W_CheckNumForName (name);
    }
    Z_Free (names);
    
    // Load the map texture definitions from textures.lmp.
    // The data is contained in one or two lumps,
    //  TEXTURE1 for shareware, plus TEXTURE2 for commercial.
    maptex = maptex1 = W_CacheLumpName ("TEXTURE1", PU_STATIC);
    numtextures1 = LONG(*maptex);
    maxoff = W_LumpLength (W_GetNumForName ("TEXTURE1"));
    directory = maptex+1;
        
    if (W_CheckNumForName ("TEXTURE2") != -1)
    {
        maptex2 = W_CacheLumpName ("TEXTURE2", PU_STATIC);
        numtextures2 = LONG(*maptex2);
        maxoff2 = W_LumpLength (W_GetNumForName ("TEXTURE2"));
    }
    else
    {
        maptex2 = NULL;
        numtextures2 = 0;
        maxoff2 = 0;
    }
    numtextures = numtextures1 + numtextures2;
        
    textures = Z_Malloc (numtextures*4, PU_STATIC, 0);
    texturecolumnlump = Z_Malloc (numtextures*4, PU_STATIC, 0);
    texturecolumnofs = Z_Malloc (numtextures*4, PU_STATIC, 0);
    texturecomposite = Z_Malloc (numtextures*4, PU_STATIC, 0);
    texturecompositesize = Z_Malloc (numtextures*4, PU_STATIC, 0);
    texturewidthmask = Z_Malloc (numtextures*4, PU_STATIC, 0);
    textureheight = Z_Malloc (numtextures*4, PU_STATIC, 0);

    totalwidth = 0;
    
    //  Really complex printing shit...
    temp1 = W_GetNumForName ("S_START");  // P_???????
    temp2 = W_GetNumForName ("S_END") - 1;
    temp3 = ((temp2-temp1+63)/64) + ((numtextures+63)/64);
    printf("[");
    for (i = 0; i < temp3; i++)
        printf(" ");
    printf("         ]");
    for (i = 0; i < temp3; i++)
        printf("\x8");
    printf("\x8\x8\x8\x8\x8\x8\x8\x8\x8\x8");   
        
    for (i=0 ; i<numtextures ; i++, directory++)
    {
        if (!(i&63))
            printf (".");

        if (i == numtextures1)
        {
            // Start looking in second texture file.
            maptex = maptex2;
            maxoff = maxoff2;
            directory = maptex+1;
        }
                
        offset = LONG(*directory);

        if (offset > maxoff)
            I_Error ("R_InitTextures: bad texture directory");
        
        mtexture = (maptexture_t *) ( (byte *)maptex + offset);

        texture = textures[i] =
            Z_Malloc (sizeof(texture_t)
                      + sizeof(texpatch_t)*(SHORT(mtexture->patchcount)-1),
                      PU_STATIC, 0);
        
        texture->width = SHORT(mtexture->width);
        texture->height = SHORT(mtexture->height);
        texture->patchcount = SHORT(mtexture->patchcount);

        memcpy (texture->name, mtexture->name, sizeof(texture->name));
        mpatch = &mtexture->patches[0];
        patch = &texture->patches[0];

        for (j=0 ; j<texture->patchcount ; j++, mpatch++, patch++)
        {
            patch->originx = SHORT(mpatch->originx);
            patch->originy = SHORT(mpatch->originy);
            patch->patch = patchlookup[SHORT(mpatch->patch)];
            if (patch->patch == -1)
            {
                I_Error ("R_InitTextures: Missing patch in texture %s",
                         texture->name);
            }
        }               
        texturecolumnlump[i] = Z_Malloc (texture->width*2, PU_STATIC,0);
        texturecolumnofs[i] = Z_Malloc (texture->width*2, PU_STATIC,0);

        j = 1;
        while (j*2 <= texture->width)
            j<<=1;

        texturewidthmask[i] = j-1;
        textureheight[i] = texture->height<<FRACBITS;
                
        totalwidth += texture->width;
    }

    Z_Free (maptex1);
    if (maptex2)
        Z_Free (maptex2);
    
    // Precalculate whatever possible.  
    for (i=0 ; i<numtextures ; i++)
        R_GenerateLookup (i);
    
    // Create translation table for global animation.
    texturetranslation = Z_Malloc ((numtextures+1)*4, PU_STATIC, 0);
    
    for (i=0 ; i<numtextures ; i++)
        texturetranslation[i] = i;
}
Example #29
0
void LoadTGA ( const char *name, byte **pic, int *width, int *height)
{
	char sErrorString[1024];
	bool bFormatErrors = false;

	// these don't need to be declared or initialised until later, but the compiler whines that 'goto' skips them.
	//
	byte *pRGBA = NULL;	
	byte *pOut	= NULL;
	byte *pIn	= NULL;


	*pic = NULL;

#define TGA_FORMAT_ERROR(blah) {sprintf(sErrorString,blah); bFormatErrors = true; goto TGADone;}
//#define TGA_FORMAT_ERROR(blah) Com_Error( ERR_DROP, blah );

	//
	// load the file
	//
	byte *pTempLoadedBuffer = 0;
	ri->FS_ReadFile ( ( char * ) name, (void **)&pTempLoadedBuffer);
	if (!pTempLoadedBuffer) {
		return;
	}

	TGAHeader_t *pHeader = (TGAHeader_t *) pTempLoadedBuffer;

	if (pHeader->byColourmapType!=0)
	{	
		TGA_FORMAT_ERROR("LoadTGA: colourmaps not supported\n" );		
	}

	if (pHeader->byImageType != 2 && pHeader->byImageType != 3 && pHeader->byImageType != 10)
	{
		TGA_FORMAT_ERROR("LoadTGA: Only type 2 (RGB), 3 (gray), and 10 (RLE-RGB) images supported\n");		
	}
		
	if (pHeader->w1stColourMapEntry != 0)
	{
		TGA_FORMAT_ERROR("LoadTGA: colourmaps not supported\n" );		
	}

	if (pHeader->wColourMapLength !=0 && pHeader->wColourMapLength != 256)
	{
		TGA_FORMAT_ERROR("LoadTGA: ColourMapLength must be either 0 or 256\n" );
	}

	if (pHeader->byColourMapEntrySize != 0 && pHeader->byColourMapEntrySize != 24)
	{
		TGA_FORMAT_ERROR("LoadTGA: ColourMapEntrySize must be either 0 or 24\n" );
	}

	if ( ( pHeader->byImagePlanes != 24 && pHeader->byImagePlanes != 32) && (pHeader->byImagePlanes != 8 && pHeader->byImageType != 3))
	{
		TGA_FORMAT_ERROR("LoadTGA: Only type 2 (RGB), 3 (gray), and 10 (RGB) TGA images supported\n");
	}

	if ((pHeader->byScanLineOrder&0x30)!=0x00 &&
		(pHeader->byScanLineOrder&0x30)!=0x10 &&
		(pHeader->byScanLineOrder&0x30)!=0x20 &&
		(pHeader->byScanLineOrder&0x30)!=0x30
		)
	{
		TGA_FORMAT_ERROR("LoadTGA: ScanLineOrder must be either 0x00,0x10,0x20, or 0x30\n");		
	}



	// these last checks are so i can use ID's RLE-code. I don't dare fiddle with it or it'll probably break...
	//
	if ( pHeader->byImageType == 10)
	{
		if ((pHeader->byScanLineOrder & 0x30) != 0x00)
		{
			TGA_FORMAT_ERROR("LoadTGA: RLE-RGB Images (type 10) must be in bottom-to-top format\n");
		}
		if (pHeader->byImagePlanes != 24 && pHeader->byImagePlanes != 32)	// probably won't happen, but avoids compressed greyscales?
		{
			TGA_FORMAT_ERROR("LoadTGA: RLE-RGB Images (type 10) must be 24 or 32 bit\n");
		}
	}

	// now read the actual bitmap in...
	//
	// Image descriptor bytes
	// bits 0-3 = # attr bits (alpha chan)
	// bits 4-5 = pixel order/dir
	// bits 6-7 scan line interleave (00b=none,01b=2way interleave,10b=4way)
	//
	int iYStart,iXStart,iYStep,iXStep;

	switch(pHeader->byScanLineOrder & 0x30)		
	{
		default:	// default case stops the compiler complaining about using uninitialised vars
		case 0x00:					//	left to right, bottom to top

			iXStart = 0;
			iXStep  = 1;

			iYStart = pHeader->wImageHeight-1;
			iYStep  = -1;

			break;

		case 0x10:					//  right to left, bottom to top

			iXStart = pHeader->wImageWidth-1;
			iXStep  = -1;

			iYStart = pHeader->wImageHeight-1;
			iYStep	= -1;

			break;

		case 0x20:					//  left to right, top to bottom

			iXStart = 0;
			iXStep  = 1;

			iYStart = 0;
			iYStep  = 1;

			break;

		case 0x30:					//  right to left, top to bottom

			iXStart = pHeader->wImageWidth-1;
			iXStep  = -1;

			iYStart = 0;
			iYStep  = 1;

			break;
	}

	// feed back the results...
	//
	if (width)
		*width = pHeader->wImageWidth;
	if (height)
		*height = pHeader->wImageHeight;

	pRGBA	= (byte *) Z_Malloc (pHeader->wImageWidth * pHeader->wImageHeight * 4, TAG_TEMP_WORKSPACE, qfalse);
	*pic	= pRGBA;
	pOut	= pRGBA;
	pIn		= pTempLoadedBuffer + sizeof(*pHeader);

	// I don't know if this ID-thing here is right, since comments that I've seen are at the end of the file, 
	//	with a zero in this field. However, may as well...
	//
	if (pHeader->byIDFieldLength != 0)
		pIn += pHeader->byIDFieldLength;	// skip TARGA image comment

	byte red,green,blue,alpha;

	if ( pHeader->byImageType == 2 || pHeader->byImageType == 3 )	// RGB or greyscale
	{
		for (int y=iYStart, iYCount=0; iYCount<pHeader->wImageHeight; y+=iYStep, iYCount++)
		{
			pOut = pRGBA + y * pHeader->wImageWidth *4;			
			for (int x=iXStart, iXCount=0; iXCount<pHeader->wImageWidth; x+=iXStep, iXCount++)
			{
				switch (pHeader->byImagePlanes)
				{
					case 8:
						blue	= *pIn++;
						green	= blue;
						red		= blue;
						*pOut++ = red;
						*pOut++ = green;
						*pOut++ = blue;
						*pOut++ = 255;
						break;

					case 24:
						blue	= *pIn++;
						green	= *pIn++;
						red		= *pIn++;
						*pOut++ = red;
						*pOut++ = green;
						*pOut++ = blue;
						*pOut++ = 255;
						break;

					case 32:
						blue	= *pIn++;
						green	= *pIn++;
						red		= *pIn++;
						alpha	= *pIn++;
						*pOut++ = red;
						*pOut++ = green;
						*pOut++ = blue;
						*pOut++ = alpha;
						break;
					
					default:
						assert(0);	// if we ever hit this, someone deleted a header check higher up
						TGA_FORMAT_ERROR("LoadTGA: Image can only have 8, 24 or 32 planes for RGB/greyscale\n");						
						break;
				}
			}		
		}
	}
	else 
	if (pHeader->byImageType == 10)   // RLE-RGB
	{
		// I've no idea if this stuff works, I normally reject RLE targas, but this is from ID's code
		//	so maybe I should try and support it...
		//
		byte packetHeader, packetSize, j;

		for (int y = pHeader->wImageHeight-1; y >= 0; y--)
		{
			pOut = pRGBA + y * pHeader->wImageWidth *4;
			for (int x=0; x<pHeader->wImageWidth;)
			{
				packetHeader = *pIn++;
				packetSize   = 1 + (packetHeader & 0x7f);
				if (packetHeader & 0x80)         // run-length packet
				{
					switch (pHeader->byImagePlanes) 
					{
						case 24:

							blue	= *pIn++;
							green	= *pIn++;
							red		= *pIn++;
							alpha	= 255;
							break;

						case 32:
							
							blue	= *pIn++;
							green	= *pIn++;
							red		= *pIn++;
							alpha	= *pIn++;
							break;

						default:
							assert(0);	// if we ever hit this, someone deleted a header check higher up
							TGA_FORMAT_ERROR("LoadTGA: RLE-RGB can only have 24 or 32 planes\n");
							break;
					}
	
					for (j=0; j<packetSize; j++) 
					{
						*pOut++	= red;
						*pOut++	= green;
						*pOut++	= blue;
						*pOut++	= alpha;
						x++;
						if (x == pHeader->wImageWidth)  // run spans across rows
						{
							x = 0;
							if (y > 0)
								y--;
							else
								goto breakOut;
							pOut = pRGBA + y * pHeader->wImageWidth * 4;
						}
					}
				}
				else 
				{	// non run-length packet

					for (j=0; j<packetSize; j++) 
					{
						switch (pHeader->byImagePlanes) 
						{
							case 24:

								blue	= *pIn++;
								green	= *pIn++;
								red		= *pIn++;
								*pOut++ = red;
								*pOut++ = green;
								*pOut++ = blue;
								*pOut++ = 255;
								break;

							case 32:
								blue	= *pIn++;
								green	= *pIn++;
								red		= *pIn++;
								alpha	= *pIn++;
								*pOut++ = red;
								*pOut++ = green;
								*pOut++ = blue;
								*pOut++ = alpha;
								break;

							default:
								assert(0);	// if we ever hit this, someone deleted a header check higher up
								TGA_FORMAT_ERROR("LoadTGA: RLE-RGB can only have 24 or 32 planes\n");
								break;
						}
						x++;
						if (x == pHeader->wImageWidth)  // pixel packet run spans across rows
						{
							x = 0;
							if (y > 0)
								y--;
							else
								goto breakOut;
							pOut = pRGBA + y * pHeader->wImageWidth * 4;
						}
					}
				}
			}
			breakOut:;
		}
	}

TGADone:

	ri->FS_FreeFile (pTempLoadedBuffer);

	if (bFormatErrors)
	{
		Com_Error( ERR_DROP, "%s( File: \"%s\" )\n",sErrorString,name);
	}
}
Example #30
0
void *Z_MemDup(void const *ptr, size_t size)
{
    void *copy = Z_Malloc(size, PU_APPSTATIC, 0);
    memcpy(copy, ptr, size);
    return copy;
}