UCProcess.cpp

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2002-2005 The Pentagram team
00003 
00004 This program is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU General Public License
00006 as published by the Free Software Foundation; either version 2
00007 of the License, or (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 */
00018 
00019 #include "pent_include.h"
00020 
00021 #include "UCProcess.h"
00022 #include "UCMachine.h"
00023 #include "Usecode.h"
00024 #include "GameData.h"
00025 #include "IDataSource.h"
00026 #include "ODataSource.h"
00027 
00028 // p_dynamic_cast stuff
00029 DEFINE_RUNTIME_CLASSTYPE_CODE(UCProcess,Process);
00030 
00031 UCProcess::UCProcess() : Process()// !! fixme
00032 {
00033         usecode = GameData::get_instance()->getMainUsecode();
00034 }
00035 
00036 UCProcess::UCProcess(uint16 classid_, uint16 offset_, uint32 this_ptr,
00037                                           int thissize, const uint8* args, int argsize)
00038         : Process()
00039 {
00040         classid = 0xFFFF;
00041         ip = 0xFFFF;
00042         bp = 0x0000;
00043         usecode = GameData::get_instance()->getMainUsecode();
00044         temp32 = 0;
00045 
00046         load(classid_, offset_, this_ptr, thissize, args, argsize);
00047 }
00048 
00049 UCProcess::~UCProcess()
00050 {
00051 
00052 }
00053 
00054 void UCProcess::load(uint16 classid_, uint16 offset_, uint32 this_ptr,
00055                                          int thissize, const uint8* args, int argsize)
00056 {
00057         if (usecode->get_class_size(classid_) == 0)
00058                 perr << "Class is empty..." << std::endl;
00059 
00060         classid = 0xFFFF;
00061         ip = 0xFFFF;
00062         bp = 0x0000;
00063         uint16 thissp = 0;
00064 
00065         // first, push the derefenced this pointer
00066         if (this_ptr != 0 && thissize > 0) {
00067                 stack.addSP(-thissize);
00068                 UCMachine::get_instance()->
00069                         dereferencePointer(this_ptr, stack.access(), thissize);
00070                 thissp = stack.getSP();
00071         }
00072 
00073         // next, push the arguments
00074         stack.push(args, argsize);
00075 
00076         // then, push the new this pointer
00077         if (thissp != 0)
00078                 stack.push4(UCMachine::stackToPtr(pid, thissp));
00079 
00080         // finally, call the specified function
00081         call(classid_, offset_);
00082 }
00083 
00084 bool UCProcess::run(const uint32 /*framenum*/)
00085 {
00086         if (flags & PROC_SUSPENDED)
00087                 return false;
00088 
00089         // pass to UCMachine for execution
00090 
00091         return UCMachine::get_instance()->execProcess(this);
00092 }
00093 
00094 void UCProcess::call(uint16 classid_, uint16 offset_)
00095 {
00096         stack.push2(classid); // BP+04 prev class
00097         stack.push2(ip);      // BP+02 prev IP
00098         stack.push2(bp);      // BP+00 prev BP
00099 
00100         classid = classid_;
00101         ip = offset_;
00102         bp = static_cast<uint16>(stack.getSP()); // TRUNCATES!
00103 }
00104 
00105 bool UCProcess::ret()
00106 {
00107         stack.setSP(bp);
00108 
00109         bp = stack.pop2();
00110         ip = stack.pop2();
00111         classid = stack.pop2();
00112 
00113         if (ip == 0xFFFF && classid == 0xFFFF)
00114                 return true;
00115         else
00116                 return false;
00117 }
00118 
00119 void UCProcess::freeOnTerminate(uint16 index, int type)
00120 {
00121         assert(type >= 1 && type <= 3);
00122 
00123         std::pair<uint16, int> p;
00124         p.first = index;
00125         p.second = type;
00126 
00127         freeonterminate.push_back(p);
00128 }
00129 
00130 void UCProcess::terminate()
00131 {
00132         std::list<std::pair<uint16, int> >::iterator i;
00133 
00134         for (i = freeonterminate.begin(); i != freeonterminate.end(); ++i) {
00135                 uint16 index = (*i).first;
00136                 int type = (*i).second;
00137 
00138                 switch (type) {
00139                 case 1: // string
00140                         UCMachine::get_instance()->freeString(index);
00141                         break;
00142                 case 2: // stringlist
00143                         UCMachine::get_instance()->freeStringList(index);
00144                         break;
00145                 case 3: // list
00146                         UCMachine::get_instance()->freeList(index);
00147                         break;
00148                 }
00149         }
00150 
00151         freeonterminate.clear();
00152 
00153         Process::terminate();
00154 }
00155 
00156 void UCProcess::dumpInfo()
00157 {
00158         Process::dumpInfo();
00159 
00160         if (classid == 0xFFFF) {
00161                 pout.printf("IP undefined\n");
00162         } else {
00163                 const char* classname = GameData::get_instance()->getMainUsecode()->
00164                         get_class_name(classid);
00165                 pout.printf("classname: %s, IP: %04X:%04X\n", classname, classid, ip);
00166         }
00167 }
00168 
00169 void UCProcess::saveData(ODataSource* ods)
00170 {
00171         Process::saveData(ods);
00172 
00173         ods->write2(bp);
00174         ods->write2(classid);
00175         ods->write2(ip);
00176         ods->write4(temp32);
00177         ods->write4(freeonterminate.size());
00178         std::list<std::pair<uint16, int> >::iterator iter;
00179         for (iter = freeonterminate.begin(); iter != freeonterminate.end(); ++iter)
00180         {
00181                 ods->write2(iter->first);
00182                 ods->write4(static_cast<uint32>(iter->second));
00183         }
00184         stack.save(ods);
00185 }
00186 
00187 bool UCProcess::loadData(IDataSource* ids, uint32 version)
00188 {
00189         if (!Process::loadData(ids, version)) return false;
00190 
00191         bp = ids->read2();
00192         classid = ids->read2();
00193         ip = ids->read2();
00194         temp32 = ids->read4();
00195         uint32 freecount = ids->read4();
00196         for (unsigned int i = 0; i < freecount; ++i) {
00197                 std::pair<uint16, int> p;
00198                 p.first = ids->read2();
00199                 p.second = static_cast<int>(ids->read4());
00200                 freeonterminate.push_back(p);
00201         }
00202         stack.load(ids, version);
00203 
00204         return true;
00205 }

Generated on Fri Jul 27 22:27:50 2007 for pentagram by  doxygen 1.4.7