/******************************************************************** * ConvertTMPQHeader ********************************************************************/ void ConvertTMPQHeader(void *header) { TMPQHeader2 * theHeader = (TMPQHeader2 *)header; theHeader->dwID = SwapULong(theHeader->dwID); theHeader->dwHeaderSize = SwapULong(theHeader->dwHeaderSize); theHeader->dwArchiveSize = SwapULong(theHeader->dwArchiveSize); theHeader->wFormatVersion = SwapUShort(theHeader->wFormatVersion); theHeader->wBlockSize = SwapUShort(theHeader->wBlockSize); theHeader->dwHashTablePos = SwapULong(theHeader->dwHashTablePos); theHeader->dwBlockTablePos = SwapULong(theHeader->dwBlockTablePos); theHeader->dwHashTableSize = SwapULong(theHeader->dwHashTableSize); theHeader->dwBlockTableSize = SwapULong(theHeader->dwBlockTableSize); if(theHeader->wFormatVersion >= MPQ_FORMAT_VERSION_2) { DWORD dwTemp = theHeader->ExtBlockTablePos.LowPart; theHeader->ExtBlockTablePos.LowPart = theHeader->ExtBlockTablePos.HighPart; theHeader->ExtBlockTablePos.HighPart = dwTemp; theHeader->ExtBlockTablePos.LowPart = SwapULong(theHeader->ExtBlockTablePos.LowPart); theHeader->ExtBlockTablePos.HighPart = SwapULong(theHeader->ExtBlockTablePos.HighPart); theHeader->wHashTablePosHigh = SwapUShort(theHeader->wHashTablePosHigh); theHeader->wBlockTablePosHigh = SwapUShort(theHeader->wBlockTablePosHigh); } }
void nfHiColorDecomp(unsigned char *comp,unsigned int x, unsigned int y, unsigned int w, unsigned int h) { unsigned char *tbuf; unsigned int new_row; unsigned int parms_sz; unsigned short *bx; unsigned char *si; unsigned char *di; unsigned int dx; unsigned int si2; unsigned int i,j,k; unsigned char a,b; nf_new_x = x*SWIDTH*2; nf_new_w = w*SWIDTH*2; nf_new_y = y*SHEIGHT; nf_new_h = h*SHEIGHT; new_row = nf_new_row0 - nf_new_w; parms_sz = (w*h*nf_fqty)<<1; // Move to correct place in current buffer tbuf = nf_buf_cur; if (x||y) { tbuf += nf_new_y*nf_width + nf_new_x; } // ds:si indexes comp (to get new section data) // es:di indexes current screen buffer // dx is a frequently used constant // ds/fs:bx indexes section params si = comp; di = tbuf; dx = nf_new_line; // width - SWIDTH bx = (unsigned short *) si; // Parms index si+= parms_sz; // Skip over flags (w*h*2) // Iterate over params and copy new hires data to appropriate sections. for (k=0;k<h;k++) { for (i=0;i<w;i++) { if (!*bx) { Move16; /* First row */ di+=dx; Move16; /* Second row */ di+=dx; Move16; /* Third row */ di+=dx; Move16; /* Fourth row */ di+=dx; Move16; /* Fifth row */ di+=dx; Move16; /* Sixth row */ di+=dx; Move16; /* Seventh row */ di+=dx; Move16; /* Eighth row */ di-=nf_back_right; } ++bx; di+=SWIDTH*2; } di+=new_row; } // Iterate over flags and motion source addresses from params // to determine which sections to move. // fs:bx indexes params. // ds:si indexes source from buffer // ds will either be segment of current or previous buffer // si will be computed as +- 16K relative to di. bx = (unsigned short *) comp; // Move back to start of section parms di = tbuf; for (k=0;k<h;k++) { for (i=0;i<w;i++) { si2 = (unsigned int) SwapUShort(*bx); if (si2&0x8000) { // Move one section from previous screen to current screen. // Enter with ds pointing to previous screen, // es:di to destination screen section, // relative value of source offset in si. ms_30: si2-=0xC000; // Make si absolute si2+=si2; si2+=(di-nf_buf_cur); /* Get the offset */ si=nf_buf_prv+si2; /* Make true pointer */ Move162; /* First row */ si+=dx; di+=dx; Move162; /* Second row */ si+=dx; di+=dx; Move162; /* Third row */ si+=dx; di+=dx; Move162; /* Fourth row */ si+=dx; di+=dx; Move162; /* Fifth row */ si+=dx; di+=dx; Move162; /* Sixth row */ si+=dx; di+=dx; Move162; /* Seventh row */ si+=dx; di+=dx; Move162; /* Eighth row */ di-=nf_back_right; } else if (si2) { ms_10: // Move one section from current screen to current screen. // Enter with ds pointing to current screen, // es:di to destination screen section, // relative value of source offset in si. si2-=0x4000; // Make si absolute si2+=si2; si=di+si2; Move162; /* First row */ si+=dx; di+=dx; Move162; /* Second row */ si+=dx; di+=dx; Move162; /* Third row */ si+=dx; di+=dx; Move162; /* Fourth row */ si+=dx; di+=dx; Move162; /* Fifth row */ si+=dx; di+=dx; Move162; /* Sixth row */ si+=dx; di+=dx; Move162; /* Seventh row */ si+=dx; di+=dx; Move162; /* Eighth row */ di-=nf_back_right; } ++bx; di+=SWIDTH*2; } di+=new_row; } }
// // ACS_translateScriptACS0 // static void ACS_translateScriptACS0(acs0_tracer_t *tracer, int32_t *codeIndexMap) { byte *brover; int32_t *codePtr = tracer->vm->code, *rover; uint32_t index, opSize; int32_t op, temp; acs0_opdata_t const *opdata; int32_t **jumps, **jumpItr; // This is used to store all of the places that need to have a jump target // translated. The count was determined by the tracer. jumps = (int32_t **)Z_Malloc(tracer->jumpCount * sizeof(int32_t *), PU_STATIC, NULL); jumpItr = jumps; // Set the first instruction to a KILL. *codePtr++ = ACS_OP_KILL; for(index = 0; index < tracer->lumpLength;) { // Search for code. if(!tracer->codeTouched[index]) { ++index; continue; } // Read next instruction from file. op = ACS_readOpACS0(tracer, &opSize, index); rover = (int32_t *)(tracer->data + index + opSize); // Unrecognized instructions need to stop execution. if(op >= ACS0_OPMAX || op < 0) { *codePtr++ = ACS_OP_KILL; index += opSize; continue; } opdata = &ACS0opdata[op]; // Record jump target. codeIndexMap[index] = codePtr - tracer->vm->code; // Calculate next index. index += ACS_countOpSizeACS0(tracer, index, opSize, opdata); switch(op) { case ACS0_OP_LINESPEC1: case ACS0_OP_LINESPEC2: case ACS0_OP_LINESPEC3: case ACS0_OP_LINESPEC4: case ACS0_OP_LINESPEC5: temp = op - ACS0_OP_LINESPEC1 + 1; *codePtr++ = opdata->opdata->op; *codePtr++ = SwapLong(*rover++); *codePtr++ = temp; break; case ACS0_OP_LINESPEC1_IMM: case ACS0_OP_LINESPEC2_IMM: case ACS0_OP_LINESPEC3_IMM: case ACS0_OP_LINESPEC4_IMM: case ACS0_OP_LINESPEC5_IMM: temp = opdata->args - 1; *codePtr++ = opdata->opdata->op; *codePtr++ = SwapLong(*rover++); *codePtr++ = temp; while(temp--) *codePtr++ = SwapLong(*rover++); break; case ACS0_OP_LINESPEC5_RET: temp = op - ACS0_OP_LINESPEC5_RET + 5; *codePtr++ = opdata->opdata->op; *codePtr++ = SwapLong(*rover++); *codePtr++ = temp; break; case ACS0_OP_LINESPEC1_IMM_BYTE: case ACS0_OP_LINESPEC2_IMM_BYTE: case ACS0_OP_LINESPEC3_IMM_BYTE: case ACS0_OP_LINESPEC4_IMM_BYTE: case ACS0_OP_LINESPEC5_IMM_BYTE: brover = (byte *)rover; temp = opdata->args - 1; *codePtr++ = opdata->opdata->op; *codePtr++ = *brover++; *codePtr++ = temp; while(temp--) *codePtr++ = *brover++; break; case ACS0_OP_GET_IMM_BYTE: *codePtr++ = opdata->opdata->op; *codePtr++ = *(byte *)rover; break; case ACS0_OP_GET2_IMM_BYTE: case ACS0_OP_GET3_IMM_BYTE: case ACS0_OP_GET4_IMM_BYTE: case ACS0_OP_GET5_IMM_BYTE: brover = (byte *)rover; temp = op - ACS0_OP_GET2_IMM_BYTE + 2; *codePtr++ = opdata->opdata->op; *codePtr++ = temp; while(temp--) *codePtr++ = *brover++; break; case ACS0_OP_GET_THINGX: case ACS0_OP_GET_THINGY: case ACS0_OP_GET_THINGZ: case ACS0_OP_GET_THINGFLOORZ: case ACS0_OP_GET_THINGANGLE: case ACS0_OP_SET_THINGANGLE: case ACS0_OP_GET_THINGCEILINGZ: case ACS0_OP_GET_THINGPITCH: case ACS0_OP_SET_THINGPITCH: case ACS0_OP_CHK_THINGCEILINGTEXTURE: case ACS0_OP_CHK_THINGFLOORTEXTURE: case ACS0_OP_GET_THINGLIGHTLEVEL: *codePtr++ = opdata->opdata->op; *codePtr++ = ACS_translateThingVarACS0(opdata); break; case ACS0_OP_GETARR_IMM_BYTE: brover = (byte *)rover; temp = *brover++; *codePtr++ = opdata->opdata->op; *codePtr++ = temp; while(temp--) *codePtr++ = *brover++; break; case ACS0_OP_BRANCH_IMM: case ACS0_OP_BRANCH_NOTZERO: case ACS0_OP_BRANCH_ZERO: *jumpItr++ = codePtr + 1; goto case_direct; case ACS0_OP_BRANCH_CASE: *jumpItr++ = codePtr + 2; goto case_direct; case ACS0_OP_CHANGEFLOOR_IMM: case ACS0_OP_CHANGECEILING_IMM: ACS_translateFuncACS0(codePtr, opdata); *codePtr++ = SwapLong(*rover++); *codePtr++ = tracer->vm->getStringIndex(SwapLong(*rover++)); // tag string for(int i = opdata->args - 2; i--;) *codePtr++ = SwapLong(*rover++); break; case ACS0_OP_DELAY_IMM_BYTE: brover = (byte *)rover; *codePtr++ = opdata->opdata->op; for(int i = opdata->args; i--;) *codePtr++ = *brover++; break; case ACS0_OP_ACTIVATORHEALTH: case ACS0_OP_ACTIVATORARMOR: case ACS0_OP_ACTIVATORFRAGS: case ACS0_OP_PLAYERNUMBER: case ACS0_OP_ACTIVATORTID: *codePtr++ = ACS_OP_GET_IMM; *codePtr++ = 0; *codePtr++ = opdata->opdata->op; *codePtr++ = ACS_translateThingVarACS0(opdata); break; case ACS0_OP_GAMETYPE_ONEFLAGCTF: *codePtr++ = ACS_OP_GET_IMM; *codePtr++ = 0; break; case ACS0_OP_GAMETYPE_SINGLEPLAYER: *codePtr++ = opdata->opdata->op; *codePtr++ = ACS_OP_GET_IMM; *codePtr++ = gt_single; *codePtr++ = ACS_OP_CMP_EQ; break; case ACS0_OP_RANDOM_IMM_BYTE: brover = (byte *)rover; ACS_translateFuncACS0(codePtr, opdata); for(int i = opdata->args; i--;) *codePtr++ = *brover++; break; case ACS0_OP_SETMUSIC_IMM: case ACS0_OP_SETMUSICLOCAL_IMM: case ACS0_OP_SPAWNPOINT_IMM: case ACS0_OP_SPAWNSPOT_IMM: ACS_translateFuncACS0(codePtr, opdata); *codePtr++ = tracer->vm->getStringIndex(SwapLong(*rover++)); // tag string for(int i = opdata->args - 1; i--;) *codePtr++ = SwapLong(*rover++); break; case ACS0_OP_BRANCH_CALLDISCARD: *codePtr++ = opdata->opdata->op; if(tracer->compressed) *codePtr++ = *(byte *)rover; else *codePtr++ = SwapLong(*rover); *codePtr++ = ACS_OP_STACK_DROP; break; case ACS0_OP_BRANCH_RETURNVOID: *codePtr++ = ACS_OP_GET_IMM; *codePtr++ = 0; *codePtr++ = opdata->opdata->op; break; case ACS0_OP_BRANCH_CASETABLE: // Align rover. rover = (int32_t *)(((uintptr_t)rover + 3) & ~3); temp = SwapLong(*rover++); *codePtr++ = opdata->opdata->op; *codePtr++ = temp; while(temp--) { *codePtr++ = SwapLong(*rover++); *jumpItr++ = codePtr; *codePtr++ = SwapLong(*rover++); } break; case ACS0_OP_CALLFUNC: if(tracer->compressed) { brover = (uint8_t *)rover; uint8_t argc = *brover++; uint16_t func = SwapUShort(*(uint16_t *)brover); ACS_translateFuncACS0(codePtr, func, argc); } else ACS_translateFuncACS0(codePtr, SwapLong(rover[1]), SwapLong(rover[0])); break; default: case_direct: // Direct translation. if(opdata->opdata->op == ACS_OP_CALLFUNC || opdata->opdata->op == ACS_OP_CALLFUNC_IMM) { ACS_translateFuncACS0(codePtr, opdata); } else *codePtr++ = opdata->opdata->op; if(tracer->compressed && opdata->compressed) { brover = (byte *)rover; for(int i = opdata->args; i--;) *codePtr++ = *brover++; } else { for(int i = opdata->args; i--;) *codePtr++ = SwapLong(*rover++); } break; } } // Set the last instruction to a KILL. *codePtr++ = ACS_OP_KILL; #ifdef RANGECHECK // If this isn't true, something very wrong has happened internally. if(codePtr != tracer->vm->code + tracer->vm->numCode) { I_Error("Incorrect code count. %i/%i/%i", (int)(codePtr - tracer->vm->code), (int)tracer->vm->numCode, (int)(tracer->lumpLength / 4)); } // Same here, this is just a sanity check. if(jumpItr != jumps + tracer->jumpCount) { I_Error("Incorrect jump count. %i/%i", (int)(jumpItr - jumps), (int)tracer->jumpCount); } #endif // Translate jumps. Has to be done after code in order to jump forward. while(jumpItr != jumps) { codePtr = *--jumpItr; if ((uint32_t)*codePtr < tracer->lumpLength) *codePtr = codeIndexMap[*codePtr]; else *codePtr = 0; } }
// // ACS_traceScriptACS0 // static void ACS_traceScriptACS0(acs0_tracer_t *tracer, uint32_t index) { uint32_t indexNext, opSize; int32_t op; acs0_opdata_t const *opdata; for(;;) { // Read next instruction from file. op = ACS_readOpACS0(tracer, &opSize, index); // Invalid opcode terminates tracer. if(op >= ACS0_OPMAX || op < 0) { // But flag it so that a KILL gets generated by the translator. ACS_touchScriptACS0(tracer->codeTouched + index, tracer->codeTouched + index + opSize); ++tracer->vm->numCode; return; } opdata = &ACS0opdata[op]; // Calculate next index. indexNext = index + ACS_countOpSizeACS0(tracer, index, opSize, opdata); // Leaving the bounds of the lump also terminates the tracer. if(indexNext > tracer->lumpLength) return; // If already touched this instruction, stop tracing. if(ACS_touchScriptACS0(tracer->codeTouched + index, tracer->codeTouched + indexNext)) return; // Determine how many internal codes this counts for. switch(op) { case ACS0_OP_LINESPEC1_IMM: case ACS0_OP_LINESPEC2_IMM: case ACS0_OP_LINESPEC3_IMM: case ACS0_OP_LINESPEC4_IMM: case ACS0_OP_LINESPEC5_IMM: case ACS0_OP_LINESPEC1_IMM_BYTE: case ACS0_OP_LINESPEC2_IMM_BYTE: case ACS0_OP_LINESPEC3_IMM_BYTE: case ACS0_OP_LINESPEC4_IMM_BYTE: case ACS0_OP_LINESPEC5_IMM_BYTE: case ACS0_OP_GET2_IMM_BYTE: case ACS0_OP_GET3_IMM_BYTE: case ACS0_OP_GET4_IMM_BYTE: case ACS0_OP_GET5_IMM_BYTE: tracer->vm->numCode += opdata->args + 2; break; case ACS0_OP_GETARR_IMM_BYTE: tracer->vm->numCode += *(tracer->data + index + opSize) + 2; break; case ACS0_OP_ACTIVATORHEALTH: case ACS0_OP_ACTIVATORARMOR: case ACS0_OP_ACTIVATORFRAGS: case ACS0_OP_BRANCH_RETURNVOID: case ACS0_OP_PLAYERNUMBER: case ACS0_OP_ACTIVATORTID: case ACS0_OP_SIGILPIECES: tracer->vm->numCode += opdata->opdata->args + 1 + 2; // GET_IMM 0 break; case ACS0_OP_GAMETYPE_ONEFLAGCTF: tracer->vm->numCode += 2; // GET_IMM break; case ACS0_OP_GAMETYPE_SINGLEPLAYER: tracer->vm->numCode += 4; // GAMETYPE + GET_IMM + CMP_EQ break; case ACS0_OP_BRANCH_CALLDISCARD: tracer->vm->numCode += opdata->opdata->args + 1 + 1; // DROP break; case ACS0_OP_BRANCH_CASETABLE: tracer->vm->numCode += 2; // More alignment stuff. (Wow, that's a mouthfull.) tracer->vm->numCode += SwapULong(*(uint32_t *)(((uintptr_t)tracer->data + index + opSize + 3) & ~3)) * 2; break; case ACS0_OP_CALLFUNC: if(tracer->compressed) { uint8_t argc = tracer->data[index + opSize]; uint16_t func = SwapUShort(*(uint16_t *)(tracer->data + index + opSize + 1)); tracer->vm->numCode += ACS_traceFuncACS0(func, argc); } else { uint32_t argc = SwapULong(*(uint32_t *)(tracer->data + index + opSize + 0)); uint32_t func = SwapULong(*(uint32_t *)(tracer->data + index + opSize + 4)); tracer->vm->numCode += ACS_traceFuncACS0(func, argc); } break; default: // Translation to CALLFUNC. if(opdata->opdata->op == ACS_OP_CALLFUNC_IMM) { // Adds the func and argc arguments. tracer->vm->numCode += opdata->args + 1 + 2; break; } // Direct translation. #ifdef RANGECHECK // This should never happen. if(opdata->opdata->args == -1) I_Error("Unknown translation for opcode. opcode %i", (int)op); #endif tracer->vm->numCode += opdata->opdata->args + 1; break; } // Advance the index past the instruction. switch(op) { case ACS0_OP_SCRIPT_TERMINATE: case ACS0_OP_BRANCH_RETURN: case ACS0_OP_BRANCH_RETURNVOID: return; case ACS0_OP_BRANCH_IMM: ++tracer->jumpCount; index = SwapLong(*(int32_t *)(tracer->data + index + opSize)); continue; case ACS0_OP_BRANCH_NOTZERO: case ACS0_OP_BRANCH_ZERO: ++tracer->jumpCount; ACS_traceScriptACS0(tracer, SwapLong(*(int32_t *)(tracer->data + index + opSize))); break; case ACS0_OP_BRANCH_CASE: ++tracer->jumpCount; ACS_traceScriptACS0(tracer, SwapLong(*(int32_t *)(tracer->data + index + opSize + 4))); break; case ACS0_OP_BRANCH_CASETABLE: { uint32_t jumps, *rover; rover = (uint32_t *)(tracer->data + index + opSize); // And alignment again. rover = (uint32_t *)(((uintptr_t)rover + 3) & ~3); jumps = SwapULong(*rover++); tracer->jumpCount += jumps; // Trace all of the jump targets. // Start by incrementing rover to point to address. for(++rover; jumps--; rover += 2) ACS_traceScriptACS0(tracer, SwapULong(*rover)); } break; } index = indexNext; } }