mirror of
https://github.com/scummvm/scummvm.git
synced 2026-06-20 05:45:29 +00:00
ULTIMA8: Use 2 bytes of intrinsic stack for UINT8
This fixes #12917. The usecode "push byte" opcodes (0x0A and 0x5D) always push 16 bits on the stack, but the ARG_UINT8 macro was only removing 1 byte. Most of the time this went unnoticed because the UINT8 was the last argument in most cases (eg, a z val), or unused. This led to an inconsistency where sometimes z values were being popped with ARG_UINT16 and sometimes ARG_UINT8. The original games do not support z values beyond 254, so this should always be UINT8. Additionaly, a while back "push byte" was fixed so it always sign extends, but this could result in a case where we pop incorrect values. For example, a high Z value could get sign-extended on push, and then popped back as a UINT16, giving a z of 64000ish. Fix by always moving the SP by 2 bytes, only use the first one. Correcting this also fixes the strange color ordering I thought was needed for I_jumpToAllGivenColor in Crusader: No Regret, where actually it should have been popping the values as 16-bit instead of 8-bit.
This commit is contained in:
@@ -253,9 +253,9 @@ uint32 PaletteFaderProcess::I_fadeToGivenColor(const uint8 *args,
|
||||
else if (_fader) _fader->terminate();
|
||||
|
||||
// TODO: guessing that color order should be same as other one below?
|
||||
ARG_UINT8(b);
|
||||
ARG_UINT8(r);
|
||||
ARG_UINT8(g);
|
||||
ARG_UINT8(b);
|
||||
ARG_UINT16(nsteps);
|
||||
ARG_UINT16(unk);
|
||||
|
||||
@@ -326,9 +326,9 @@ uint32 PaletteFaderProcess::I_jumpToAllGivenColor(const uint8 *args,
|
||||
if (_fader && _fader->_priority > 0x7FFF) return 0;
|
||||
else if (_fader) _fader->terminate();
|
||||
|
||||
ARG_UINT8(b);
|
||||
ARG_UINT8(r);
|
||||
ARG_UINT8(g);
|
||||
ARG_UINT8(b);
|
||||
|
||||
// Transform matrix goes 0~2048, scale 0-63 vals from input
|
||||
const int16 r16 = static_cast<int16>(r) * 32;
|
||||
|
||||
@@ -34,7 +34,9 @@ typedef uint32(*Intrinsic)(const uint8 *args, unsigned int argsize);
|
||||
|
||||
// TODO: range checking on args
|
||||
|
||||
#define ARG_UINT8(x) uint8 x = (*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);
|
||||
@@ -88,7 +90,6 @@ typedef uint32(*Intrinsic)(const uint8 *args, unsigned int argsize);
|
||||
WorldPoint x; \
|
||||
UCMachine::get_instance()->dereferencePointer(ucptr_##x, x._buf, 5);
|
||||
|
||||
#define ARG_NULL8() args+=1;
|
||||
#define ARG_NULL16() args+=2;
|
||||
#define ARG_NULL32() args+=4;
|
||||
|
||||
|
||||
@@ -2545,8 +2545,8 @@ uint32 Actor::I_pathfindToPoint(const uint8 *args, unsigned int /*argsize*/) {
|
||||
ARG_ACTOR_FROM_PTR(actor);
|
||||
ARG_UINT16(x);
|
||||
ARG_UINT16(y);
|
||||
ARG_UINT16(z);
|
||||
ARG_NULL16(); // unknown. Only one instance of this in U8, value is 5.
|
||||
ARG_UINT8(z);
|
||||
ARG_NULL16(); // unknown. Only one instance of this in U8, values are 5,1.
|
||||
if (!actor) return 0;
|
||||
|
||||
if (GAME_IS_CRUSADER) {
|
||||
|
||||
@@ -1352,7 +1352,7 @@ uint32 CurrentMap::I_canExistAt(const uint8 *args, unsigned int argsize) {
|
||||
ARG_UINT16(shape);
|
||||
ARG_UINT16(x);
|
||||
ARG_UINT16(y);
|
||||
ARG_UINT16(z);
|
||||
ARG_UINT8(z);
|
||||
if (argsize > 8) {
|
||||
//!! TODO: figure these out
|
||||
ARG_UINT16(unk1); // is either 1 or 4
|
||||
|
||||
@@ -173,7 +173,7 @@ uint32 FireballProcess::I_TonysBalls(const uint8 *args,
|
||||
ARG_NULL16(); // unknown
|
||||
ARG_SINT16(x);
|
||||
ARG_SINT16(y);
|
||||
ARG_UINT16(z);
|
||||
ARG_UINT8(z);
|
||||
|
||||
Item *ball = ItemFactory::createItem(260, 4, 0, Item::FLG_FAST_ONLY,
|
||||
0, 0, 0, true);
|
||||
|
||||
@@ -3160,7 +3160,7 @@ uint32 Item::I_legalCreateAtCoords(const uint8 *args, unsigned int /*argsize*/)
|
||||
ARG_UINT16(frame);
|
||||
ARG_UINT16(x);
|
||||
ARG_UINT16(y);
|
||||
ARG_UINT16(z);
|
||||
ARG_UINT8(z);
|
||||
|
||||
if (GAME_IS_CRUSADER) {
|
||||
x *= 2;
|
||||
@@ -3357,7 +3357,7 @@ uint32 Item::I_push(const uint8 *args, unsigned int /*argsize*/) {
|
||||
return 0;
|
||||
|
||||
#if 0
|
||||
perr << "Pushing item to ethereal void: " << item->getShape() << "," << item->getFrame() << Std::endl;
|
||||
perr << "Pushing item to ethereal void: id: " << item->getObjId() << " shp: " << item->getShape() << "," << item->getFrame() << Std::endl;
|
||||
#endif
|
||||
|
||||
item->moveToEtherealVoid();
|
||||
@@ -3423,7 +3423,7 @@ uint32 Item::I_popToCoords(const uint8 *args, unsigned int /*argsize*/) {
|
||||
ARG_NULL32(); // ARG_ITEM_FROM_PTR(item); // unused
|
||||
ARG_UINT16(x);
|
||||
ARG_UINT16(y);
|
||||
ARG_UINT16(z);
|
||||
ARG_UINT8(z);
|
||||
|
||||
World *w = World::get_instance();
|
||||
|
||||
@@ -3521,7 +3521,7 @@ uint32 Item::I_move(const uint8 *args, unsigned int /*argsize*/) {
|
||||
ARG_ITEM_FROM_PTR(item);
|
||||
ARG_UINT16(x);
|
||||
ARG_UINT16(y);
|
||||
ARG_UINT16(z);
|
||||
ARG_UINT8(z);
|
||||
if (!item)
|
||||
return 0;
|
||||
|
||||
@@ -3881,7 +3881,7 @@ uint32 Item::I_explode(const uint8 *args, unsigned int argsize) {
|
||||
uint32 Item::I_igniteChaos(const uint8 *args, unsigned int /*argsize*/) {
|
||||
ARG_UINT16(x);
|
||||
ARG_UINT16(y);
|
||||
ARG_NULL8();
|
||||
ARG_UINT8(z); // unused
|
||||
|
||||
assert(GAME_IS_U8);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user