aboutsummaryrefslogtreecommitdiff
path: root/engines/dreamweb/object.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/dreamweb/object.cpp')
-rw-r--r--engines/dreamweb/object.cpp517
1 files changed, 475 insertions, 42 deletions
diff --git a/engines/dreamweb/object.cpp b/engines/dreamweb/object.cpp
index 54979309f4..9d5ea15fa3 100644
--- a/engines/dreamweb/object.cpp
+++ b/engines/dreamweb/object.cpp
@@ -58,15 +58,11 @@ void DreamBase::fillRyan() {
showRyanPage();
}
-void DreamGenContext::isItWorn() {
- flags._z = isItWorn((const DynObject *)es.ptr(bx, sizeof(DynObject)));
-}
-
bool DreamBase::isItWorn(const DynObject *object) {
return (object->id[0] == 'W'-'A') && (object->id[1] == 'E'-'A');
}
-void DreamGenContext::wornError() {
+void DreamBase::wornError() {
data.byte(kCommandtype) = 255;
delPointer();
printMessage(76, 21, 57, 240, false);
@@ -79,11 +75,7 @@ void DreamGenContext::wornError() {
workToScreenM();
}
-void DreamGenContext::makeWorn() {
- makeWorn((DynObject *)es.ptr(bx, sizeof(DynObject)));
-}
-
-void DreamGenContext::makeWorn(DynObject *object) {
+void DreamBase::makeWorn(DynObject *object) {
object->id[0] = 'W'-'A';
object->id[1] = 'E'-'A';
}
@@ -155,7 +147,7 @@ void DreamGenContext::examineOb(bool examineAgain) {
data.byte(kCommandtype) = 255;
readMouse();
showPointer();
- workToScreenCPP();
+ workToScreen();
delPointer();
examineAgain = false;
}
@@ -170,8 +162,8 @@ void DreamGenContext::examineOb(bool examineAgain) {
switch (data.byte(kInvopen)) {
case 0: {
- RectWithCallback examList[] = {
- { 273,320,157,198,&DreamGenContext::getBackFromOb },
+ RectWithCallback<DreamGenContext> examList[] = {
+ { 273,320,157,198,&DreamBase::getBackFromOb },
{ 260,300,0,44,&DreamGenContext::useObject },
{ 210,254,0,44,&DreamGenContext::selectOpenOb },
{ 144,176,64,96,&DreamGenContext::setPickup },
@@ -184,8 +176,8 @@ void DreamGenContext::examineOb(bool examineAgain) {
}
case 1: {
// Note: This table contains the non-constant _openChangeSize!
- RectWithCallback invList1[] = {
- { 273,320,157,198,&DreamGenContext::getBackFromOb },
+ RectWithCallback<DreamGenContext> invList1[] = {
+ { 273,320,157,198,&DreamBase::getBackFromOb },
{ 255,294,0,24,&DreamGenContext::dropObject },
{ kInventx+167,kInventx+167+(18*3),kInventy-18,kInventy-2,&DreamGenContext::incRyanPage },
{ kInventx,_openChangeSize,kInventy+100,kInventy+100+kItempicsize,&DreamGenContext::useOpened },
@@ -197,8 +189,8 @@ void DreamGenContext::examineOb(bool examineAgain) {
break;
}
default: {
- RectWithCallback withList1[] = {
- { 273,320,157,198,&DreamGenContext::getBackFromOb },
+ RectWithCallback<DreamGenContext> withList1[] = {
+ { 273,320,157,198,&DreamBase::getBackFromOb },
{ kInventx+167,kInventx+167+(18*3),kInventy-18,kInventy-2,&DreamGenContext::incRyanPage },
{ kInventx,kInventx+(5*kItempicsize), kInventy,kInventy+(2*kItempicsize),&DreamGenContext::selectOb },
{ 0,320,0,200,&DreamBase::blank },
@@ -235,8 +227,7 @@ void DreamGenContext::inventory() {
if (data.byte(kCommandtype) != 239) {
data.byte(kCommandtype) = 239;
- al = 32;
- commandOnly();
+ commandOnly(32);
}
if (data.word(kMousebutton) == data.word(kOldbutton))
@@ -260,7 +251,7 @@ void DreamGenContext::inventory() {
openInv();
readMouse();
showPointer();
- workToScreenCPP();
+ workToScreen();
delPointer();
data.byte(kOpenedob) = 255;
examineOb(false);
@@ -286,7 +277,7 @@ void DreamBase::getBackFromOb() {
}
void DreamGenContext::getOpenedSize() {
- //ax = getOpenedSizeCPP();
+ //ax = getOpenedSlotCount();
// We need to call the ASM-style versions of get*Ad, as these also set
// bx and es
@@ -309,7 +300,7 @@ void DreamGenContext::getOpenedSize() {
}
}
-byte DreamGenContext::getOpenedSizeCPP() {
+byte DreamGenContext::getOpenedSlotCount() {
byte obj = data.byte(kOpenedob);
switch (data.byte(kOpenedtype)) {
case 4:
@@ -321,6 +312,18 @@ byte DreamGenContext::getOpenedSizeCPP() {
}
}
+byte DreamGenContext::getOpenedSlotSize() {
+ byte obj = data.byte(kOpenedob);
+ switch (data.byte(kOpenedtype)) {
+ case 4:
+ return getExAd(obj)->slotSize;
+ case 2:
+ return getFreeAd(obj)->slotSize;
+ default:
+ return getSetAd(obj)->slotSize;
+ }
+}
+
void DreamGenContext::openOb() {
uint8 commandLine[64] = "OBJECT NAME ONE ";
@@ -331,7 +334,7 @@ void DreamGenContext::openOb() {
al = printDirect(commandLine, data.word(kLastxpos) + 5, kInventy+86, 220, false);
fillOpen();
- _openChangeSize = getOpenedSizeCPP() * kItempicsize + kInventx;
+ _openChangeSize = getOpenedSlotCount() * kItempicsize + kInventx;
}
void DreamGenContext::identifyOb() {
@@ -351,12 +354,10 @@ void DreamGenContext::identifyOb() {
data.byte(kInmaparea) = 1;
ah = bl;
push(ax);
- findPathOfPoint();
- data.byte(kPointerspath) = dl;
+ data.byte(kPointerspath) = findPathOfPoint(al, ah);
ax = pop();
push(ax);
- findFirstPath();
- data.byte(kPointerfirstpath) = al;
+ data.byte(kPointerfirstpath) = findFirstPath(al, ah);
ax = pop();
byte x = al;
@@ -419,8 +420,7 @@ void DreamGenContext::selectOb() {
void DreamGenContext::setPickup() {
if (data.byte(kObjecttype) != kSetObjectType1 && data.byte(kObjecttype) != kSetObjectType3) {
- // The original called getAnyAd() here. However, since object types
- // 1 and 3 are excluded, the resulting object is a DynObject
+ // Object types 1 and 3 are excluded, so the resulting object is a DynObject
uint8 dummy;
DynObject *object = (DynObject *)getAnyAd(&dummy, &dummy);
if (object->mapad[0] == 4) {
@@ -466,10 +466,6 @@ void DreamGenContext::setPickup() {
workToScreenM();
}
-void DreamGenContext::deleteExFrame() {
- deleteExFrame(al);
-}
-
void DreamBase::deleteExFrame(uint8 frameNum) {
Frame *frame = (Frame *)getSegment(data.word(kExtras)).ptr(kExframedata + sizeof(Frame)*frameNum, sizeof(Frame));
@@ -493,10 +489,6 @@ void DreamBase::deleteExFrame(uint8 frameNum) {
}
}
-void DreamGenContext::deleteExText() {
- deleteExText(al);
-}
-
void DreamBase::deleteExText(uint8 textNum) {
uint16 offset = getSegment(data.word(kExtras)).word(kExtextdat + 2*textNum);
@@ -519,11 +511,6 @@ void DreamBase::deleteExText(uint8 textNum) {
}
}
-// This takes es:di and cl as input, but es:di always points to getExAd(cl)
-void DreamGenContext::deleteExObject() {
- deleteExObject(cl);
-}
-
void DreamBase::deleteExObject(uint8 index) {
DynObject *obj = getExAd(index);
@@ -631,4 +618,450 @@ void DreamGenContext::outOfInv() {
delPointer();
}
+void DreamBase::purgeALocation(uint8 index) {
+ // index == al
+ for (uint8 i = 0; i < kNumexobjects; ++i) {
+ DynObject *t = getExAd(i);
+ if (t->currentLocation == index && t->mapad[0] == 0) {
+ deleteExObject(i);
+ }
+ }
+}
+
+const uint8 *DreamBase::getObTextStart() {
+ uint16 textSeg, textDatOff, textOff;
+ if (data.byte(kObjecttype) == kFreeObjectType) {
+ textSeg = data.word(kFreedesc);
+ textDatOff = kFreetextdat;
+ textOff = kFreetext;
+ } else if (data.byte(kObjecttype) == kSetObjectType1) {
+ textSeg = data.word(kSetdesc);
+ textDatOff = kSettextdat;
+ textOff = kSettext;
+ } else {
+ textSeg = data.word(kExtras);
+ textDatOff = kExtextdat;
+ textOff = kExtext;
+ }
+ const uint8 *textBase = getSegment(textSeg).ptr(textOff, 0);
+ const uint8 *text = textBase + getSegment(textSeg).word(textDatOff + 2*data.byte(kCommand));
+
+ if (data.byte(kObjecttype) != kSetObjectType1)
+ return text;
+
+ const uint8 *obname = text;
+ while (true) {
+ const uint8 *start = text;
+ findNextColon(&text);
+
+ // Not an empty description string?
+ if (*text != 0 && *text != ':')
+ return start;
+
+ // If the description string (of a SetObjectType1 object) is empty,
+ // look for an object with the same name.
+ // Example: Eden's garage door outside has two parts. The right part
+ // has no description of its own but uses that of the left part.
+
+ bool found = false;
+ do {
+ text++;
+ uint8 c = *obname;
+
+ // scan for matching first character
+ while (*text != c) {
+ text++;
+
+ // arbitrary give-up counter
+ if (text - (textBase - textOff) >= 8000) {
+ warning("Object description for %d/%d not found", data.byte(kObjecttype), data.byte(kCommand));
+ return obname;
+ }
+ }
+
+ // found matching first character, so match the rest
+ const uint8 *s1 = obname;
+ const uint8 *s2 = text;
+ do {
+ s1++;
+ s2++;
+ } while (*s1 != ':' && *s1 != 0 && *s1 == *s2);
+
+ if (*s1 == ':' || *s1 == 0)
+ found = true; // (prefix) matched the entire object name
+ } while (!found);
+
+ // We found an object with the same name. The next loop iteration
+ // will check if this one again has an empty description.
+ }
+}
+
+void DreamBase::dropObject() {
+ if (data.byte(kCommandtype) != 223) {
+ data.byte(kCommandtype) = 223;
+ if (!data.byte(kPickup)) {
+ blank();
+ return;
+ }
+ commandWithOb(37, data.byte(kObjecttype), data.byte(kItemframe));
+ }
+
+ if (data.word(kMousebutton) == data.word(kOldbutton) || !(data.word(kMousebutton) & 1))
+ return;
+
+ if (isItWorn(getEitherAdCPP())) {
+ wornError();
+ return;
+ }
+
+ if (data.byte(kReallocation) != 47) {
+ byte flag, flagEx, type, flagX, flagY;
+ checkOne(data.byte(kRyanx) + 12, data.byte(kRyany) + 12, &flag, &flagEx, &type, &flagX, &flagY);
+
+ if (flag >= 2) {
+ dropError();
+ return;
+ }
+ } else {
+ dropError();
+ return;
+ }
+
+ if (data.byte(kMapxsize) == 64 && data.byte(kMapysize) == 64) {
+ // Inside lift
+ dropError();
+ return;
+ }
+
+ if (compare(data.byte(kItemframe), 4, "GUNA") || compare(data.byte(kItemframe), 4, "SHLD")) {
+ cantDrop();
+ return;
+ }
+
+ data.byte(kObjecttype) = 4;
+ DynObject *object = getExAd(data.byte(kItemframe));
+ object->mapad[0] = 0;
+ object->mapad[1] = ((data.byte(kRyanx) + 4) >> 4) + data.byte(kMapx);
+ object->mapad[2] = (data.byte(kRyanx) + 4) & 0xF;
+ object->mapad[3] = ((data.byte(kRyany) + 8) >> 4) + data.byte(kMapy);
+ object->mapad[4] = (data.byte(kRyany) + 8) & 0xF;
+ data.byte(kPickup) = 0;
+ object->currentLocation = data.byte(kReallocation);
+}
+
+bool DreamGenContext::checkObjectSizeCPP() {
+ byte containerSize = getOpenedSlotSize();
+ DynObject *object = getEitherAdCPP();
+ // If there is no size defined for the object in the editor, set its size
+ // to 6. This could be a bad idea, according to the original source.
+ byte objectSize = (object->objectSize != 255) ? object->objectSize : 6;
+
+ if (containerSize >= 100) {
+ // Special type of container: only objects of the same special type fit.
+ if (containerSize == objectSize)
+ return true;
+
+ errorMessage3();
+ return false;
+ }
+
+ if (objectSize >= 100) {
+ // Special type of object, but a regular container.
+ // Subtract 100 from the size to get its regular size.
+ objectSize -= 100;
+ }
+
+ if (containerSize >= objectSize)
+ return true;
+
+ errorMessage2();
+ return false;
+}
+
+void DreamGenContext::selectOpenOb() {
+ uint8 slotSize, slotCount;
+ getAnyAd(&slotSize, &slotCount);
+ if (slotCount == 255) {
+ // Can't open the object
+ blank();
+ return;
+ }
+
+ if (data.byte(kCommandtype) != 224) {
+ data.byte(kCommandtype) = 224;
+ commandWithOb(38, data.byte(kObjecttype), data.byte(kCommand));
+ }
+
+ if (data.word(kMousebutton) == data.word(kOldbutton) || !(data.word(kMousebutton) & 1))
+ return;
+
+ data.byte(kOpenedob) = data.byte(kCommand);
+ data.byte(kOpenedtype) = data.byte(kObjecttype);
+ createPanel();
+ showPanel();
+ showMan();
+ examIcon();
+ showExit();
+ openInv();
+ openOb();
+ underTextLine();
+ readMouse();
+ showPointer();
+ workToScreen();
+ delPointer();
+}
+
+void DreamGenContext::reExFromInv() {
+ uint16 objectId = getSegment(data.word(kBuffers)).word(findInvPosCPP());
+ data.byte(kCommandtype) = objectId >> 8;
+ data.byte(kCommand) = objectId & 0x00FF;
+ data.byte(kExamagain) = 1;
+ data.byte(kPointermode) = 0;
+}
+
+void DreamGenContext::swapWithInv() {
+ uint16 subject = (data.byte(kObjecttype) << 8) | data.byte(kItemframe);
+ if (subject == data.word(kOldsubject)) {
+ if (data.byte(kCommandtype) != 243) {
+ data.byte(kCommandtype) = 243;
+ data.word(kOldsubject) = subject;
+ commandWithOb(34, data.byte(kObjecttype), data.byte(kItemframe));
+ }
+ } else {
+ data.word(kOldsubject) = subject;
+ commandWithOb(34, data.byte(kObjecttype), data.byte(kItemframe));
+ }
+
+ if (data.word(kMousebutton) == data.word(kOldbutton) || !(data.word(kMousebutton) & 1))
+ return;
+
+ byte prevType = data.byte(kObjecttype);
+ byte prevFrame = data.byte(kItemframe);
+ uint16 objectId = getSegment(data.word(kBuffers)).word(findInvPosCPP());
+ data.byte(kItemframe) = objectId & 0x00FF;
+ data.byte(kObjecttype) = objectId >> 8;
+ DynObject *object = getEitherAdCPP();
+ object->mapad[0] = 20;
+ object->mapad[1] = 255;
+ byte prevType2 = data.byte(kObjecttype);
+ byte prevFrame2 = data.byte(kItemframe);
+ data.byte(kObjecttype) = prevType;
+ data.byte(kItemframe) = prevFrame;
+ //findInvPosCPP(); // found in the original source, but it seems to be useless
+ delPointer();
+ object = getEitherAdCPP();
+ object->mapad[0] = 4;
+ object->mapad[1] = 255;
+ object->mapad[2] = data.byte(kLastinvpos);
+ data.byte(kObjecttype) = prevType2;
+ data.byte(kItemframe) = prevFrame2;
+ fillRyan();
+ readMouse();
+ showPointer();
+ workToScreen();
+ delPointer();
+}
+
+void DreamGenContext::useOpened() {
+ if (data.byte(kOpenedob) == 255)
+ return; // cannot use opened object
+
+ if (!data.byte(kPickup)) {
+ outOfOpen();
+ return;
+ }
+
+ uint16 objectId = getSegment(data.word(kBuffers)).word(findOpenPos());
+
+ if ((objectId & 0x00FF) != 255) {
+ swapWithOpen();
+ return;
+ }
+
+ if (data.byte(kPickup) != 1) {
+ blank();
+ return;
+ }
+
+ objectId = (data.byte(kObjecttype) << 8) | data.byte(kItemframe);
+ if (objectId == data.word(kOldsubject)) {
+ if (data.byte(kCommandtype) != 227) {
+ data.byte(kCommandtype) = 227;
+ data.word(kOldsubject) = objectId;
+ commandWithOb(35, data.byte(kObjecttype), data.byte(kItemframe));
+ }
+ } else {
+ data.word(kOldsubject) = objectId;
+ commandWithOb(35, data.byte(kObjecttype), data.byte(kItemframe));
+ }
+
+ if (data.word(kMousebutton) == data.word(kOldbutton) || !(data.word(kMousebutton) & 1))
+ return;
+
+ if (isItWorn(getEitherAdCPP())) {
+ wornError();
+ return;
+ }
+
+ delPointer();
+
+ if (data.byte(kItemframe) == data.byte(kOpenedob) &&
+ data.byte(kObjecttype) == data.byte(kOpenedtype)) {
+ errorMessage1();
+ return;
+ }
+
+ if (!checkObjectSizeCPP())
+ return;
+
+ data.byte(kPickup) = 0;
+ DynObject *object = getEitherAdCPP();
+ object->mapad[0] = data.byte(kOpenedtype);
+ object->mapad[1] = data.byte(kOpenedob);
+ object->mapad[2] = data.byte(kLastinvpos);
+ object->mapad[3] = data.byte(kReallocation);
+ fillOpen();
+ underTextLine();
+ readMouse();
+ useOpened();
+ showPointer();
+ workToScreen();
+ delPointer();
+}
+
+void DreamGenContext::outOfOpen() {
+ if (data.byte(kOpenedob) == 255)
+ return; // cannot use opened object
+
+ uint16 objectId = getSegment(data.word(kBuffers)).word(findOpenPos());
+
+ if ((objectId & 0x00FF) == 255) {
+ blank();
+ return;
+ }
+
+ if (objectId == data.word(kOldsubject)) {
+ if (data.byte(kCommandtype) != 228) {
+ data.byte(kCommandtype) = 228;
+ data.word(kOldsubject) = objectId;
+ commandWithOb(36, objectId >> 8, objectId & 0x00FF);
+ }
+ } else {
+ data.word(kOldsubject) = objectId;
+ commandWithOb(36, objectId >> 8, objectId & 0x00FF);
+ }
+
+ if (data.word(kMousebutton) == data.word(kOldbutton))
+ return; // notletgo4
+
+ if (data.word(kMousebutton) != 1) {
+ if (data.word(kMousebutton) != 2)
+ return; // notletgo4
+
+ reExFromOpen();
+ return;
+ }
+
+ delPointer();
+ data.byte(kPickup) = 1;
+ objectId = getSegment(data.word(kBuffers)).word(findOpenPos());
+ data.byte(kObjecttype) = objectId >> 8;
+ data.byte(kItemframe) = objectId & 0xFF;
+
+ if (data.byte(kObjecttype) != 4) {
+ transferToEx();
+ data.byte(kItemframe) = al;
+ data.byte(kObjecttype) = 4;
+ }
+
+ DynObject *object = getEitherAdCPP();
+ object->mapad[0] = 20;
+ object->mapad[1] = 255;
+
+ fillOpen();
+ underTextLine();
+ readMouse();
+ useOpened();
+ showPointer();
+ workToScreen();
+ delPointer();
+}
+
+void DreamGenContext::swapWithOpen() {
+ uint16 subject = (data.byte(kObjecttype) << 8) | data.byte(kItemframe);
+ if (subject == data.word(kOldsubject)) {
+ if (data.byte(kCommandtype) != 242) {
+ data.byte(kCommandtype) = 242;
+ data.word(kOldsubject) = subject;
+ commandWithOb(34, data.byte(kObjecttype), data.byte(kItemframe));
+ }
+ } else {
+ data.word(kOldsubject) = subject;
+ commandWithOb(34, data.byte(kObjecttype), data.byte(kItemframe));
+ }
+
+ if (data.word(kMousebutton) == data.word(kOldbutton) || !(data.word(kMousebutton) & 1))
+ return;
+
+ if (isItWorn(getEitherAdCPP())) {
+ wornError();
+ return;
+ }
+
+ delPointer();
+
+ if (data.byte(kItemframe) == data.byte(kOpenedob) &&
+ data.byte(kObjecttype) == data.byte(kOpenedtype)) {
+ errorMessage1();
+ return;
+ }
+
+ if (!checkObjectSizeCPP())
+ return;
+
+ byte prevType = data.byte(kObjecttype);
+ byte prevFrame = data.byte(kItemframe);
+ uint16 objectId = getSegment(data.word(kBuffers)).word(findOpenPos());
+ data.byte(kObjecttype) = objectId >> 8;
+ data.byte(kItemframe) = objectId & 0xFF;
+
+ if (data.byte(kObjecttype) != 4) {
+ transferToEx();
+ data.byte(kItemframe) = al;
+ data.byte(kObjecttype) = 4;
+ }
+
+ DynObject *object = getEitherAdCPP();
+ object->mapad[0] = 20;
+ object->mapad[1] = 255;
+
+ byte prevType2 = data.byte(kObjecttype);
+ byte prevFrame2 = data.byte(kItemframe);
+ data.byte(kObjecttype) = prevType;
+ data.byte(kItemframe) = prevFrame;
+ //findOpenPos(); // was in the original source, looks to be unused
+ object = getEitherAdCPP();
+ object->mapad[0] = data.byte(kOpenedtype);
+ object->mapad[1] = data.byte(kOpenedob);
+ object->mapad[2] = data.byte(kLastinvpos);
+ object->mapad[3] = data.byte(kReallocation);
+ data.byte(kObjecttype) = prevType2;
+ data.byte(kItemframe) = prevFrame2;
+ fillOpen();
+ fillRyan();
+ underTextLine();
+ readMouse();
+ useOpened();
+ showPointer();
+ workToScreen();
+ delPointer();
+}
+
+uint16 DreamBase::findOpenPos() {
+ uint16 pos = (data.word(kMousex) - kInventx) / kItempicsize;
+ data.byte(kLastinvpos) = pos & 0xFF;
+
+ return pos * 2 + kOpeninvlist; // return the object position in the inventory data
+}
+
} // End of namespace DreamGen