/* ================== Mod_LoadModel Loads a model into the cache ================== */ static model_t *Mod_LoadModel (model_t *mod, qboolean crash) { unsigned int *buf; if (mod->needload == NL_PRESENT) return mod; // // load the file // buf = (unsigned int *)FS_LoadTempFile (mod->name); if (!buf) { if (crash) SV_Error ("%s: %s not found", __thisfunc__, mod->name); return NULL; } // // allocate a new model // COM_FileBase (mod->name, loadname, sizeof(loadname)); loadmodel = mod; // // fill it in // // call the apropriate loader mod->needload = NL_PRESENT; Mod_LoadBrushModel (mod, buf); return mod; }
qbool VM_LoadBytecode( vm_t * vm, sys_callex_t syscall1 ) { char name[MAX_OSPATH]; byte *buff; vmHeader_t *header; qvm_t *qvm; char num[32]; int filesize; snprintf( name, sizeof( name ), "%s.qvm", vm->name ); Con_DPrintf( "VM_LoadBytecode: load %s\n", name ); buff = FS_LoadTempFile( name , &filesize ); if ( !buff ) return false; // add qvm crc to the serverinfo snprintf( num, sizeof(num), "%i", CRC_Block( ( byte * ) buff, filesize ) ); Info_SetValueForStarKey( svs.info, "*progs", num, MAX_SERVERINFO_STRING ); header = ( vmHeader_t * ) buff; header->vmMagic = LittleLong( header->vmMagic ); header->instructionCount = LittleLong( header->instructionCount ); header->codeOffset = LittleLong( header->codeOffset ); header->codeLength = LittleLong( header->codeLength ); header->dataOffset = LittleLong( header->dataOffset ); header->dataLength = LittleLong( header->dataLength ); header->litLength = LittleLong( header->litLength ); header->bssLength = LittleLong( header->bssLength ); // check file if ( header->vmMagic != VM_MAGIC || header->instructionCount <= 0 || header->codeLength <= 0 ) { return false; } // create vitrual machine if(vm->hInst) qvm = (qvm_t *)vm->hInst; else qvm = (qvm_t *) Q_malloc (sizeof (qvm_t)); qvm->len_cs = header->instructionCount + 1; //bad opcode padding. qvm->len_ds = header->dataOffset + header->litLength + header->bssLength; //align ds qvm->ds_mask = 1; while( qvm->ds_mask < qvm->len_ds) qvm->ds_mask<<=1; qvm->len_ds = qvm->ds_mask; qvm->ds_mask--; qvm->len_ss = 0x10000; // default by q3asm if ( qvm->len_ds < qvm->len_ss ) Sys_Error( "VM_LoadBytecode: stacksize greater than data segment" ); qvm->cs = ( qvm_instruction_t * ) Hunk_AllocName( qvm->len_cs * sizeof( qvm_instruction_t ), "qvmcode" ); qvm->ds = (byte *) Hunk_AllocName( qvm->len_ds, "qvmdata" ); qvm->ss = qvm->ds + qvm->len_ds - qvm->len_ss; // setup registers qvm->PC = 0; qvm->SP = 0; qvm->LP = qvm->len_ds - sizeof(int); qvm->cycles = 0; qvm->reenter = 0; qvm->syscall = syscall1; // load instructions { byte *src = buff + header->codeOffset; qvm_instruction_t *dst = qvm->cs; opcode_t op; int i; for ( i = 0; i < header->instructionCount; i++, dst++ ) { op = (opcode_t) *src++; dst->opcode = op; switch ( op ) { case OP_ARG: dst->parm._int = ( int ) *src++; break; case OP_ENTER: case OP_LEAVE: case OP_CONST: case OP_LOCAL: case OP_EQ: case OP_NE: case OP_LTI: case OP_LEI: case OP_GTI: case OP_GEI: case OP_LTU: case OP_LEU: case OP_GTU: case OP_GEU: case OP_EQF: case OP_NEF: case OP_LTF: case OP_LEF: case OP_GTF: case OP_GEF: case OP_BLOCK_COPY: dst->parm._int = LittleLong( *( int * ) src ); src += 4; break; default: dst->parm._int = 0; break; } } dst->opcode = OP_BREAK; dst->parm._int = 0; } // load data segment { int *src = ( int * ) ( buff + header->dataOffset ); int *dst = ( int * ) qvm->ds; int i; for ( i = 0; i < header->dataLength / 4; i++ ) *dst++ = LittleLong( *src++ ); memcpy( dst, src, header->litLength ); } LoadMapFile( qvm, vm->name ); vm->type = VM_BYTECODE; vm->hInst = qvm; return true; }
void LoadMapFile( qvm_t*qvm, char* fname ) { char name[MAX_OSPATH]; char lineBuffer[MAX_LINE_LENGTH]; char symname[MAX_LINE_LENGTH]; int i,off,seg,len,num_symbols = 0; symbols_t *sym = NULL; byte *buff; byte *p; Con_DPrintf("Loading symbol information\n"); snprintf( name, sizeof( name ), "%s.map", fname ); buff = FS_LoadTempFile( name , NULL ); qvm->sym_info = NULL; if ( !buff ) return; p=buff; while(*p) { for( i = 0; i < MAX_LINE_LENGTH; i++) { if( p[i] == 0 || p[i] == '\n') break; } if ( i == MAX_LINE_LENGTH ) { return; } memcpy( lineBuffer, p, i ); lineBuffer[i] = 0; p += i; if( *p == '\n') p++; if( 3 != sscanf( lineBuffer,"%d %8x %s",&seg,&off,symname) ) return; len = strlen(symname); if(!len)continue; if( off < 0 ) continue; if( seg == 0 && off >= qvm->len_cs) { Con_DPrintf("bad cs off in map file %s.map\n",fname); qvm->sym_info = NULL; return; } if( seg >= 1 && off >= qvm->len_ds ) { Con_DPrintf("bad ds off in map file %s.map\n",fname); continue; } if( !qvm->sym_info ) { qvm->sym_info = (symbols_t *) Hunk_Alloc( sizeof(symbols_t) + len + 1); sym = qvm->sym_info; } else { sym->next = (symbols_t *) Hunk_Alloc( sizeof(symbols_t) + len + 1); sym = sym->next; } sym->seg = seg; sym->off = off; sym->next= NULL; num_symbols++; strlcpy(sym->name, symname, len + 1); } Con_DPrintf("%i symbols loaded from %s\n",num_symbols,name); }
/* ============= LoadTGA ============= */ void LoadTGA (char *filename, byte **out, int *width, int *height) { int columns, rows, numPixels; byte *pixbuf, *tgabuf; int row, column; TargaHeader targa_header; *out = NULL; tgabuf = FS_LoadTempFile (filename); if (!tgabuf) { Com_DPrintf ("LoadTGA: Could not open %s\n", filename); return; } targa_header.id_length = *(byte *)tgabuf++; targa_header.colormap_type = *(byte *)tgabuf++; targa_header.image_type = *(byte *)tgabuf++; targa_header.colormap_index = LittleShort (*(short *)tgabuf); tgabuf += 2; targa_header.colormap_length = LittleShort (*(short *)tgabuf); tgabuf += 2; targa_header.colormap_size = *(byte *)tgabuf++; targa_header.x_origin = LittleShort (*(short *)tgabuf); tgabuf += 2; targa_header.y_origin = LittleShort (*(short *)tgabuf); tgabuf += 2; targa_header.width = LittleShort (*(short *)tgabuf); tgabuf += 2; targa_header.height = LittleShort (*(short *)tgabuf); tgabuf += 2; targa_header.pixel_size = *(byte *)tgabuf++; targa_header.attributes = *(byte *)tgabuf++; if (targa_header.image_type != 2 && targa_header.image_type != 10) { Com_DPrintf ("LoadTGA: Only type 2 and 10 targa RGB images supported\n"); return; } if (targa_header.colormap_type != 0 || (targa_header.pixel_size != 32 && targa_header.pixel_size != 24)) { Com_DPrintf ("LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n"); return; } columns = targa_header.width; rows = targa_header.height; numPixels = columns * rows; if (width) *width = columns; if (height) *height = rows; *out = Q_malloc (numPixels*4 + 128000 /* !!!!TESTING */); if (targa_header.id_length != 0) tgabuf += targa_header.id_length; if (targa_header.image_type==2) { // Uncompressed, RGB images for (row = rows - 1; row >= 0; row--) { pixbuf = *out + ((targa_header.attributes & 0x20) ? rows-1-row : row) * columns * 4; for(column=0; column<columns; column++) { unsigned char red,green,blue,alphabyte; switch (targa_header.pixel_size) { case 24: blue = *(byte *)tgabuf++; green = *(byte *)tgabuf++; red = *(byte *)tgabuf++; *pixbuf++ = red; *pixbuf++ = green; *pixbuf++ = blue; *pixbuf++ = 255; break; case 32: blue = *(byte *)tgabuf++; green = *(byte *)tgabuf++; red = *(byte *)tgabuf++; alphabyte = *(byte *)tgabuf++; *pixbuf++ = red; *pixbuf++ = green; *pixbuf++ = blue; *pixbuf++ = alphabyte; break; } } } } else if (targa_header.image_type==10) { // Runlength encoded RGB images unsigned char red = 0,green = 0,blue = 0,alphabyte = 0,packetHeader = 0,packetSize = 0,j = 0; for (row = rows - 1; row >= 0; row--) { pixbuf = *out + ((targa_header.attributes & 0x20) ? rows-1-row : row) * columns * 4; for(column=0; column<columns; ) { packetHeader = *(byte *)tgabuf++; packetSize = 1 + (packetHeader & 0x7f); if (packetHeader & 0x80) { // run-length packet switch (targa_header.pixel_size) { case 24: blue = *(byte *)tgabuf++; green = *(byte *)tgabuf++; red = *(byte *)tgabuf++; alphabyte = 255; break; case 32: blue = *(byte *)tgabuf++; green = *(byte *)tgabuf++; red = *(byte *)tgabuf++; alphabyte = *(byte *)tgabuf++; 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 = *out + row*columns*4; } } } else { // non run-length packet for(j=0;j<packetSize;j++) { switch (targa_header.pixel_size) { case 24: blue = *(byte *)tgabuf++; green = *(byte *)tgabuf++; red = *(byte *)tgabuf++; *pixbuf++ = red; *pixbuf++ = green; *pixbuf++ = blue; *pixbuf++ = 255; break; case 32: blue = *(byte *)tgabuf++; green = *(byte *)tgabuf++; red = *(byte *)tgabuf++; alphabyte = *(byte *)tgabuf++; *pixbuf++ = red; *pixbuf++ = green; *pixbuf++ = blue; *pixbuf++ = alphabyte; break; } column++; if (column==columns) { // pixel packet run spans across rows column=0; if (row>0) row--; else goto breakOut; pixbuf = *out + row*columns*4; } } } } breakOut:; } } }
/* ============ LoadPCX ============ */ void LoadPCX (char *filename, byte **pic, int *width, int *height) { pcx_t *pcx; byte *pcxbuf, *out, *pix; int x, y; int dataByte, runLength; *pic = NULL; pcxbuf = FS_LoadTempFile (filename); if (!pcxbuf) { Com_DPrintf ("LoadPCX: Could not open %s\n", filename); return; } // // parse the PCX file // pcx = (pcx_t *)pcxbuf; pcx->xmax = LittleShort (pcx->xmax); pcx->xmin = LittleShort (pcx->xmin); pcx->ymax = LittleShort (pcx->ymax); pcx->ymin = LittleShort (pcx->ymin); 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); pix = &pcx->data; if (pcx->manufacturer != 0x0a || pcx->version != 5 || pcx->encoding != 1 || pcx->bits_per_pixel != 8 || pcx->xmax >= 640 || pcx->ymax >= 480) { Com_DPrintf ("LoadPCX: Bad pcx file %s\n", filename); return; } if (width) *width = pcx->xmax+1; if (height) *height = pcx->ymax+1; *pic = out = Q_malloc ((pcx->xmax+1) * (pcx->ymax+1)); for (y=0 ; y<=pcx->ymax ; y++, out += pcx->xmax+1) { for (x=0 ; x<=pcx->xmax ; ) { if (pix - (byte *)pcx > fs_filesize) { Q_free (*pic); *pic = NULL; Com_DPrintf ("LoadPCX: %s is malformed\n", filename); return; } dataByte = *pix++; if((dataByte & 0xC0) == 0xC0) { runLength = dataByte & 0x3F; if (pix - (byte *)pcx > fs_filesize) { Q_free (*pic); *pic = NULL; Com_DPrintf ("LoadPCX: %s is malformed\n", filename); return; } dataByte = *pix++; } else runLength = 1; // sanity check if (runLength + x > pcx->xmax + 2) { Q_free (*pic); *pic = NULL; Com_DPrintf ("LoadPCX: %s is malformed\n", filename); return; } while (runLength-- > 0) out[x++] = dataByte; } } if (pix - (byte *)pcx > fs_filesize) { Q_free (*pic); *pic = NULL; Com_DPrintf ("LoadPCX: %s is malformed\n", filename); } }
/* ========== Skin_Cache Returns a pointer to the skin bitmap, or NULL to use the default ========== */ byte *Skin_Cache (skin_t *skin) { char name[1024]; byte *raw; byte *out, *pix; pcx_t *pcx; int x, y; int dataByte; int runLength; if (cls.downloadtype == dl_skin) return NULL; // use base until downloaded if (noskins.integer == 1) // JACK: So NOSKINS > 1 will show skins, but return NULL; // not download new ones. if (skin->failedload) return NULL; out = (byte *) Cache_Check (&skin->cache); if (out) return out; // // load the pic from disk // q_snprintf (name, sizeof(name), "skins/%s.pcx", skin->name); raw = FS_LoadTempFile (name, NULL); if (!raw) { Con_Printf ("Couldn't load skin %s\n", name); q_snprintf (name, sizeof(name), "skins/%s.pcx", baseskin.string); raw = FS_LoadTempFile (name, NULL); if (!raw) { skin->failedload = true; return NULL; } } // // parse the PCX file // pcx = (pcx_t *)raw; raw = &pcx->data; if (pcx->manufacturer != 0x0a || pcx->version != 5 || pcx->encoding != 1 || pcx->bits_per_pixel != 8 || pcx->xmax >= 320 || pcx->ymax >= 200) { skin->failedload = true; Con_Printf ("Bad skin %s\n", name); return NULL; } out = (byte *) Cache_Alloc (&skin->cache, 320*200, skin->name); if (!out) Sys_Error ("%s: couldn't allocate", __thisfunc__); pix = out; memset (out, 0, 320*200); for (y = 0; y < pcx->ymax; y++, pix += 320) { for (x = 0; x <= pcx->xmax ; ) { if ((size_t)(raw - (byte*)pcx) > fs_filesize) { Cache_Free (&skin->cache); skin->failedload = true; Con_Printf ("Skin %s was malformed. You should delete it.\n", name); return NULL; } dataByte = *raw++; if ((dataByte & 0xC0) == 0xC0) { runLength = dataByte & 0x3F; if ((size_t)(raw - (byte*)pcx) > fs_filesize) { Cache_Free (&skin->cache); skin->failedload = true; Con_Printf ("Skin %s was malformed. You should delete it.\n", name); return NULL; } dataByte = *raw++; } else runLength = 1; // skin sanity check if (runLength + x > pcx->xmax + 2) { Cache_Free (&skin->cache); skin->failedload = true; Con_Printf ("Skin %s was malformed. You should delete it.\n", name); return NULL; } while (runLength-- > 0) pix[x++] = dataByte; } } if ((size_t)(raw - (byte *)pcx) > fs_filesize) { Cache_Free (&skin->cache); skin->failedload = true; Con_Printf ("Skin %s was malformed. You should delete it.\n", name); return NULL; } skin->failedload = false; return out; }