/* ================= Mod_LoadMarksurfaces ================= */ void Mod_LoadMarksurfaces (lump_t *l) { int i, j, count; short *in; msurface_t **out; in = (short *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) VID_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name); count = l->filelen / sizeof(*in); out = (msurface_t **) Hunk_Alloc ( count*sizeof(*out)); loadmodel->marksurfaces = out; loadmodel->nummarksurfaces = count; for ( i=0 ; i<count ; i++) { j = LittleShort(in[i]); if (j < 0 || j >= loadmodel->numsurfaces) VID_Error (ERR_DROP, "Mod_ParseMarksurfaces: bad surface number"); out[i] = loadmodel->surfaces + j; } }
/* * @brief */ static void R_LoadBspLeafSurfaces(r_bsp_model_t *bsp, const d_bsp_lump_t *l) { int32_t i; r_bsp_surface_t **out; const uint16_t *in = (const void *) (mod_base + l->file_ofs); if (l->file_len % sizeof(*in)) { Com_Error(ERR_DROP, "Funny lump size\n"); } bsp->num_leaf_surfaces = l->file_len / sizeof(*in); bsp->leaf_surfaces = out = Z_LinkMalloc(bsp->num_leaf_surfaces * sizeof(*out), bsp); for (i = 0; i < bsp->num_leaf_surfaces; i++) { const uint16_t j = (uint16_t) LittleShort(in[i]); if (j >= bsp->num_surfaces) { Com_Error(ERR_DROP, "Bad surface number: %d\n", j); } out[i] = bsp->surfaces + j; } }
void DiskWriterIO::SetClockRate(double samples_per_tick) { TimePerTick = samples_per_tick / OPL_SAMPLE_RATE * 1000.0; if (Format == FMT_RDOS) { double clock_rate; int clock_mul; WORD clock_word; clock_rate = samples_per_tick * ADLIB_CLOCK_MUL; clock_mul = 1; // The RDos raw format's clock rate is stored in a word. Therefore, // the longest tick that can be stored is only ~55 ms. while (clock_rate / clock_mul + 0.5 > 65535.0) { clock_mul++; } clock_word = WORD(clock_rate / clock_mul + 0.5); if (NeedClockRate) { // Set the initial clock rate. clock_word = LittleShort(clock_word); fseek(File, 8, SEEK_SET); fwrite(&clock_word, 2, 1, File); fseek(File, 0, SEEK_END); NeedClockRate = false; } else { // Change the clock rate in the middle of the song. BYTE clock_change[4] = { 0, 2, clock_word & 255, clock_word >> 8 }; fwrite(clock_change, 1, 4, File); } } }
/* * @brief */ static void Cm_LoadBspLeafBrushes(const d_bsp_lump_t *l) { const uint16_t *in = (const void *) (cm_bsp.base + l->file_ofs); if (l->file_len % sizeof(*in)) { Com_Error(ERR_DROP, "Funny lump size\n"); } const int32_t count = l->file_len / sizeof(*in); if (count < 1) { Com_Error(ERR_DROP, "Invalid leaf brush count: %d\n", count); } if (count > MAX_BSP_LEAF_BRUSHES) { Com_Error(ERR_DROP, "%d > MAX_BSP_LEAF_BRUSHES\n", count); } uint16_t *out = cm_bsp.leaf_brushes; cm_bsp.num_leaf_brushes = count; for (int32_t i = 0; i < count; i++, in++, out++) { *out = LittleShort(*in); } }
/* ================= Mod_LoadMarksurfaces ================= */ void Mod_LoadMarksurfaces (lump_t *l) { int i, j, count; unsigned short *in; // JDH: was signed short msurface_t **out; in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) Host_Error ("Mod_LoadMarksurfaces: funny lump size in %s", loadmodel->name); // was Sys_Error count = l->filelen / sizeof(*in); out = Hunk_AllocName (count * sizeof(*out), mod_loadname); loadmodel->marksurfaces = out; loadmodel->nummarksurfaces = count; for (i=0 ; i<count ; i++) { j = (unsigned short) LittleShort(in[i]); if (j >= loadmodel->numsurfaces) Host_Error ("Mod_LoadMarksurfaces: bad surface number"); // was Sys_Error out[i] = loadmodel->surfaces + j; } }
void Mod_LoadLeafs(lump_t *l) { dleaf_t *in; mleaf_t *out; int i, j, count, p; in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) { ri.Sys_Error(ERR_DROP, "MOD_LoadBmodel: funny lump size in %s", loadmodel->name); } count = l->filelen / sizeof(*in); out = Hunk_Alloc(count * sizeof(*out)); loadmodel->leafs = out; loadmodel->numleafs = count; for (i = 0; i < count; i++, in++, out++) { for (j = 0; j < 3; j++) { out->minmaxs[j] = LittleShort(in->mins[j]); out->minmaxs[3 + j] = LittleShort(in->maxs[j]); } p = LittleLong(in->contents); out->contents = p; out->cluster = LittleShort(in->cluster); out->area = LittleShort(in->area); out->firstmarksurface = loadmodel->marksurfaces + LittleShort(in->firstleafface); out->nummarksurfaces = LittleShort(in->numleaffaces); } }
/* ================ usercmd_t::ByteSwap ================ */ void usercmd_t::ByteSwap( void ) { angles[0] = LittleShort( angles[0] ); angles[1] = LittleShort( angles[1] ); angles[2] = LittleShort( angles[2] ); sequence = LittleLong( sequence ); }
/* ================= R_LoadMD3 ================= */ static qboolean R_LoadMD3 (model_t *mod, int lod, void *buffer, const char *mod_name ) { int i, j; md3Header_t *pinmodel; md3Frame_t *frame; md3Surface_t *surf; md3Shader_t *shader; md3Triangle_t *tri; md3St_t *st; md3XyzNormal_t *xyz; md3Tag_t *tag; int version; int size; pinmodel = (md3Header_t *)buffer; version = LittleLong (pinmodel->version); if (version != MD3_VERSION) { ri.Printf( PRINT_WARNING, "R_LoadMD3: %s has wrong version (%i should be %i)\n", mod_name, version, MD3_VERSION); return qfalse; } mod->type = MOD_MESH; size = LittleLong(pinmodel->ofsEnd); mod->dataSize += size; mod->md3[lod] = ri.Hunk_Alloc( size, h_low ); memcpy (mod->md3[lod], buffer, LittleLong(pinmodel->ofsEnd) ); LL(mod->md3[lod]->ident); LL(mod->md3[lod]->version); LL(mod->md3[lod]->numFrames); LL(mod->md3[lod]->numTags); LL(mod->md3[lod]->numSurfaces); LL(mod->md3[lod]->ofsFrames); LL(mod->md3[lod]->ofsTags); LL(mod->md3[lod]->ofsSurfaces); LL(mod->md3[lod]->ofsEnd); if ( mod->md3[lod]->numFrames < 1 ) { ri.Printf( PRINT_WARNING, "R_LoadMD3: %s has no frames\n", mod_name ); return qfalse; } // swap all the frames frame = (md3Frame_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsFrames ); for ( i = 0 ; i < mod->md3[lod]->numFrames ; i++, frame++) { frame->radius = LittleFloat( frame->radius ); for ( j = 0 ; j < 3 ; j++ ) { frame->bounds[0][j] = LittleFloat( frame->bounds[0][j] ); frame->bounds[1][j] = LittleFloat( frame->bounds[1][j] ); frame->localOrigin[j] = LittleFloat( frame->localOrigin[j] ); } } // swap all the tags tag = (md3Tag_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsTags ); for ( i = 0 ; i < mod->md3[lod]->numTags * mod->md3[lod]->numFrames ; i++, tag++) { for ( j = 0 ; j < 3 ; j++ ) { tag->origin[j] = LittleFloat( tag->origin[j] ); tag->axis[0][j] = LittleFloat( tag->axis[0][j] ); tag->axis[1][j] = LittleFloat( tag->axis[1][j] ); tag->axis[2][j] = LittleFloat( tag->axis[2][j] ); } } // swap all the surfaces surf = (md3Surface_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsSurfaces ); for ( i = 0 ; i < mod->md3[lod]->numSurfaces ; i++) { LL(surf->ident); LL(surf->flags); LL(surf->numFrames); LL(surf->numShaders); LL(surf->numTriangles); LL(surf->ofsTriangles); LL(surf->numVerts); LL(surf->ofsShaders); LL(surf->ofsSt); LL(surf->ofsXyzNormals); LL(surf->ofsEnd); if ( surf->numVerts > SHADER_MAX_VERTEXES ) { ri.Error (ERR_DROP, "R_LoadMD3: %s has more than %i verts on a surface (%i)", mod_name, SHADER_MAX_VERTEXES, surf->numVerts ); } if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) { ri.Error (ERR_DROP, "R_LoadMD3: %s has more than %i triangles on a surface (%i)", mod_name, SHADER_MAX_INDEXES / 3, surf->numTriangles ); } // change to surface identifier surf->ident = SF_MD3; // lowercase the surface name so skin compares are faster Q_strlwr( surf->name ); // strip off a trailing _1 or _2 // this is a crutch for q3data being a mess j = strlen( surf->name ); if ( j > 2 && surf->name[j-2] == '_' ) { surf->name[j-2] = 0; } // register the shaders shader = (md3Shader_t *) ( (byte *)surf + surf->ofsShaders ); for ( j = 0 ; j < surf->numShaders ; j++, shader++ ) { shader_t *sh; sh = R_FindShader( shader->name, LIGHTMAP_NONE, qtrue ); if ( sh->defaultShader ) { shader->shaderIndex = 0; } else { shader->shaderIndex = sh->index; } } // swap all the triangles tri = (md3Triangle_t *) ( (byte *)surf + surf->ofsTriangles ); for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) { LL(tri->indexes[0]); LL(tri->indexes[1]); LL(tri->indexes[2]); } // swap all the ST st = (md3St_t *) ( (byte *)surf + surf->ofsSt ); for ( j = 0 ; j < surf->numVerts ; j++, st++ ) { st->st[0] = LittleFloat( st->st[0] ); st->st[1] = LittleFloat( st->st[1] ); } // swap all the XyzNormals xyz = (md3XyzNormal_t *) ( (byte *)surf + surf->ofsXyzNormals ); for ( j = 0 ; j < surf->numVerts * surf->numFrames ; j++, xyz++ ) { xyz->xyz[0] = LittleShort( xyz->xyz[0] ); xyz->xyz[1] = LittleShort( xyz->xyz[1] ); xyz->xyz[2] = LittleShort( xyz->xyz[2] ); xyz->normal = LittleShort( xyz->normal ); } // find the next surface surf = (md3Surface_t *)( (byte *)surf + surf->ofsEnd ); } return qtrue; }
void convert_sample_data(Sample *sp, const void *data) { /* convert everything to 32-bit floating point data */ sample_t *newdata = NULL; switch (sp->modes & (PATCH_16 | PATCH_UNSIGNED)) { case 0: { /* 8-bit, signed */ SBYTE *cp = (SBYTE *)data; newdata = (sample_t *)safe_malloc((sp->data_length + 1) * sizeof(sample_t)); for (int i = 0; i < sp->data_length; ++i) { if (cp[i] < 0) { newdata[i] = float(cp[i]) / 128.f; } else { newdata[i] = float(cp[i]) / 127.f; } } break; } case PATCH_UNSIGNED: { /* 8-bit, unsigned */ BYTE *cp = (BYTE *)data; newdata = (sample_t *)safe_malloc((sp->data_length + 1) * sizeof(sample_t)); for (int i = 0; i < sp->data_length; ++i) { int c = cp[i] - 128; if (c < 0) { newdata[i] = float(c) / 128.f; } else { newdata[i] = float(c) / 127.f; } } break; } case PATCH_16: { /* 16-bit, signed */ SWORD *cp = (SWORD *)data; /* Convert these to samples */ sp->data_length >>= 1; sp->loop_start >>= 1; sp->loop_end >>= 1; newdata = (sample_t *)safe_malloc((sp->data_length + 1) * sizeof(sample_t)); for (int i = 0; i < sp->data_length; ++i) { int c = LittleShort(cp[i]); if (c < 0) { newdata[i] = float(c) / 32768.f; } else { newdata[i] = float(c) / 32767.f; } } break; } case PATCH_16 | PATCH_UNSIGNED: { /* 16-bit, unsigned */ WORD *cp = (WORD *)data; /* Convert these to samples */ sp->data_length >>= 1; sp->loop_start >>= 1; sp->loop_end >>= 1; newdata = (sample_t *)safe_malloc((sp->data_length + 1) * sizeof(sample_t)); for (int i = 0; i < sp->data_length; ++i) { int c = LittleShort(cp[i]) - 32768; if (c < 0) { newdata[i] = float(c) / 32768.f; } else { newdata[i] = float(c) / 32767.f; } } break; } } /* Duplicate the final sample for linear interpolation. */ newdata[sp->data_length] = newdata[sp->data_length - 1]; if (sp->data != NULL) { free(sp->data); } sp->data = newdata; }
/* ============= LoadTGA ============= */ void LoadTGA( const char *name, byte **pic, int *width, int *height, byte alphaByte ) { unsigned int columns, rows, numPixels; byte *pixbuf; int row, column; byte *buf_p; byte *buffer; TargaHeader targa_header; byte *targa_rgba; *pic = NULL; // // load the file // ri.FS_ReadFile( ( char * ) name, ( void ** ) &buffer ); if ( !buffer ) { return; } 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 != 2 && targa_header.image_type != 10 && targa_header.image_type != 3 ) { ri.FS_FreeFile( buffer ); ri.Error( ERR_DROP, "LoadTGA: Only type 2 (RGB), 3 (gray), and 10 (RGB) TGA images supported (%s)", name ); } if ( targa_header.colormap_type != 0 ) { ri.FS_FreeFile( buffer ); ri.Error( ERR_DROP, "LoadTGA: colormaps not supported (%s)", name ); } if ( ( targa_header.pixel_size != 32 && targa_header.pixel_size != 24 ) && targa_header.image_type != 3 ) { ri.FS_FreeFile( buffer ); ri.Error( ERR_DROP, "LoadTGA: Only 32 or 24 bit images supported (no colormaps) (%s)", name ); } columns = targa_header.width; rows = targa_header.height; numPixels = columns * rows * 4; if ( width ) { *width = columns; } if ( height ) { *height = rows; } if ( !columns || !rows || numPixels > 0x7FFFFFFF || numPixels / columns / 4 != rows ) { ri.FS_FreeFile( buffer ); ri.Error( ERR_DROP, "LoadTGA: %s has an invalid image size", name ); } targa_rgba = (byte*) ri.Z_Malloc( numPixels ); *pic = targa_rgba; if ( targa_header.id_length != 0 ) { buf_p += targa_header.id_length; // skip TARGA image comment } if ( targa_header.image_type == 2 || targa_header.image_type == 3 ) { // Uncompressed RGB or gray scale image for ( row = rows - 1; row >= 0; row-- ) { pixbuf = targa_rgba + row * columns * 4; for ( column = 0; column < columns; column++ ) { unsigned char red, green, blue, alpha; switch ( targa_header.pixel_size ) { case 8: blue = *buf_p++; green = blue; red = blue; *pixbuf++ = red; *pixbuf++ = green; *pixbuf++ = blue; *pixbuf++ = alphaByte; break; case 24: blue = *buf_p++; green = *buf_p++; red = *buf_p++; *pixbuf++ = red; *pixbuf++ = green; *pixbuf++ = blue; *pixbuf++ = alphaByte; break; case 32: blue = *buf_p++; green = *buf_p++; red = *buf_p++; alpha = *buf_p++; *pixbuf++ = red; *pixbuf++ = green; *pixbuf++ = blue; *pixbuf++ = alpha; break; default: ri.Free( targa_rgba ); ri.FS_FreeFile( buffer ); ri.Error( ERR_DROP, "LoadTGA: illegal pixel_size '%d' in file '%s'", targa_header.pixel_size, name ); } } } } else if ( targa_header.image_type == 10 ) { // Runlength encoded RGB images unsigned char red, green, blue, alpha, packetHeader, packetSize, j; red = 0; green = 0; blue = 0; alpha = alphaByte; for ( row = rows - 1; row >= 0; row-- ) { pixbuf = targa_rgba + row * columns * 4; for ( column = 0; column < columns; ) { packetHeader = *buf_p++; packetSize = 1 + ( packetHeader & 0x7f ); if ( packetHeader & 0x80 ) { // run-length packet switch ( targa_header.pixel_size ) { case 24: blue = *buf_p++; green = *buf_p++; red = *buf_p++; alpha = alphaByte; break; case 32: blue = *buf_p++; green = *buf_p++; red = *buf_p++; alpha = *buf_p++; break; default: ri.Free( targa_rgba ); ri.FS_FreeFile( buffer ); ri.Error( ERR_DROP, "LoadTGA: illegal pixel_size '%d' in file '%s'", targa_header.pixel_size, name ); } for ( j = 0; j < packetSize; j++ ) { *pixbuf++ = red; *pixbuf++ = green; *pixbuf++ = blue; *pixbuf++ = alpha; column++; if ( column == columns ) { // run spans across rows column = 0; if ( row > 0 ) { row--; } else { goto breakOut; } pixbuf = targa_rgba + row * columns * 4; } } } else { // non run-length packet for ( j = 0; j < packetSize; j++ ) { switch ( targa_header.pixel_size ) { case 24: blue = *buf_p++; green = *buf_p++; red = *buf_p++; *pixbuf++ = red; *pixbuf++ = green; *pixbuf++ = blue; *pixbuf++ = alphaByte; break; case 32: blue = *buf_p++; green = *buf_p++; red = *buf_p++; alpha = *buf_p++; *pixbuf++ = red; *pixbuf++ = green; *pixbuf++ = blue; *pixbuf++ = alpha; break; default: ri.Free( targa_rgba ); ri.FS_FreeFile( buffer ); ri.Error( ERR_DROP, "LoadTGA: illegal pixel_size '%d' in file '%s'", targa_header.pixel_size, name ); } column++; if ( column == columns ) { // pixel packet run spans across rows column = 0; if ( row > 0 ) { row--; } else { goto breakOut; } pixbuf = targa_rgba + row * columns * 4; } } } } breakOut: ; } } #if 1 // TTimo: this is the chunk of code to ensure a behavior that meets TGA specs // bk0101024 - fix from Leonardo // bit 5 set => top-down if ( targa_header.attributes & 0x20 ) { unsigned char *flip; unsigned char *src, *dst; //ri.Printf(PRINT_WARNING, "WARNING: '%s' TGA file header declares top-down image, flipping\n", name); flip = ( unsigned char * ) ri.Hunk_AllocateTempMemory( columns * 4 ); for ( row = 0; row < rows / 2; row++ ) { src = targa_rgba + row * 4 * columns; dst = targa_rgba + ( rows - row - 1 ) * 4 * columns; memcpy( flip, src, columns * 4 ); memcpy( src, dst, columns * 4 ); memcpy( dst, flip, columns * 4 ); } ri.Hunk_FreeTempMemory( flip ); } #else // instead we just print a warning if ( targa_header.attributes & 0x20 ) { ri.Printf( PRINT_WARNING, "WARNING: '%s' TGA file header declares top-down image, ignoring\n", name ); } #endif ri.FS_FreeFile( buffer ); }
void LoadPCX(const char *filename, byte ** pic, byte ** palette, int *width, int *height) { byte *raw; pcx_t *pcx; int x, y, lsize; int len; int dataByte, runLength; byte *out, *pix; /* load the file */ len = vfsLoadFile(filename, (void **)&raw, 0); if(len == -1) Error("LoadPCX: Couldn't read %s", filename); /* parse the PCX file */ pcx = (pcx_t *) raw; raw = &pcx->data; pcx->xmin = LittleShort(pcx->xmin); pcx->ymin = LittleShort(pcx->ymin); pcx->xmax = LittleShort(pcx->xmax); pcx->ymax = LittleShort(pcx->ymax); pcx->hres = LittleShort(pcx->hres); pcx->vres = LittleShort(pcx->vres); pcx->bytes_per_line = LittleShort(pcx->bytes_per_line); pcx->palette_type = LittleShort(pcx->palette_type); if(pcx->manufacturer != 0x0a || pcx->version != 5 || pcx->encoding != 1 || pcx->bits_per_pixel != 8 || pcx->xmax >= 640 || pcx->ymax >= 480) Error("Bad pcx file %s", filename); if(palette) { *palette = safe_malloc(768); memcpy(*palette, (byte *) pcx + len - 768, 768); } if(width) *width = pcx->xmax + 1; if(height) *height = pcx->ymax + 1; if(!pic) return; out = safe_malloc((pcx->ymax + 1) * (pcx->xmax + 1)); if(!out) Error("LoadPCX: couldn't allocate"); *pic = out; pix = out; /* RR2DO2: pcx fix */ lsize = pcx->color_planes * pcx->bytes_per_line; /* go scanline by scanline */ for(y = 0; y <= pcx->ymax; y++, pix += pcx->xmax + 1) { /* do a scanline */ for(x = 0; x <= pcx->xmax;) { /* RR2DO2 */ DECODEPCX(raw, dataByte, runLength); while(runLength-- > 0) pix[x++] = dataByte; } /* RR2DO2: discard any other data */ while(x < lsize) { DECODEPCX(raw, dataByte, runLength); x++; } while(runLength-- > 0) x++; } /* validity check */ if(raw - (byte *) pcx > len) Error("PCX file %s was malformed", filename); free(pcx); }
/* ================= Mod_LoadFaces ================= */ void Mod_LoadFaces (lump_t *l) { dface_t *in; msurface_t *out; int i, count, surfnum; int planenum, side; in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); count = l->filelen / sizeof(*in); out = Hunk_AllocName ( count*sizeof(*out), loadname); loadmodel->surfaces = out; loadmodel->numsurfaces = count; for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++) { out->firstedge = LittleLong(in->firstedge); out->numedges = LittleShort(in->numedges); out->flags = 0; planenum = LittleShort(in->planenum); side = LittleShort(in->side); if (side) out->flags |= SURF_PLANEBACK; out->plane = loadmodel->planes + planenum; out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo); CalcSurfaceExtents (out); // lighting info for (i=0 ; i<MAXLIGHTMAPS ; i++) out->styles[i] = in->styles[i]; i = LittleLong(in->lightofs); if (i == -1) out->samples = NULL; else out->samples = loadmodel->lightdata + i; // set the drawing flags flag if (!Q_strncmp(out->texinfo->texture->name,"sky",3)) // sky { out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED); #ifndef QUAKE2 GL_SubdivideSurface (out); // cut up polygon for warps #endif continue; } if (!Q_strncmp(out->texinfo->texture->name,"*",1)) // turbulent { out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED); for (i=0 ; i<2 ; i++) { out->extents[i] = 16384; out->texturemins[i] = -8192; } GL_SubdivideSurface (out); // cut up polygon for warps continue; } } }
/* ================ ResampleSfx ================ */ void ResampleSfx (sfx_t *sfx, int inrate, int inwidth, byte *data) { int outcount; int srcsample; float stepscale; int i; int sample, samplefrac, fracstep; sfxcache_t *sc; sc = sfx->cache; if (!sc) return; stepscale = (float)inrate / dma.speed; // this is usually 0.5, 1, or 2 outcount = sc->length / stepscale; sc->length = outcount; if (sc->loopstart != -1) sc->loopstart = sc->loopstart / stepscale; sc->speed = dma.speed; // moved in S_LoadSound /* if (s_loadas8bit->value) sc->width = 1; else sc->width = inwidth; */ sc->stereo = 0; // resample / decimate to the current source rate if (stepscale == 1 && inwidth == 1 && sc->width == 1) { #if DEBUG_AUDIO Com_Printf ("ResampleSfx : fast case 1\n" ); #endif // fast special case for (i=0 ; i<outcount ; i++) ((signed char *)sc->data)[i] = (int)( (unsigned char)(data[i]) - 128); } else if (stepscale == 1 && inwidth == 2 && sc->width == 1 ) { #if DEBUG_AUDIO Com_Printf ("ResampleSfx : fast case 2\n" ); #endif // fast special case : used for android on arm processor for (i=0 ; i<outcount ; i++) ((signed char *)sc->data)[i] = ( (signed char)(data[2*i+1]) ); } else { #if DEBUG_AUDIO Com_Printf ("ResampleSfx : stepscale=%.1f inwidth=%d outwidth=%d\n", stepscale, inwidth, sc->width ); #endif // general case samplefrac = 0; fracstep = stepscale*256; for (i=0 ; i<outcount ; i++) { srcsample = samplefrac >> 8; samplefrac += fracstep; if (inwidth == 2) sample = LittleShort ( ((short *)data)[srcsample] ); else sample = (int)( (unsigned char)(data[srcsample]) - 128) << 8; if (sc->width == 2) ((short *)sc->data)[i] = sample; else ((signed char *)sc->data)[i] = sample >> 8; } } }
qboolean AAS_RT_ReadRouteTable(fileHandle_t fp) { int ident, version, i; unsigned short int crc, crc_aas; aas_rt_t *routetable; aas_rt_child_t *child; aas_rt_parent_t *parent; aas_rt_parent_link_t *plink; unsigned short int *psi; qboolean doswap; #ifdef DEBUG_READING_TIME int pretime; pretime = Sys_MilliSeconds(); #endif routetable = (*aasworld).routetable; doswap = (LittleLong(1) != 1); // check ident AAS_RT_DBG_Read(&ident, sizeof(ident), fp); ident = LittleLong(ident); if (ident != RTBID) { AAS_Error("File is not an RTB file\n"); botimport.FS_FCloseFile(fp); return qfalse; } // check version AAS_RT_DBG_Read(&version, sizeof(version), fp); version = LittleLong(version); if (version != RTBVERSION) { AAS_Error("File is version %i not %i\n", version, RTBVERSION); botimport.FS_FCloseFile(fp); return qfalse; } // read the CRC check on the AAS data AAS_RT_DBG_Read(&crc, sizeof(crc), fp); crc = LittleShort(crc); // calculate a CRC on the AAS areas crc_aas = CRC_ProcessString((unsigned char *)(*aasworld).areas, sizeof(aas_area_t) * (*aasworld).numareas); if (crc != crc_aas) { AAS_Error("Route-table is from different AAS file, ignoring.\n"); botimport.FS_FCloseFile(fp); return qfalse; } // read the route-table // children botimport.FS_Read(&routetable->numChildren, sizeof(int), fp); routetable->numChildren = LittleLong(routetable->numChildren); routetable->children = (aas_rt_child_t *) AAS_RT_GetClearedMemory(routetable->numChildren * sizeof(aas_rt_child_t)); botimport.FS_Read(routetable->children, routetable->numChildren * sizeof(aas_rt_child_t), fp); child = &routetable->children[0]; if (doswap) { for (i = 0; i < routetable->numChildren; i++, child++) { child->areanum = LittleShort(child->areanum); child->numParentLinks = LittleLong(child->numParentLinks); child->startParentLinks = LittleLong(child->startParentLinks); } } // parents botimport.FS_Read(&routetable->numParents, sizeof(int), fp); routetable->numParents = LittleLong(routetable->numParents); routetable->parents = (aas_rt_parent_t *) AAS_RT_GetClearedMemory(routetable->numParents * sizeof(aas_rt_parent_t)); botimport.FS_Read(routetable->parents, routetable->numParents * sizeof(aas_rt_parent_t), fp); parent = &routetable->parents[0]; if (doswap) { for (i = 0; i < routetable->numParents; i++, parent++) { parent->areanum = LittleShort(parent->areanum); parent->numParentChildren = LittleLong(parent->numParentChildren); parent->startParentChildren = LittleLong(parent->startParentChildren); parent->numVisibleParents = LittleLong(parent->numVisibleParents); parent->startVisibleParents = LittleLong(parent->startVisibleParents); } } // parentChildren botimport.FS_Read(&routetable->numParentChildren, sizeof(int), fp); routetable->numParentChildren = LittleLong(routetable->numParentChildren); routetable->parentChildren = (unsigned short int *) AAS_RT_GetClearedMemory(routetable->numParentChildren * sizeof(unsigned short int)); botimport.FS_Read(routetable->parentChildren, routetable->numParentChildren * sizeof(unsigned short int), fp); psi = &routetable->parentChildren[0]; if (doswap) { for (i = 0; i < routetable->numParentChildren; i++, psi++) { *psi = LittleShort(*psi); } } // visibleParents botimport.FS_Read(&routetable->numVisibleParents, sizeof(int), fp); routetable->numVisibleParents = LittleLong(routetable->numVisibleParents); routetable->visibleParents = (unsigned short int *) AAS_RT_GetClearedMemory(routetable->numVisibleParents * sizeof(unsigned short int)); botimport.FS_Read(routetable->visibleParents, routetable->numVisibleParents * sizeof(unsigned short int), fp); psi = &routetable->visibleParents[0]; if (doswap) { for (i = 0; i < routetable->numVisibleParents; i++, psi++) { *psi = LittleShort(*psi); } } // parentLinks botimport.FS_Read(&routetable->numParentLinks, sizeof(int), fp); routetable->numParentLinks = LittleLong(routetable->numParentLinks); routetable->parentLinks = (aas_rt_parent_link_t *) AAS_RT_GetClearedMemory(routetable->numParentLinks * sizeof(aas_rt_parent_link_t)); botimport.FS_Read(routetable->parentLinks, routetable->numParentLinks * sizeof(aas_parent_link_t), fp); plink = &routetable->parentLinks[0]; if (doswap) { for (i = 0; i < routetable->numParentLinks; i++, plink++) { plink->childIndex = LittleShort(plink->childIndex); plink->parent = LittleShort(plink->parent); } } // build the areaChildIndexes routetable->areaChildIndexes = (unsigned short int *) AAS_RT_GetClearedMemory((*aasworld).numareas * sizeof(unsigned short int)); child = routetable->children; for (i = 0; i < routetable->numChildren; i++, child++) { routetable->areaChildIndexes[child->areanum] = i + 1; } botimport.Print(PRT_MESSAGE, "Total Parents: %d\n", routetable->numParents); botimport.Print(PRT_MESSAGE, "Total Children: %d\n", routetable->numChildren); botimport.Print(PRT_MESSAGE, "Total Memory Used: %d\n", memorycount); #ifdef DEBUG_READING_TIME botimport.Print(PRT_MESSAGE, "Route-Table read time: %i\n", Sys_MilliSeconds() - pretime); #endif botimport.FS_FCloseFile(fp); return qtrue; }
static void write_short(FILE *f, short v) { v = LittleShort(v); write_data(&v, sizeof(v), f); }
/* ================= idFile::WriteUnsignedShort ================= */ int idFile::WriteUnsignedShort( const unsigned short value ) { unsigned short v = LittleShort(value); return Write( &v, sizeof( v ) ); }
/* ================= R_LoadMDC ================= */ qboolean R_LoadMDC(model_t *mod, int lod, void *buffer, int bufferSize, const char *modName) { int i, j, k; mdcHeader_t *mdcModel = ( mdcHeader_t * ) buffer; md3Frame_t *mdcFrame; mdcSurface_t *mdcSurf; md3Shader_t *mdcShader; md3Triangle_t *mdcTri; md3St_t *mdcst; md3XyzNormal_t *mdcxyz; mdcXyzCompressed_t *mdcxyzComp; mdcTag_t *mdcTag; mdcTagName_t *mdcTagName; mdvModel_t *mdvModel; mdvFrame_t *frame; mdvSurface_t *surf; //, *surface; //unused srfTriangle_t *tri; mdvXyz_t *v; mdvSt_t *st; mdvTag_t *tag; mdvTagName_t *tagName; short *ps; int version; int size; version = LittleLong(mdcModel->version); if (version != MDC_VERSION) { Ren_Warning("R_LoadMD3: %s has wrong version (%i should be %i)\n", modName, version, MDC_VERSION); return qfalse; } mod->type = MOD_MESH; size = LittleLong(mdcModel->ofsEnd); mod->dataSize += size; mdvModel = mod->mdv[lod] = ri.Hunk_Alloc(sizeof(mdvModel_t), h_low); LL(mdcModel->ident); LL(mdcModel->version); LL(mdcModel->numFrames); LL(mdcModel->numTags); LL(mdcModel->numSurfaces); LL(mdcModel->ofsFrames); LL(mdcModel->ofsTags); LL(mdcModel->ofsSurfaces); LL(mdcModel->ofsEnd); LL(mdcModel->ofsEnd); LL(mdcModel->flags); LL(mdcModel->numSkins); if (mdcModel->numFrames < 1) { Ren_Warning("R_LoadMDC: '%s' has no frames\n", modName); return qfalse; } // swap all the frames mdvModel->numFrames = mdcModel->numFrames; mdvModel->frames = frame = ri.Hunk_Alloc(sizeof(*frame) * mdcModel->numFrames, h_low); mdcFrame = ( md3Frame_t * )(( byte * ) mdcModel + mdcModel->ofsFrames); for (i = 0; i < mdcModel->numFrames; i++, frame++, mdcFrame++) { #if 1 // ET HACK if (strstr(mod->name, "sherman") || strstr(mod->name, "mg42")) { frame->radius = 256; for (j = 0; j < 3; j++) { frame->bounds[0][j] = 128; frame->bounds[1][j] = -128; frame->localOrigin[j] = LittleFloat(mdcFrame->localOrigin[j]); } } else #endif { frame->radius = LittleFloat(mdcFrame->radius); for (j = 0; j < 3; j++) { frame->bounds[0][j] = LittleFloat(mdcFrame->bounds[0][j]); frame->bounds[1][j] = LittleFloat(mdcFrame->bounds[1][j]); frame->localOrigin[j] = LittleFloat(mdcFrame->localOrigin[j]); } } } // swap all the tags mdvModel->numTags = mdcModel->numTags; mdvModel->tags = tag = ri.Hunk_Alloc(sizeof(*tag) * (mdcModel->numTags * mdcModel->numFrames), h_low); mdcTag = ( mdcTag_t * )(( byte * ) mdcModel + mdcModel->ofsTags); for (i = 0; i < mdcModel->numTags * mdcModel->numFrames; i++, tag++, mdcTag++) { vec3_t angles; for (j = 0; j < 3; j++) { tag->origin[j] = ( float ) LittleShort(mdcTag->xyz[j]) * MD3_XYZ_SCALE; angles[j] = ( float ) LittleShort(mdcTag->angles[j]) * MDC_TAG_ANGLE_SCALE; } AnglesToAxis(angles, tag->axis); } mdvModel->tagNames = tagName = ri.Hunk_Alloc(sizeof(*tagName) * (mdcModel->numTags), h_low); mdcTagName = ( mdcTagName_t * )(( byte * ) mdcModel + mdcModel->ofsTagNames); for (i = 0; i < mdcModel->numTags; i++, tagName++, mdcTagName++) { Q_strncpyz(tagName->name, mdcTagName->name, sizeof(tagName->name)); } // swap all the surfaces mdvModel->numSurfaces = mdcModel->numSurfaces; mdvModel->surfaces = surf = ri.Hunk_Alloc(sizeof(*surf) * mdcModel->numSurfaces, h_low); mdcSurf = ( mdcSurface_t * )(( byte * ) mdcModel + mdcModel->ofsSurfaces); for (i = 0; i < mdcModel->numSurfaces; i++) { LL(mdcSurf->ident); LL(mdcSurf->flags); LL(mdcSurf->numBaseFrames); LL(mdcSurf->numCompFrames); LL(mdcSurf->numShaders); LL(mdcSurf->numTriangles); LL(mdcSurf->ofsTriangles); LL(mdcSurf->numVerts); LL(mdcSurf->ofsShaders); LL(mdcSurf->ofsSt); LL(mdcSurf->ofsXyzNormals); LL(mdcSurf->ofsXyzNormals); LL(mdcSurf->ofsXyzCompressed); LL(mdcSurf->ofsFrameBaseFrames); LL(mdcSurf->ofsFrameCompFrames); LL(mdcSurf->ofsEnd); if (mdcSurf->numVerts > SHADER_MAX_VERTEXES) { Ren_Drop("R_LoadMDC: %s has more than %i verts on a surface (%i)", modName, SHADER_MAX_VERTEXES, mdcSurf->numVerts); } if (mdcSurf->numTriangles > SHADER_MAX_TRIANGLES) { Ren_Drop("R_LoadMDC: %s has more than %i triangles on a surface (%i)", modName, SHADER_MAX_TRIANGLES, mdcSurf->numTriangles); } // change to surface identifier surf->surfaceType = SF_MDV; // give pointer to model for Tess_SurfaceMDX surf->model = mdvModel; // copy surface name Q_strncpyz(surf->name, mdcSurf->name, sizeof(surf->name)); // lowercase the surface name so skin compares are faster Q_strlwr(surf->name); // strip off a trailing _1 or _2 // this is a crutch for q3data being a mess j = strlen(surf->name); if (j > 2 && surf->name[j - 2] == '_') { surf->name[j - 2] = 0; } // register the shaders /* surf->numShaders = md3Surf->numShaders; surf->shaders = shader = ri.Hunk_Alloc(sizeof(*shader) * md3Surf->numShaders, h_low); md3Shader = (md3Shader_t *) ((byte *) md3Surf + md3Surf->ofsShaders); for(j = 0; j < md3Surf->numShaders; j++, shader++, md3Shader++) { shader_t *sh; sh = R_FindShader(md3Shader->name, SHADER_3D_DYNAMIC, RSF_DEFAULT); if(sh->defaultShader) { shader->shaderIndex = 0; } else { shader->shaderIndex = sh->index; } } */ // only consider the first shader mdcShader = ( md3Shader_t * )(( byte * ) mdcSurf + mdcSurf->ofsShaders); surf->shader = R_FindShader(mdcShader->name, SHADER_3D_DYNAMIC, qtrue); // swap all the triangles surf->numTriangles = mdcSurf->numTriangles; surf->triangles = tri = ri.Hunk_Alloc(sizeof(*tri) * mdcSurf->numTriangles, h_low); mdcTri = ( md3Triangle_t * )(( byte * ) mdcSurf + mdcSurf->ofsTriangles); for (j = 0; j < mdcSurf->numTriangles; j++, tri++, mdcTri++) { tri->indexes[0] = LittleLong(mdcTri->indexes[0]); tri->indexes[1] = LittleLong(mdcTri->indexes[1]); tri->indexes[2] = LittleLong(mdcTri->indexes[2]); } // swap all the XyzNormals mdcxyz = ( md3XyzNormal_t * )(( byte * ) mdcSurf + mdcSurf->ofsXyzNormals); for (j = 0; j < mdcSurf->numVerts * mdcSurf->numBaseFrames; j++, mdcxyz++) { mdcxyz->xyz[0] = LittleShort(mdcxyz->xyz[0]); mdcxyz->xyz[1] = LittleShort(mdcxyz->xyz[1]); mdcxyz->xyz[2] = LittleShort(mdcxyz->xyz[2]); mdcxyz->normal = LittleShort(mdcxyz->normal); } // swap all the XyzCompressed mdcxyzComp = ( mdcXyzCompressed_t * )(( byte * ) mdcSurf + mdcSurf->ofsXyzCompressed); for (j = 0; j < mdcSurf->numVerts * mdcSurf->numCompFrames; j++, mdcxyzComp++) { LL(mdcxyzComp->ofsVec); } // swap the frameBaseFrames ps = ( short * )(( byte * ) mdcSurf + mdcSurf->ofsFrameBaseFrames); for (j = 0; j < mdcModel->numFrames; j++, ps++) { *ps = LittleShort(*ps); } // swap the frameCompFrames ps = ( short * )(( byte * ) mdcSurf + mdcSurf->ofsFrameCompFrames); for (j = 0; j < mdcModel->numFrames; j++, ps++) { *ps = LittleShort(*ps); } surf->numVerts = mdcSurf->numVerts; surf->verts = v = ri.Hunk_Alloc(sizeof(*v) * (mdcSurf->numVerts * mdcModel->numFrames), h_low); for (j = 0; j < mdcModel->numFrames; j++) { int baseFrame; int compFrame = 0; baseFrame = ( int ) *(( short * )(( byte * ) mdcSurf + mdcSurf->ofsFrameBaseFrames) + j); mdcxyz = ( md3XyzNormal_t * )(( byte * ) mdcSurf + mdcSurf->ofsXyzNormals + baseFrame * mdcSurf->numVerts * sizeof(md3XyzNormal_t)); if (mdcSurf->numCompFrames > 0) { compFrame = ( int ) *(( short * )(( byte * ) mdcSurf + mdcSurf->ofsFrameCompFrames) + j); if (compFrame >= 0) { mdcxyzComp = ( mdcXyzCompressed_t * )(( byte * ) mdcSurf + mdcSurf->ofsXyzCompressed + compFrame * mdcSurf->numVerts * sizeof(mdcXyzCompressed_t)); } } for (k = 0; k < mdcSurf->numVerts; k++, v++, mdcxyz++) { v->xyz[0] = LittleShort(mdcxyz->xyz[0]) * MD3_XYZ_SCALE; v->xyz[1] = LittleShort(mdcxyz->xyz[1]) * MD3_XYZ_SCALE; v->xyz[2] = LittleShort(mdcxyz->xyz[2]) * MD3_XYZ_SCALE; if (mdcSurf->numCompFrames > 0 && compFrame >= 0) { vec3_t ofsVec; R_MDC_DecodeXyzCompressed2(LittleShort(mdcxyzComp->ofsVec), ofsVec); VectorAdd(v->xyz, ofsVec, v->xyz); mdcxyzComp++; } } } // swap all the ST surf->st = st = ri.Hunk_Alloc(sizeof(*st) * mdcSurf->numVerts, h_low); mdcst = ( md3St_t * )(( byte * ) mdcSurf + mdcSurf->ofsSt); for (j = 0; j < mdcSurf->numVerts; j++, mdcst++, st++) { st->st[0] = LittleFloat(mdcst->st[0]); st->st[1] = LittleFloat(mdcst->st[1]); } // find the next surface mdcSurf = ( mdcSurface_t * )(( byte * ) mdcSurf + mdcSurf->ofsEnd); surf++; } #if 1 // create VBO surfaces from md3 surfaces { mdvNormTanBi_t *vertexes; mdvNormTanBi_t *vert; growList_t vboSurfaces; srfVBOMDVMesh_t *vboSurf; byte *data; int dataSize; int dataOfs; vec4_t tmp; GLuint ofsTexCoords; GLuint ofsTangents; GLuint ofsBinormals; GLuint ofsNormals; GLuint sizeXYZ = 0; GLuint sizeTangents = 0; GLuint sizeBinormals = 0; GLuint sizeNormals = 0; int vertexesNum; int f; Com_InitGrowList(&vboSurfaces, 10); for (i = 0, surf = mdvModel->surfaces; i < mdvModel->numSurfaces; i++, surf++) { //allocate temp memory for vertex data vertexes = (mdvNormTanBi_t *)ri.Hunk_AllocateTempMemory(sizeof(*vertexes) * surf->numVerts * mdvModel->numFrames); // calc tangent spaces { const float *v0, *v1, *v2; const float *t0, *t1, *t2; vec3_t tangent; vec3_t binormal; vec3_t normal; for (j = 0, vert = vertexes; j < (surf->numVerts * mdvModel->numFrames); j++, vert++) { VectorClear(vert->tangent); VectorClear(vert->binormal); VectorClear(vert->normal); } for (f = 0; f < mdvModel->numFrames; f++) { for (j = 0, tri = surf->triangles; j < surf->numTriangles; j++, tri++) { v0 = surf->verts[surf->numVerts * f + tri->indexes[0]].xyz; v1 = surf->verts[surf->numVerts * f + tri->indexes[1]].xyz; v2 = surf->verts[surf->numVerts * f + tri->indexes[2]].xyz; t0 = surf->st[tri->indexes[0]].st; t1 = surf->st[tri->indexes[1]].st; t2 = surf->st[tri->indexes[2]].st; #if 1 R_CalcTangentSpace(tangent, binormal, normal, v0, v1, v2, t0, t1, t2); #else R_CalcNormalForTriangle(normal, v0, v1, v2); R_CalcTangentsForTriangle(tangent, binormal, v0, v1, v2, t0, t1, t2); #endif for (k = 0; k < 3; k++) { float *v; v = vertexes[surf->numVerts * f + tri->indexes[k]].tangent; VectorAdd(v, tangent, v); v = vertexes[surf->numVerts * f + tri->indexes[k]].binormal; VectorAdd(v, binormal, v); v = vertexes[surf->numVerts * f + tri->indexes[k]].normal; VectorAdd(v, normal, v); } } } for (j = 0, vert = vertexes; j < (surf->numVerts * mdvModel->numFrames); j++, vert++) { VectorNormalize(vert->tangent); VectorNormalize(vert->binormal); VectorNormalize(vert->normal); } } //Ren_Print("...calculating MDC mesh VBOs ( '%s', %i verts %i tris )\n", surf->name, surf->numVerts, surf->numTriangles); // create surface vboSurf = ri.Hunk_Alloc(sizeof(*vboSurf), h_low); Com_AddToGrowList(&vboSurfaces, vboSurf); vboSurf->surfaceType = SF_VBO_MDVMESH; vboSurf->mdvModel = mdvModel; vboSurf->mdvSurface = surf; vboSurf->numIndexes = surf->numTriangles * 3; vboSurf->numVerts = surf->numVerts; /* vboSurf->vbo = R_CreateVBO2(va("staticWorldMesh_vertices %i", vboSurfaces.currentElements), numVerts, optimizedVerts, ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_TANGENT | ATTR_BINORMAL | ATTR_NORMAL | ATTR_COLOR); */ vboSurf->ibo = R_CreateIBO2(va("staticMDCMesh_IBO %s", surf->name), surf->numTriangles, surf->triangles, VBO_USAGE_STATIC); // create VBO vertexesNum = surf->numVerts; dataSize = (surf->numVerts * mdvModel->numFrames * sizeof(vec4_t) * 4) + // xyz, tangent, binormal, normal (surf->numVerts * sizeof(vec4_t)); // texcoords data = ri.Hunk_AllocateTempMemory(dataSize); dataOfs = 0; // feed vertex XYZ for (f = 0; f < mdvModel->numFrames; f++) { for (j = 0; j < vertexesNum; j++) { for (k = 0; k < 3; k++) { tmp[k] = surf->verts[f * vertexesNum + j].xyz[k]; } tmp[3] = 1; Com_Memcpy(data + dataOfs, ( vec_t * ) tmp, sizeof(vec4_t)); dataOfs += sizeof(vec4_t); } if (f == 0) { sizeXYZ = dataOfs; } } // feed vertex texcoords ofsTexCoords = dataOfs; for (j = 0; j < vertexesNum; j++) { for (k = 0; k < 2; k++) { tmp[k] = surf->st[j].st[k]; } tmp[2] = 0; tmp[3] = 1; Com_Memcpy(data + dataOfs, ( vec_t * ) tmp, sizeof(vec4_t)); dataOfs += sizeof(vec4_t); } // feed vertex tangents ofsTangents = dataOfs; for (f = 0; f < mdvModel->numFrames; f++) { for (j = 0; j < vertexesNum; j++) { for (k = 0; k < 3; k++) { tmp[k] = vertexes[f * vertexesNum + j].tangent[k]; } tmp[3] = 1; Com_Memcpy(data + dataOfs, ( vec_t * ) tmp, sizeof(vec4_t)); dataOfs += sizeof(vec4_t); } if (f == 0) { sizeTangents = dataOfs - ofsTangents; } } // feed vertex binormals ofsBinormals = dataOfs; for (f = 0; f < mdvModel->numFrames; f++) { for (j = 0; j < vertexesNum; j++) { for (k = 0; k < 3; k++) { tmp[k] = vertexes[f * vertexesNum + j].binormal[k]; } tmp[3] = 1; Com_Memcpy(data + dataOfs, ( vec_t * ) tmp, sizeof(vec4_t)); dataOfs += sizeof(vec4_t); } if (f == 0) { sizeBinormals = dataOfs - ofsBinormals; } } // feed vertex normals ofsNormals = dataOfs; for (f = 0; f < mdvModel->numFrames; f++) { for (j = 0; j < vertexesNum; j++) { for (k = 0; k < 3; k++) { tmp[k] = vertexes[f * vertexesNum + j].normal[k]; } tmp[3] = 1; Com_Memcpy(data + dataOfs, ( vec_t * ) tmp, sizeof(vec4_t)); dataOfs += sizeof(vec4_t); } if (f == 0) { sizeNormals = dataOfs - ofsNormals; } } vboSurf->vbo = R_CreateVBO(va("staticMDCMesh_VBO '%s'", surf->name), data, dataSize, VBO_USAGE_STATIC); vboSurf->vbo->ofsXYZ = 0; vboSurf->vbo->ofsTexCoords = ofsTexCoords; vboSurf->vbo->ofsLightCoords = ofsTexCoords; vboSurf->vbo->ofsTangents = ofsTangents; vboSurf->vbo->ofsBinormals = ofsBinormals; vboSurf->vbo->ofsNormals = ofsNormals; vboSurf->vbo->sizeXYZ = sizeXYZ; vboSurf->vbo->sizeTangents = sizeTangents; vboSurf->vbo->sizeBinormals = sizeBinormals; vboSurf->vbo->sizeNormals = sizeNormals; ri.Hunk_FreeTempMemory(data); ri.Hunk_FreeTempMemory(vertexes); } // move VBO surfaces list to hunk mdvModel->numVBOSurfaces = vboSurfaces.currentElements; mdvModel->vboSurfaces = ri.Hunk_Alloc(mdvModel->numVBOSurfaces * sizeof(*mdvModel->vboSurfaces), h_low); for (i = 0; i < mdvModel->numVBOSurfaces; i++) { mdvModel->vboSurfaces[i] = ( srfVBOMDVMesh_t * ) Com_GrowListElement(&vboSurfaces, i); } Com_DestroyGrowList(&vboSurfaces); } #endif return qtrue; }
/* ================= R_LoadMD3 ================= */ static qboolean R_LoadMD3 (model_t *mod, int lod, void *buffer, const char *mod_name, qboolean &bAlreadyCached ) { int i, j; md3Header_t *pinmodel; md3Surface_t *surf; md3Shader_t *shader; int version; int size; #if 0 //#ifndef _M_IX86 md3Frame_t *frame; md3Triangle_t *tri; md3St_t *st; md3XyzNormal_t *xyz; md3Tag_t *tag; #endif pinmodel= (md3Header_t *)buffer; // // read some fields from the binary, but only LittleLong() them when we know this wasn't an already-cached model... // version = pinmodel->version; size = pinmodel->ofsEnd; if (!bAlreadyCached) { version = LittleLong(version); size = LittleLong(size); } if (version != MD3_VERSION) { ri.Printf( PRINT_WARNING, "R_LoadMD3: %s has wrong version (%i should be %i)\n", mod_name, version, MD3_VERSION); return qfalse; } mod->type = MOD_MESH; mod->dataSize += size; qboolean bAlreadyFound = qfalse; mod->md3[lod] = (md3Header_t *) RE_RegisterModels_Malloc(size, buffer, mod_name, &bAlreadyFound, TAG_MODEL_MD3); assert(bAlreadyCached == bAlreadyFound); if (!bAlreadyFound) { // horrible new hackery, if !bAlreadyFound then we've just done a tag-morph, so we need to set the // bool reference passed into this function to true, to tell the caller NOT to do an FS_Freefile since // we've hijacked that memory block... // // Aaaargh. Kill me now... // bAlreadyCached = qtrue; assert( mod->md3[lod] == buffer ); // memcpy( mod->md3[lod], buffer, size ); // and don't do this now, since it's the same thing LL(mod->md3[lod]->ident); LL(mod->md3[lod]->version); LL(mod->md3[lod]->numFrames); LL(mod->md3[lod]->numTags); LL(mod->md3[lod]->numSurfaces); LL(mod->md3[lod]->ofsFrames); LL(mod->md3[lod]->ofsTags); LL(mod->md3[lod]->ofsSurfaces); LL(mod->md3[lod]->ofsEnd); } if ( mod->md3[lod]->numFrames < 1 ) { ri.Printf( PRINT_WARNING, "R_LoadMD3: %s has no frames\n", mod_name ); return qfalse; } if (bAlreadyFound) { return qtrue; // All done. Stop, go no further, do not pass Go... } #if 0 //#ifndef _M_IX86 // // optimisation, we don't bother doing this for standard intel case since our data's already in that format... // // swap all the frames frame = (md3Frame_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsFrames ); for ( i = 0 ; i < mod->md3[lod]->numFrames ; i++, frame++) { frame->radius = LittleFloat( frame->radius ); for ( j = 0 ; j < 3 ; j++ ) { frame->bounds[0][j] = LittleFloat( frame->bounds[0][j] ); frame->bounds[1][j] = LittleFloat( frame->bounds[1][j] ); frame->localOrigin[j] = LittleFloat( frame->localOrigin[j] ); } } // swap all the tags tag = (md3Tag_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsTags ); for ( i = 0 ; i < mod->md3[lod]->numTags * mod->md3[lod]->numFrames ; i++, tag++) { for ( j = 0 ; j < 3 ; j++ ) { tag->origin[j] = LittleFloat( tag->origin[j] ); tag->axis[0][j] = LittleFloat( tag->axis[0][j] ); tag->axis[1][j] = LittleFloat( tag->axis[1][j] ); tag->axis[2][j] = LittleFloat( tag->axis[2][j] ); } } #endif // swap all the surfaces surf = (md3Surface_t *) ( (byte *)mod->md3[lod] + mod->md3[lod]->ofsSurfaces ); for ( i = 0 ; i < mod->md3[lod]->numSurfaces ; i++) { LL(surf->flags); LL(surf->numFrames); LL(surf->numShaders); LL(surf->numTriangles); LL(surf->ofsTriangles); LL(surf->numVerts); LL(surf->ofsShaders); LL(surf->ofsSt); LL(surf->ofsXyzNormals); LL(surf->ofsEnd); if ( surf->numVerts > SHADER_MAX_VERTEXES ) { Com_Error (ERR_DROP, "R_LoadMD3: %s has more than %i verts on a surface (%i)", mod_name, SHADER_MAX_VERTEXES, surf->numVerts ); } if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) { Com_Error (ERR_DROP, "R_LoadMD3: %s has more than %i triangles on a surface (%i)", mod_name, SHADER_MAX_INDEXES / 3, surf->numTriangles ); } // change to surface identifier surf->ident = SF_MD3; // lowercase the surface name so skin compares are faster Q_strlwr( surf->name ); // strip off a trailing _1 or _2 // this is a crutch for q3data being a mess j = strlen( surf->name ); if ( j > 2 && surf->name[j-2] == '_' ) { surf->name[j-2] = 0; } // register the shaders shader = (md3Shader_t *) ( (byte *)surf + surf->ofsShaders ); for ( j = 0 ; j < surf->numShaders ; j++, shader++ ) { shader_t *sh; sh = R_FindShader( shader->name, lightmapsNone, stylesDefault, qtrue ); if ( sh->defaultShader ) { shader->shaderIndex = 0; } else { shader->shaderIndex = sh->index; } RE_RegisterModels_StoreShaderRequest(mod_name, &shader->name[0], &shader->shaderIndex); } #if 0 //#ifndef _M_IX86 // // optimisation, we don't bother doing this for standard intel case since our data's already in that format... // // swap all the triangles tri = (md3Triangle_t *) ( (byte *)surf + surf->ofsTriangles ); for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) { LL(tri->indexes[0]); LL(tri->indexes[1]); LL(tri->indexes[2]); } // swap all the ST st = (md3St_t *) ( (byte *)surf + surf->ofsSt ); for ( j = 0 ; j < surf->numVerts ; j++, st++ ) { st->st[0] = LittleFloat( st->st[0] ); st->st[1] = LittleFloat( st->st[1] ); } // swap all the XyzNormals xyz = (md3XyzNormal_t *) ( (byte *)surf + surf->ofsXyzNormals ); for ( j = 0 ; j < surf->numVerts * surf->numFrames ; j++, xyz++ ) { xyz->xyz[0] = LittleShort( xyz->xyz[0] ); xyz->xyz[1] = LittleShort( xyz->xyz[1] ); xyz->xyz[2] = LittleShort( xyz->xyz[2] ); xyz->normal = LittleShort( xyz->normal ); } #endif // find the next surface surf = (md3Surface_t *)( (byte *)surf + surf->ofsEnd ); } return qtrue; }
bool FZipFile::Open(bool quiet) { DWORD centraldir = Zip_FindCentralDir(Reader); FZipEndOfCentralDirectory info; int skipped = 0; Lumps = NULL; if (centraldir == 0) { if (!quiet) Printf(TEXTCOLOR_RED "\n%s: ZIP file corrupt!\n", Filename); return false; } // Read the central directory info. Reader->Seek(centraldir, SEEK_SET); Reader->Read(&info, sizeof(FZipEndOfCentralDirectory)); // No multi-disk zips! if (info.NumEntries != info.NumEntriesOnAllDisks || info.FirstDisk != 0 || info.DiskNumber != 0) { if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Multipart Zip files are not supported.\n", Filename); return false; } NumLumps = LittleShort(info.NumEntries); Lumps = new FZipLump[NumLumps]; // Load the entire central directory. Too bad that this contains variable length entries... int dirsize = LittleLong(info.DirectorySize); void *directory = malloc(dirsize); Reader->Seek(LittleLong(info.DirectoryOffset), SEEK_SET); Reader->Read(directory, dirsize); char *dirptr = (char*)directory; FZipLump *lump_p = Lumps; for (DWORD i = 0; i < NumLumps; i++) { FZipCentralDirectoryInfo *zip_fh = (FZipCentralDirectoryInfo *)dirptr; int len = LittleShort(zip_fh->NameLength); FString name(dirptr + sizeof(FZipCentralDirectoryInfo), len); dirptr += sizeof(FZipCentralDirectoryInfo) + LittleShort(zip_fh->NameLength) + LittleShort(zip_fh->ExtraLength) + LittleShort(zip_fh->CommentLength); if (dirptr > ((char*)directory) + dirsize) // This directory entry goes beyond the end of the file. { free(directory); if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Central directory corrupted.", Filename); return false; } // skip Directories if (name[len - 1] == '/' && LittleLong(zip_fh->UncompressedSize) == 0) { skipped++; continue; } // Ignore unknown compression formats zip_fh->Method = LittleShort(zip_fh->Method); if (zip_fh->Method != METHOD_STORED && zip_fh->Method != METHOD_DEFLATE && zip_fh->Method != METHOD_LZMA && zip_fh->Method != METHOD_BZIP2 && zip_fh->Method != METHOD_IMPLODE && zip_fh->Method != METHOD_SHRINK) { if (!quiet) Printf(TEXTCOLOR_YELLOW "\n%s: '%s' uses an unsupported compression algorithm (#%d).\n", Filename, name.GetChars(), zip_fh->Method); skipped++; continue; } // Also ignore encrypted entries zip_fh->Flags = LittleShort(zip_fh->Flags); if (zip_fh->Flags & ZF_ENCRYPTED) { if (!quiet) Printf(TEXTCOLOR_YELLOW "\n%s: '%s' is encrypted. Encryption is not supported.\n", Filename, name.GetChars()); skipped++; continue; } FixPathSeperator(name); name.ToLower(); lump_p->LumpNameSetup(name); lump_p->LumpSize = LittleLong(zip_fh->UncompressedSize); lump_p->Owner = this; // The start of the Reader will be determined the first time it is accessed. lump_p->Flags = LUMPF_ZIPFILE | LUMPFZIP_NEEDFILESTART; lump_p->Method = BYTE(zip_fh->Method); lump_p->GPFlags = zip_fh->Flags; lump_p->CompressedSize = LittleLong(zip_fh->CompressedSize); lump_p->Position = LittleLong(zip_fh->LocalHeaderOffset); lump_p->CheckEmbedded(); // Ignore some very specific names if (0 == stricmp("dehacked.exe", name)) { memset(lump_p->Name, 0, sizeof(lump_p->Name)); } lump_p++; } // Resize the lump record array to its actual size NumLumps -= skipped; free(directory); if (!quiet && !batchrun) Printf(TEXTCOLOR_NORMAL ", %d lumps\n", NumLumps); PostProcessArchive(&Lumps[0], sizeof(FZipLump)); return true; }
fracstep = ((unsigned)rate << 8) / (unsigned)dma.speed; samplefrac = 0; if( width == 2 ) { int16 *in = (int16 *)data; if( nchannels == 2 ) { for( src = 0; src < samples; samplefrac += fracstep, src = (samplefrac >> 8) ) { dst = s_rawend++ & (MAX_RAW_SAMPLES - 1); s_rawsamples[dst].left = LittleShort( in[src*2] ) * snd_vol; s_rawsamples[dst].right = LittleShort( in[src*2+1] ) * snd_vol; } } else { for( src = 0; src < samples; samplefrac += fracstep, src = (samplefrac >> 8) ) { dst = s_rawend++ & (MAX_RAW_SAMPLES - 1); s_rawsamples[dst].left = s_rawsamples[dst].right = LittleShort( in[src] ) * snd_vol; } } } else { if( nchannels == 2 ) { char *in = (char *)data; for( src = 0; src < samples; samplefrac += fracstep, src = (samplefrac >> 8) ) { dst = s_rawend++ & (MAX_RAW_SAMPLES - 1); s_rawsamples[dst].left = in[src*2] << 8 * snd_vol; s_rawsamples[dst].right = in[src*2+1] << 8 * snd_vol; } } else { for( src = 0; src < samples; samplefrac += fracstep, src = (samplefrac >> 8) ) { dst = s_rawend++ & (MAX_RAW_SAMPLES - 1); s_rawsamples[dst].left = s_rawsamples[dst].right = (data[src] - 128) << 8 * snd_vol;
/* ============= LoadTGABuffer ============= */ void LoadTGABuffer(byte * buffer, byte ** pic, int *width, int *height) { int columns, rows, numPixels; byte *pixbuf; int row, column; byte *buf_p; TargaHeader targa_header; byte *targa_rgba; *pic = NULL; 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 != 2 && targa_header.image_type != 10 && targa_header.image_type != 3) { Error("LoadTGA: Only type 2 (RGB), 3 (gray), and 10 (RGB) TGA images supported\n"); } if(targa_header.colormap_type != 0) { Error("LoadTGA: colormaps not supported\n"); } if((targa_header.pixel_size != 32 && targa_header.pixel_size != 24) && targa_header.image_type != 3) { Error("LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n"); } columns = targa_header.width; rows = targa_header.height; numPixels = columns * rows; if(width) *width = columns; if(height) *height = rows; targa_rgba = safe_malloc(numPixels * 4); *pic = targa_rgba; if(targa_header.id_length != 0) buf_p += targa_header.id_length; // skip TARGA image comment if(targa_header.image_type == 2 || targa_header.image_type == 3) { // Uncompressed RGB or gray scale image for(row = rows - 1; row >= 0; row--) { pixbuf = targa_rgba + row * columns * 4; for(column = 0; column < columns; column++) { unsigned char red, green, blue, alphabyte; switch (targa_header.pixel_size) { case 8: blue = *buf_p++; green = blue; red = blue; *pixbuf++ = red; *pixbuf++ = green; *pixbuf++ = blue; *pixbuf++ = 255; break; case 24: blue = *buf_p++; green = *buf_p++; red = *buf_p++; *pixbuf++ = red; *pixbuf++ = green; *pixbuf++ = blue; *pixbuf++ = 255; break; case 32: blue = *buf_p++; green = *buf_p++; red = *buf_p++; alphabyte = *buf_p++; *pixbuf++ = red; *pixbuf++ = green; *pixbuf++ = blue; *pixbuf++ = alphabyte; break; default: //Error("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name ); break; } } } } else if(targa_header.image_type == 10) { // Runlength encoded RGB images unsigned char red, green, blue, alphabyte, packetHeader, packetSize, j; red = 0; green = 0; blue = 0; alphabyte = 0xff; for(row = rows - 1; row >= 0; row--) { pixbuf = targa_rgba + row * columns * 4; for(column = 0; column < columns;) { packetHeader = *buf_p++; packetSize = 1 + (packetHeader & 0x7f); if(packetHeader & 0x80) { // run-length packet switch (targa_header.pixel_size) { case 24: blue = *buf_p++; green = *buf_p++; red = *buf_p++; alphabyte = 255; break; case 32: blue = *buf_p++; green = *buf_p++; red = *buf_p++; alphabyte = *buf_p++; break; default: //Error("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name ); break; } for(j = 0; j < packetSize; j++) { *pixbuf++ = red; *pixbuf++ = green; *pixbuf++ = blue; *pixbuf++ = alphabyte; column++; if(column == columns) { // run spans across rows column = 0; if(row > 0) row--; else goto breakOut; pixbuf = targa_rgba + row * columns * 4; } } } else { // non run-length packet for(j = 0; j < packetSize; j++) { switch (targa_header.pixel_size) { case 24: blue = *buf_p++; green = *buf_p++; red = *buf_p++; *pixbuf++ = red; *pixbuf++ = green; *pixbuf++ = blue; *pixbuf++ = 255; break; case 32: blue = *buf_p++; green = *buf_p++; red = *buf_p++; alphabyte = *buf_p++; *pixbuf++ = red; *pixbuf++ = green; *pixbuf++ = blue; *pixbuf++ = alphabyte; break; default: //Sys_Printf("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name ); break; } column++; if(column == columns) { // pixel packet run spans across rows column = 0; if(row > 0) row--; else goto breakOut; pixbuf = targa_rgba + row * columns * 4; } } } } breakOut:; } } //free(buffer); }
/* ================== CIN_LoadPCX TODO: fill in cinematic_t ================== */ static bool CIN_LoadPCX (cinematic_t *cin, const char *name, int flags){ pcxHeader_t *header; byte *data, *pcxData; byte *in, *out; byte palette[768]; int x, y, length; int dataByte, runLength; // Load the file length = FS_ReadFile(name, (void **)&data); if (!data) return false; // Parse the PCX header header = (pcxHeader_t *)data; header->xMin = LittleShort(header->xMin); header->yMin = LittleShort(header->yMin); header->xMax = LittleShort(header->xMax); header->yMax = LittleShort(header->yMax); header->hRes = LittleShort(header->hRes); header->vRes = LittleShort(header->vRes); header->bytesPerLine = LittleShort(header->bytesPerLine); header->paletteType = LittleShort(header->paletteType); in = &header->data; if (header->manufacturer != 0x0A || header->version != 5 || header->encoding != 1) Com_Error(ERR_DROP, "CIN_LoadPCX: invalid PCX header (%s)\n", name); if (header->bitsPerPixel != 8 || header->colorPlanes != 1) Com_Error(ERR_DROP, "CIN_LoadPCX: only 8 bit PCX images supported (%s)\n", name); if (header->xMax <= 0 || header->yMax <= 0 || header->xMax >= 640 || header->yMax >= 480) Com_Error(ERR_DROP, "CIN_LoadPCX: bad image size (%i x %i) (%s)\n", header->xMax, header->yMax, name); Mem_Copy(palette, (byte *)data + length - 768, 768); pcxData = out = (byte *)Mem_Alloc((header->xMax+1) * (header->yMax+1) * 4, TAG_TEMPORARY); for (y = 0; y <= header->yMax; y++){ for (x = 0; x <= header->xMax; ){ dataByte = *in++; if ((dataByte & 0xC0) == 0xC0){ runLength = dataByte & 0x3F; dataByte = *in++; } else runLength = 1; while (runLength-- > 0){ out[0] = palette[dataByte*3+0]; out[1] = palette[dataByte*3+1]; out[2] = palette[dataByte*3+2]; out[3] = 255; out += 4; x++; } } } if (in - data > length){ Com_DPrintf(S_COLOR_YELLOW "CIN_LoadPCX: PCX file was malformed (%s)\n", name); FS_FreeFile(data); Mem_Free(pcxData); pcxData = NULL; return false; } // Free the file data FS_FreeFile(data); // Fill it in cin->playing = true; cin->isRoQ = false; Str_Copy(cin->name, name, sizeof(cin->name)); cin->flags = flags; cin->file = 0; cin->size = 0; cin->offset = 0; cin->startTime = 0; cin->frameRate = 0; cin->frameCount = -1; // Resample video if needed CIN_ResampleVideo(cin); return true; }
/* If panning or note_to_use != -1, it will be used for all samples, instead of the sample-specific values in the instrument file. For note_to_use, any value <0 or >127 will be forced to 0. For other parameters, 1 means yes, 0 means no, other values are undefined. TODO: do reverse loops right */ static Instrument *load_instrument(Renderer *song, const char *name, int percussion, int panning, int note_to_use, int strip_loop, int strip_envelope, int strip_tail) { Instrument *ip; Sample *sp; FileReader *fp; GF1PatchHeader header; GF1InstrumentData idata; GF1LayerData layer_data; GF1PatchData patch_data; int i, j; bool noluck = false; if (!name) return 0; /* Open patch file */ if ((fp = pathExpander.openFileReader(name, NULL)) == NULL) { /* Try with various extensions */ FString tmp = name; tmp += ".pat"; if ((fp = pathExpander.openFileReader(tmp, NULL)) == NULL) { #ifdef __unix__ // Windows isn't case-sensitive. tmp.ToUpper(); if ((fp = pathExpander.openFileReader(tmp, NULL)) == NULL) #endif { noluck = true; } } } if (noluck) { cmsg(CMSG_ERROR, VERB_NORMAL, "Instrument `%s' can't be found.\n", name); return 0; } cmsg(CMSG_INFO, VERB_NOISY, "Loading instrument %s\n", name); /* Read some headers and do cursory sanity checks. */ if (sizeof(header) != fp->Read(&header, sizeof(header))) { failread: cmsg(CMSG_ERROR, VERB_NORMAL, "%s: Error reading instrument.\n", name); delete fp; return 0; } if (strncmp(header.Header, GF1_HEADER_TEXT, HEADER_SIZE - 4) != 0) { cmsg(CMSG_ERROR, VERB_NORMAL, "%s: Not an instrument.\n", name); delete fp; return 0; } if (strcmp(header.Header + 8, "110") < 0) { cmsg(CMSG_ERROR, VERB_NORMAL, "%s: Is an old and unsupported patch version.\n", name); delete fp; return 0; } if (sizeof(idata) != fp->Read(&idata, sizeof(idata))) { goto failread; } header.WaveForms = LittleShort(header.WaveForms); header.MasterVolume = LittleShort(header.MasterVolume); header.DataSize = LittleLong(header.DataSize); idata.Instrument = LittleShort(idata.Instrument); if (header.Instruments != 1 && header.Instruments != 0) /* instruments. To some patch makers, 0 means 1 */ { cmsg(CMSG_ERROR, VERB_NORMAL, "Can't handle patches with %d instruments.\n", header.Instruments); delete fp; return 0; } if (idata.Layers != 1 && idata.Layers != 0) /* layers. What's a layer? */ { cmsg(CMSG_ERROR, VERB_NORMAL, "Can't handle instruments with %d layers.\n", idata.Layers); delete fp; return 0; } if (sizeof(layer_data) != fp->Read(&layer_data, sizeof(layer_data))) { goto failread; } if (layer_data.Samples == 0) { cmsg(CMSG_ERROR, VERB_NORMAL, "Instrument has 0 samples.\n"); delete fp; return 0; } ip = new Instrument; ip->samples = layer_data.Samples; ip->sample = (Sample *)safe_malloc(sizeof(Sample) * layer_data.Samples); memset(ip->sample, 0, sizeof(Sample) * layer_data.Samples); for (i = 0; i < layer_data.Samples; ++i) { if (sizeof(patch_data) != fp->Read(&patch_data, sizeof(patch_data))) { fail: cmsg(CMSG_ERROR, VERB_NORMAL, "Error reading sample %d.\n", i); delete ip; delete fp; return 0; } sp = &(ip->sample[i]); sp->data_length = LittleLong(patch_data.WaveSize); sp->loop_start = LittleLong(patch_data.StartLoop); sp->loop_end = LittleLong(patch_data.EndLoop); sp->sample_rate = LittleShort(patch_data.SampleRate); sp->low_freq = float(LittleLong(patch_data.LowFrequency)); sp->high_freq = float(LittleLong(patch_data.HighFrequency)) + 0.9999f; sp->root_freq = float(LittleLong(patch_data.RootFrequency)); sp->high_vel = 127; sp->velocity = -1; sp->type = INST_GUS; // Expand to SF2 range. if (panning == -1) { sp->panning = (patch_data.Balance & 0x0F) * 1000 / 15 - 500; } else { sp->panning = (panning & 0x7f) * 1000 / 127 - 500; } song->compute_pan((sp->panning + 500) / 1000.0, INST_GUS, sp->left_offset, sp->right_offset); /* tremolo */ if (patch_data.TremoloRate == 0 || patch_data.TremoloDepth == 0) { sp->tremolo_sweep_increment = 0; sp->tremolo_phase_increment = 0; sp->tremolo_depth = 0; cmsg(CMSG_INFO, VERB_DEBUG, " * no tremolo\n"); } else { sp->tremolo_sweep_increment = convert_tremolo_sweep(song, patch_data.TremoloSweep); sp->tremolo_phase_increment = convert_tremolo_rate(song, patch_data.TremoloRate); sp->tremolo_depth = patch_data.TremoloDepth; cmsg(CMSG_INFO, VERB_DEBUG, " * tremolo: sweep %d, phase %d, depth %d\n", sp->tremolo_sweep_increment, sp->tremolo_phase_increment, sp->tremolo_depth); } /* vibrato */ if (patch_data.VibratoRate == 0 || patch_data.VibratoDepth == 0) { sp->vibrato_sweep_increment = 0; sp->vibrato_control_ratio = 0; sp->vibrato_depth = 0; cmsg(CMSG_INFO, VERB_DEBUG, " * no vibrato\n"); } else { sp->vibrato_control_ratio = convert_vibrato_rate(song, patch_data.VibratoRate); sp->vibrato_sweep_increment = convert_vibrato_sweep(song, patch_data.VibratoSweep, sp->vibrato_control_ratio); sp->vibrato_depth = patch_data.VibratoDepth; cmsg(CMSG_INFO, VERB_DEBUG, " * vibrato: sweep %d, ctl %d, depth %d\n", sp->vibrato_sweep_increment, sp->vibrato_control_ratio, sp->vibrato_depth); } sp->modes = patch_data.Modes; /* Mark this as a fixed-pitch instrument if such a deed is desired. */ if (note_to_use != -1) { sp->scale_note = note_to_use; sp->scale_factor = 0; } else { sp->scale_note = LittleShort(patch_data.ScaleFrequency); sp->scale_factor = LittleShort(patch_data.ScaleFactor); if (sp->scale_factor <= 2) { sp->scale_factor *= 1024; } else if (sp->scale_factor > 2048) { sp->scale_factor = 1024; } if (sp->scale_factor != 1024) { cmsg(CMSG_INFO, VERB_DEBUG, " * Scale: note %d, factor %d\n", sp->scale_note, sp->scale_factor); } } #if 0 /* seashore.pat in the Midia patch set has no Sustain. I don't understand why, and fixing it by adding the Sustain flag to all looped patches probably breaks something else. We do it anyway. */ if (sp->modes & PATCH_LOOPEN) { sp->modes |= PATCH_SUSTAIN; } #endif /* [RH] Alas, eawpats has percussion instruments with bad envelopes. :( * (See cymchina.pat for one example of this sadness.) * Do this logic for instruments without a description, only. Hopefully that * catches all the patches that need it without including any extra. */ for (j = 0; j < DESC_SIZE; ++j) { if (header.Description[j] != 0) break; } /* Strip any loops and envelopes we're permitted to */ /* [RH] (But PATCH_BACKWARD isn't a loop flag at all!) */ if ((strip_loop == 1) && (sp->modes & (PATCH_SUSTAIN | PATCH_LOOPEN | PATCH_BIDIR | PATCH_BACKWARD))) { cmsg(CMSG_INFO, VERB_DEBUG, " - Removing loop and/or sustain\n"); if (j == DESC_SIZE) { sp->modes &= ~(PATCH_SUSTAIN | PATCH_LOOPEN | PATCH_BIDIR | PATCH_BACKWARD); } } if (strip_envelope == 1) { cmsg(CMSG_INFO, VERB_DEBUG, " - Removing envelope\n"); /* [RH] The envelope isn't really removed, but this is the way the standard * Gravis patches get that effect: All rates at maximum, and all offsets at * a constant level. */ if (j == DESC_SIZE) { int k; for (k = 1; k < ENVELOPES; ++k) { /* Find highest offset. */ if (patch_data.EnvelopeOffset[k] > patch_data.EnvelopeOffset[0]) { patch_data.EnvelopeOffset[0] = patch_data.EnvelopeOffset[k]; } } for (k = 0; k < ENVELOPES; ++k) { patch_data.EnvelopeRate[k] = 63; patch_data.EnvelopeOffset[k] = patch_data.EnvelopeOffset[0]; } } } for (j = 0; j < 6; j++) { sp->envelope.gf1.rate[j] = patch_data.EnvelopeRate[j]; /* [RH] GF1NEW clamps the offsets to the range [5,251], so we do too. */ sp->envelope.gf1.offset[j] = clamp<BYTE>(patch_data.EnvelopeOffset[j], 5, 251); } /* Then read the sample data */ if (((sp->modes & PATCH_16) && sp->data_length/2 > MAX_SAMPLE_SIZE) || (!(sp->modes & PATCH_16) && sp->data_length > MAX_SAMPLE_SIZE)) { goto fail; } sp->data = (sample_t *)safe_malloc(sp->data_length); if (sp->data_length != fp->Read(sp->data, sp->data_length)) goto fail; convert_sample_data(sp, sp->data); /* Reverse reverse loops and pass them off as normal loops */ if (sp->modes & PATCH_BACKWARD) { int t; /* The GUS apparently plays reverse loops by reversing the whole sample. We do the same because the GUS does not SUCK. */ cmsg(CMSG_WARNING, VERB_NORMAL, "Reverse loop in %s\n", name); reverse_data((sample_t *)sp->data, 0, sp->data_length); sp->data[sp->data_length] = sp->data[sp->data_length - 1]; t = sp->loop_start; sp->loop_start = sp->data_length - sp->loop_end; sp->loop_end = sp->data_length - t; sp->modes &= ~PATCH_BACKWARD; sp->modes |= PATCH_LOOPEN; /* just in case */ } /* Then fractional samples */ sp->data_length <<= FRACTION_BITS; sp->loop_start <<= FRACTION_BITS; sp->loop_end <<= FRACTION_BITS; /* Adjust for fractional loop points. */ sp->loop_start |= (patch_data.Fractions & 0x0F) << (FRACTION_BITS-4); sp->loop_end |= (patch_data.Fractions & 0xF0) << (FRACTION_BITS-4-4); /* If this instrument will always be played on the same note, and it's not looped, we can resample it now. */ if (sp->scale_factor == 0 && !(sp->modes & PATCH_LOOPEN)) { pre_resample(song, sp); } if (strip_tail == 1) { /* Let's not really, just say we did. */ cmsg(CMSG_INFO, VERB_DEBUG, " - Stripping tail\n"); sp->data_length = sp->loop_end; } } delete fp; return ip; }
/* ============= HL_SwapBSPFile Byte swaps all data in a bsp file. ============= */ void HL_SwapBSPFile (qboolean todisk) { int i, j, k, c; hl_dmodel_t *d; hl_dmiptexlump_t *mtl; // models for (i = 0; i < hl_nummodels; i++) { d = &hl_dmodels[i]; for (j = 0; j < HL_MAX_MAP_HULLS; j++) d->headnode[j] = LittleLong(d->headnode[j]); d->visleafs = LittleLong(d->visleafs); d->firstface = LittleLong(d->firstface); d->numfaces = LittleLong(d->numfaces); for (j = 0; j < 3; j++) { d->mins[j] = LittleFloat(d->mins[j]); d->maxs[j] = LittleFloat(d->maxs[j]); d->origin[j] = LittleFloat(d->origin[j]); } } // // vertexes // for (i = 0; i < hl_numvertexes; i++) { for (j = 0; j < 3; j++) hl_dvertexes[i].point[j] = LittleFloat (hl_dvertexes[i].point[j]); } // // planes // for (i=0 ; i<hl_numplanes ; i++) { for (j=0 ; j<3 ; j++) hl_dplanes[i].normal[j] = LittleFloat (hl_dplanes[i].normal[j]); hl_dplanes[i].dist = LittleFloat (hl_dplanes[i].dist); hl_dplanes[i].type = LittleLong (hl_dplanes[i].type); } // // texinfos // for (i=0 ; i<hl_numtexinfo ; i++) { for (j=0 ; j<2 ; j++) { for (k=0; k<4; k++) { hl_texinfo[i].vecs[j][k] = LittleFloat (hl_texinfo[i].vecs[j][k]); } } hl_texinfo[i].miptex = LittleLong (hl_texinfo[i].miptex); hl_texinfo[i].flags = LittleLong (hl_texinfo[i].flags); } // // faces // for (i=0 ; i<hl_numfaces ; i++) { hl_dfaces[i].texinfo = LittleShort (hl_dfaces[i].texinfo); hl_dfaces[i].planenum = LittleShort (hl_dfaces[i].planenum); hl_dfaces[i].side = LittleShort (hl_dfaces[i].side); hl_dfaces[i].lightofs = LittleLong (hl_dfaces[i].lightofs); hl_dfaces[i].firstedge = LittleLong (hl_dfaces[i].firstedge); hl_dfaces[i].numedges = LittleShort (hl_dfaces[i].numedges); } // // nodes // for (i=0 ; i<hl_numnodes ; i++) { hl_dnodes[i].planenum = LittleLong (hl_dnodes[i].planenum); for (j=0 ; j<3 ; j++) { hl_dnodes[i].mins[j] = LittleShort (hl_dnodes[i].mins[j]); hl_dnodes[i].maxs[j] = LittleShort (hl_dnodes[i].maxs[j]); } hl_dnodes[i].children[0] = LittleShort (hl_dnodes[i].children[0]); hl_dnodes[i].children[1] = LittleShort (hl_dnodes[i].children[1]); hl_dnodes[i].firstface = LittleShort (hl_dnodes[i].firstface); hl_dnodes[i].numfaces = LittleShort (hl_dnodes[i].numfaces); } // // leafs // for (i=0 ; i<hl_numleafs ; i++) { hl_dleafs[i].contents = LittleLong (hl_dleafs[i].contents); for (j=0 ; j<3 ; j++) { hl_dleafs[i].mins[j] = LittleShort (hl_dleafs[i].mins[j]); hl_dleafs[i].maxs[j] = LittleShort (hl_dleafs[i].maxs[j]); } hl_dleafs[i].firstmarksurface = LittleShort (hl_dleafs[i].firstmarksurface); hl_dleafs[i].nummarksurfaces = LittleShort (hl_dleafs[i].nummarksurfaces); hl_dleafs[i].visofs = LittleLong (hl_dleafs[i].visofs); } // // clipnodes // for (i=0 ; i<hl_numclipnodes ; i++) { hl_dclipnodes[i].planenum = LittleLong (hl_dclipnodes[i].planenum); hl_dclipnodes[i].children[0] = LittleShort (hl_dclipnodes[i].children[0]); hl_dclipnodes[i].children[1] = LittleShort (hl_dclipnodes[i].children[1]); } // // miptex // if (hl_texdatasize) { mtl = (hl_dmiptexlump_t *)hl_dtexdata; if (todisk) c = mtl->nummiptex; else c = LittleLong(mtl->nummiptex); mtl->nummiptex = LittleLong (mtl->nummiptex); for (i=0 ; i<c ; i++) mtl->dataofs[i] = LittleLong(mtl->dataofs[i]); } // // marksurfaces // for (i=0 ; i<hl_nummarksurfaces ; i++) hl_dmarksurfaces[i] = LittleShort (hl_dmarksurfaces[i]); // // surfedges // for (i=0 ; i<hl_numsurfedges ; i++) hl_dsurfedges[i] = LittleLong (hl_dsurfedges[i]); // // edges // for (i=0 ; i<hl_numedges ; i++) { hl_dedges[i].v[0] = LittleShort (hl_dedges[i].v[0]); hl_dedges[i].v[1] = LittleShort (hl_dedges[i].v[1]); } } //end of the function HL_SwapBSPFile
/* ==================== CL_GetDemoMessage FIXME... ==================== */ qboolean CL_GetDemoMessage (void) { int r, i, j; float f; float demotime; byte c; usercmd_t *pcmd; // read the time from the packet fread(&demotime, sizeof(demotime), 1, cls.demofile); demotime = LittleFloat(demotime); // decide if it is time to grab the next message if (cls.timedemo) { if (cls.td_lastframe < 0) cls.td_lastframe = demotime; else if (demotime > cls.td_lastframe) { cls.td_lastframe = demotime; // rewind back to time fseek(cls.demofile, ftell(cls.demofile) - sizeof(demotime), SEEK_SET); return 0; // allready read this frame's message } if (!cls.td_starttime && cls.state == ca_active) { cls.td_starttime = Sys_DoubleTime(); cls.td_startframe = host_framecount; } realtime = demotime; // warp } else if (!cl.paused && cls.state >= ca_onserver) { // allways grab until fully connected if (realtime + 1.0 < demotime) { // too far back realtime = demotime - 1.0; // rewind back to time fseek(cls.demofile, ftell(cls.demofile) - sizeof(demotime), SEEK_SET); return 0; } else if (realtime < demotime) { // rewind back to time fseek(cls.demofile, ftell(cls.demofile) - sizeof(demotime), SEEK_SET); return 0; // don't need another message yet } } else realtime = demotime; // we're warping if (cls.state < ca_demostart) Host_Error ("CL_GetDemoMessage: cls.state != ca_active"); // get the msg type fread (&c, sizeof(c), 1, cls.demofile); switch (c) { case dem_cmd : // user sent input i = cls.netchan.outgoing_sequence & UPDATE_MASK; pcmd = &cl.frames[i].cmd; r = fread (pcmd, sizeof(*pcmd), 1, cls.demofile); if (r != 1) { CL_StopPlayback (); return 0; } // byte order stuff for (j = 0; j < 3; j++) pcmd->angles[j] = LittleFloat(pcmd->angles[j]); pcmd->forwardmove = LittleShort(pcmd->forwardmove); pcmd->sidemove = LittleShort(pcmd->sidemove); pcmd->upmove = LittleShort(pcmd->upmove); cl.frames[i].senttime = demotime; cl.frames[i].receivedtime = -1; // we haven't gotten a reply yet cls.netchan.outgoing_sequence++; for (i=0 ; i<3 ; i++) { r = fread (&f, 4, 1, cls.demofile); cl.viewangles[i] = LittleFloat (f); } break; case dem_read: // get the next message fread (&net_message.cursize, 4, 1, cls.demofile); net_message.cursize = LittleLong (net_message.cursize); //Con_Printf("read: %ld bytes\n", net_message.cursize); if (net_message.cursize > MAX_MSGLEN) Sys_Error ("Demo message > MAX_MSGLEN"); r = fread (net_message.data, net_message.cursize, 1, cls.demofile); if (r != 1) { CL_StopPlayback (); return 0; } break; case dem_set : fread (&i, 4, 1, cls.demofile); cls.netchan.outgoing_sequence = LittleLong(i); fread (&i, 4, 1, cls.demofile); cls.netchan.incoming_sequence = LittleLong(i); break; default : Con_Printf("Corrupted demo.\n"); CL_StopPlayback (); return 0; } return 1; }
/* ============== WritePCXfile ============== */ void WritePCXfile (char *filename, byte *data, int width, int height, int rowbytes, byte *palette, qboolean upload) { int i, j, length; pcx_t *pcx; byte *pack; pcx = Hunk_TempAlloc (width*height*2+1000); if (pcx == NULL) { Con_Printf("SCR_ScreenShot_f: not enough memory\n"); return; } pcx->manufacturer = 0x0a; // PCX id pcx->version = 5; // 256 color pcx->encoding = 1; // uncompressed pcx->bits_per_pixel = 8; // 256 color pcx->xmin = 0; pcx->ymin = 0; pcx->xmax = LittleShort((short)(width-1)); pcx->ymax = LittleShort((short)(height-1)); pcx->hres = LittleShort((short)width); pcx->vres = LittleShort((short)height); Q_memset (pcx->palette,0,sizeof(pcx->palette)); pcx->color_planes = 1; // chunky image pcx->bytes_per_line = LittleShort((short)width); pcx->palette_type = LittleShort(2); // not a grey scale Q_memset (pcx->filler,0,sizeof(pcx->filler)); // pack the image pack = &pcx->data; for (i=0 ; i<height ; i++) { for (j=0 ; j<width ; j++) { if ( (*data & 0xc0) != 0xc0) *pack++ = *data++; else { *pack++ = 0xc1; *pack++ = *data++; } } data += rowbytes - width; } // write the palette *pack++ = 0x0c; // palette ID byte for (i=0 ; i<768 ; i++) *pack++ = *palette++; // write output file length = (int) (pack - (byte *)pcx); if (upload) CL_StartUpload((void *)pcx, length); else COM_WriteFile (filename, pcx, length); }
static qboolean R_LoadMDR( model_t *mod, void *buffer, int filesize, const char *mod_name ) { int i, j, k, l; mdrHeader_t *pinmodel, *mdr; mdrFrame_t *frame; mdrLOD_t *lod, *curlod; mdrSurface_t *surf, *cursurf; mdrTriangle_t *tri, *curtri; mdrVertex_t *v, *curv; mdrWeight_t *weight, *curweight; mdrTag_t *tag, *curtag; int size; shader_t *sh; pinmodel = (mdrHeader_t *)buffer; pinmodel->version = LittleLong(pinmodel->version); if (pinmodel->version != MDR_VERSION) { ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has wrong version (%i should be %i)\n", mod_name, pinmodel->version, MDR_VERSION); return qfalse; } size = LittleLong(pinmodel->ofsEnd); if(size > filesize) { ri.Printf(PRINT_WARNING, "R_LoadMDR: Header of %s is broken. Wrong filesize declared!\n", mod_name); return qfalse; } mod->type = MOD_MDR; pinmodel->numFrames = LittleLong(pinmodel->numFrames); pinmodel->numBones = LittleLong(pinmodel->numBones); pinmodel->ofsFrames = LittleLong(pinmodel->ofsFrames); // This is a model that uses some type of compressed Bones. We don't want to uncompress every bone for each rendered frame // over and over again, we'll uncompress it in this function already, so we must adjust the size of the target md4. if(pinmodel->ofsFrames < 0) { // mdrFrame_t is larger than mdrCompFrame_t: size += pinmodel->numFrames * sizeof(frame->name); // now add enough space for the uncompressed bones. size += pinmodel->numFrames * pinmodel->numBones * ((sizeof(mdrBone_t) - sizeof(mdrCompBone_t))); } mod->dataSize += size; mod->md4 = mdr = ri.Hunk_Alloc( size, h_low ); // Copy all the values over from the file and fix endian issues in the process, if necessary. mdr->ident = LittleLong(pinmodel->ident); mdr->version = pinmodel->version; // Don't need to swap byte order on this one, we already did above. strlcpy(mdr->name, pinmodel->name, sizeof(mdr->name)); mdr->numFrames = pinmodel->numFrames; mdr->numBones = pinmodel->numBones; mdr->numLODs = LittleLong(pinmodel->numLODs); mdr->numTags = LittleLong(pinmodel->numTags); // We don't care about offset values, we'll generate them ourselves while loading. mod->numLods = mdr->numLODs; if ( mdr->numFrames < 1 ) { ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has no frames\n", mod_name); return qfalse; } /* The first frame will be put into the first free space after the header */ frame = (mdrFrame_t *)(mdr + 1); mdr->ofsFrames = (int)((byte *) frame - (byte *) mdr); if (pinmodel->ofsFrames < 0) { mdrCompFrame_t *cframe; // compressed model... cframe = (mdrCompFrame_t *)((byte *) pinmodel - pinmodel->ofsFrames); for(i = 0; i < mdr->numFrames; i++) { for(j = 0; j < 3; j++) { frame->bounds[0][j] = LittleFloat(cframe->bounds[0][j]); frame->bounds[1][j] = LittleFloat(cframe->bounds[1][j]); frame->localOrigin[j] = LittleFloat(cframe->localOrigin[j]); } frame->radius = LittleFloat(cframe->radius); frame->name[0] = '\0'; // No name supplied in the compressed version. for(j = 0; j < mdr->numBones; j++) { for(k = 0; k < (sizeof(cframe->bones[j].Comp) / 2); k++) { // Do swapping for the uncompressing functions. They seem to use shorts // values only, so I assume this will work. Never tested it on other // platforms, though. ((unsigned short *)(cframe->bones[j].Comp))[k] = LittleShort( ((unsigned short *)(cframe->bones[j].Comp))[k] ); } /* Now do the actual uncompressing */ MC_UnCompress(frame->bones[j].matrix, cframe->bones[j].Comp); } // Next Frame... cframe = (mdrCompFrame_t *) &cframe->bones[j]; frame = (mdrFrame_t *) &frame->bones[j]; } } else { mdrFrame_t *curframe; // uncompressed model... // curframe = (mdrFrame_t *)((byte *) pinmodel + pinmodel->ofsFrames); // swap all the frames for ( i = 0 ; i < mdr->numFrames ; i++) { for(j = 0; j < 3; j++) { frame->bounds[0][j] = LittleFloat(curframe->bounds[0][j]); frame->bounds[1][j] = LittleFloat(curframe->bounds[1][j]); frame->localOrigin[j] = LittleFloat(curframe->localOrigin[j]); } frame->radius = LittleFloat(curframe->radius); strlcpy(frame->name, curframe->name, sizeof(frame->name)); for (j = 0; j < (int) (mdr->numBones * sizeof(mdrBone_t) / 4); j++) { ((float *)frame->bones)[j] = LittleFloat( ((float *)curframe->bones)[j] ); } curframe++; frame++; } } // frame should now point to the first free address after all frames. lod = (mdrLOD_t *) frame; mdr->ofsLODs = (int) ((byte *) lod - (byte *)mdr); curlod = (mdrLOD_t *)((byte *) pinmodel + LittleLong(pinmodel->ofsLODs)); // swap all the LOD's for ( l = 0 ; l < mdr->numLODs ; l++) { lod->numSurfaces = LittleLong(curlod->numSurfaces); // swap all the surfaces surf = (mdrSurface_t *) (lod + 1); lod->ofsSurfaces = (int)((byte *) surf - (byte *) lod); cursurf = (mdrSurface_t *) ((byte *)curlod + LittleLong(curlod->ofsSurfaces)); for ( i = 0 ; i < lod->numSurfaces ; i++) { // first do some copying stuff surf->ident = SF_MDR; strlcpy(surf->name, cursurf->name, sizeof(surf->name)); strlcpy(surf->shader, cursurf->shader, sizeof(surf->shader)); surf->ofsHeader = (byte *) mdr - (byte *) surf; surf->numVerts = LittleLong(cursurf->numVerts); surf->numTriangles = LittleLong(cursurf->numTriangles); // numBoneReferences and BoneReferences generally seem to be unused // now do the checks that may fail. if ( surf->numVerts > SHADER_MAX_VERTEXES ) { ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has more than %i verts on a surface (%i)", mod_name, SHADER_MAX_VERTEXES, surf->numVerts ); return qfalse; } if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) { ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has more than %i triangles on a surface (%i)", mod_name, SHADER_MAX_INDEXES / 3, surf->numTriangles ); return qfalse; } // lowercase the surface name so skin compares are faster Q_strlwr( surf->name ); // register the shaders sh = R_FindShader(surf->shader, LIGHTMAP_NONE, qtrue); if ( sh->defaultShader ) { surf->shaderIndex = 0; } else { surf->shaderIndex = sh->index; } // now copy the vertexes. v = (mdrVertex_t *) (surf + 1); surf->ofsVerts = (int)((byte *) v - (byte *) surf); curv = (mdrVertex_t *) ((byte *)cursurf + LittleLong(cursurf->ofsVerts)); for(j = 0; j < surf->numVerts; j++) { v->normal[0] = LittleFloat(curv->normal[0]); v->normal[1] = LittleFloat(curv->normal[1]); v->normal[2] = LittleFloat(curv->normal[2]); v->texCoords[0] = LittleFloat(curv->texCoords[0]); v->texCoords[1] = LittleFloat(curv->texCoords[1]); v->numWeights = LittleLong(curv->numWeights); weight = &v->weights[0]; curweight = &curv->weights[0]; // Now copy all the weights for(k = 0; k < v->numWeights; k++) { weight->boneIndex = LittleLong(curweight->boneIndex); weight->boneWeight = LittleFloat(curweight->boneWeight); weight->offset[0] = LittleFloat(curweight->offset[0]); weight->offset[1] = LittleFloat(curweight->offset[1]); weight->offset[2] = LittleFloat(curweight->offset[2]); weight++; curweight++; } v = (mdrVertex_t *) weight; curv = (mdrVertex_t *) curweight; } // we know the offset to the triangles now: tri = (mdrTriangle_t *) v; surf->ofsTriangles = (int)((byte *) tri - (byte *) surf); curtri = (mdrTriangle_t *)((byte *) cursurf + LittleLong(cursurf->ofsTriangles)); for(j = 0; j < surf->numTriangles; j++) { tri->indexes[0] = LittleLong(curtri->indexes[0]); tri->indexes[1] = LittleLong(curtri->indexes[1]); tri->indexes[2] = LittleLong(curtri->indexes[2]); tri++; curtri++; } // tri now points to the end of the surface. surf->ofsEnd = (byte *) tri - (byte *) surf; surf = (mdrSurface_t *) tri; // find the next surface. cursurf = (mdrSurface_t *) ((byte *) cursurf + LittleLong(cursurf->ofsEnd)); } // surf points to the next lod now. lod->ofsEnd = (int)((byte *) surf - (byte *) lod); lod = (mdrLOD_t *) surf; // find the next LOD. curlod = (mdrLOD_t *)((byte *) curlod + LittleLong(curlod->ofsEnd)); } // lod points to the first tag now, so update the offset too. tag = (mdrTag_t *) lod; mdr->ofsTags = (int)((byte *) tag - (byte *) mdr); curtag = (mdrTag_t *) ((byte *)pinmodel + LittleLong(pinmodel->ofsTags)); for (i = 0 ; i < mdr->numTags ; i++) { tag->boneIndex = LittleLong(curtag->boneIndex); strlcpy(tag->name, curtag->name, sizeof(tag->name)); tag++; curtag++; } // And finally we know the offset to the end. mdr->ofsEnd = (int)((byte *) tag - (byte *) mdr); // phew! we're done. return qtrue; }
/* ================= idFile::ReadUnsignedShort ================= */ int idFile::ReadUnsignedShort( unsigned short &value ) { int result = Read( &value, sizeof( value ) ); value = LittleShort(value); return result; }
static qboolean R_LoadMDX( model_t *mod, void *buffer, const char *mod_name ) { int i, j; mdxHeader_t *pinmodel, *mdx; mdxFrame_t *frame; short *bframe; mdxBoneInfo_t *bi; int version; int size; int frameSize; pinmodel = ( mdxHeader_t * ) buffer; version = LittleLong( pinmodel->version ); if ( version != MDX_VERSION ) { ri.Printf( PRINT_WARNING, "R_LoadMDX: %s has wrong version (%i should be %i)\n", mod_name, version, MDX_VERSION ); return qfalse; } mod->type = MOD_MDX; size = LittleLong( pinmodel->ofsEnd ); mod->dataSize += size; mdx = mod->mdx = ri.Hunk_Alloc( size, h_low ); memcpy( mdx, buffer, LittleLong( pinmodel->ofsEnd ) ); LL( mdx->ident ); LL( mdx->version ); LL( mdx->numFrames ); LL( mdx->numBones ); LL( mdx->ofsFrames ); LL( mdx->ofsBones ); LL( mdx->ofsEnd ); LL( mdx->torsoParent ); if ( LittleLong( 1 ) != 1 ) { // swap all the frames frameSize = ( int )( sizeof( mdxBoneFrameCompressed_t ) ) * mdx->numBones; for ( i = 0; i < mdx->numFrames; i++ ) { frame = ( mdxFrame_t * )( ( byte * ) mdx + mdx->ofsFrames + i * frameSize + i * sizeof( mdxFrame_t ) ); frame->radius = LittleFloat( frame->radius ); for ( j = 0; j < 3; j++ ) { frame->bounds[ 0 ][ j ] = LittleFloat( frame->bounds[ 0 ][ j ] ); frame->bounds[ 1 ][ j ] = LittleFloat( frame->bounds[ 1 ][ j ] ); frame->localOrigin[ j ] = LittleFloat( frame->localOrigin[ j ] ); frame->parentOffset[ j ] = LittleFloat( frame->parentOffset[ j ] ); } bframe = ( short * )( ( byte * ) mdx + mdx->ofsFrames + i * frameSize + ( ( i + 1 ) * sizeof( mdxFrame_t ) ) ); for ( j = 0; j < mdx->numBones * sizeof( mdxBoneFrameCompressed_t ) / sizeof( short ); j++ ) { ( ( short * ) bframe ) [ j ] = LittleShort( ( ( short * ) bframe ) [ j ] ); } } // swap all the bones for ( i = 0; i < mdx->numBones; i++ ) { bi = ( mdxBoneInfo_t * )( ( byte * ) mdx + mdx->ofsBones + i * sizeof( mdxBoneInfo_t ) ); LL( bi->parent ); bi->torsoWeight = LittleFloat( bi->torsoWeight ); bi->parentDist = LittleFloat( bi->parentDist ); LL( bi->flags ); } } return qtrue; }
/* ================= idFile::WriteShort ================= */ int idFile::WriteShort( const short value ) { short v = LittleShort(value); return Write( &v, sizeof( v ) ); }