Initial commit
This commit is contained in:
134
engines/ultima/ultima8/usecode/bit_set.cpp
Normal file
134
engines/ultima/ultima8/usecode/bit_set.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/misc/debugger.h"
|
||||
#include "ultima/ultima8/usecode/bit_set.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
BitSet::BitSet() : _size(0), _bytes(0), _data(nullptr) {
|
||||
}
|
||||
|
||||
|
||||
BitSet::BitSet(unsigned int size) : _data(nullptr) {
|
||||
setSize(size);
|
||||
}
|
||||
|
||||
BitSet::~BitSet() {
|
||||
delete[] _data;
|
||||
}
|
||||
|
||||
void BitSet::setSize(unsigned int size) {
|
||||
if (_data) delete[] _data;
|
||||
|
||||
_size = size;
|
||||
_bytes = _size / 8;
|
||||
if (_size % 8 != 0) _bytes++;
|
||||
|
||||
_data = new uint8[_bytes];
|
||||
for (unsigned int i = 0; i < _bytes; ++i)
|
||||
_data[i] = 0;
|
||||
}
|
||||
|
||||
uint32 BitSet::getEntries(unsigned int pos, unsigned int n) const {
|
||||
assert(n <= 32);
|
||||
assert(pos + n <= _size);
|
||||
if (n == 0) return 0;
|
||||
|
||||
unsigned int firstbyte = pos / 8;
|
||||
unsigned int lastbyte = (pos + n - 1) / 8;
|
||||
|
||||
if (firstbyte == lastbyte) {
|
||||
return ((_data[firstbyte] >> (pos % 8)) & ((1 << n) - 1));
|
||||
}
|
||||
|
||||
unsigned int firstbits = 8 - (pos % 8);
|
||||
unsigned int lastbits = ((pos + n - 1) % 8) + 1;
|
||||
|
||||
unsigned int firstmask = ((1 << firstbits) - 1) << (8 - firstbits);
|
||||
unsigned int lastmask = ((1 << lastbits) - 1);
|
||||
|
||||
uint32 ret = 0;
|
||||
|
||||
ret |= (_data[firstbyte] & firstmask) >> (8 - firstbits);
|
||||
unsigned int shift = firstbits;
|
||||
for (unsigned int i = firstbyte + 1; i < lastbyte; ++i) {
|
||||
ret |= (_data[i] << shift);
|
||||
shift += 8;
|
||||
}
|
||||
ret |= (_data[lastbyte] & lastmask) << shift;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void BitSet::setEntries(unsigned int pos, unsigned int n, uint32 bits) {
|
||||
assert(n <= 32);
|
||||
assert(pos + n <= _size);
|
||||
if (n == 0) return;
|
||||
|
||||
unsigned int firstbyte = pos / 8;
|
||||
unsigned int lastbyte = (pos + n - 1) / 8;
|
||||
|
||||
if (firstbyte == lastbyte) {
|
||||
_data[firstbyte] &= ~(((1 << n) - 1) << (pos % 8));
|
||||
_data[firstbyte] |= (bits & ((1 << n) - 1)) << (pos % 8);
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int firstbits = 8 - (pos % 8);
|
||||
unsigned int lastbits = ((pos + n - 1) % 8) + 1;
|
||||
|
||||
unsigned int firstmask = ((1 << firstbits) - 1) << (8 - firstbits);
|
||||
unsigned int lastmask = ((1 << lastbits) - 1);
|
||||
|
||||
_data[firstbyte] &= ~firstmask;
|
||||
_data[firstbyte] |= (bits << (8 - firstbits)) & firstmask;
|
||||
unsigned int shift = firstbits;
|
||||
for (unsigned int i = firstbyte + 1; i < lastbyte; ++i) {
|
||||
_data[i] = (bits >> shift);
|
||||
shift += 8;
|
||||
}
|
||||
_data[lastbyte] &= ~lastmask;
|
||||
_data[lastbyte] |= (bits >> shift) & lastmask;
|
||||
}
|
||||
|
||||
void BitSet::save(Common::WriteStream *ws) {
|
||||
ws->writeUint32LE(_size);
|
||||
ws->write(_data, _bytes);
|
||||
}
|
||||
|
||||
bool BitSet::load(Common::ReadStream *rs, uint32 version) {
|
||||
uint32 s = rs->readUint32LE();
|
||||
|
||||
if (s > 1024 * 1024) {
|
||||
warning("Improbable globals size %d, corrupt save?", s);
|
||||
return false;
|
||||
}
|
||||
|
||||
setSize(s);
|
||||
rs->read(_data, _bytes);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
64
engines/ultima/ultima8/usecode/bit_set.h
Normal file
64
engines/ultima/ultima8/usecode/bit_set.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_USECODE_BITSET_H
|
||||
#define ULTIMA8_USECODE_BITSET_H
|
||||
|
||||
#include "ultima/ultima8/usecode/global_storage.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class BitSet : public GlobalStorage {
|
||||
public:
|
||||
BitSet();
|
||||
BitSet(unsigned int size);
|
||||
~BitSet();
|
||||
|
||||
//! set the size. The old value is cleared
|
||||
//! \param size the new size (in bits)
|
||||
void setSize(unsigned int size) override;
|
||||
|
||||
//! get a value
|
||||
//! \param pos zero-based position (in bits)
|
||||
//! \param n number of bits (no greater than 32)
|
||||
//! \return the value these bits represent
|
||||
uint32 getEntries(unsigned int pos, unsigned int n) const override;
|
||||
|
||||
//! set a value
|
||||
//! \param pos zero-based position (in bits)
|
||||
//! \param n number of bits (no greater than 32)
|
||||
//! \param bits the value to set
|
||||
void setEntries(unsigned int pos, unsigned int n, uint32 bits) override;
|
||||
|
||||
void save(Common::WriteStream *ws) override;
|
||||
bool load(Common::ReadStream *rs, uint32 version) override;
|
||||
|
||||
private:
|
||||
unsigned int _size;
|
||||
unsigned int _bytes;
|
||||
uint8 *_data;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
95
engines/ultima/ultima8/usecode/byte_set.cpp
Normal file
95
engines/ultima/ultima8/usecode/byte_set.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/misc/debugger.h"
|
||||
#include "ultima/ultima8/usecode/byte_set.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
ByteSet::ByteSet() : _size(0), _data(nullptr) {
|
||||
}
|
||||
|
||||
|
||||
ByteSet::ByteSet(unsigned int size) : _data(nullptr) {
|
||||
setSize(size);
|
||||
}
|
||||
|
||||
ByteSet::~ByteSet() {
|
||||
delete[] _data;
|
||||
}
|
||||
|
||||
void ByteSet::setSize(unsigned int size) {
|
||||
if (_data) delete[] _data;
|
||||
|
||||
_size = size;
|
||||
_data = new uint8[_size];
|
||||
for (unsigned int i = 0; i < _size; ++i)
|
||||
_data[i] = 0;
|
||||
}
|
||||
|
||||
uint32 ByteSet::getEntries(unsigned int pos, unsigned int n) const {
|
||||
assert(n <= 2);
|
||||
assert(pos + n <= _size);
|
||||
if (n == 0) return 0;
|
||||
|
||||
if (n == 1) {
|
||||
return _data[pos];
|
||||
} else if (n == 2) {
|
||||
return (_data[pos] << 8) | _data[pos + 1];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ByteSet::setEntries(unsigned int pos, unsigned int n, uint32 val) {
|
||||
assert(n <= 2);
|
||||
assert(pos + n <= _size);
|
||||
if (n == 0) return;
|
||||
|
||||
if (n == 1) {
|
||||
_data[pos] = static_cast<uint8>(val);
|
||||
} else if (n == 2) {
|
||||
_data[pos] = static_cast<uint8>((val & 0xFF00) >> 8);
|
||||
_data[pos + 1] = static_cast<uint8>(val & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
void ByteSet::save(Common::WriteStream *ws) {
|
||||
ws->writeUint32LE(_size);
|
||||
ws->write(_data, _size);
|
||||
}
|
||||
|
||||
bool ByteSet::load(Common::ReadStream *rs, uint32 version) {
|
||||
uint32 s = rs->readUint32LE();
|
||||
|
||||
if (s > 1024 * 1024) {
|
||||
warning("Improbable globals size %d, corrupt save?", s);
|
||||
return false;
|
||||
}
|
||||
|
||||
setSize(s);
|
||||
rs->read(_data, _size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
65
engines/ultima/ultima8/usecode/byte_set.h
Normal file
65
engines/ultima/ultima8/usecode/byte_set.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_USECODE_BYTESET_H
|
||||
#define ULTIMA8_USECODE_BYTESET_H
|
||||
|
||||
#include "ultima/ultima8/usecode/global_storage.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
// This is a minimal implementation just to support what Crusader needs.
|
||||
|
||||
class ByteSet : public GlobalStorage {
|
||||
public:
|
||||
ByteSet();
|
||||
ByteSet(unsigned int size);
|
||||
~ByteSet();
|
||||
|
||||
//! set the size. The old value is cleared
|
||||
//! \param size the new size (in bytes)
|
||||
void setSize(unsigned int size) override;
|
||||
|
||||
//! get a value
|
||||
//! \param pos zero-based position (in bytes:)
|
||||
//! \param n number of bytes (no greater than 2)
|
||||
//! \return the value these bytes represent
|
||||
uint32 getEntries(unsigned int pos, unsigned int n) const override;
|
||||
|
||||
//! set a value
|
||||
//! \param pos zero-based position (in bytes)
|
||||
//! \param n number of bytes (no greater than 2)
|
||||
//! \param val the value to set
|
||||
void setEntries(unsigned int pos, unsigned int n, uint32 val) override;
|
||||
|
||||
void save(Common::WriteStream *ws) override;
|
||||
bool load(Common::ReadStream *rs, uint32 version) override;
|
||||
|
||||
private:
|
||||
unsigned int _size;
|
||||
uint8 *_data;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
57
engines/ultima/ultima8/usecode/global_storage.h
Normal file
57
engines/ultima/ultima8/usecode/global_storage.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_USECODE_GLOBAL_STORAGE_H
|
||||
#define ULTIMA8_USECODE_GLOBAL_STORAGE_H
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
/**
|
||||
* Base class for globals that are accessed by the Usecode.
|
||||
* In U8 this is a bitfield, in Crusader it's a byte array.
|
||||
*/
|
||||
class GlobalStorage {
|
||||
public:
|
||||
virtual ~GlobalStorage() {};
|
||||
|
||||
virtual void setSize(unsigned int size) = 0;
|
||||
|
||||
//! get a value
|
||||
//! \param pos zero-based position
|
||||
//! \param n number of entries to read
|
||||
//! \return the value these entries represent
|
||||
virtual uint32 getEntries(unsigned int pos, unsigned int n) const = 0;
|
||||
|
||||
//! set a value
|
||||
//! \param pos zero-based position
|
||||
//! \param n number of entries (no greater than one uint32-worth)
|
||||
//! \param val the value to set
|
||||
virtual void setEntries(unsigned int pos, unsigned int n, uint32 val) = 0;
|
||||
|
||||
virtual void save(Common::WriteStream *ws) = 0;
|
||||
virtual bool load(Common::ReadStream *rs, uint32 version) = 0;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
100
engines/ultima/ultima8/usecode/intrinsics.h
Normal file
100
engines/ultima/ultima8/usecode/intrinsics.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_USECODE_INTRINSICS_H
|
||||
#define ULTIMA8_USECODE_INTRINSICS_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
typedef uint32(*Intrinsic)(const uint8 *args, unsigned int argsize);
|
||||
|
||||
#define INTRINSIC(x) static uint32 x (const uint8* args, unsigned int argsize)
|
||||
|
||||
// TODO: range checking on args
|
||||
|
||||
// UINT8s are pushed on the stack as words (see push byte opcodes),
|
||||
// so we ignore the top byte when popping.
|
||||
#define ARG_UINT8(x) uint8 x = (*args++); args++;
|
||||
#define ARG_UINT16(x) uint16 x = (*args++); x += ((*args++) << 8);
|
||||
#define ARG_UINT32(x) uint32 x = (*args++); x += ((*args++) << 8); \
|
||||
x+= ((*args++) << 16); x += ((*args++) << 24);
|
||||
#define ARG_SINT8(x) int8 x = (*args++);
|
||||
#define ARG_SINT16(x) int16 x = (*args++); x += ((*args++) << 8);
|
||||
#define ARG_SINT32(x) int32 x = (*args++); x += ((*args++) << 8); \
|
||||
x+= ((*args++) << 16); x += ((*args++) << 24);
|
||||
#define ARG_UC_PTR(x) uint32 x = (*args++); x += ((*args++) << 8); \
|
||||
x+= ((*args++) << 16); x += ((*args++) << 24);
|
||||
#define ARG_OBJID(x) ObjId x = (*args++); x += ((*args++) << 8);
|
||||
#define ARG_PROCID(x) ProcId x = (*args++); x += ((*args++) << 8);
|
||||
|
||||
#define ARG_OBJECT_FROM_PTR(x) ARG_UC_PTR(ucptr_##x); \
|
||||
uint16 id_##x = UCMachine::ptrToObject(ucptr_##x); \
|
||||
Object* x = getObject(id_##x);
|
||||
#define ARG_OBJECT_FROM_ID(x) ARG_OBJID(id_##x); \
|
||||
Object* x = getObject(id_##x);
|
||||
|
||||
#define ARG_ITEM_FROM_PTR(x) ARG_UC_PTR(ucptr_##x); \
|
||||
uint16 id_##x = UCMachine::ptrToObject(ucptr_##x); \
|
||||
Item* x = getItem(id_##x);
|
||||
#define ARG_ITEM_FROM_ID(x) ARG_OBJID(id_##x); \
|
||||
Item* x = getItem(id_##x);
|
||||
|
||||
#define ARG_CONTAINER_FROM_PTR(x) ARG_UC_PTR(ucptr_##x); \
|
||||
uint16 id_##x = UCMachine::ptrToObject(ucptr_##x); \
|
||||
Container* x = getContainer(id_##x);
|
||||
#define ARG_CONTAINER_FROM_ID(x) ARG_OBJID(id_##x); \
|
||||
Container* x = getContainer(id_##x);
|
||||
|
||||
#define ARG_ACTOR_FROM_PTR(x) ARG_UC_PTR(ucptr_##x); \
|
||||
uint16 id_##x = UCMachine::ptrToObject(ucptr_##x); \
|
||||
Actor* x = getActor(id_##x);
|
||||
#define ARG_ACTOR_FROM_ID(x) ARG_OBJID(id_##x); \
|
||||
Actor* x = getActor(id_##x);
|
||||
|
||||
#define ARG_EGG_FROM_PTR(x) ARG_UC_PTR(ucptr_##x); \
|
||||
uint16 id_##x = UCMachine::ptrToObject(ucptr_##x); \
|
||||
Egg* x = dynamic_cast<Egg*>(getObject(id_##x));
|
||||
#define ARG_EGG_FROM_ID(x) ARG_OBJID(id_##x); \
|
||||
Egg* x = dynamic_cast<Egg*>(getObject(id_##x));
|
||||
|
||||
#define ARG_STRING(x) ARG_UC_PTR(ucptr_##x); \
|
||||
uint16 id_##x = UCMachine::ptrToObject(ucptr_##x); \
|
||||
Std::string x = UCMachine::get_instance()->getString(id_##x);
|
||||
|
||||
#define ARG_LIST(x) ARG_UINT16(id_##x); \
|
||||
UCList* x = UCMachine::get_instance()->getList(id_##x);
|
||||
|
||||
#define ARG_WORLDPOINT(x) ARG_UC_PTR(ucptr_##x); \
|
||||
WorldPoint x; \
|
||||
UCMachine::get_instance()->dereferencePointer(ucptr_##x, x._buf, 5);
|
||||
|
||||
// See comment on ARG_UINT8 for why +2 on NULL8
|
||||
#define ARG_NULL8() args+=2;
|
||||
#define ARG_NULL16() args+=2;
|
||||
#define ARG_NULL32() args+=4;
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
1164
engines/ultima/ultima8/usecode/regret_intrinsics.h
Normal file
1164
engines/ultima/ultima8/usecode/regret_intrinsics.h
Normal file
File diff suppressed because it is too large
Load Diff
1373
engines/ultima/ultima8/usecode/remorse_intrinsics.h
Normal file
1373
engines/ultima/ultima8/usecode/remorse_intrinsics.h
Normal file
File diff suppressed because it is too large
Load Diff
337
engines/ultima/ultima8/usecode/u8_intrinsics.h
Normal file
337
engines/ultima/ultima8/usecode/u8_intrinsics.h
Normal file
@@ -0,0 +1,337 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_USECODE_U8INTRINSICS_H
|
||||
#define ULTIMA8_USECODE_U8INTRINSICS_H
|
||||
|
||||
#include "ultima/ultima8/usecode/intrinsics.h"
|
||||
|
||||
#include "ultima/ultima8/world/item.h"
|
||||
#include "ultima/ultima8/usecode/uc_machine.h"
|
||||
#include "ultima/ultima8/world/container.h"
|
||||
#include "ultima/ultima8/world/actors/actor.h"
|
||||
#include "ultima/ultima8/world/actors/main_actor.h"
|
||||
#include "ultima/ultima8/kernel/kernel.h"
|
||||
#include "ultima/ultima8/world/camera_process.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
#include "ultima/ultima8/world/egg.h"
|
||||
#include "ultima/ultima8/world/monster_egg.h"
|
||||
#include "ultima/ultima8/world/current_map.h"
|
||||
#include "ultima/ultima8/gfx/palette_fader_process.h"
|
||||
#include "ultima/ultima8/world/sprite_process.h"
|
||||
#include "ultima/ultima8/audio/music_process.h"
|
||||
#include "ultima/ultima8/gumps/scroll_gump.h"
|
||||
#include "ultima/ultima8/gumps/book_gump.h"
|
||||
#include "ultima/ultima8/gumps/readable_gump.h"
|
||||
#include "ultima/ultima8/gumps/target_gump.h"
|
||||
#include "ultima/ultima8/world/actors/grant_peace_process.h"
|
||||
#include "ultima/ultima8/world/fireball_process.h"
|
||||
#include "ultima/ultima8/world/actors/heal_process.h"
|
||||
#include "ultima/ultima8/gfx/inverter_process.h"
|
||||
#include "ultima/ultima8/audio/audio_process.h"
|
||||
#include "ultima/ultima8/games/game.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
// Ultima 8 Intrinsics
|
||||
const Intrinsic U8Intrinsics[] = {
|
||||
// 0x000
|
||||
TargetGump::I_target,
|
||||
0, //U
|
||||
Item::I_touch,
|
||||
Item::I_getX,
|
||||
Item::I_getY,
|
||||
Item::I_getZ,
|
||||
Item::I_getCX,
|
||||
Item::I_getCY,
|
||||
Item::I_getCZ,
|
||||
0, //U
|
||||
0, //U
|
||||
0, //U
|
||||
Item::I_getPoint,
|
||||
Item::I_getShape,
|
||||
Item::I_setShape,
|
||||
Item::I_getFrame,
|
||||
// 0x010
|
||||
Item::I_setFrame,
|
||||
Item::I_getQuality,
|
||||
Item::I_getUnkEggType,
|
||||
Item::I_getQuantity,
|
||||
0, //U
|
||||
Item::I_getContainer,
|
||||
Item::I_getRootContainer,
|
||||
0, //U
|
||||
0, //U
|
||||
Item::I_getQ,
|
||||
Item::I_setQ,
|
||||
Item::I_setQuality,
|
||||
0, //U
|
||||
Item::I_setQuantity,
|
||||
Item::I_getFamily,
|
||||
Item::I_getTypeFlag,
|
||||
// 0x020
|
||||
Item::I_getStatus,
|
||||
Item::I_orStatus,
|
||||
Item::I_andStatus,
|
||||
Item::I_getFootpadData,
|
||||
0, //U
|
||||
Item::I_overlaps,
|
||||
Item::I_overlapsXY,
|
||||
Item::I_isOn,
|
||||
0, //U
|
||||
0, //U
|
||||
0, //U
|
||||
Item::I_ascend,
|
||||
Item::I_getWeight,
|
||||
Item::I_getWeightIncludingContents,
|
||||
Item::I_getSurfaceWeight,
|
||||
0, //U
|
||||
// 0x030
|
||||
0, //U
|
||||
Item::I_legalCreateAtCoords,
|
||||
Item::I_create,
|
||||
Item::I_legalCreateAtPoint,
|
||||
Item::I_legalCreateInCont,
|
||||
Item::I_push,
|
||||
Item::I_popToCoords,
|
||||
Item::I_popToContainer,
|
||||
Item::I_pop,
|
||||
Item::I_popToEnd,
|
||||
Item::I_destroy,
|
||||
Container::I_removeContents,
|
||||
Container::I_destroyContents,
|
||||
Item::I_isExplosive,
|
||||
Item::I_move,
|
||||
0, //U
|
||||
// 0x040
|
||||
Item::I_legalMoveToPoint,
|
||||
Item::I_legalMoveToContainer,
|
||||
Actor::I_isNPC,
|
||||
0, //U
|
||||
Item::I_hurl,
|
||||
Item::I_shoot,
|
||||
Item::I_fall,
|
||||
Item::I_grab,
|
||||
0, //U
|
||||
Item::I_bark,
|
||||
Item::I_ask,
|
||||
Item::I_getSliderInput,
|
||||
Item::I_openGump,
|
||||
Item::I_closeGump,
|
||||
0, //U
|
||||
0, //U
|
||||
// 0x050
|
||||
Item::I_getMapArray,
|
||||
0, //U
|
||||
Item::I_setMapArray,
|
||||
Item::I_receiveHit,
|
||||
Item::I_explode,
|
||||
Item::I_canReach,
|
||||
Item::I_getRange,
|
||||
0, //U
|
||||
Item::I_getDirToCoords,
|
||||
Item::I_getDirFromCoords,
|
||||
Item::I_getDirToItem,
|
||||
Item::I_getDirFromItem,
|
||||
Item::I_look,
|
||||
Item::I_use,
|
||||
0, //U
|
||||
0, //U
|
||||
// 0x060
|
||||
0, //U
|
||||
Item::I_gotHit,
|
||||
0, //U
|
||||
0, //U
|
||||
0, //U
|
||||
0, //U
|
||||
0, //U
|
||||
Item::I_enterFastArea,
|
||||
0, //U
|
||||
0, //U
|
||||
0, //U
|
||||
0, //U
|
||||
0, //U
|
||||
Item::I_guardianBark,
|
||||
BookGump::I_readBook,
|
||||
ScrollGump::I_readScroll,
|
||||
// 0x070
|
||||
ReadableGump::I_readGrave,
|
||||
ReadableGump::I_readPlaque,
|
||||
Egg::I_getEggXRange,
|
||||
Egg::I_getEggYRange,
|
||||
Egg::I_setEggXRange,
|
||||
Egg::I_setEggYRange,
|
||||
Egg::I_getEggId,
|
||||
Egg::I_setEggId,
|
||||
0, //U
|
||||
MonsterEgg::I_monsterEggHatch,
|
||||
MonsterEgg::I_getMonId,
|
||||
0, //U
|
||||
0, //U
|
||||
0, //U
|
||||
0, //U
|
||||
0, //U
|
||||
// 0x080
|
||||
Actor::I_isBusy,
|
||||
Actor::I_areEnemiesNear,
|
||||
Actor::I_isInCombat,
|
||||
Actor::I_setInCombat,
|
||||
Actor::I_clrInCombat,
|
||||
Actor::I_setTarget,
|
||||
Actor::I_getTarget,
|
||||
Actor::I_setAlignment,
|
||||
Actor::I_getAlignment,
|
||||
Actor::I_setEnemyAlignment,
|
||||
Actor::I_getEnemyAlignment,
|
||||
Actor::I_isEnemy,
|
||||
Actor::I_isDead,
|
||||
Actor::I_setDead,
|
||||
Actor::I_clrDead,
|
||||
Actor::I_isImmortal,
|
||||
// 0x090
|
||||
Actor::I_setImmortal,
|
||||
Actor::I_clrImmortal,
|
||||
Actor::I_isWithstandDeath,
|
||||
Actor::I_setWithstandDeath,
|
||||
Actor::I_clrWithstandDeath,
|
||||
Actor::I_isFeignDeath,
|
||||
Actor::I_setFeignDeath,
|
||||
Actor::I_clrFeignDeath,
|
||||
0, //U
|
||||
0, //U
|
||||
0, //U
|
||||
0, //U
|
||||
Actor::I_getDir,
|
||||
Actor::I_getMap,
|
||||
Actor::I_teleport,
|
||||
Actor::I_doAnim,
|
||||
// 0x0A0
|
||||
Actor::I_getLastAnimSet,
|
||||
Actor::I_pathfindToPoint,
|
||||
Actor::I_pathfindToItem,
|
||||
Actor::I_getStr,
|
||||
Actor::I_getInt,
|
||||
Actor::I_getDex,
|
||||
Actor::I_getHp,
|
||||
Actor::I_getMana,
|
||||
Actor::I_setStr,
|
||||
Actor::I_setInt,
|
||||
Actor::I_setDex,
|
||||
Actor::I_setHp,
|
||||
Actor::I_setMana,
|
||||
Actor::I_createActor,
|
||||
Actor::I_setActivity,
|
||||
Actor::I_setAirWalkEnabled,
|
||||
// 0x0B0
|
||||
Actor::I_getAirWalkEnabled,
|
||||
Actor::I_schedule,
|
||||
Actor::I_getEquip,
|
||||
Actor::I_setEquip,
|
||||
Ultima8Engine::I_closeItemGumps,
|
||||
CameraProcess::I_scrollTo,
|
||||
UCMachine::I_urandom,
|
||||
UCMachine::I_rndRange,
|
||||
GrantPeaceProcess::I_castGrantPeace,
|
||||
UCMachine::I_numToStr,
|
||||
0, //U
|
||||
MusicProcess::I_playMusic,
|
||||
UCMachine::I_getName, //temp
|
||||
Item::I_igniteChaos,
|
||||
CameraProcess::I_setCenterOn,
|
||||
CameraProcess::I_moveTo,
|
||||
// 0x0C0
|
||||
0, //U
|
||||
0, //U
|
||||
0, //U
|
||||
0, //U
|
||||
0, //U
|
||||
0, //U
|
||||
CameraProcess::I_startQuake,
|
||||
CameraProcess::I_stopQuake,
|
||||
InverterProcess::I_invertScreen,
|
||||
0, //U
|
||||
Kernel::I_getNumProcesses,
|
||||
Kernel::I_resetRef,
|
||||
MainActor::I_teleportToEgg,
|
||||
Kernel::I_resetRef,
|
||||
0, // setRef
|
||||
Ultima8Engine::I_getAvatarInStasis,
|
||||
// 0x0D0
|
||||
Ultima8Engine::I_setAvatarInStasis,
|
||||
Item::I_getEtherealTop,
|
||||
Ultima8Engine::I_getCurrentTimerTick,
|
||||
0, //U (canGetThere)
|
||||
CurrentMap::I_canExistAt,
|
||||
SpriteProcess::I_createSprite,
|
||||
SpriteProcess::I_createSprite,
|
||||
Item::I_getFamilyOfType,
|
||||
Ultima8Engine::I_getTimeInGameHours,
|
||||
Ultima8Engine::I_getTimeInMinutes,
|
||||
Ultima8Engine::I_getTimeInSeconds,
|
||||
Ultima8Engine::I_setTimeInGameHours,
|
||||
0, // U (SetTimeInMinutes)
|
||||
0, // U (SetTimeInSeconds)
|
||||
PaletteFaderProcess::I_fadeToBlack,
|
||||
PaletteFaderProcess::I_fadeFromBlack,
|
||||
// 0x0E0
|
||||
PaletteFaderProcess::I_fadeToPaletteTransform,
|
||||
PaletteFaderProcess::I_lightningBolt,
|
||||
PaletteFaderProcess::I_fadeToWhite,
|
||||
PaletteFaderProcess::I_fadeFromWhite,
|
||||
Game::I_playEndgame,
|
||||
HealProcess::I_feedAvatar,
|
||||
MainActor::I_accumulateStrength,
|
||||
MainActor::I_accumulateIntelligence,
|
||||
MainActor::I_accumulateDexterity,
|
||||
MainActor::I_clrAvatarInCombat,
|
||||
MainActor::I_setAvatarInCombat,
|
||||
MainActor::I_isAvatarInCombat,
|
||||
AudioProcess::I_playSFX, // int16
|
||||
AudioProcess::I_playSFX, // int16 uint8
|
||||
AudioProcess::I_playSFX, // int16 uint16 ObjID
|
||||
AudioProcess::I_playAmbientSFX, // int16 Unused (but implemented)
|
||||
// 0x0F0
|
||||
AudioProcess::I_playAmbientSFX, // int16 uint8 Unused (but implemented)
|
||||
AudioProcess::I_playAmbientSFX, // int16 uint16 ObjID
|
||||
AudioProcess::I_isSFXPlaying,
|
||||
AudioProcess::I_setVolumeSFX,
|
||||
AudioProcess::I_stopSFX, // int16
|
||||
AudioProcess::I_stopSFX, // int16 ObjID
|
||||
0, //U
|
||||
0, //U
|
||||
MusicProcess::I_stopMusic,
|
||||
0, //U
|
||||
0, //U
|
||||
FireballProcess::I_TonysBalls,
|
||||
Ultima8Engine::I_avatarCanCheat,
|
||||
Ultima8Engine::I_makeAvatarACheater,
|
||||
UCMachine::I_true, // isGameRunning
|
||||
0, //U
|
||||
// 0x100
|
||||
0, //U
|
||||
0 //U
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
139
engines/ultima/ultima8/usecode/uc_list.cpp
Normal file
139
engines/ultima/ultima8/usecode/uc_list.cpp
Normal file
@@ -0,0 +1,139 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/misc/debugger.h"
|
||||
|
||||
#include "ultima/ultima8/usecode/uc_list.h"
|
||||
#include "ultima/ultima8/usecode/uc_machine.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
uint16 UCList::getStringIndex(uint32 index) const {
|
||||
return _elements[index * 2] + (_elements[index * 2 + 1] << 8);
|
||||
}
|
||||
|
||||
const Std::string &UCList::getString(uint32 index) const {
|
||||
uint16 sindex = getStringIndex(index);
|
||||
return UCMachine::get_instance()->getString(sindex);
|
||||
}
|
||||
|
||||
void UCList::freeStrings() {
|
||||
UCMachine *ucm = UCMachine::get_instance();
|
||||
for (unsigned int i = 0; i < _size; i++) {
|
||||
ucm->freeString(getStringIndex(i));
|
||||
}
|
||||
free();
|
||||
}
|
||||
|
||||
void UCList::copyStringList(const UCList &l) {
|
||||
UCMachine *ucm = UCMachine::get_instance();
|
||||
freeStrings();
|
||||
for (unsigned int i = 0; i < l._size; i++) {
|
||||
uint16 s = ucm->duplicateString(l.getStringIndex(i));
|
||||
uint8 tmp[2]; // ugly...
|
||||
tmp[0] = static_cast<uint8>(s & 0xFF);
|
||||
tmp[1] = static_cast<uint8>(s >> 8);
|
||||
append(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
void UCList::unionStringList(UCList &l) {
|
||||
UCMachine *ucm = UCMachine::get_instance();
|
||||
// take the union of two stringlists
|
||||
// i.e., append the second to this one, removing any duplicates
|
||||
for (unsigned int i = 0; i < l._size; i++) {
|
||||
if (!stringInList(l.getStringIndex(i))) {
|
||||
append(l[i]);
|
||||
} else {
|
||||
// free it if we're not keeping it
|
||||
ucm->freeString(l.getStringIndex(i));
|
||||
}
|
||||
}
|
||||
l.free(); // NB: do _not_ free the strings in l, since they're in this one
|
||||
}
|
||||
|
||||
void UCList::subtractStringList(const UCList &l) {
|
||||
for (unsigned int i = 0; i < l._size; i++)
|
||||
removeString(l.getStringIndex(i));
|
||||
}
|
||||
|
||||
bool UCList::stringInList(uint16 s) const {
|
||||
Std::string str = UCMachine::get_instance()->getString(s);
|
||||
for (unsigned int i = 0; i < _size; i++)
|
||||
if (getString(i) == str)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void UCList::assignString(uint32 index, uint16 str) {
|
||||
// assign string str to element index
|
||||
// free old contents of element index; take ownership of str(?)
|
||||
|
||||
UCMachine::get_instance()->freeString(getStringIndex(index));
|
||||
_elements[index * _elementSize] = static_cast<uint8>(str & 0xFF);
|
||||
_elements[index * _elementSize + 1] = static_cast<uint8>(str >> 8);
|
||||
}
|
||||
|
||||
void UCList::removeString(uint16 s, bool nodel) {
|
||||
// do we need to erase all occurrences of str or just the first one?
|
||||
// (deleting all, currently)
|
||||
const Std::string &str = UCMachine::get_instance()->getString(s);
|
||||
for (unsigned int i = 0; i < _size; i++) {
|
||||
if (getString(i) == str) {
|
||||
// free string
|
||||
if (!nodel)
|
||||
UCMachine::get_instance()->freeString(getStringIndex(i));
|
||||
|
||||
// remove string from list
|
||||
_elements.erase(_elements.begin() + i * _elementSize,
|
||||
_elements.begin() + (i + 1)*_elementSize);
|
||||
_size--;
|
||||
i--; // back up a bit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UCList::save(Common::WriteStream *ws) const {
|
||||
ws->writeUint32LE(_elementSize);
|
||||
ws->writeUint32LE(_size);
|
||||
if (_size > 0)
|
||||
ws->write(&(_elements[0]), _size * _elementSize);
|
||||
}
|
||||
|
||||
|
||||
bool UCList::load(Common::ReadStream *rs, uint32 version) {
|
||||
_elementSize = rs->readUint32LE();
|
||||
_size = rs->readUint32LE();
|
||||
if (_elementSize * _size > 1024 * 1024) {
|
||||
warning("Improbable UCList size %d x %d, corrupt save?", _elementSize, _size);
|
||||
return false;
|
||||
}
|
||||
_elements.resize(_size * _elementSize);
|
||||
if (_size > 0)
|
||||
rs->read(&(_elements[0]), _size * _elementSize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
178
engines/ultima/ultima8/usecode/uc_list.h
Normal file
178
engines/ultima/ultima8/usecode/uc_list.h
Normal file
@@ -0,0 +1,178 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_USECODE_UCLIST_H
|
||||
#define ULTIMA8_USECODE_UCLIST_H
|
||||
|
||||
#include "ultima/shared/std/containers.h"
|
||||
#include "ultima/shared/std/string.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
// stringlists: _elementSize = 2, each element is actually a stringref
|
||||
// see for example the 0x0E opcode: there is no way to see if the
|
||||
// created list is a stringlist or not
|
||||
// the opcodes which do need a distinction have a operand for this.
|
||||
|
||||
// Question: how are unionList/subtractList supposed to know what to do?
|
||||
// their behaviour differs if this is a stringlist
|
||||
|
||||
// Question: does subtractList remove _all_ occurrences of elements or only 1?
|
||||
|
||||
class UCList {
|
||||
Std::vector<uint8> _elements;
|
||||
unsigned int _elementSize;
|
||||
unsigned int _size;
|
||||
|
||||
public:
|
||||
UCList(unsigned int elementSize, unsigned int capacity = 0) :
|
||||
_elementSize(elementSize), _size(0) {
|
||||
if (capacity > 0)
|
||||
_elements.reserve(_elementSize * capacity);
|
||||
}
|
||||
|
||||
~UCList() {
|
||||
// Slight problem: we don't know if we're a stringlist.
|
||||
// So we need to hope something else has ensured any strings
|
||||
// are already freed.
|
||||
free();
|
||||
}
|
||||
|
||||
const uint8 *operator[](uint32 index) const {
|
||||
// check that index isn't out of bounds...
|
||||
return &(_elements[index * _elementSize]);
|
||||
}
|
||||
|
||||
uint16 getuint16(uint32 index) const {
|
||||
assert(_elementSize == 2);
|
||||
uint16 t = _elements[index * _elementSize];
|
||||
t += _elements[index * _elementSize + 1] << 8;
|
||||
return t;
|
||||
}
|
||||
|
||||
void append(const uint8 *e) {
|
||||
_elements.resize((_size + 1) * _elementSize);
|
||||
for (unsigned int i = 0; i < _elementSize; i++)
|
||||
_elements[_size * _elementSize + i] = e[i];
|
||||
_size++;
|
||||
}
|
||||
|
||||
void appenduint16(uint16 val) {
|
||||
assert(_elementSize == 2);
|
||||
uint8 buf[2];
|
||||
buf[0] = static_cast<uint8>(val);
|
||||
buf[1] = static_cast<uint8>(val >> 8);
|
||||
append(buf);
|
||||
}
|
||||
|
||||
void remove(const uint8 *e) {
|
||||
// do we need to erase all occurrences of e or just the first one?
|
||||
// (deleting all, currently)
|
||||
for (unsigned int i = 0; i < _size; i++) {
|
||||
bool equal = true;
|
||||
for (unsigned int j = 0; j < _elementSize && equal; j++)
|
||||
equal = equal && (_elements[i * _elementSize + j] == e[j]);
|
||||
if (equal) {
|
||||
_elements.erase(_elements.begin() + i * _elementSize,
|
||||
_elements.begin() + (i + 1)*_elementSize);
|
||||
_size--;
|
||||
i--; // back up a bit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool inList(const uint8 *e) const {
|
||||
for (unsigned int i = 0; i < _size; i++) {
|
||||
bool equal = true;
|
||||
for (unsigned int j = 0; j < _elementSize && equal; j++)
|
||||
equal = (_elements[i * _elementSize + j] == e[j]);
|
||||
if (equal)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void appendList(const UCList &l) {
|
||||
// elementsizes should match...
|
||||
assert(_elementSize == l.getElementSize());
|
||||
_elements.reserve(_elementSize * (_size + l._size));
|
||||
for (unsigned int i = 0; i < l._size; i++)
|
||||
append(l[i]);
|
||||
}
|
||||
void unionList(const UCList &l) { // like append, but remove duplicates
|
||||
// elementsizes should match...
|
||||
assert(_elementSize == l.getElementSize());
|
||||
_elements.reserve(_elementSize * (_size + l._size));
|
||||
for (unsigned int i = 0; i < l._size; i++)
|
||||
if (!inList(l[i]))
|
||||
append(l[i]);
|
||||
}
|
||||
void subtractList(const UCList &l) {
|
||||
// elementsizes should match...
|
||||
assert(_elementSize == l.getElementSize());
|
||||
for (unsigned int i = 0; i < l._size; i++)
|
||||
remove(l[i]);
|
||||
}
|
||||
|
||||
void free() {
|
||||
_elements.clear();
|
||||
_size = 0;
|
||||
}
|
||||
uint32 getSize() const {
|
||||
return _size;
|
||||
}
|
||||
unsigned int getElementSize() const {
|
||||
return _elementSize;
|
||||
}
|
||||
|
||||
void assign(uint32 index, const uint8 *e) {
|
||||
// need to check that index isn't out-of-bounds? (or grow list?)
|
||||
for (unsigned int i = 0; i < _elementSize; i++)
|
||||
_elements[index * _elementSize + i] = e[i];
|
||||
}
|
||||
|
||||
void copyList(const UCList &l) { // deep copy for list
|
||||
free();
|
||||
appendList(l);
|
||||
}
|
||||
|
||||
void freeStrings();
|
||||
void copyStringList(const UCList &l) ;
|
||||
void unionStringList(UCList &l);
|
||||
void subtractStringList(const UCList &l);
|
||||
bool stringInList(uint16 str) const;
|
||||
void assignString(uint32 index, uint16 str);
|
||||
void removeString(uint16 str, bool nodel = false);
|
||||
|
||||
uint16 getStringIndex(uint32 index) const;
|
||||
|
||||
void save(Common::WriteStream *ws) const;
|
||||
bool load(Common::ReadStream *rs, uint32 version);
|
||||
|
||||
private:
|
||||
const Std::string &getString(uint32 index) const;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
2417
engines/ultima/ultima8/usecode/uc_machine.cpp
Normal file
2417
engines/ultima/ultima8/usecode/uc_machine.cpp
Normal file
File diff suppressed because it is too large
Load Diff
137
engines/ultima/ultima8/usecode/uc_machine.h
Normal file
137
engines/ultima/ultima8/usecode/uc_machine.h
Normal file
@@ -0,0 +1,137 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_USECODE_UCMACHINE_H
|
||||
#define ULTIMA8_USECODE_UCMACHINE_H
|
||||
|
||||
#include "ultima/ultima8/misc/common_types.h"
|
||||
#include "ultima/ultima8/misc/set.h"
|
||||
#include "ultima/shared/std/string.h"
|
||||
#include "ultima/shared/std/containers.h"
|
||||
#include "ultima/ultima8/usecode/intrinsics.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class Debugger;
|
||||
class Process;
|
||||
class UCProcess;
|
||||
class ConvertUsecode;
|
||||
class GlobalStorage;
|
||||
class UCList;
|
||||
class idMan;
|
||||
|
||||
class UCMachine {
|
||||
friend class Debugger;
|
||||
public:
|
||||
UCMachine(const Intrinsic *iset, unsigned int icount);
|
||||
~UCMachine();
|
||||
|
||||
static UCMachine *get_instance() {
|
||||
return _ucMachine;
|
||||
}
|
||||
|
||||
void reset();
|
||||
|
||||
void execProcess(UCProcess *proc);
|
||||
|
||||
const Std::string &getString(uint16 str) const;
|
||||
UCList *getList(uint16 l);
|
||||
|
||||
void freeString(uint16 s);
|
||||
void freeStringList(uint16 l);
|
||||
void freeList(uint16 l);
|
||||
|
||||
uint16 duplicateString(uint16 str);
|
||||
|
||||
void usecodeStats() const;
|
||||
|
||||
static uint32 listToPtr(uint16 l);
|
||||
static uint32 stringToPtr(uint16 s);
|
||||
static uint32 stackToPtr(uint16 pid, uint16 offset);
|
||||
static uint32 globalToPtr(uint16 offset);
|
||||
static uint32 objectToPtr(uint16 objID);
|
||||
|
||||
static uint16 ptrToObject(uint32 ptr);
|
||||
|
||||
bool assignPointer(uint32 ptr, const uint8 *data, uint32 size);
|
||||
bool dereferencePointer(uint32 ptr, uint8 *data, uint32 size);
|
||||
|
||||
void saveGlobals(Common::WriteStream *ws) const;
|
||||
void saveStrings(Common::WriteStream *ws) const;
|
||||
void saveLists(Common::WriteStream *ws) const;
|
||||
|
||||
bool loadGlobals(Common::ReadStream *rs, uint32 version);
|
||||
bool loadStrings(Common::ReadStream *rs, uint32 version);
|
||||
bool loadLists(Common::ReadStream *rs, uint32 version);
|
||||
|
||||
INTRINSIC(I_true);
|
||||
INTRINSIC(I_false);
|
||||
INTRINSIC(I_dummyProcess);
|
||||
INTRINSIC(I_getName);
|
||||
INTRINSIC(I_urandom);
|
||||
INTRINSIC(I_rndRange);
|
||||
INTRINSIC(I_numToStr);
|
||||
|
||||
protected:
|
||||
void loadIntrinsics(const Intrinsic *i, unsigned int icount);
|
||||
|
||||
private:
|
||||
ConvertUsecode *_convUse;
|
||||
const Intrinsic *_intrinsics;
|
||||
unsigned int _intrinsicCount;
|
||||
|
||||
GlobalStorage *_globals;
|
||||
|
||||
Common::HashMap<uint16, UCList *> _listHeap;
|
||||
Common::HashMap<uint16, Std::string> _stringHeap;
|
||||
|
||||
// Add a string to the list (copies the string)
|
||||
uint16 assignString(const char *str);
|
||||
uint16 assignList(UCList *l);
|
||||
|
||||
idMan *_listIDs;
|
||||
idMan *_stringIDs;
|
||||
|
||||
static UCMachine *_ucMachine;
|
||||
|
||||
// tracing
|
||||
bool _tracingEnabled;
|
||||
bool _traceAll;
|
||||
Set<ObjId> _traceObjIDs;
|
||||
Set<ProcId> _tracePIDs;
|
||||
Set<uint16> _traceClasses;
|
||||
|
||||
inline bool trace_show(ProcId pid, ObjId objid, uint16 ucclass) {
|
||||
if (!_tracingEnabled) return false;
|
||||
if (_traceAll) return true;
|
||||
if (_traceObjIDs.find(objid) != _traceObjIDs.end()) return true;
|
||||
if (_tracePIDs.find(pid) != _tracePIDs.end()) return true;
|
||||
if (_traceClasses.find(ucclass) != _traceClasses.end()) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
189
engines/ultima/ultima8/usecode/uc_process.cpp
Normal file
189
engines/ultima/ultima8/usecode/uc_process.cpp
Normal file
@@ -0,0 +1,189 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/usecode/uc_process.h"
|
||||
#include "ultima/ultima8/usecode/uc_machine.h"
|
||||
#include "ultima/ultima8/usecode/usecode.h"
|
||||
#include "ultima/ultima8/games/game_data.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(UCProcess)
|
||||
|
||||
UCProcess::UCProcess() : Process(), _classId(0xFFFF), _ip(0xFFFF),
|
||||
_bp(0x0000), _temp32(0) { // !! fixme
|
||||
_usecode = GameData::get_instance()->getMainUsecode();
|
||||
}
|
||||
|
||||
UCProcess::UCProcess(uint16 classid, uint16 offset, uint32 this_ptr,
|
||||
int thissize, const uint8 *args, int argsize)
|
||||
: Process(), _classId(0xFFFF), _ip(0xFFFF), _bp(0x0000), _temp32(0) {
|
||||
_usecode = GameData::get_instance()->getMainUsecode();
|
||||
|
||||
load(classid, offset, this_ptr, thissize, args, argsize);
|
||||
}
|
||||
|
||||
UCProcess::~UCProcess() {
|
||||
}
|
||||
|
||||
void UCProcess::load(uint16 classid, uint16 offset, uint32 this_ptr,
|
||||
int thissize, const uint8 *args, int argsize) {
|
||||
if (_usecode->get_class_size(classid) == 0)
|
||||
warning("Class is empty.");
|
||||
|
||||
_classId = 0xFFFF;
|
||||
_ip = 0xFFFF;
|
||||
_bp = 0x0000;
|
||||
uint16 thissp = 0;
|
||||
|
||||
// first, push the derefenced this pointer
|
||||
if (this_ptr != 0 && thissize > 0) {
|
||||
_stack.addSP(-thissize);
|
||||
UCMachine::get_instance()->
|
||||
dereferencePointer(this_ptr, _stack.access(), thissize);
|
||||
thissp = _stack.getSP();
|
||||
}
|
||||
|
||||
// next, push the arguments
|
||||
_stack.push(args, argsize);
|
||||
|
||||
// then, push the new this pointer
|
||||
if (thissp != 0)
|
||||
_stack.push4(UCMachine::stackToPtr(_pid, thissp));
|
||||
|
||||
// finally, call the specified function
|
||||
call(classid, offset);
|
||||
}
|
||||
|
||||
void UCProcess::run() {
|
||||
if (_flags & PROC_SUSPENDED)
|
||||
return;
|
||||
|
||||
// pass to UCMachine for execution
|
||||
UCMachine::get_instance()->execProcess(this);
|
||||
}
|
||||
|
||||
void UCProcess::call(uint16 classid, uint16 offset) {
|
||||
_stack.push2(_classId); // BP+04 prev class
|
||||
_stack.push2(_ip); // BP+02 prev IP
|
||||
_stack.push2(_bp); // BP+00 prev BP
|
||||
|
||||
_classId = classid;
|
||||
_ip = offset;
|
||||
_bp = static_cast<uint16>(_stack.getSP()); // TRUNCATES!
|
||||
}
|
||||
|
||||
bool UCProcess::ret() {
|
||||
_stack.setSP(_bp);
|
||||
|
||||
_bp = _stack.pop2();
|
||||
_ip = _stack.pop2();
|
||||
_classId = _stack.pop2();
|
||||
|
||||
if (_ip == 0xFFFF && _classId == 0xFFFF)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void UCProcess::freeOnTerminate(uint16 index, int type) {
|
||||
assert(type >= 1 && type <= 3);
|
||||
|
||||
Common::Pair<uint16, int> p;
|
||||
p.first = index;
|
||||
p.second = type;
|
||||
|
||||
_freeOnTerminate.push_back(p);
|
||||
}
|
||||
|
||||
void UCProcess::terminate() {
|
||||
for (auto &i : _freeOnTerminate) {
|
||||
uint16 index = i.first;
|
||||
int typeNum = i.second;
|
||||
|
||||
switch (typeNum) {
|
||||
case 1: // string
|
||||
UCMachine::get_instance()->freeString(index);
|
||||
break;
|
||||
case 2: // stringlist
|
||||
UCMachine::get_instance()->freeStringList(index);
|
||||
break;
|
||||
case 3: // list
|
||||
UCMachine::get_instance()->freeList(index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_freeOnTerminate.clear();
|
||||
|
||||
Process::terminate();
|
||||
}
|
||||
|
||||
Common::String UCProcess::dumpInfo() const {
|
||||
Common::String info = Process::dumpInfo();
|
||||
|
||||
if (_classId == 0xFFFF) {
|
||||
info += ", IP undefined";
|
||||
} else {
|
||||
const char *classname = GameData::get_instance()->getMainUsecode()->
|
||||
get_class_name(_classId);
|
||||
info += Common::String::format(", classname: %s, IP: %04X:%04X", classname, _classId, _ip);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
void UCProcess::saveData(Common::WriteStream *ws) {
|
||||
Process::saveData(ws);
|
||||
|
||||
ws->writeUint16LE(_bp);
|
||||
ws->writeUint16LE(_classId);
|
||||
ws->writeUint16LE(_ip);
|
||||
ws->writeUint32LE(_temp32);
|
||||
ws->writeUint32LE(static_cast<uint32>(_freeOnTerminate.size()));
|
||||
for (const auto &i : _freeOnTerminate) {
|
||||
ws->writeUint16LE(i.first);
|
||||
ws->writeUint32LE(static_cast<uint32>(i.second));
|
||||
}
|
||||
_stack.save(ws);
|
||||
}
|
||||
|
||||
bool UCProcess::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
if (!Process::loadData(rs, version)) return false;
|
||||
|
||||
_bp = rs->readUint16LE();
|
||||
_classId = rs->readUint16LE();
|
||||
_ip = rs->readUint16LE();
|
||||
_temp32 = rs->readUint32LE();
|
||||
uint32 freecount = rs->readUint32LE();
|
||||
for (unsigned int i = 0; i < freecount; ++i) {
|
||||
Common::Pair<uint16, int> p;
|
||||
p.first = rs->readUint16LE();
|
||||
p.second = static_cast<int>(rs->readUint32LE());
|
||||
_freeOnTerminate.push_back(p);
|
||||
}
|
||||
_stack.load(rs, version);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
90
engines/ultima/ultima8/usecode/uc_process.h
Normal file
90
engines/ultima/ultima8/usecode/uc_process.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef ULTIMA8_USECODE_UCPROCESS_H
|
||||
#define ULTIMA8_USECODE_UCPROCESS_H
|
||||
|
||||
#include "ultima/shared/std/containers.h"
|
||||
#include "ultima/ultima8/kernel/process.h"
|
||||
#include "ultima/ultima8/usecode/uc_stack.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class Usecode;
|
||||
|
||||
// probably won't inherit from Process directly in the future
|
||||
class UCProcess : public Process {
|
||||
friend class UCMachine;
|
||||
friend class Kernel;
|
||||
public:
|
||||
UCProcess();
|
||||
UCProcess(uint16 classid, uint16 offset, uint32 this_ptr = 0,
|
||||
int thissize = 0, const uint8 *args = 0, int argsize = 0);
|
||||
~UCProcess() override;
|
||||
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
void run() override;
|
||||
|
||||
void terminate() override;
|
||||
|
||||
void freeOnTerminate(uint16 index, int type);
|
||||
|
||||
void setReturnValue(uint32 retval) {
|
||||
_temp32 = retval;
|
||||
}
|
||||
|
||||
uint16 getClassId() const {
|
||||
return _classId;
|
||||
}
|
||||
|
||||
Common::String dumpInfo() const override;
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
|
||||
protected:
|
||||
void load(uint16 classid, uint16 offset, uint32 this_ptr = 0,
|
||||
int thissize = 0, const uint8 *args = 0, int argsize = 0);
|
||||
void call(uint16 classid, uint16 offset);
|
||||
bool ret();
|
||||
|
||||
// stack base pointer
|
||||
uint16 _bp;
|
||||
|
||||
Usecode *_usecode;
|
||||
|
||||
uint16 _classId;
|
||||
uint16 _ip;
|
||||
|
||||
uint32 _temp32;
|
||||
|
||||
// data stack
|
||||
UCStack _stack;
|
||||
|
||||
// "Free Me" list
|
||||
Std::list<Common::Pair<uint16, int> > _freeOnTerminate;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
56
engines/ultima/ultima8/usecode/uc_stack.cpp
Normal file
56
engines/ultima/ultima8/usecode/uc_stack.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/misc/debugger.h"
|
||||
#include "ultima/ultima8/usecode/uc_stack.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
void UCStack::save(Common::WriteStream *ws) {
|
||||
ws->writeUint32LE(_size);
|
||||
ws->writeUint32LE(getSP());
|
||||
|
||||
ws->write(_bufPtr, stacksize());
|
||||
}
|
||||
|
||||
bool UCStack::load(Common::ReadStream *rs, uint32 version) {
|
||||
_size = rs->readUint32LE();
|
||||
#ifdef USE_DYNAMIC_UCSTACK
|
||||
if (_buf) delete[] _buf;
|
||||
_buf = new uint8[_size];
|
||||
#else
|
||||
if (_size > sizeof(_bufArray)) {
|
||||
warning("UCStack _size mismatch (buf_array too small)");
|
||||
return false;
|
||||
}
|
||||
_buf = _bufArray;
|
||||
#endif
|
||||
uint32 sp = rs->readUint32LE();
|
||||
_bufPtr = _buf + sp;
|
||||
|
||||
rs->read(_bufPtr, _size - sp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
191
engines/ultima/ultima8/usecode/uc_stack.h
Normal file
191
engines/ultima/ultima8/usecode/uc_stack.h
Normal file
@@ -0,0 +1,191 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_USECODE_UCSTACK_H
|
||||
#define ULTIMA8_USECODE_UCSTACK_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
// A little-endian stack for use with usecode
|
||||
class BaseUCStack {
|
||||
protected:
|
||||
uint8 *_buf;
|
||||
uint8 *_bufPtr;
|
||||
uint32 _size;
|
||||
public:
|
||||
|
||||
BaseUCStack(uint32 len, uint8 *b) : _buf(b), _size(len) {
|
||||
// stack grows downward, so start at the end of the buffer
|
||||
_bufPtr = _buf + _size;
|
||||
}
|
||||
virtual ~BaseUCStack() { }
|
||||
|
||||
inline uint32 getSize() const {
|
||||
return _size;
|
||||
}
|
||||
|
||||
inline uint32 stacksize() const {
|
||||
return _size - (_bufPtr - _buf);
|
||||
}
|
||||
|
||||
inline void addSP(const int32 offset) {
|
||||
_bufPtr += offset;
|
||||
}
|
||||
|
||||
inline unsigned int getSP() const {
|
||||
return static_cast<unsigned int>(_bufPtr - _buf);
|
||||
}
|
||||
|
||||
inline void setSP(unsigned int pos) {
|
||||
_bufPtr = _buf + pos;
|
||||
}
|
||||
|
||||
//
|
||||
// Push values to the stack
|
||||
//
|
||||
|
||||
inline void push1(uint8 val) {
|
||||
_bufPtr--;
|
||||
_bufPtr[0] = val;
|
||||
}
|
||||
|
||||
inline void push2(uint16 val) {
|
||||
_bufPtr -= 2;
|
||||
_bufPtr[0] = static_cast<uint8>(val & 0xFF);
|
||||
_bufPtr[1] = static_cast<uint8>((val >> 8) & 0xFF);
|
||||
}
|
||||
inline void push4(uint32 val) {
|
||||
_bufPtr -= 4;
|
||||
_bufPtr[0] = static_cast<uint8>(val & 0xFF);
|
||||
_bufPtr[1] = static_cast<uint8>((val >> 8) & 0xFF);
|
||||
_bufPtr[2] = static_cast<uint8>((val >> 16) & 0xFF);
|
||||
_bufPtr[3] = static_cast<uint8>((val >> 24) & 0xFF);
|
||||
}
|
||||
// Push an arbitrary number of bytes of 0
|
||||
inline void push0(const uint32 count) {
|
||||
_bufPtr -= count;
|
||||
memset(_bufPtr, 0, count);
|
||||
}
|
||||
// Push an arbitrary number of bytes
|
||||
inline void push(const uint8 *in, const uint32 count) {
|
||||
_bufPtr -= count;
|
||||
memcpy(_bufPtr, in, count);
|
||||
}
|
||||
|
||||
//
|
||||
// Pop values from the stack
|
||||
//
|
||||
|
||||
inline uint16 pop2() {
|
||||
uint8 b0, b1;
|
||||
b0 = *_bufPtr++;
|
||||
b1 = *_bufPtr++;
|
||||
return (b0 | (b1 << 8));
|
||||
}
|
||||
inline uint32 pop4() {
|
||||
uint8 b0, b1, b2, b3;
|
||||
b0 = *_bufPtr++;
|
||||
b1 = *_bufPtr++;
|
||||
b2 = *_bufPtr++;
|
||||
b3 = *_bufPtr++;
|
||||
return (b0 | (b1 << 8) | (b2 << 16) | (b3 << 24));
|
||||
}
|
||||
inline void pop(uint8 *out, const uint32 count) {
|
||||
memcpy(out, _bufPtr, count);
|
||||
_bufPtr += count;
|
||||
}
|
||||
|
||||
//
|
||||
// Access a value from a location in the stack
|
||||
//
|
||||
|
||||
inline uint8 access1(const uint32 offset) const {
|
||||
return _buf[offset];
|
||||
}
|
||||
inline uint16 access2(const uint32 offset) const {
|
||||
return (_buf[offset] | (_buf[offset + 1] << 8));
|
||||
}
|
||||
inline uint32 access4(const uint32 offset) const {
|
||||
return _buf[offset] | (_buf[offset + 1] << 8) |
|
||||
(_buf[offset + 2] << 16) | (_buf[offset + 3] << 24);
|
||||
}
|
||||
inline uint8 *access(const uint32 offset) {
|
||||
return _buf + offset;
|
||||
}
|
||||
inline uint8 *access() {
|
||||
return _bufPtr;
|
||||
}
|
||||
|
||||
//
|
||||
// Assign a value to a location in the stack
|
||||
//
|
||||
|
||||
inline void assign1(const uint32 offset, const uint8 val) {
|
||||
const_cast<uint8 *>(_buf)[offset] = static_cast<uint8>(val & 0xFF);
|
||||
}
|
||||
inline void assign2(const uint32 offset, const uint16 val) {
|
||||
const_cast<uint8 *>(_buf)[offset] = static_cast<uint8>(val & 0xFF);
|
||||
const_cast<uint8 *>(_buf)[offset + 1] = static_cast<uint8>((val >> 8) & 0xFF);
|
||||
}
|
||||
inline void assign4(const uint32 offset, const uint32 val) {
|
||||
const_cast<uint8 *>(_buf)[offset] = static_cast<uint8>(val & 0xFF);
|
||||
const_cast<uint8 *>(_buf)[offset + 1] = static_cast<uint8>((val >> 8) & 0xFF);
|
||||
const_cast<uint8 *>(_buf)[offset + 2] = static_cast<uint8>((val >> 16) & 0xFF);
|
||||
const_cast<uint8 *>(_buf)[offset + 3] = static_cast<uint8>((val >> 24) & 0xFF);
|
||||
}
|
||||
inline void assign(const uint32 offset, const uint8 *in, const uint32 len) {
|
||||
memcpy(const_cast<uint8 *>(_buf) + offset, in, len);
|
||||
}
|
||||
};
|
||||
|
||||
class DynamicUCStack : public BaseUCStack {
|
||||
public:
|
||||
DynamicUCStack(uint32 len = 0x1000) : BaseUCStack(len, new uint8[len]) { }
|
||||
~DynamicUCStack() override {
|
||||
delete [] _buf;
|
||||
}
|
||||
|
||||
#ifdef USE_DYNAMIC_UCSTACK
|
||||
#define UCStack DynamicUCStack
|
||||
void save(Common::WriteStream *ws);
|
||||
bool load(Common::ReadStream *rs, uint32 version);
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifndef USE_DYNAMIC_UCSTACK
|
||||
class UCStack : public BaseUCStack {
|
||||
uint8 _bufArray[0x1000];
|
||||
public:
|
||||
UCStack() : BaseUCStack(0x1000, _bufArray) { }
|
||||
~UCStack() override { }
|
||||
|
||||
void save(Common::WriteStream *ws);
|
||||
bool load(Common::ReadStream *rs, uint32 version);
|
||||
};
|
||||
#endif
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
59
engines/ultima/ultima8/usecode/usecode.cpp
Normal file
59
engines/ultima/ultima8/usecode/usecode.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/misc/common_types.h"
|
||||
|
||||
#include "ultima/ultima8/usecode/usecode.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
uint32 Usecode::get_class_event(uint32 classid, uint32 eventid) {
|
||||
if (get_class_size(classid) == 0) return 0;
|
||||
|
||||
if (eventid >= get_class_event_count(classid)) {
|
||||
warning("eventid too high: %u >= %u for class %u",
|
||||
eventid, get_class_event_count(classid), classid);
|
||||
}
|
||||
|
||||
const uint8 *data = get_class(classid);
|
||||
|
||||
uint32 offset = 0;
|
||||
if (GAME_IS_U8) {
|
||||
offset = data[12 + (eventid * 4) + 0];
|
||||
offset += data[12 + (eventid * 4) + 1] << 8;
|
||||
offset += data[12 + (eventid * 4) + 2] << 16;
|
||||
offset += data[12 + (eventid * 4) + 3] << 24;
|
||||
} else if (GAME_IS_CRUSADER) {
|
||||
offset = data[20 + (eventid * 6) + 2];
|
||||
offset += data[20 + (eventid * 6) + 3] << 8;
|
||||
offset += data[20 + (eventid * 6) + 4] << 16;
|
||||
offset += data[20 + (eventid * 6) + 5] << 24;
|
||||
} else {
|
||||
warning("Invalid game type.");
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
49
engines/ultima/ultima8/usecode/usecode.h
Normal file
49
engines/ultima/ultima8/usecode/usecode.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_USECODE_USECODE_H
|
||||
#define ULTIMA8_USECODE_USECODE_H
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
/**
|
||||
* Usecode is the main engine code in the U8 engine. It has a simple assembly language
|
||||
* executed by the UCMachine.
|
||||
*/
|
||||
class Usecode {
|
||||
public:
|
||||
Usecode() { }
|
||||
virtual ~Usecode() { }
|
||||
|
||||
virtual const uint8 *get_class(uint32 classid) = 0;
|
||||
virtual uint32 get_class_size(uint32 classid) = 0;
|
||||
virtual const char *get_class_name(uint32 classid) = 0;
|
||||
virtual uint32 get_class_base_offset(uint32 classid) = 0;
|
||||
virtual uint32 get_class_event_count(uint32 classid) = 0;
|
||||
|
||||
virtual uint32 get_class_event(uint32 classid, uint32 eventid);
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
82
engines/ultima/ultima8/usecode/usecode_flex.cpp
Normal file
82
engines/ultima/ultima8/usecode/usecode_flex.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima8/misc/debugger.h"
|
||||
|
||||
#include "ultima/ultima8/usecode/usecode_flex.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
const uint8 *UsecodeFlex::get_class(uint32 classid) {
|
||||
const uint8 *obj = get_object_nodel(classid + 2);
|
||||
return obj;
|
||||
}
|
||||
|
||||
uint32 UsecodeFlex::get_class_size(uint32 classid) {
|
||||
uint32 size = get_size(classid + 2);
|
||||
return size;
|
||||
}
|
||||
|
||||
const char *UsecodeFlex::get_class_name(uint32 classid) {
|
||||
if (get_size(classid + 2) > 0) {
|
||||
const uint8 *name_object = get_object_nodel(1);
|
||||
return reinterpret_cast<const char *>(name_object + 4 + (13 * classid));
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 UsecodeFlex::get_class_base_offset(uint32 classid) {
|
||||
if (get_size(classid + 2) == 0) return 0;
|
||||
|
||||
if (GAME_IS_U8) {
|
||||
return 0x0C;
|
||||
} else if (GAME_IS_CRUSADER) {
|
||||
const uint8 *obj = get_object_nodel(classid + 2);
|
||||
uint32 offset = obj[8];
|
||||
offset += obj[9] << 8;
|
||||
offset += obj[10] << 16;
|
||||
offset += obj[11] << 24;
|
||||
offset--;
|
||||
return offset;
|
||||
} else {
|
||||
warning("Invalid game type.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 UsecodeFlex::get_class_event_count(uint32 classid) {
|
||||
if (get_size(classid + 2) == 0) return 0;
|
||||
|
||||
if (GAME_IS_U8) {
|
||||
return 32;
|
||||
} else if (GAME_IS_CRUSADER) {
|
||||
return (get_class_base_offset(classid) + 19) / 6;
|
||||
} else {
|
||||
warning("Invalid game type.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
46
engines/ultima/ultima8/usecode/usecode_flex.h
Normal file
46
engines/ultima/ultima8/usecode/usecode_flex.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_USECODE_USECODEFLEX_H
|
||||
#define ULTIMA8_USECODE_USECODEFLEX_H
|
||||
|
||||
#include "ultima/ultima8/usecode/usecode.h"
|
||||
#include "ultima/ultima8/filesys/raw_archive.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class UsecodeFlex : public Usecode, protected RawArchive {
|
||||
public:
|
||||
UsecodeFlex(Common::SeekableReadStream *rs) : RawArchive(rs) { }
|
||||
~UsecodeFlex() override { }
|
||||
|
||||
const uint8 *get_class(uint32 classid) override;
|
||||
uint32 get_class_size(uint32 classid) override;
|
||||
const char *get_class_name(uint32 classid) override;
|
||||
uint32 get_class_base_offset(uint32 classid) override;
|
||||
uint32 get_class_event_count(uint32 classid) override;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user