bool FUNCGETREF::execute(void) { bool result= true; VMREGTYPE pString= 0; const char* string= "null"; VMREGTYPE count= 0; if(machine.pop(pString) && (string=machine.GetString((VPVOID)pString))!=0) { VMLONG strlength= strlen((const char*)string); parent= machine.GetFlow(); result= machine.WriteMem((VPVOID)reltolinear(SECONDOBJECT_LENGTH_IMAGE),&strlength,sizeof(strlength)) && machine.WriteMem((VPVOID)reltolinear(SECONDOBJECT_IMAGE),(void*)string,strlength+1); if(result) { Context context= machine.GetFlow(); isplayer= !_stricmp(string,"player") || !_stricmp(string,"playersavegame"); if(isplayer) context.Eip= (DWORD)reltolinear(FIXUPPLAYER); else context.Eip= (DWORD)reltolinear(FIXUPINSTANCE); machine.SetFlow(context); result= machine.SetVMDebuggerBreakpoint(this); } } else result= false; return result; }
bool FUNCPOSITIONCELL::execute(void) { bool result= false; VMREGTYPE stackpointer= 0; struct{TES3COORDINATE coord; TES3FLOAT zAngle; VMREGTYPE pString;} stackparams; TES3ROTATION angle= {0,0,0}; const char* string= "null"; if(machine.GetRegister(SP,stackpointer) && machine.ReadMem((VPVOID)stackpointer,&stackparams,sizeof(stackparams)) && (string=machine.GetString((VPVOID)stackparams.pString))!=0) { angle.z= stackparams.zAngle; VMLONG strlength= strlen((const char*)string); stackpointer+= sizeof(stackparams); result= (machine.SetRegister(SP,stackpointer) && machine.WriteMem((VPVOID)reltolinear(DESTINATION_IMAGE),&stackparams.coord,sizeof(stackparams.coord)) && machine.WriteMem((VPVOID)reltolinear(TARGETROT_IMAGE),&angle,sizeof(angle)) && machine.WriteMem((VPVOID)reltolinear(TARGETCELL_IMAGE),(void*)string,strlength+1) && CallOriginalFunction(machine,ORIG_POSITIONCELL)); } return false; // required to make virtualmachine stop running }
bool FUNCREF::setref(VPREFERENCE target) { TES3REFERENCE ref; OPCODE deref= ORIG_DEREF; BYTE inref= 1; const Context& context= machine.GetFlow(); machine.SetFlags((VMREGTYPE)target); return (!target || (machine.ReadMem((VPVOID)target,&ref,sizeof(ref)) && machine.WriteMem((VPVOID)reltolinear(TES3OP_IMAGE),&deref,sizeof(deref)) && machine.WriteMem((VPVOID)reltolinear(SCRIPTTARGETREF_IMAGE),&target,sizeof(target)) && machine.WriteMem((VPVOID)reltolinear(SCRIPTTARGETTEMPL_IMAGE),&ref.templ,sizeof(ref.templ)) && machine.WriteMem((VPVOID)context.Ebp+RUNSCRIPT_INREFOFFSET,&inref,sizeof(inref)))); }
bool FUNCGETCOMBAT::execute(void) { bool result= false; VPREFERENCE ref= 0; VPREFERENCE target= 0; VPMACH mach= 0; if(machine.ReadMem((VPVOID)reltolinear(SCRIPTTARGETREF_IMAGE),&ref,sizeof(ref))) { if(REFERENCE::GetMach(machine,(VPREFERENCE)ref,mach)) { if(mach) { if(machine.ReadMem((VPVOID)&mach->combattarget,&mach,sizeof(mach))) { if(mach) result= machine.ReadMem((VPVOID)&mach->ref,&target,sizeof(target)); else result= true; } } else result= true; } } if(result) result= machine.push((VMREGTYPE)target); #ifdef DEBUGGING cLog::mLogMessage("%lx = FUNCGETCOMBAT(%lx) %s\n",target,ref,result?"succeeded":"failed"); #endif return result; }
bool FUNCREFID::execute(void) { bool result= false; VMPTR<TES3REFERENCE*> pref(machine); VMPTR<TES3REFERENCE> ref(machine); VMPTR<TES3TEMPLATE> templ(machine); VMPTR<TES3IDSTRING> id(machine); const char* idstring= "null"; try { pref= (TES3REFERENCE**)reltolinear(SCRIPTTARGETREF_IMAGE); ref= *pref; templ= ref->templ; id= (VPIDSTRING)templ->objectid; idstring= strings.add((const char*)id->id); result= machine.push((VMREGTYPE)idstring); } catch(...) { result= false; } return result; }
bool FUNCDISTANCE::execute(void) { bool result= false; VMREGTYPE target= 0; VMFLOAT distance= 0; VMPTR<TES3REFERENCE*> pref(machine); VMPTR<TES3REFERENCE> thisref(machine); VMPTR<TES3REFERENCE> targetref(machine); try { if(machine.pop(target)) { pref= (TES3REFERENCE**)reltolinear(SCRIPTTARGETREF_IMAGE); thisref= *pref; targetref= (TES3REFERENCE*)target; FLOAT dx= targetref->x - thisref->x; FLOAT dy= targetref->y - thisref->y; FLOAT dz= targetref->z - thisref->z; distance= sqrt(dx*dx+dy*dy+dz*dz); result= machine.push(distance); } } catch(...) { result= false; } return result; }
bool FUNCFIRSTSTATIC::execute(void) { bool result = false; static VPCELLMASTER cellmaster= 0; VPCELLPTR pcellptr; TES3CELLPTR cellptr; VPCELL intcell= 0; VPREFERENCE ref= 0; exteriors[0] = 0; if((cellmaster || getMachine().ReadMem((VPVOID)reltolinear(MASTERCELL_IMAGE),&cellmaster,sizeof(cellmaster))) && getMachine().ReadMem((VPVOID)&cellmaster->interiorcell,&intcell,sizeof(intcell))) { if(intcell) result = getMachine().ReadMem((VPVOID)&intcell->statics.first,&ref,sizeof(ref)); else { if(getMachine().ReadMem((VPVOID)&cellmaster->exteriorcells[CENTRE],&pcellptr,sizeof(pcellptr)) && getMachine().ReadMem((VPVOID)pcellptr,&cellptr,sizeof(cellptr))) { if(cellptr.size==1) result= getMachine().ReadMem((VPVOID)&cellptr.first->statics.first,&ref,sizeof(ref)); else result= true; } } } result= getMachine().push((VMREGTYPE)ref) && result; return result; }
bool FUNCGETCOMBAT::execute(void) { bool result= false; VPREFERENCE ref= 0; VPREFERENCE target= 0; VPMACH mach= 0; if(machine.ReadMem((VPVOID)reltolinear(SCRIPTTARGETREF_IMAGE),&ref,sizeof(ref))) { if(REFERENCE::GetMach(machine,(VPREFERENCE)ref,mach)) { if(mach) { if(machine.ReadMem((VPVOID)&mach->combattarget,&mach,sizeof(mach))) { if(mach) result= machine.ReadMem((VPVOID)&mach->ref,&target,sizeof(target)); else result= true; } } else result= true; } } if(result) result= machine.push((VMREGTYPE)target); return result; }
bool GetLocalVars(TES3MACHINE& machine, TES3VARIABLES* vars) { VPVARIABLES pvars= 0; return machine.ReadMem((VPVOID)reltolinear(LOCALVARIABLES_IMAGE),&pvars,sizeof(pvars)) && pvars && machine.ReadMem((VPVOID)pvars,vars,sizeof(TES3VARIABLES)); }
bool FUNCPOSITION::execute(void) { bool result= false; VMREGTYPE stackpointer= 0; struct{TES3COORDINATE coord; TES3FLOAT zAngle;} stackparams; TES3ROTATION angle= {0,0,0}; if(machine.GetRegister(SP,stackpointer) && machine.ReadMem((VPVOID)stackpointer,&stackparams,sizeof(stackparams))) { angle.z= stackparams.zAngle; stackpointer+= sizeof(stackparams); result= (machine.SetRegister(SP,stackpointer) && machine.WriteMem((VPVOID)reltolinear(DESTINATION_IMAGE),&stackparams.coord,sizeof(stackparams.coord)) && machine.WriteMem((VPVOID)reltolinear(TARGETROT_IMAGE),&angle,sizeof(angle)) && CallOriginalFunction(machine,ORIG_POSITION)); } return false; // required to make virtualmachine stop running }
bool FUNCSETLOCAL::execute(void) { bool result= false; VMREGTYPE stackpointer= 0; struct{VMREGTYPE type, index, value;} stackparams; // 2005-06-30 CDC If there is at least one item on the stack, make sure there are three if(machine.GetRegister(SP,stackpointer) && stackpointer) { if ( !(stackpointer + sizeof(VMREGTYPE)) && machine.push((VMREGTYPE)0) ) stackpointer-= 2 * sizeof(VMREGTYPE); else if ( !(stackpointer + 2 * sizeof(VMREGTYPE)) && machine.push((VMREGTYPE)0) && machine.push((VMREGTYPE)0) ) stackpointer-= sizeof(VMREGTYPE); VPREFERENCE pref= 0; TES3VARIABLES vars; if( machine.ReadMem((VPVOID)stackpointer,&stackparams,sizeof(stackparams)) && machine.ReadMem((VPVOID)reltolinear(SCRIPTTARGETREF_IMAGE),&pref,sizeof(pref)) && opcode==SETFOREIGN?GetRefVars(machine,pref,&vars):GetLocalVars(machine,&vars)) { switch(stackparams.type) { case 's': { TES3SHORT val= (TES3SHORT)stackparams.value; TES3SHORT* addr= &vars.shorts[stackparams.index]; result= machine.WriteMem((VPVOID)addr,&val,sizeof(val)); } break; case 'l': { TES3LONG val= (TES3LONG)stackparams.value; TES3LONG* addr= &vars.longs[stackparams.index]; result= machine.WriteMem((VPVOID)addr,&val,sizeof(val)); } break; case 'f': { TES3FLOAT val= *((TES3FLOAT*)&stackparams.value); TES3FLOAT* addr= &vars.floats[stackparams.index]; result= machine.WriteMem((VPVOID)addr,&val,sizeof(val)); } break; } { stackpointer+= sizeof(stackparams); result= machine.SetRegister(SP,stackpointer); } } } return result; }
bool FUNCSTARTCOMBAT::execute(void) { VMREGTYPE target= 0; bool result= (machine.pop(target) && machine.WriteMem((VPVOID)reltolinear(SECONDOBJECT_IMAGE),&target,sizeof(target)) && CallOriginalFunction(machine,ORIG_STARTCOMBAT)); return result; }
//this function calls the original function you want to run using the correct opcode //you'll need to set parameters yourself, this ONLY calls the correct command bool FUNCEXTENDER::CallOriginalFunction(TES3MACHINE& machine, OPCODE originalopcode) { Context context = machine.GetFlow(); //get the currect 'flow' (registerstates...) context.Edx = originalopcode; //set the Edx register to the 'originalopcode' opcode. context.Eip = (DWORD)reltolinear(RUNFUNCOPCODETEST); //change the Eip register (instruction pointer) to ... //...the converted (from relative to linear), RUNFUNCOPCODETEST (don't know what that is yet...) ... //...i think it's the location of the function that will accept the opcode in the Edx register, and check if ... //...the correct function exists, and run if yes. machine.SetFlow(context); //and set the new flow, so the game will use it. return true; }
bool FUNCAITRAVEL::execute(void) { bool result= false; VMREGTYPE stackpointer= 0; TES3COORDINATE coord; result= (machine.GetRegister(SP,stackpointer) && machine.SetRegister(SP,stackpointer+sizeof(coord)) && machine.ReadMem((VPVOID)stackpointer,&coord,sizeof(coord)) && machine.WriteMem((VPVOID)reltolinear(DESTINATION_IMAGE),&coord,sizeof(coord)) && CallOriginalFunction(machine,ORIG_AITRAVEL)); return false; // required to make virtualmachine stop running }
bool FUNCREFPCTARGET::execute(void) { bool result= false; static VPVIEWMASTER viewmaster= 0; VPREFERENCE target= 0; result= ((viewmaster || getMachine().ReadMem((VPVOID)reltolinear(MASTER2_IMAGE),&viewmaster,sizeof(viewmaster))) && getMachine().ReadMem((VPVOID)&viewmaster->target,&target,sizeof(target)) && setref(target)); return result; }
bool FUNCFIRSTITEM::execute(void) { bool result= false; static VPCELLMASTER cellmaster= 0; VPCELLPTR pcellptr; TES3CELLPTR cellptr; VPCELL intcell= 0; VPREFERENCE ref= 0; // 2005-07-02 CDC int i; exteriors[0] = 0; if((cellmaster || getMachine().ReadMem((VPVOID)reltolinear(MASTERCELL_IMAGE),&cellmaster,sizeof(cellmaster))) && getMachine().ReadMem((VPVOID)&cellmaster->interiorcell,&intcell,sizeof(intcell))) { if(intcell) result= getMachine().ReadMem((VPVOID)&intcell->otheritems.first,&ref,sizeof(ref)); else { if(getMachine().ReadMem((VPVOID)&cellmaster->exteriorcells[CENTRE],&pcellptr,sizeof(pcellptr)) && getMachine().ReadMem((VPVOID)pcellptr,&cellptr,sizeof(cellptr))) { if(cellptr.size==1) { result= getMachine().ReadMem((VPVOID)&cellptr.first->otheritems.first,&ref,sizeof(ref)); for ( i=0; i<8; i++ ) // Read the other 8 exteriors too { if(getMachine().ReadMem((VPVOID)&cellmaster->exteriorcells[(i<4?i:i+1)],&pcellptr,sizeof(pcellptr)) && getMachine().ReadMem((VPVOID)pcellptr,&cellptr,sizeof(cellptr))) { if(cellptr.size==1) getMachine().ReadMem((VPVOID)&cellptr.first->otheritems.first,&exteriors[i],sizeof(VPREFERENCE)); else { exteriors[i] = 0; i = 9; } } } } else result= true; } } } result= getMachine().push((VMREGTYPE)ref) && result; return result; }
bool FUNCPLACEAT::breakpoint() { bool result= false; Context flow= machine.GetFlow(); machine.SetFlow(parent); VMREGTYPE templ= flow.Eax; if(templ) { VMREGTYPE count= 1; TES3COORDINATE relpos= { 256,1,0 }; result=(machine.WriteMem((VPVOID)reltolinear(SECONDOBJECT_IMAGE),&templ,sizeof(templ)) && machine.WriteMem((VPVOID)reltolinear(VARINDEX_IMAGE),(void*)&count,sizeof(count)) && machine.WriteMem((VPVOID)reltolinear(DESTINATIONX_IMAGE),(void*)&relpos,sizeof(relpos)) && machine.SetVMDebuggerBreakpoint(&part2) && CallOriginalFunction(machine,ORIG_PLACEATPC)); } else result= machine.push(templ); return result; }
bool FUNCSTARTCOMBAT::execute(void) { VMREGTYPE target= 0; bool result= (machine.pop(target) && machine.WriteMem((VPVOID)reltolinear(SECONDOBJECT_IMAGE),&target,sizeof(target)) && CallOriginalFunction(machine,ORIG_STARTCOMBAT)); #ifdef DEBUGGING cLog::mLogMessage("FUNCSTARTCOMBAT(%lx) %s\n",target,result?"succeeded":"failed"); #endif return result; }
bool FUNCPLACEAT::execute(void) { bool result= true; VMREGTYPE pString= 0; const char* string= "null"; if(machine.pop(pString) && (string=machine.GetString((VPVOID)pString))!=0) { VMLONG strlength= strlen((const char*)string); parent= machine.GetFlow(); result= machine.WriteMem((VPVOID)reltolinear(SECONDOBJECT_LENGTH_IMAGE),&strlength,sizeof(strlength)) && machine.WriteMem((VPVOID)reltolinear(SECONDOBJECT_IMAGE),(void*)string,strlength+1); if(result) { Context Context= machine.GetFlow(); Context.Eip= (DWORD)reltolinear(FIXUPTEMPLATE); machine.SetFlow(Context); result= machine.SetVMDebuggerBreakpoint(this); } } else result= false; return result; }
bool FUNCGETLOCAL::execute(void) { bool result= false; VMREGTYPE stackpointer= 0, value= 0; struct{VMREGTYPE type, index;} stackparams; if(machine.GetRegister(SP,stackpointer)) { VPREFERENCE pref= 0; TES3VARIABLES vars; if( machine.ReadMem((VPVOID)stackpointer,&stackparams,sizeof(stackparams)) && machine.ReadMem((VPVOID)reltolinear(SCRIPTTARGETREF_IMAGE),&pref,sizeof(pref)) && opcode==GETFOREIGN?GetRefVars(machine,pref,&vars):GetLocalVars(machine,&vars)) { switch(stackparams.type) { case 's': { TES3SHORT val; TES3SHORT* addr= &vars.shorts[stackparams.index]; result= machine.ReadMem((VPVOID)addr,&val,sizeof(val)); value= val; } break; case 'l': { TES3LONG* addr= &vars.longs[stackparams.index]; result= machine.ReadMem((VPVOID)addr,&value,sizeof(value)); } break; case 'f': { TES3FLOAT* addr= &vars.floats[stackparams.index]; result= machine.ReadMem((VPVOID)addr,&value,sizeof(value)); } break; } // 2005-06-30 CDC Clearing the stack isn't optional, we used them even if we couldn't finish the read stackpointer+= sizeof(stackparams); machine.SetRegister(SP,stackpointer); result= machine.push(value); } } return result; }
bool FUNCREFTYPE::execute(void) { bool result= false; VMPTR<TES3REFERENCE*> pref(machine); VMPTR<TES3REFERENCE> ref(machine); VMPTR<TES3TEMPLATE> templ(machine); try { pref= (TES3REFERENCE**)reltolinear(SCRIPTTARGETREF_IMAGE); ref= *pref; templ= ref->templ; result= machine.push((VMREGTYPE)templ->type); } catch(...) { result= false; } return result; }
bool FUNCPCCELLID::execute(void) { bool result= false; VMPTR<TES3CELLMASTER*> pcellmaster(machine); VMPTR<TES3CELLMASTER> cellmaster(machine); VMPTR<TES3CELL> cell(machine); VMPTR<TES3IDSTRING> cellname(machine); const char* cellid= "Wilderness"; try { pcellmaster= (TES3CELLMASTER**)reltolinear(MASTERCELL_IMAGE); cellmaster= *pcellmaster; cell= cellmaster->interiorcell; if(!cell) { VMPTR<TES3CELLPTR> cellptr(machine); cellptr= cellmaster->exteriorcells[CENTRE]; cell= cellptr->first; } if(cell) { cellname= (VPIDSTRING)cell->cellname; if(cellname) cellid=(const char*)cellname->id; } cellid= strings.add(cellid); // LOG::log("%s = PCCELLID()\n",cellid); result= machine.push((VMREGTYPE)cellid); } catch(...) { cLog::mLogMessage("PCCELLID() exception\n"); result= false; } return result; }