/* * CMod_LoadTexinfo */ static void CMod_LoadTexinfo( cmodel_state_t *cms, lump_t *l ) { int i; int count; cshaderref_t *out; q2texinfo_t *in; size_t len, bufLen, bufSize; char *buffer; in = ( void * )( cms->cmod_base + l->fileofs ); if( l->filelen % sizeof( *in ) ) { Com_Error( ERR_DROP, "CMod_LoadTexinfo: funny lump size" ); } count = l->filelen / sizeof( *in ); if( count < 1 ) { Com_Error( ERR_DROP, "Map with no textures" ); } out = cms->map_shaderrefs = Mem_Alloc( cms->mempool, count * sizeof( *out ) ); cms->numshaderrefs = count; buffer = NULL; bufLen = bufSize = 0; for( i = 0; i < count; i++, in++, out++, bufLen += len + 1 ) { len = strlen( in->texture ); if( bufLen + len >= bufSize ) { bufSize = bufLen + len + 128; if( buffer ) { buffer = Mem_Realloc( buffer, bufSize ); } else { buffer = Mem_Alloc( cms->mempool, bufSize ); } } out->name = ( char * )( ( void * )bufLen ); strcpy( buffer + bufLen, in->texture ); out->contents = 0; // unused out->flags = CMod_SurfaceFlags( LittleLong( in->flags ), 0 ); } for( i = 0; i < count; i++ ) cms->map_shaderrefs[i].name = buffer + ( size_t )( ( void * )cms->map_shaderrefs[i].name ); }
/* ================ FS_AddSideToPack ================ */ qboolean FS_AddSideToPack( const char *name, int adjust_flags ) { byte *out, *flipped; qboolean resampled = false; // first side set average size for all cubemap sides! if( !image.cubemap ) { image.source_width = image.width; image.source_height = image.height; image.source_type = image.type; } // keep constant size, render.dll expecting it image.size = image.source_width * image.source_height * 4; // mixing dds format with any existing ? if( image.type != image.source_type ) return false; // flip image if needed flipped = Image_FlipInternal( image.rgba, &image.width, &image.height, image.source_type, adjust_flags ); if( !flipped ) return false; // try to reasmple dxt? if( flipped != image.rgba ) image.rgba = Image_Copy( image.size ); // resampling image if needed out = Image_ResampleInternal((uint *)image.rgba, image.width, image.height, image.source_width, image.source_height, image.source_type, &resampled ); if( !out ) return false; // try to reasmple dxt? if( resampled ) image.rgba = Image_Copy( image.size ); image.cubemap = Mem_Realloc( host.imagepool, image.cubemap, image.ptr + image.size ); Q_memcpy( image.cubemap + image.ptr, image.rgba, image.size ); // add new side Mem_Free( image.rgba ); // release source buffer image.ptr += image.size; // move to next image.num_sides++; // bump sides count return true; }
/* ================ Sound_ResampleInternal We need convert sound to signed even if nothing to resample ================ */ qboolean Sound_ResampleInternal( wavdata_t *sc, int inrate, int inwidth, int outrate, int outwidth ) { float stepscale; int outcount, srcsample; int i, sample, sample2, samplefrac, fracstep; byte *data; data = sc->buffer; stepscale = (float)inrate / outrate; // this is usually 0.5, 1, or 2 outcount = sc->samples / stepscale; sc->size = outcount * outwidth * sc->channels; sound.tempbuffer = (byte *)Mem_Realloc( host.soundpool, sound.tempbuffer, sc->size ); sc->samples = outcount; if( sc->loopStart != -1 ) sc->loopStart = sc->loopStart / stepscale; // resample / decimate to the current source rate if( stepscale == 1.0f && inwidth == 1 && outwidth == 1 ) { Sound_ConvertToSigned( data, sc->channels, outcount ); } else { // general case samplefrac = 0; fracstep = stepscale * 256; if( sc->channels == 2 ) { for( i = 0; i < outcount; i++ ) { srcsample = samplefrac >> 8; samplefrac += fracstep; if( inwidth == 2 ) { sample = ((short *)data)[srcsample*2+0]; sample2 = ((short *)data)[srcsample*2+1]; } else { sample = (int)((char)(data[srcsample*2+0])) << 8; sample2 = (int)((char)(data[srcsample*2+1])) << 8; } if( outwidth == 2 ) { ((short *)sound.tempbuffer)[i*2+0] = sample; ((short *)sound.tempbuffer)[i*2+1] = sample2; } else { ((signed char *)sound.tempbuffer)[i*2+0] = sample >> 8; ((signed char *)sound.tempbuffer)[i*2+1] = sample2 >> 8; } } } else { for( i = 0; i < outcount; i++ ) { srcsample = samplefrac >> 8; samplefrac += fracstep; if( inwidth == 2 ) sample = ((short *)data)[srcsample]; else sample = (int)( (char)(data[srcsample])) << 8; if( outwidth == 2 ) ((short *)sound.tempbuffer)[i] = sample; else ((signed char *)sound.tempbuffer)[i] = sample >> 8; } } MsgDev( D_NOTE, "Sound_Resample: from[%d bit %d kHz] to [%d bit %d kHz]\n", inwidth * 8, inrate, outwidth * 8, outrate ); }
/* ============= Image_SaveJPG ============= */ bool Image_SaveJPG( const char *name, rgbdata_t *pix ) { struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; byte *scanline, *input; uint i, linesize; file_t *file; if( FS_FileExists( name ) && !(image.cmd_flags & IL_ALLOW_OVERWRITE )) return false; // already existed // Open the file file = FS_Open( name, "wb" ); if( !file ) return false; if( setjmp( error_save_jpeg )) goto error_caught; cinfo.err = jpeg_std_error( &jerr ); cinfo.err->error_exit = JPEG_ErrorSave; jpeg_create_compress( &cinfo ); JPEG_FileDest( &cinfo, file ); // Set the parameters for compression cinfo.image_width = pix->width; cinfo.image_height = pix->height; // get image description switch( pix->type ) { case PF_RGBA_32: input = image.tempbuffer = Mem_Realloc( Sys.imagepool, image.tempbuffer, pix->width * pix->height * 3 ); for( i = 0; i < pix->width * pix->height; i++ ) { input[i*3+0] = pix->buffer[i*4+0]; input[i*3+1] = pix->buffer[i*4+1]; input[i*3+2] = pix->buffer[i*4+2]; } cinfo.input_components = 3; break; case PF_RGB_24: cinfo.input_components = 3; input = pix->buffer; break; default: MsgDev( D_ERROR, "Image_SaveJPG: unsupported image type %s\n", PFDesc[pix->type].name ); goto error_caught; } if( cinfo.input_components == 3 ) cinfo.in_color_space = JCS_RGB; else cinfo.in_color_space = JCS_GRAYSCALE; jpeg_set_defaults( &cinfo ); jpeg_set_quality( &cinfo, (jpg_quality->value * 10), true ); // turn off subsampling (to make text look better) cinfo.optimize_coding = 1; cinfo.comp_info[0].h_samp_factor = 1; cinfo.comp_info[0].v_samp_factor = 1; cinfo.comp_info[1].h_samp_factor = 1; cinfo.comp_info[1].v_samp_factor = 1; cinfo.comp_info[2].h_samp_factor = 1; cinfo.comp_info[2].v_samp_factor = 1; jpeg_start_compress( &cinfo, true ); // compress each scanline linesize = cinfo.image_width * cinfo.input_components; while( cinfo.next_scanline < cinfo.image_height ) { scanline = &input[cinfo.next_scanline * linesize]; jpeg_write_scanlines( &cinfo, &scanline, 1 ); } jpeg_finish_compress( &cinfo ); jpeg_destroy_compress( &cinfo ); FS_Close( file ); return true; error_caught: jpeg_destroy_compress( &cinfo ); FS_Close( file ); FS_Delete( name ); // kill invalid file return false; }
/* * IN_RawInput_MouseRead */ void IN_RawInput_MouseRead( HANDLE in_device_handle ) { int i = 0, tbuttons, j; int dwSize; if( !raw || !rawmice || rawmicecount < 1 ) { return; // no thx } // get raw input if( ( *_GRID )( (HRAWINPUT)in_device_handle, RID_INPUT, NULL, &dwSize, sizeof( RAWINPUTHEADER ) ) == -1 ) { Com_Printf( "Raw input: unable to add to get size of raw input header.\n" ); return; } if( dwSize > ribuffersize ) { ribuffersize = dwSize; raw = Mem_Realloc( raw, dwSize ); } if( ( *_GRID )( (HRAWINPUT)in_device_handle, RID_INPUT, raw, &dwSize, sizeof( RAWINPUTHEADER ) ) != dwSize ) { Com_Printf( "Raw input: unable to add to get raw input header.\n" ); return; } // find mouse in our mouse list for( ; i < rawmicecount; i++ ) { if( rawmice[i].rawinputhandle == raw->header.hDevice ) { break; } } if( i == rawmicecount ) { // we're not tracking this mouse return; } // movement if( raw->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE ) { if( rawmice[i].pos[0] != RI_INVALID_POS ) { rawmice[i].delta[0] += raw->data.mouse.lLastX - rawmice[i].pos[0]; rawmice[i].delta[1] += raw->data.mouse.lLastY - rawmice[i].pos[1]; } rawmice[i].pos[0] = raw->data.mouse.lLastX; rawmice[i].pos[1] = raw->data.mouse.lLastY; } else { // RELATIVE rawmice[i].delta[0] += raw->data.mouse.lLastX; rawmice[i].delta[1] += raw->data.mouse.lLastY; rawmice[i].pos[0] = RI_INVALID_POS; } // buttons if( raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_1_DOWN ) { Key_MouseEvent( K_MOUSE1, true, sys_msg_time ); } if( raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_1_UP ) { Key_MouseEvent( K_MOUSE1, false, sys_msg_time ); } if( raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_2_DOWN ) { Key_MouseEvent( K_MOUSE2, true, sys_msg_time ); } if( raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_2_UP ) { Key_MouseEvent( K_MOUSE2, false, sys_msg_time ); } if( raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_3_DOWN ) { Key_MouseEvent( K_MOUSE3, true, sys_msg_time ); } if( raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_3_UP ) { Key_MouseEvent( K_MOUSE3, false, sys_msg_time ); } if( raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_DOWN ) { Key_MouseEvent( K_MOUSE4, true, sys_msg_time ); } if( raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_UP ) { Key_MouseEvent( K_MOUSE4, false, sys_msg_time ); } if( raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_DOWN ) { Key_MouseEvent( K_MOUSE5, true, sys_msg_time ); } if( raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_UP ) { Key_MouseEvent( K_MOUSE5, false, sys_msg_time ); } // mouse wheel if( raw->data.mouse.usButtonFlags & RI_MOUSE_WHEEL ) { // if the current message has a mouse_wheel message if( (SHORT)raw->data.mouse.usButtonData > 0 ) { Key_Event( K_MWHEELUP, true, sys_msg_time ); Key_Event( K_MWHEELUP, false, sys_msg_time ); } if( (SHORT)raw->data.mouse.usButtonData < 0 ) { Key_Event( K_MWHEELDOWN, true, sys_msg_time ); Key_Event( K_MWHEELDOWN, false, sys_msg_time ); } } // extra buttons tbuttons = raw->data.mouse.ulRawButtons & RI_RAWBUTTON_MASK; for( j = 6; j < rawmice[i].numbuttons; j++ ) { if( ( tbuttons & ( 1 << j ) ) && !( rawmice[i].buttons & ( 1 << j ) ) ) { Key_MouseEvent( K_MOUSE1 + j, true, sys_msg_time ); } if( !( tbuttons & ( 1 << j ) ) && ( rawmice[i].buttons & ( 1 << j ) ) ) { Key_MouseEvent( K_MOUSE1 + j, false, sys_msg_time ); } } rawmice[i].buttons &= ~RI_RAWBUTTON_MASK; rawmice[i].buttons |= tbuttons; }
/* ================ FS_LoadImage loading and unpack to rgba any known image ================ */ rgbdata_t *FS_LoadImage( const char *filename, const byte *buffer, size_t size ) { const char *ext = FS_FileExtension( filename ); string path, loadname, sidename; qboolean anyformat = true; int i, filesize = 0; const loadpixformat_t *format; const cubepack_t *cmap; byte *f; Image_Reset(); // clear old image Q_strncpy( loadname, filename, sizeof( loadname )); if( Q_stricmp( ext, "" )) { // we needs to compare file extension with list of supported formats // and be sure what is real extension, not a filename with dot for( format = image.loadformats; format && format->formatstring; format++ ) { if( !Q_stricmp( format->ext, ext )) { FS_StripExtension( loadname ); anyformat = false; break; } } } // HACKHACK: skip any checks, load file from buffer if( filename[0] == '#' && buffer && size ) goto load_internal; // now try all the formats in the selected list for( format = image.loadformats; format && format->formatstring; format++) { if( anyformat || !Q_stricmp( ext, format->ext )) { Q_sprintf( path, format->formatstring, loadname, "", format->ext ); image.hint = format->hint; f = FS_LoadFile( path, &filesize, false ); if( f && filesize > 0 ) { if( format->loadfunc( path, f, filesize )) { Mem_Free( f ); // release buffer return ImagePack(); // loaded } else Mem_Free(f); // release buffer } } } // check all cubemap sides with package suffix for( cmap = load_cubemap; cmap && cmap->type; cmap++ ) { for( i = 0; i < 6; i++ ) { // for support mixed cubemaps e.g. sky_ft.bmp, sky_rt.tga // NOTE: all loaders must keep sides in one format for all for( format = image.loadformats; format && format->formatstring; format++ ) { if( anyformat || !Q_stricmp( ext, format->ext )) { Q_sprintf( path, format->formatstring, loadname, cmap->type[i].suf, format->ext ); image.hint = cmap->type[i].hint; // side hint f = FS_LoadFile( path, &filesize, false ); if( f && filesize > 0 ) { // this name will be used only for tell user about problems if( format->loadfunc( path, f, filesize )) { Q_snprintf( sidename, sizeof( sidename ), "%s%s.%s", loadname, cmap->type[i].suf, format->ext ); if( FS_AddSideToPack( sidename, cmap->type[i].flags )) // process flags to flip some sides { Mem_Free( f ); break; // loaded } } Mem_Free( f ); } } } if( image.num_sides != i + 1 ) // check side { // first side not found, probably it's not cubemap // it contain info about image_type and dimensions, don't generate black cubemaps if( !image.cubemap ) break; MsgDev( D_ERROR, "FS_LoadImage: couldn't load (%s%s), create black image\n", loadname, cmap->type[i].suf ); // Mem_Alloc already filled memblock with 0x00, no need to do it again image.cubemap = Mem_Realloc( host.imagepool, image.cubemap, image.ptr + image.size ); image.ptr += image.size; // move to next image.num_sides++; // merge counter } } // make sure what all sides is loaded if( image.num_sides != 6 ) { // unexpected errors ? if( image.cubemap ) Mem_Free( image.cubemap ); Image_Reset(); } else break; } if( image.cubemap ) return ImagePack(); // all done load_internal: for( format = image.loadformats; format && format->formatstring; format++ ) { if( anyformat || !Q_stricmp( ext, format->ext )) { image.hint = format->hint; if( buffer && size > 0 ) { if( format->loadfunc( loadname, buffer, size )) return ImagePack(); // loaded } } } if( !image.loadformats || image.loadformats->ext == NULL ) MsgDev( D_NOTE, "FS_LoadImage: imagelib offline\n" ); else if( filename[0] != '#' ) MsgDev( D_WARN, "FS_LoadImage: couldn't load \"%s\"\n", loadname ); // clear any force flags image.force_flags = 0; return NULL; }