aboutsummaryrefslogtreecommitdiff
path: root/engines/dreamweb/stubs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/dreamweb/stubs.cpp')
-rw-r--r--engines/dreamweb/stubs.cpp1981
1 files changed, 1176 insertions, 805 deletions
diff --git a/engines/dreamweb/stubs.cpp b/engines/dreamweb/stubs.cpp
index 54685a018a..9b85cbb9f4 100644
--- a/engines/dreamweb/stubs.cpp
+++ b/engines/dreamweb/stubs.cpp
@@ -23,131 +23,184 @@
#include "dreamweb/dreamweb.h"
#include "engines/util.h"
#include "graphics/surface.h"
+#include "common/config-manager.h"
namespace DreamGen {
-Common::String getFilename(Context &context) {
- uint16 name_ptr = context.dx;
- Common::String name;
- uint8 c;
- while((c = context.cs.byte(name_ptr++)) != 0)
- name += (char)c;
- return name;
-}
+void DreamGenContext::dreamweb() {
+ STACK_CHECK;
+ seecommandtail();
+ checkbasemem();
+ soundstartup();
+ setkeyboardint();
+ setupemm();
+ allocatebuffers();
+ setmouse();
+ fadedos();
+ gettime();
+ clearbuffers();
+ clearpalette();
+ set16colpalette();
+ readsetdata();
+ data.byte(kWongame) = 0;
-void DreamGenContext::multiget() {
- unsigned w = (uint8)cl, h = (uint8)ch;
- unsigned x = (uint16)di, y = (uint16)bx;
- unsigned src = x + y * kScreenwidth;
- unsigned dst = (uint16)si;
- es = ds;
- ds = data.word(kWorkspace);
- if (y + h > 200)
- h = 200 - y;
- if (x + w > 320)
- w = 320 - x;
- //debug(1, "multiget %u,%u %ux%u -> segment: %04x->%04x", x, y, w, h, (uint16)ds, (uint16)es);
- for(unsigned l = 0; l < h; ++l) {
- uint8 *src_p = ds.ptr(src + kScreenwidth * l, w);
- uint8 *dst_p = es.ptr(dst + w * l, w);
- memcpy(dst_p, src_p, w);
- }
- si += w * h;
- di = src + kScreenwidth * h;
- cx = 0;
-}
+ dx = 1909;
+ loadsample();
+ setsoundoff();
-void DreamGenContext::multiput() {
- unsigned w = (uint8)cl, h = (uint8)ch;
- unsigned x = (uint16)di, y = (uint16)bx;
- unsigned src = (uint16)si;
- unsigned dst = x + y * kScreenwidth;
- es = data.word(kWorkspace);
- if (y + h > 200)
- h = 200 - y;
- if (x + w > 320)
- w = 320 - x;
- //debug(1, "multiput %ux%u -> segment: %04x->%04x", w, h, (uint16)ds, (uint16)es);
- for(unsigned l = 0; l < h; ++l) {
- uint8 *src_p = ds.ptr(src + w * l, w);
- uint8 *dst_p = es.ptr(dst + kScreenwidth * l, w);
- memcpy(dst_p, src_p, w);
- }
- si += w * h;
- di = dst + kScreenwidth * h;
- cx = 0;
-}
+ bool firstLoop = true;
-void DreamGenContext::multidump() {
- ds = data.word(kWorkspace);
- int w = (uint8)cl, h = (uint8)ch;
- int x = (int16)di, y = (int16)bx;
- unsigned offset = x + y * kScreenwidth;
- //debug(1, "multidump %ux%u(segment: %04x) -> %d,%d(address: %d)", w, h, (uint16)ds, x, y, offset);
- engine->blit(ds.ptr(offset, w * h), kScreenwidth, x, y, w, h);
- si = di = offset + h * kScreenwidth;
- cx = 0;
-}
+ int savegameId = Common::ConfigManager::instance().getInt("save_slot");
-void DreamGenContext::worktoscreen() {
- ds = data.word(kWorkspace);
- uint size = 320 * 200;
- engine->blit(ds.ptr(0, size), 320, 0, 0, 320, 200);
- di = si = size;
- cx = 0;
-}
+ while (true) {
-void DreamGenContext::printundermon() {
- engine->printUnderMonitor();
-}
+ scanfornames();
-void DreamGenContext::cls() {
- engine->cls();
-}
+ bool startNewGame = true;
-void DreamGenContext::frameoutnm(uint8* dst, const uint8* src, uint16 pitch, uint16 width, uint16 height, uint16 x, uint16 y) {
- dst += pitch * y + x;
+ if (firstLoop && savegameId >= 0) {
- for (uint16 j = 0; j < height; ++j) {
- memcpy(dst, src, width);
- dst += pitch;
- src += width;
- }
-}
+ // loading a savegame requested from launcher/command line
-void DreamGenContext::frameoutbh(uint8* dst, const uint8* src, uint16 pitch, uint16 width, uint16 height, uint16 x, uint16 y) {
- uint16 stride = pitch - width;
- dst += y * pitch + x;
+ cls();
+ setmode();
+ loadpalfromiff();
+ clearpalette();
+
+ ax = savegameId;
+ doload();
+ worktoscreen();
+ fadescreenup();
+ startNewGame = false;
+
+ } else if (al == 0 && firstLoop) {
+
+ // no savegames found, and we're not restarting.
+
+ setmode();
+ loadpalfromiff();
+
+ } else {
+ // "dodecisions"
+
+ // Savegames found, so ask if we should load one.
+ // (If we're restarting after game over, we also always show these
+ // options.)
+
+ cls();
+ setmode();
+ decide();
+ if (data.byte(kQuitrequested))
+ return; // exit game
+
+ if (data.byte(kGetback) == 4)
+ startNewGame = false; // savegame has been loaded
- for (uint16 i = 0; i < height; ++i) {
- for (uint16 j = 0; j < width; ++j) {
- if (*dst == 0xff) {
- *dst = *src;
- }
- ++src;
- ++dst;
}
- dst += stride;
- }
-}
-void DreamGenContext::frameoutfx(uint8* dst, const uint8* src, uint16 pitch, uint16 width, uint16 height, uint16 x, uint16 y) {
- uint16 stride = pitch - width;
- dst += y * pitch + x;
- dst -= width;
+ firstLoop = false;
+
+ if (startNewGame) {
+ // "playgame"
+
+ titles();
+ if (data.byte(kQuitrequested))
+ return; // exit game
+ credits();
+
+ if (data.byte(kQuitrequested))
+ return; // exit game
+
+ clearchanges();
+ setmode();
+ loadpalfromiff();
+ data.byte(kLocation) = 255;
+ data.byte(kRoomafterdream) = 1;
+ data.byte(kNewlocation) = 35;
+ data.byte(kVolume) = 7;
+ loadroom();
+ clearsprites();
+ initman();
+ entrytexts();
+ entryanims();
+ data.byte(kDestpos) = 3;
+ initialinv();
+ data.byte(kLastflag) = 32;
+ startup1();
+ data.byte(kVolumeto) = 0;
+ data.byte(kVolumedirection) = -1;
+ data.byte(kCommandtype) = 255;
- for (uint16 j = 0; j < height; ++j) {
- for (uint16 i = 0; i < width; ++i) {
- uint8 pixel = src[width - i - 1];
- if (pixel)
- *dst = pixel;
- ++dst;
}
- src += width;
- dst += stride;
+
+ // main loop
+ while (true) {
+
+ if (data.byte(kQuitrequested))
+ return; // exit game
+
+ screenupdate();
+
+ if (data.byte(kWongame) != 0) {
+ // "endofgame"
+ clearbeforeload();
+ fadescreendowns();
+ cx = 200;
+ hangon();
+ endgame();
+ quickquit2();
+ return;
+ }
+
+ if (data.byte(kMandead) == 1 || data.byte(kMandead) == 2)
+ break;
+
+ if (data.word(kWatchingtime) > 0) {
+ if (data.byte(kFinaldest) == data.byte(kManspath))
+ data.word(kWatchingtime)--;
+ }
+
+ if (data.word(kWatchingtime) == 0) {
+ // "notwatching"
+
+ if (data.byte(kMandead) == 4)
+ break;
+
+ if (data.byte(kNewlocation) != 255) {
+ // "loadnew"
+ clearbeforeload();
+ loadroom();
+ clearsprites();
+ initman();
+ entrytexts();
+ entryanims();
+ data.byte(kNewlocation) = 255;
+ startup();
+ data.byte(kCommandtype) = 255;
+ worktoscreenm();
+ }
+ }
+ }
+
+ // "gameover"
+ clearbeforeload();
+ showgun();
+ fadescreendown();
+ cx = 100;
+ hangon();
+
}
}
+static Common::String getFilename(Context &context) {
+ uint16 name_ptr = context.dx;
+ Common::String name;
+ uint8 c;
+ while((c = context.cs.byte(name_ptr++)) != 0)
+ name += (char)c;
+ return name;
+}
+
void DreamGenContext::seecommandtail() {
data.word(kSoundbaseadd) = 0x220;
data.byte(kSoundint) = 5;
@@ -232,55 +285,171 @@ void DreamGenContext::dontloadseg() {
}
void DreamGenContext::mousecall() {
- engine->mouseCall();
+ uint16 x, y, state;
+ engine->mouseCall(&x, &y, &state);
+ cx = x;
+ dx = y;
+ bx = state;
+}
+
+void DreamGenContext::readmouse() {
+ data.word(kOldbutton) = data.word(kMousebutton);
+ data.word(kOldx) = data.word(kMousex);
+ data.word(kOldy) = data.word(kMousey);
+ uint16 x, y, state;
+ engine->mouseCall(&x, &y, &state);
+ data.word(kMousex) = x;
+ data.word(kMousey) = y;
+ data.word(kMousebutton) = state;
+}
+
+void DreamGenContext::readmouse1() {
+ data.word(kOldx) = data.word(kMousex);
+ data.word(kOldy) = data.word(kMousey);
+ uint16 x, y, state;
+ engine->mouseCall(&x, &y, &state);
+ data.word(kMousex) = x;
+ data.word(kMousey) = y;
+ data.word(kMousebutton1) = state;
+}
+
+void DreamGenContext::readmouse2() {
+ data.word(kOldx) = data.word(kMousex);
+ data.word(kOldy) = data.word(kMousey);
+ uint16 x, y, state;
+ engine->mouseCall(&x, &y, &state);
+ data.word(kMousex) = x;
+ data.word(kMousey) = y;
+ data.word(kMousebutton2) = state;
+}
+
+void DreamGenContext::readmouse3() {
+ data.word(kOldx) = data.word(kMousex);
+ data.word(kOldy) = data.word(kMousey);
+ uint16 x, y, state;
+ engine->mouseCall(&x, &y, &state);
+ data.word(kMousex) = x;
+ data.word(kMousey) = y;
+ data.word(kMousebutton3) = state;
+}
+
+void DreamGenContext::readmouse4() {
+ data.word(kOldbutton) = data.word(kMousebutton);
+ data.word(kOldx) = data.word(kMousex);
+ data.word(kOldy) = data.word(kMousey);
+ uint16 x, y, state;
+ engine->mouseCall(&x, &y, &state);
+ data.word(kMousex) = x;
+ data.word(kMousey) = y;
+ data.word(kMousebutton) = state | data.word(kMousebutton1) | data.word(kMousebutton2) | data.word(kMousebutton3);
}
void DreamGenContext::setmouse() {
data.word(kOldpointerx) = 0xffff;
}
-uint8 DreamGenContext::getnextword(uint8 *totalWidth, uint8 *charCount) {
- *totalWidth = 0;
- *charCount = 0;
- while(true) {
- uint8 firstChar = es.byte(di);
- ++di;
- ++*charCount;
- if ((firstChar == ':') || (firstChar == 0)) { //endall
- *totalWidth += 6;
- return 1;
- }
- if (firstChar == 32) { //endword
- *totalWidth += 6;
- return 0;
- }
- firstChar = engine->modifyChar(firstChar);
- if (firstChar != 255) {
- uint8 secondChar = es.byte(di);
- uint8 width = ds.byte(6*(firstChar - 32 + data.word(kCharshift)));
- width = kernchars(firstChar, secondChar, width);
- *totalWidth += width;
- }
+void DreamGenContext::dumptextline() {
+ if (data.byte(kNewtextline) != 1)
+ return;
+ data.byte(kNewtextline) = 0;
+ uint16 x = data.word(kTextaddressx);
+ uint16 y = data.word(kTextaddressy);
+ if (data.byte(kForeignrelease) != 0)
+ y -= 3;
+ multidump(x, y, 228, 13);
+}
+
+void DreamGenContext::getundertimed() {
+ uint16 y = data.byte(kTimedy);
+ if (data.byte(kForeignrelease))
+ y -= 3;
+ ds = data.word(kBuffers);
+ si = kUndertimedtext;
+ multiget(ds.ptr(si, 0), data.byte(kTimedx), y, 240, kUndertimedysize);
+}
+
+void DreamGenContext::putundertimed() {
+ uint16 y = data.byte(kTimedy);
+ if (data.byte(kForeignrelease))
+ y -= 3;
+ ds = data.word(kBuffers);
+ si = kUndertimedtext;
+ multiput(ds.ptr(si, 0), data.byte(kTimedx), y, 240, kUndertimedysize);
+}
+
+void DreamGenContext::usetimedtext() {
+ if (data.word(kTimecount) == 0)
+ return;
+ --data.word(kTimecount);
+ if (data.word(kTimecount) == 0) {
+ putundertimed();
+ data.byte(kNeedtodumptimed) = 1;
+ return;
}
-}
-void DreamGenContext::getnextword() {
- uint8 totalWidth, charCount;
- al = getnextword(&totalWidth, &charCount);
- bl = totalWidth;
- bh = charCount;
-}
+ if (data.word(kTimecount) == data.word(kCounttotimed))
+ getundertimed();
+ else if (data.word(kTimecount) > data.word(kCounttotimed))
+ return;
-uint8 DreamGenContext::kernchars(uint8 firstChar, uint8 secondChar, uint8 width) {
- if ((firstChar == 'a') || (al == 'u')) {
- if ((secondChar == 'n') || (secondChar == 't') || (secondChar == 'r') || (secondChar == 'i') || (secondChar == 'l'))
- return width-1;
+ es = data.word(kTimedseg);
+ si = data.word(kTimedoffset);
+ const uint8 *string = es.ptr(si, 0);
+ uint16 y = data.byte(kTimedy);
+ printdirect(&string, data.byte(kTimedx), &y, 237, true);
+ data.byte(kNeedtodumptimed) = 1;
+}
+
+void DreamGenContext::setuptimedtemp() {
+ setuptimedtemp(al, ah, bl, bh, cx, dx);
+}
+
+void DreamGenContext::setuptimedtemp(uint8 textIndex, uint8 voiceIndex, uint8 x, uint8 y, uint16 countToTimed, uint16 timeCount) {
+#if 1 // if cd
+ if (voiceIndex != 0) {
+ push(ax);
+ push(bx);
+ push(cx);
+ push(dx);
+ dl = 'T';
+ dh = voiceIndex;
+ cl = 'T';
+ ah = 0;
+ loadspeech();
+ if (data.byte(kSpeechloaded) == 1) {
+ al = 50+12;
+ playchannel1();
+ }
+ dx = pop();
+ cx = pop();
+ bx = pop();
+ ax = pop();
+ if ((data.byte(kSpeechloaded) == 1) && (data.byte(kSubtitles) != 1))
+ return;
}
- return width;
-}
+#endif
-void DreamGenContext::kernchars() {
- cl = kernchars(al, ah, cl);
+ if (data.word(kTimecount) != 0)
+ return;
+ data.byte(kTimedy) = y;
+ data.byte(kTimedx) = x;
+ data.word(kCounttotimed) = countToTimed;
+ data.word(kTimecount) = timeCount + countToTimed;
+ data.word(kTimedseg) = data.word(kTextfile1);
+ data.word(kTimedoffset) = kTextstart + segRef(data.word(kTextfile1)).word(textIndex * 2);
+ const uint8 *string = segRef(data.word(kTextfile1)).ptr(data.word(kTimedoffset), 0);
+ debug(1, "setuptimedtemp: (%d, %d) => '%s'", textIndex, voiceIndex, string);
+}
+
+void DreamGenContext::dumptimedtext() {
+ if (data.byte(kNeedtodumptimed) != 1)
+ return;
+ uint8 y = data.byte(kTimedy);
+ if (data.byte(kForeignrelease) != 0)
+ y -= 3;
+
+ multidump(data.byte(kTimedx), y, 240, kUndertimedysize);
+ data.byte(kNeedtodumptimed) = 0;
}
void DreamGenContext::gettime() {
@@ -296,12 +465,17 @@ void DreamGenContext::gettime() {
}
void DreamGenContext::allocatemem() {
- uint size = (bx + 2) * 16;
+ ax = allocatemem(bx);
+}
+
+uint16 DreamGenContext::allocatemem(uint16 paragraphs) {
+ uint size = (paragraphs + 2) * 16;
debug(1, "allocate mem, %u bytes", size);
flags._c = false;
SegmentRef seg = allocateSegment(size);
- ax = (uint16)seg;
- debug(1, "\tsegment address -> %04x", (uint16)ax);
+ uint16 result = (uint16)seg;
+ debug(1, "\tsegment address -> %04x", result);
+ return result;
}
void DreamGenContext::deallocatemem() {
@@ -476,8 +650,6 @@ void DreamGenContext::dosreturn() {
}
void DreamGenContext::set16colpalette() {
- //fixme: this is a bit hackish, set16colpalette called after initialization and nearly before main loop.
- engine->enableSavingOrLoading();
}
void DreamGenContext::mode640x480() {
@@ -495,764 +667,963 @@ void DreamGenContext::fadedos() {
engine->fadeDos();
}
-void DreamGenContext::doshake() {
- uint8 &counter = data.byte(kShakecounter);
- _cmp(counter, 48);
- if (flags.z())
+void DreamGenContext::eraseoldobs() {
+ if (data.byte(kNewobs) == 0)
return;
- _add(counter, 1);
- static const int shakeTable[] = {
- 0, -2, 3, -2, 0, 2, 4, -1,
- 1, -3, 3, 2, 0, -2, 3, -2,
- 0, 2, 4, -1, 1, -3, 3, 2,
- 0, -2, 3, -2, 0, 2, 4, -1,
-
- 1, -3, 3, 2, 0, -2, 3, -2,
- 0, 2, 4, -1, 1, -3, 3, 2,
- 0, -2, 3, -2, 0, 2, 4, -1,
- 1, -3, 3, 2, 0, -2, 3, -2,
-
- 0, 2, 4, -1, 1, -3, 3, 2,
- 0, -2, 3, -2, 0, 2, 4, -1,
- 1, -3, 3, 2, 0, -2, 3, -2,
- 0, 2, 4, -1, 1, -3, 3, 2,
-
- 0, -2, 3, -2, 0, 2, 4, -1,
- 1, -3, 3, 0,
- };
- int offset = shakeTable[counter];
- engine->setShakePos(offset >= 0? offset: -offset);
-}
-
-void DreamGenContext::vsync() {
- push(ax);
- push(bx);
- push(cx);
- push(dx);
- push(si);
- push(di);
- push(es);
- push(ds);
- engine->waitForVSync();
- ds = pop();
- es = pop();
- di = pop();
- si = pop();
- dx = pop();
- cx = pop();
- bx = pop();
- ax = pop();
+ Sprite *sprites = spritetable();
+ for (size_t i=0; i < 16; ++i) {
+ Sprite &sprite = sprites[i];
+ if (sprite.objData() != 0xffff) {
+ memset(&sprite, 0xff, sizeof(Sprite));
+ }
+ }
}
-void DreamGenContext::setmode() {
- vsync();
- initGraphics(320, 200, false);
+void DreamGenContext::modifychar() {
+ al = engine->modifyChar(al);
}
-void DreamGenContext::showpcx() {
- Common::String name = getFilename(*this);
- Common::File pcxFile;
-
- if (!pcxFile.open(name)) {
- warning("showpcx: Could not open '%s'", name.c_str());
- return;
- }
-
- uint8 *maingamepal;
- int i, j;
-
- // Read the 16-color palette into the 'maingamepal' buffer. Note that
- // the color components have to be adjusted from 8 to 6 bits.
-
- pcxFile.seek(16, SEEK_SET);
- es = data.word(kBuffers);
- maingamepal = es.ptr(kMaingamepal, 768);
- pcxFile.read(maingamepal, 48);
-
- memset(maingamepal + 48, 0xff, 720);
- for (i = 0; i < 48; i++) {
- maingamepal[i] >>= 2;
- }
-
- // Decode the image data.
-
- Graphics::Surface *s = g_system->lockScreen();
- Common::Rect rect(640, 480);
-
- s->fillRect(rect, 0);
- pcxFile.seek(128, SEEK_SET);
-
- for (int y = 0; y < 480; y++) {
- byte *dst = (byte *)s->getBasePtr(0, y);
- int decoded = 0;
-
- while (decoded < 320) {
- byte col = pcxFile.readByte();
- byte len;
-
- if ((col & 0xc0) == 0xc0) {
- len = col & 0x3f;
- col = pcxFile.readByte();
- } else {
- len = 1;
- }
-
- // The image uses 16 colors and is stored as four bit
- // planes, one for each bit of the color, least
- // significant bit plane first.
-
- for (i = 0; i < len; i++) {
- int plane = decoded / 80;
- int pos = decoded % 80;
-
- for (j = 0; j < 8; j++) {
- byte bit = (col >> (7 - j)) & 1;
- dst[8 * pos + j] |= (bit << plane);
- }
+void DreamGenContext::lockmon() {
+ // Pressing space pauses text output in the monitor. We use the "hard"
+ // key because calling readkey() drains characters from the input
+ // buffer, we we want the user to be able to type ahead while the text
+ // is being printed.
+ if (data.byte(kLasthardkey) == 57) {
+ // Clear the keyboard buffer. Otherwise the space that caused
+ // the pause will be read immediately unpause the game.
+ do {
+ readkey();
+ } while (data.byte(kCurrentkey) != 0);
- decoded++;
- }
+ locklighton();
+ while (!engine->shouldQuit()) {
+ engine->waitForVSync();
+ readkey();
+ if (data.byte(kCurrentkey) == ' ')
+ break;
}
+ // Forget the last "hard" key, otherwise the space that caused
+ // the unpausing will immediately re-pause the game.
+ data.byte(kLasthardkey) = 0;
+ locklightoff();
}
-
- g_system->unlockScreen();
- pcxFile.close();
}
-/*
-void DreamGenContext::frameoutv() {
- uint16 pitch = dx;
- uint16 width = cx & 0xff;
- uint16 height = cx >> 8;
-
- const uint8* src = ds.ptr(si, width * height);
- uint8* dst = es.ptr(0, pitch * height);
-
- frameoutv(dst, src, pitch, width, height, di, bx);
+void DreamGenContext::cancelch0() {
+ data.byte(kCh0repeat) = 0;
+ data.word(kCh0blockstocopy) = 0;
+ data.byte(kCh0playing) = 255;
+ engine->stopSound(0);
}
-*/
-void DreamGenContext::frameoutv(uint8* dst, const uint8* src, uint16 pitch, uint16 width, uint16 height, uint16 x, uint16 y) {
- // NB : These resilience checks were not in the original engine, but did they result in undefined behaviour
- // or was something broken during porting to C++?
- assert(pitch == 320);
+void DreamGenContext::cancelch1() {
+ data.word(kCh1blockstocopy) = 0;
+ data.byte(kCh1playing) = 255;
+ engine->stopSound(1);
+}
- if(x >= 320)
- return;
- if(y >= 200)
+void DreamGenContext::makebackob(SetObject *objData) {
+ if (data.byte(kNewobs) == 0)
return;
- if(x + width > 320) {
- width = 320 - x;
- }
- if(y + height > 200) {
- height = 200 - y;
- }
-
- uint16 stride = pitch - width;
- dst += pitch * y + x;
-
- for (uint16 j = 0; j < height; ++j) {
- for (uint16 i = 0; i < width; ++i) {
- uint8 pixel = *src++;
- if (pixel)
- *dst = pixel;
- ++dst;
- }
- dst += stride;
- }
+ uint8 priority = objData->priority;
+ uint8 type = objData->type;
+ Sprite *sprite = makesprite(data.word(kObjectx), data.word(kObjecty), addr_backobject, data.word(kSetframes), 0);
+
+ uint16 objDataOffset = (uint8 *)objData - segRef(data.word(kSetdat)).ptr(0, 0);
+ assert(objDataOffset % sizeof(SetObject) == 0);
+ assert(objDataOffset < 128 * sizeof(SetObject));
+ sprite->setObjData(objDataOffset);
+ if (priority == 255)
+ priority = 0;
+ sprite->priority = priority;
+ sprite->type = type;
+ sprite->b16 = 0;
+ sprite->delay = 0;
+ sprite->frame = 0;
}
-Sprite* DreamGenContext::spritetable() {
- push(es);
- push(bx);
-
- es = data.word(kBuffers);
- bx = kSpritetable;
- Sprite *sprite = (Sprite*)es.ptr(bx, 16*sizeof(Sprite));
-
- bx = pop();
- es = pop();
+void DreamGenContext::getroomdata() {
+ bx = kRoomdata + sizeof(Room) * al;
+}
- return sprite;
+void DreamGenContext::startloading() {
+ const Room *room = (Room *)cs.ptr(bx, sizeof(Room));
+ startloading(room);
}
-uint16 DreamGenContext::showframeCPP(uint16 dst, uint16 src, uint16 x, uint16 y, uint8 frameNumber, uint8 effectsFlag) {
- es = dst;
- ds = src;
- di = x;
- bx = y;
- al = frameNumber;
- ah = effectsFlag;
+void DreamGenContext::readheader() {
+ ax = engine->readFromFile(cs.ptr(kFileheader, kHeaderlen), kHeaderlen);
+ es = cs;
+ di = kFiledata;
+}
- si = (ax & 0x1ff) * 6;
- if (ds.word(si) == 0) {
- return 0;
+void DreamGenContext::startloading(const Room *room) {
+ data.byte(kCombatcount) = 0;
+ data.byte(kRoomssample) = room->roomsSample;
+ data.byte(kMapx) = room->mapX;
+ data.byte(kMapy) = room->mapY;
+ data.byte(kLiftflag) = room->liftFlag;
+ data.byte(kManspath) = room->b21;
+ data.byte(kDestination) = room->b21;
+ data.byte(kFinaldest) = room->b21;
+ data.byte(kFacing) = room->b22;
+ data.byte(kTurntoface) = room->b22;
+ data.byte(kCounttoopen) = room->countToOpen;
+ data.byte(kLiftpath) = room->liftPath;
+ data.byte(kDoorpath) = room->doorPath;
+ data.byte(kLastweapon) = -1;
+ al = room->b27;
+ push(ax);
+ al = room->b31;
+ ah = data.byte(kReallocation);
+ data.byte(kReallocation) = al;
+ dx = bx;
+ Common::String name = getFilename(*this);
+ engine->openFile(name);
+ cs.word(kHandle) = 1; //only one handle
+ flags._c = false;
+ readheader();
+ allocateload();
+ ds = ax;
+ data.word(kBackdrop) = ax;
+ dx = (0);
+ loadseg();
+ ds = data.word(kWorkspace);
+ dx = (0);
+ cx = 132*66;
+ al = 0;
+ fillspace();
+ loadseg();
+ sortoutmap();
+ allocateload();
+ data.word(kSetframes) = ax;
+ ds = ax;
+ dx = (0);
+ loadseg();
+ ds = data.word(kSetdat);
+ dx = 0;
+ cx = (64*128);
+ al = 255;
+ fillspace();
+ loadseg();
+ allocateload();
+ data.word(kReel1) = ax;
+ ds = ax;
+ dx = 0;
+ loadseg();
+ allocateload();
+ data.word(kReel2) = ax;
+ ds = ax;
+ dx = 0;
+ loadseg();
+ allocateload();
+ data.word(kReel3) = ax;
+ ds = ax;
+ dx = 0;
+ loadseg();
+ allocateload();
+ data.word(kReels) = ax;
+ ds = ax;
+ dx = 0;
+ loadseg();
+ allocateload();
+ data.word(kPeople) = ax;
+ ds = ax;
+ dx = 0;
+ loadseg();
+ allocateload();
+ data.word(kSetdesc) = ax;
+ ds = ax;
+ dx = 0;
+ loadseg();
+ allocateload();
+ data.word(kBlockdesc) = ax;
+ ds = ax;
+ dx = 0;
+ loadseg();
+ allocateload();
+ data.word(kRoomdesc) = ax;
+ ds = ax;
+ dx = 0;
+ loadseg();
+ allocateload();
+ data.word(kFreeframes) = ax;
+ ds = ax;
+ dx = 0;
+ loadseg();
+ ds = data.word(kFreedat);
+ dx = 0;
+ cx = (16*80);
+ al = 255;
+ fillspace();
+ loadseg();
+ allocateload();
+ data.word(kFreedesc) = ax;
+ ds = ax;
+ dx = (0);
+ loadseg();
+ closefile();
+ findroominloc();
+ deletetaken();
+ setallchanges();
+ autoappear();
+ al = data.byte(kNewlocation);
+ getroomdata();
+ data.byte(kLastweapon) = -1;
+ data.byte(kMandead) = 0;
+ data.word(kLookcounter) = 160;
+ data.byte(kNewlocation) = 255;
+ data.byte(kLinepointer) = 254;
+ ax = pop();
+ if (al != 255) {
+ data.byte(kManspath) = al;
+ push(bx);
+ autosetwalk();
+ bx = pop();
}
-
-//notblankshow:
- if ((effectsFlag & 128) == 0) {
- di += ds.byte(si+4);
- bx += ds.byte(si+5);
+ findxyfrompath();
+}
+
+void DreamGenContext::fillspace() {
+ memset(ds.ptr(dx, cx), al, cx);
+}
+
+void DreamGenContext::dealwithspecial(uint8 firstParam, uint8 secondParam) {
+ uint8 type = firstParam - 220;
+ if (type == 0) {
+ placesetobject(secondParam);
+ data.byte(kHavedoneobs) = 1;
+ } else if (type == 1) {
+ removesetobject(secondParam);
+ data.byte(kHavedoneobs) = 1;
+ } else if (type == 2) {
+ al = secondParam;
+ placefreeobject();
+ data.byte(kHavedoneobs) = 1;
+ } else if (type == 3) {
+ al = secondParam;
+ removefreeobject();
+ data.byte(kHavedoneobs) = 1;
+ } else if (type == 4) {
+ switchryanoff();
+ } else if (type == 5) {
+ data.byte(kTurntoface) = secondParam;
+ data.byte(kFacing) = secondParam;
+ switchryanon();
+ } else if (type == 6) {
+ data.byte(kNewlocation) = secondParam;
+ } else {
+ movemap(secondParam);
}
-//skipoffsets:
- cx = ds.word(si+0);
- uint8 width = cl;
- uint8 height = ch;
- uint16 written = cx;
- si = ds.word(si+2) + 2080;
-
- if (effectsFlag) {
- if (effectsFlag & 128) { //centred
- di -= width / 2;
- bx -= height / 2;
- }
- if (effectsFlag & 64) { //diffdest
- frameoutfx(es.ptr(0, dx * height), ds.ptr(si, width * height), dx, width, height, di, bx);
- return written;
- }
- if (effectsFlag & 8) { //printlist
- push(ax);
- ax = di - data.word(kMapadx);
- push(bx);
- bx -= data.word(kMapady);
- ah = bl;
- bx = pop();
- //addtoprintlist(); // NB: Commented in the original asm
- ax = pop();
- }
- if (effectsFlag & 4) { //flippedx
- es = data.word(kWorkspace);
- frameoutfx(es.ptr(0, 320 * height), ds.ptr(si, width * height), 320, width, height, di, bx);
- return written;
- }
- if (effectsFlag & 2) { //nomask
- es = data.word(kWorkspace);
- frameoutnm(es.ptr(0, 320 * height), ds.ptr(si, width * height), 320, width, height, di, bx);
- return written;
- }
- if (effectsFlag & 32) {
- es = data.word(kWorkspace);
- frameoutbh(es.ptr(0, 320 * height), ds.ptr(si, width * height), 320, width, height, di, bx);
- return written;
- }
+}
+
+void DreamGenContext::plotreel() {
+ Reel *reel = getreelstart();
+ while (true) {
+ if (reel->x < 220)
+ break;
+ if (reel->x == 255)
+ break;
+ dealwithspecial(reel->x, reel->y);
+ ++data.word(kReelpointer);
+ reel += 8;
}
-//noeffects:
- es = data.word(kWorkspace);
- frameoutv(es.ptr(0, 65536), ds.ptr(si, width * height), 320, width, height, di, bx);
- return written;
-}
-
-void DreamGenContext::showframe() {
- cx = showframeCPP(es, ds, di, bx, al, ah);
-}
-
-void DreamGenContext::printsprites() {
- for (size_t priority = 0; priority < 7; ++priority) {
- Sprite *sprites = spritetable();
- for (size_t j = 0; j < 16; ++j) {
- const Sprite &sprite = sprites[j];
- if (READ_LE_UINT16(&sprite.updateCallback) == 0x0ffff)
- continue;
- if (priority != sprite.priority)
- continue;
- if (sprite.hidden == 1)
- continue;
- printasprite(&sprite);
- }
+
+ for (size_t i = 0; i < 8; ++i) {
+ if (reel->frame() != 0xffff)
+ showreelframe(reel);
+ ++reel;
}
+ soundonreels();
}
-void DreamGenContext::printasprite(const Sprite* sprite) {
- push(es);
- push(bx);
- ds = READ_LE_UINT16(&sprite->w6);
- ax = sprite->y;
- if (al >= 220) {
- bx = data.word(kMapady) - (256 - al);
+void DreamGenContext::crosshair() {
+ uint8 frame;
+ if ((data.byte(kCommandtype) != 3) && (data.byte(kCommandtype) < 10)) {
+ frame = 9;
} else {
- bx = ax + data.word(kMapady);
+ frame = 29;
}
-
- ax = sprite->x;
- if (al >= 220) {
- di = data.word(kMapadx) - (256 - al);
+ const Frame *src = (const Frame *)segRef(data.word(kIcons1)).ptr(0, 0);
+ showframe(src, kZoomx + 24, kZoomy + 19, frame, 0);
+}
+
+void DreamGenContext::deltextline() {
+ uint16 x = data.word(kTextaddressx);
+ uint16 y = data.word(kTextaddressy);
+ if (data.byte(kForeignrelease) != 0)
+ y -= 3;
+ multiput(segRef(data.word(kBuffers)).ptr(kTextunder, 0), x, y, kUndertextsizex, kUndertextsizey);
+}
+
+void DreamGenContext::commandonly() {
+ commandonly(al);
+}
+
+void DreamGenContext::commandonly(uint8 command) {
+ deltextline();
+ uint16 index = command * 2;
+ uint16 offset = kTextstart + segRef(data.word(kCommandtext)).word(index);
+ uint16 y = data.word(kTextaddressy);
+ const uint8 *string = segRef(data.word(kCommandtext)).ptr(offset, 0);
+ printdirect(&string, data.word(kTextaddressx), &y, data.byte(kTextlen), (bool)(data.byte(kTextlen) & 1));
+ data.byte(kNewtextline) = 1;
+}
+
+void DreamGenContext::checkifperson() {
+ flags._z = not checkifperson(al, ah);
+}
+
+bool DreamGenContext::checkifperson(uint8 x, uint8 y) {
+ People *people = (People *)segRef(data.word(kBuffers)).ptr(kPeoplelist, 0);
+
+ for (size_t i = 0; i < 12; ++i, ++people) {
+ if (people->b4 == 255)
+ continue;
+ data.word(kReelpointer) = people->w0();
+ Reel *reel = getreelstart();
+ if (reel->frame() == 0xffff)
+ ++reel;
+ const Frame *frame = getreelframeax(reel->frame());
+ uint8 xmin = reel->x + frame->x;
+ uint8 ymin = reel->y + frame->y;
+ uint8 xmax = xmin + frame->width;
+ uint8 ymax = ymin + frame->height;
+ if (x < xmin)
+ continue;
+ if (y < ymin)
+ continue;
+ if (x >= xmax)
+ continue;
+ if (y >= ymax)
+ continue;
+ data.word(kPersondata) = people->w2();
+ obname(people->b4, 5);
+ return true;
+ }
+ return false;
+}
+
+void DreamGenContext::checkiffree() {
+ flags._z = not checkiffree(al, ah);
+}
+
+bool DreamGenContext::checkiffree(uint8 x, uint8 y) {
+ const ObjPos *freeList = (const ObjPos *)segRef(data.word(kBuffers)).ptr(kFreelist, 80 * sizeof(ObjPos));
+ for (size_t i = 0; i < 80; ++i) {
+ const ObjPos *objPos = freeList + 79 - i;
+ if (objPos->index == 0xff)
+ continue;
+ if (x < objPos->xMin)
+ continue;
+ if (x >= objPos->xMax)
+ continue;
+ if (y < objPos->yMin)
+ continue;
+ if (y >= objPos->yMax)
+ continue;
+ obname(objPos->index, 2);
+ return true;
+ }
+ return false;
+}
+
+const uint8 *DreamGenContext::findobname(uint8 type, uint8 index) {
+ if (type == 5) {
+ uint16 i = 64 * 2 * (index & 127);
+ uint16 offset = segRef(data.word(kPeople)).word(kPersontxtdat + i) + kPersontext;
+ return segRef(data.word(kPeople)).ptr(offset, 0);
+ } else if (type == 4) {
+ uint16 offset = segRef(data.word(kExtras)).word(kExtextdat + index * 2) + kExtext;
+ return segRef(data.word(kExtras)).ptr(offset, 0);
+ } else if (type == 2) {
+ uint16 offset = segRef(data.word(kFreedesc)).word(kFreetextdat + index * 2) + kFreetext;
+ return segRef(data.word(kFreedesc)).ptr(offset, 0);
+ } else if (type == 1) {
+ uint16 offset = segRef(data.word(kSetdesc)).word(kSettextdat + index * 2) + kSettext;
+ return segRef(data.word(kSetdesc)).ptr(offset, 0);
} else {
- di = ax + data.word(kMapadx);
+ uint16 offset = segRef(data.word(kBlockdesc)).word(kBlocktextdat + index * 2) + kBlocktext;
+ return segRef(data.word(kBlockdesc)).ptr(offset, 0);
}
-
- ax = sprite->b15;
- if (sprite->b29 != 0)
- ah = 8;
- showframe();
-
- bx = pop();
- es = pop();
}
-void DreamGenContext::eraseoldobs() {
- if (data.byte(kNewobs) == 0)
- return;
+void DreamGenContext::copyname() {
+ copyname(ah, al, cs.ptr(di, 0));
+}
- Sprite *sprites = spritetable();
- for (size_t i=0; i<16; ++i) {
- Sprite &sprite = sprites[i];
- if (READ_LE_UINT16(&sprite.obj_data) != 0xffff) {
- memset(&sprite, 0xff, sizeof(Sprite));
- }
+void DreamGenContext::copyname(uint8 type, uint8 index, uint8 *dst) {
+ const uint8 *src = findobname(type, index);
+ size_t i;
+ for (i = 0; i < 28; ++i) {
+ char c = src[i];
+ if (c == ':')
+ break;
+ if (c == 0)
+ break;
+ dst[i] = c;
}
+ dst[i] = 0;
}
-void DreamGenContext::clearsprites() {
- memset(spritetable(), 0xff, sizeof(Sprite)*16);
+void DreamGenContext::commandwithob() {
+ commandwithob(al, bh, bl);
}
-Sprite* DreamGenContext::makesprite(uint8 x, uint8 y, uint16 updateCallback, uint16 somethingInDx, uint16 somethingInDi) {
- Sprite *sprite = spritetable();
- while (sprite->b15 != 0xff) { // NB: No boundchecking in the original code either
- ++sprite;
+void DreamGenContext::commandwithob(uint8 command, uint8 type, uint8 index) {
+ uint8 commandLine[64] = "OBJECT NAME ONE ";
+ deltextline();
+ uint16 commandText = kTextstart + segRef(data.word(kCommandtext)).word(command * 2);
+ uint8 textLen = data.byte(kTextlen);
+ {
+ uint16 y = data.word(kTextaddressy);
+ const uint8 *string = segRef(data.word(kCommandtext)).ptr(commandText, 0);
+ printdirect(&string, data.word(kTextaddressx), &y, textLen, (bool)(textLen & 1));
}
+ copyname(type, index, commandLine);
+ uint16 x = data.word(kLastxpos);
+ if (command != 0)
+ x += 5;
+ {
+ uint16 y = data.word(kTextaddressy);
+ const uint8 *string = commandLine;
+ printdirect(&string, x, &y, textLen, (bool)(textLen & 1));
+ }
+ data.byte(kNewtextline) = 1;
+}
- WRITE_LE_UINT16(&sprite->updateCallback, updateCallback);
- sprite->x = x;
- sprite->y = y;
- WRITE_LE_UINT16(&sprite->w6, somethingInDx);
- WRITE_LE_UINT16(&sprite->w8, somethingInDi);
- sprite->w2 = 0xffff;
- sprite->b15 = 0;
- sprite->delay = 0;
- return sprite;
+void DreamGenContext::showpanel() {
+ Frame *frame = (Frame *)segRef(data.word(kIcons1)).ptr(0, sizeof(Frame));
+ showframe(frame, 72, 0, 19, 0);
+ showframe(frame, 192, 0, 19, 0);
}
-void DreamGenContext::makesprite() { // NB: returns new sprite in es:bx
- Sprite *sprite = makesprite(si & 0xff, si >> 8, cx, dx, di);
+void DreamGenContext::blocknametext() {
+ commandwithob(0, data.byte(kCommandtype), data.byte(kCommand));
+}
- // Recover es:bx from sprite
- es = data.word(kBuffers);
- bx = kSpritetable;
- Sprite *sprites = (Sprite*)es.ptr(bx, sizeof(Sprite)*16);
- bx += sizeof(Sprite)*(sprite-sprites);
- //
+void DreamGenContext::personnametext() {
+ commandwithob(2, data.byte(kCommandtype), data.byte(kCommand) & 127);
}
-void DreamGenContext::spriteupdate() {
- Sprite *sprites = spritetable();
- sprites[0].hidden = data.byte(kRyanon);
-
- Sprite *sprite = sprites;
- for (size_t i=0; i<16; ++i) {
- uint16 updateCallback = READ_LE_UINT16(&sprite->updateCallback);
- if (updateCallback != 0xffff) {
- sprite->w24 = sprite->w2;
- if (updateCallback == addr_mainman) // NB : Let's consider the callback as an enum while more code is not ported to C++
- mainmanCPP(sprite);
- else {
- assert(updateCallback == addr_backobject);
- backobject(sprite);
- }
- }
-
- if (data.byte(kNowinnewroom) == 1)
- break;
- ++sprite;
- }
+void DreamGenContext::walktotext() {
+ commandwithob(3, data.byte(kCommandtype), data.byte(kCommand));
}
-void DreamGenContext::initman() {
- Sprite *sprite = makesprite(data.byte(kRyanx), data.byte(kRyany), addr_mainman, data.word(kMainsprites), 0);
- sprite->priority = 4;
- sprite->b22 = 0;
- sprite->b29 = 0;
-
- // Recover es:bx from sprite
- es = data.word(kBuffers);
- bx = kSpritetable;
- Sprite *sprites = (Sprite*)es.ptr(bx, sizeof(Sprite)*16);
- bx += 32*(sprite-sprites);
- //
-}
-
-void DreamGenContext::mainmanCPP(Sprite* sprite) {
- push(es);
- push(ds);
-
- // Recover es:bx from sprite
- es = data.word(kBuffers);
- bx = kSpritetable;
- Sprite *sprites = (Sprite*)es.ptr(bx, sizeof(Sprite)*16);
- bx += 32*(sprite-sprites);
- //
-
- if (data.byte(kResetmanxy) == 1) {
- data.byte(kResetmanxy) = 0;
- sprite->x = data.byte(kRyanx);
- sprite->y = data.byte(kRyany);
- sprite->b29 = 0;
- }
- --sprite->b22;
- if (sprite->b22 != 0xff) {
- ds = pop();
- es = pop();
- return;
- }
- sprite->b22 = 0;
- if (data.byte(kTurntoface) != data.byte(kFacing)) {
- aboutturn(sprite);
- } else {
- if ((data.byte(kTurndirection) != 0) && (data.byte(kLinepointer) == 254)) {
- data.byte(kReasseschanges) = 1;
- if (data.byte(kFacing) == data.byte(kLeavedirection))
- checkforexit();
+void DreamGenContext::findormake() {
+ uint8 b0 = al;
+ uint8 b2 = cl;
+ uint8 b3 = ch;
+ findormake(b0, b2, b3);
+}
+
+void DreamGenContext::findormake(uint8 index, uint8 value, uint8 type) {
+ Change *change = (Change *)segRef(data.word(kBuffers)).ptr(kListofchanges, sizeof(Change));
+ while (true) {
+ if (change->index == 0xff) {
+ change->index = index;
+ change->location = data.byte(kReallocation);
+ change->value = value;
+ change->type = type;
+ return;
}
- data.byte(kTurndirection) = 0;
- if (data.byte(kLinepointer) == 254) {
- sprite->b29 = 0;
- } else {
- ++sprite->b29;
- if (sprite->b29 == 11)
- sprite->b29 = 1;
- walking();
- if (data.byte(kLinepointer) != 254) {
- if ((data.byte(kFacing) & 1) == 0)
- walking();
- else if ((sprite->b29 != 2) && (sprite->b29 != 7))
- walking();
- }
- if (data.byte(kLinepointer) == 254) {
- if (data.byte(kTurntoface) == data.byte(kFacing)) {
- data.byte(kReasseschanges) = 1;
- if (data.byte(kFacing) == data.byte(kLeavedirection))
- checkforexit();
- }
- }
+ if ((index == change->index) && (data.byte(kReallocation) == change->location) && (type == change->type)) {
+ change->value = value;
+ return;
}
+ ++change;
}
- static const uint8 facelist[] = { 0,60,33,71,11,82,22,93 };
- sprite->b15 = sprite->b29 + facelist[data.byte(kFacing)];
- data.byte(kRyanx) = sprite->x;
- data.byte(kRyany) = sprite->y;
-
- ds = pop();
- es = pop();
}
-void DreamGenContext::walking() {
- Sprite *sprite = (Sprite*)es.ptr(bx, sizeof(Sprite));
-
- uint8 comp;
- if (data.byte(kLinedirection) != 0) {
- --data.byte(kLinepointer);
- comp = 200;
- } else {
- ++data.byte(kLinepointer);
- comp = data.byte(kLinelength);
- }
- if (data.byte(kLinepointer) < comp) {
- sprite->x = data.byte(kLinedata + data.byte(kLinepointer) * 2 + 0);
- sprite->y = data.byte(kLinedata + data.byte(kLinepointer) * 2 + 1);
- return;
- }
-
- data.byte(kLinepointer) = 254;
- data.byte(kManspath) = data.byte(kDestination);
- if (data.byte(kDestination) == data.byte(kFinaldest)) {
- facerightway();
- return;
- }
- data.byte(kDestination) = data.byte(kFinaldest);
- push(es);
- push(bx);
- autosetwalk();
- bx = pop();
- es = pop();
-}
-
-void DreamGenContext::aboutturn(Sprite* sprite) {
- if (data.byte(kTurndirection) == 1)
- goto incdir;
- else if ((int8)data.byte(kTurndirection) == -1)
- goto decdir;
- else {
- if (data.byte(kFacing) < data.byte(kTurntoface)) {
- uint8 delta = data.byte(kTurntoface) - data.byte(kFacing);
- if (delta >= 4)
- goto decdir;
- else
- goto incdir;
- } else {
- uint8 delta = data.byte(kFacing) - data.byte(kTurntoface);
- if (delta >= 4)
- goto incdir;
- else
- goto decdir;
- }
+void DreamGenContext::setallchanges() {
+ Change *change = (Change *)segRef(data.word(kBuffers)).ptr(kListofchanges, sizeof(Change));
+ while (change->index != 0xff) {
+ if (change->location == data.byte(kReallocation))
+ dochange(change->index, change->value, change->type);
+ ++change;
}
-incdir:
- data.byte(kTurndirection) = 1;
- data.byte(kFacing) = (data.byte(kFacing) + 1) & 7;
- sprite->b29 = 0;
- return;
-decdir:
- data.byte(kTurndirection) = -1;
- data.byte(kFacing) = (data.byte(kFacing) - 1) & 7;
- sprite->b29 = 0;
-}
-
-void DreamGenContext::backobject(Sprite* sprite) {
- push(es);
- push(ds);
-
- // Recover es:bx from sprite
- es = data.word(kBuffers);
- bx = kSpritetable;
- Sprite *sprites = (Sprite*)es.ptr(bx, sizeof(Sprite)*16);
- bx += 32*(sprite-sprites);
- //
+}
- ds = data.word(kSetdat);
- di = READ_LE_UINT16(&sprite->obj_data);
- ObjData* objData = (ObjData*)ds.ptr(di, 0);
+DynObject *DreamGenContext::getfreead(uint8 index) {
+ return (DynObject *)segRef(data.word(kFreedat)).ptr(0, 0) + index;
+}
- if (sprite->delay != 0) {
- --sprite->delay;
- ds = pop();
- es = pop();
- return;
- }
+DynObject *DreamGenContext::getexad(uint8 index) {
+ return (DynObject *)segRef(data.word(kExtras)).ptr(kExdata, 0) + index;
+}
- sprite->delay = objData->delay;
- if (objData->type == 6)
- widedoor(sprite, objData);
- else if (objData->type == 5)
- random(sprite, objData);
- else if (objData->type == 4)
- lockeddoorway();
- else if (objData->type == 3)
- liftsprite(sprite, objData);
- else if (objData->type == 2)
- doorway(sprite, objData);
- else if (objData->type == 1)
- constant(sprite, objData);
+DynObject *DreamGenContext::geteitheradCPP() {
+ if (data.byte(kObjecttype) == 4)
+ return getexad(data.byte(kItemframe));
else
- steady(sprite, objData);
+ return getfreead(data.byte(kItemframe));
+}
- ds = pop();
- es = pop();
+SetObject *DreamGenContext::getsetad(uint8 index) {
+ return (SetObject *)segRef(data.word(kSetdat)).ptr(0, 0) + index;
}
-void DreamGenContext::constant(Sprite* sprite, ObjData* objData) {
- ++sprite->frame;
- if (objData->b18[sprite->frame] == 255) {
- sprite->frame = 0;
- }
- uint8 b18 = objData->b18[sprite->frame];
- objData->b17 = b18;
- sprite->b15 = b18;
+void DreamGenContext::dochange() {
+ dochange(al, cl, ch);
}
-void DreamGenContext::random(Sprite* sprite, ObjData* objData) {
- randomnum1();
- uint16 r = ax;
- sprite->b15 = objData->b18[r&7];
+void DreamGenContext::dochange(uint8 index, uint8 value, uint8 type) {
+ if (type == 0) { //object
+ getsetad(index)->b58[0] = value;
+ } else if (type == 1) { //freeobject
+ DynObject *freeObject = getfreead(index);
+ if (freeObject->b2 == 0xff)
+ freeObject->b2 = value;
+ } else { //path
+ bx = kPathdata + (type - 100) * 144 + index * 8;
+ es = data.word(kReels);
+ es.byte(bx+6) = value;
+ }
}
-void DreamGenContext::doorway(Sprite* sprite, ObjData* objData) {
- data.byte(kDoorcheck1) = -24;
- data.byte(kDoorcheck2) = 10;
- data.byte(kDoorcheck3) = -30;
- data.byte(kDoorcheck4) = 10;
- dodoor(sprite, objData);
+void DreamGenContext::deletetaken() {
+ const DynObject *extraObjects = (const DynObject *)segRef(data.word(kExtras)).ptr(kExdata, 0);
+ DynObject *freeObjects = (DynObject *)segRef(data.word(kFreedat)).ptr(0, 0);
+ for(size_t i = 0; i < kNumexobjects; ++i) {
+ uint8 location = extraObjects[i].location;
+ if (location == data.byte(kReallocation)) {
+ uint8 index = extraObjects[i].index;
+ freeObjects[index].b2 = 254;
+ }
+ }
}
-void DreamGenContext::widedoor(Sprite* sprite, ObjData* objData) {
- data.byte(kDoorcheck1) = -24;
- data.byte(kDoorcheck2) = 24;
- data.byte(kDoorcheck3) = -30;
- data.byte(kDoorcheck4) = 24;
- dodoor(sprite, objData);
+void DreamGenContext::placesetobject() {
+ placesetobject(al);
}
-void DreamGenContext::dodoor() {
- Sprite *sprite = (Sprite*)es.ptr(bx, sizeof(Sprite));
- ObjData *objData = (ObjData*)ds.ptr(di, 0);
- dodoor(sprite, objData);
+void DreamGenContext::placesetobject(uint8 index) {
+ findormake(index, 0, 0);
+ getsetad(index)->b58[0] = 0;
}
-void DreamGenContext::dodoor(Sprite* sprite, ObjData* objData) {
- uint8 ryanx = data.byte(kRyanx);
- uint8 ryany = data.byte(kRyany);
- int8 deltax = ryanx - sprite->x;
- int8 deltay = ryany - sprite->y;
- if (ryanx < sprite->x) {
- if (deltax < (int8)data.byte(kDoorcheck1))
- goto shutdoor;
- } else {
- if (deltax >= data.byte(kDoorcheck2))
- goto shutdoor;
- }
- if (ryany < sprite->y) {
- if (deltay < (int8)data.byte(kDoorcheck3))
- goto shutdoor;
- } else {
- if (deltay >= data.byte(kDoorcheck4))
- goto shutdoor;
- }
-//opendoor:
- if ((data.byte(kThroughdoor) == 1) && (sprite->frame == 0))
- sprite->frame = 6;
-
- ++sprite->frame;
- if (sprite->frame == 1) { //doorsound2
- if (data.byte(kReallocation) == 5) //hoteldoor2
- al = 13;
- else
- al = 0;
- playchannel1();
- }
- if (objData->b18[sprite->frame] == 255) {
- --sprite->frame;
- }
- sprite->b15 = objData->b17 = objData->b18[sprite->frame];
- data.byte(kThroughdoor) = 1;
- return;
-shutdoor:
- if (sprite->frame == 5) { //doorsound1;
- if (data.byte(kReallocation) == 5) //hoteldoor1
- al = 13;
- else
- al = 1;
- playchannel1();
- }
- if (sprite->frame != 0) {
- --sprite->frame;
- }
- sprite->b15 = objData->b17 = objData->b18[sprite->frame];
- if (sprite->frame == 5) //nearly
- data.byte(kThroughdoor) = 0;
+void DreamGenContext::removesetobject() {
+ removesetobject(al);
}
-void DreamGenContext::steady(Sprite* sprite, ObjData* objData) {
- uint8 b18 = objData->b18[0];
- objData->b17 = b18;
- sprite->b15 = b18;
+void DreamGenContext::removesetobject(uint8 index) {
+ findormake(index, 0xff, 0);
+ getsetad(index)->b58[0] = 0xff;
}
-void DreamGenContext::turnpathonCPP(uint8 param) {
- al = param;
- push(es);
- push(bx);
- turnpathon();
- bx = pop();
- es = pop();
+void DreamGenContext::finishedwalking() {
+ flags._z = finishedwalkingCPP();
}
-void DreamGenContext::turnpathoffCPP(uint8 param) {
- al = param;
- push(es);
- push(bx);
- turnpathoff();
- bx = pop();
- es = pop();
+bool DreamGenContext::finishedwalkingCPP() {
+ return (data.byte(kLinepointer) == 254) && (data.byte(kFacing) == data.byte(kTurntoface));
}
-void DreamGenContext::liftsprite() {
- Sprite *sprite = (Sprite*)es.ptr(bx, sizeof(Sprite));
- ObjData *objData = (ObjData*)ds.ptr(di, 0);
- liftsprite(sprite, objData);
+void DreamGenContext::getflagunderp() {
+ uint8 flag, flagEx;
+ getflagunderp(&flag, &flagEx);
+ cl = flag;
+ ch = flagEx;
}
-void DreamGenContext::liftsprite(Sprite* sprite, ObjData* objData) {
- uint8 liftFlag = data.byte(kLiftflag);
- if (liftFlag == 0) { //liftclosed
- turnpathoffCPP(data.byte(kLiftpath));
+void DreamGenContext::getflagunderp(uint8 *flag, uint8 *flagEx) {
+ uint8 type, flagX, flagY;
+ checkone(data.word(kMousex) - data.word(kMapadx), data.word(kMousey) - data.word(kMapady), flag, flagEx, &type, &flagX, &flagY);
+ cl = data.byte(kLastflag) = *flag;
+ ch = data.byte(kLastflagex) = *flagEx;
+}
- if (data.byte(kCounttoopen) != 0) {
- _dec(data.byte(kCounttoopen));
- if (data.byte(kCounttoopen) == 0)
- data.byte(kLiftflag) = 3;
+void DreamGenContext::walkandexamine() {
+ if (! finishedwalkingCPP())
+ return;
+ data.byte(kCommandtype) = data.byte(kWalkexamtype);
+ data.byte(kCommand) = data.byte(kWalkexamnum);
+ data.byte(kWalkandexam) = 0;
+ if (data.byte(kCommandtype) != 5)
+ examineob();
+}
+
+void DreamGenContext::obname() {
+ obname(al, ah);
+}
+
+void DreamGenContext::obname(uint8 command, uint8 commandType) {
+ if (data.byte(kReasseschanges) == 0) {
+ if ((commandType == data.byte(kCommandtype)) && (command == data.byte(kCommand))) {
+ if (data.byte(kWalkandexam) == 1) {
+ walkandexamine();
+ return;
+ } else if (data.word(kMousebutton) == 0)
+ return;
+ else if ((data.byte(kCommandtype) == 3) && (data.byte(kLastflag) < 2))
+ return;
+ else if ((data.byte(kManspath) != data.byte(kPointerspath)) || (data.byte(kCommandtype) == 3)) {
+ setwalk();
+ data.byte(kReasseschanges) = 1;
+ return;
+ } else if (! finishedwalkingCPP())
+ return;
+ else if (data.byte(kCommandtype) == 5) {
+ if (data.word(kWatchingtime) == 0)
+ talk();
+ return;
+ } else {
+ if (data.word(kWatchingtime) == 0)
+ examineob();
+ return;
+ }
}
- sprite->frame = 0;
- sprite->b15 = objData->b17 = objData->b18[sprite->frame];
- }
- else if (liftFlag == 1) { //liftopen
- turnpathonCPP(data.byte(kLiftpath));
+ } else
+ data.byte(kReasseschanges) = 0;
- if (data.byte(kCounttoclose) != 0) {
- _dec(data.byte(kCounttoclose));
- if (data.byte(kCounttoclose) == 0)
- data.byte(kLiftflag) = 2;
- }
- sprite->frame = 12;
- sprite->b15 = objData->b17 = objData->b18[sprite->frame];
- }
- else if (liftFlag == 3) { //openlift
- if (sprite->frame == 12) {
- data.byte(kLiftflag) = 1;
+ data.byte(kCommand) = command;
+ data.byte(kCommandtype) = commandType;
+ if ((data.byte(kLinepointer) != 254) || (data.word(kWatchingtime) != 0) || (data.byte(kFacing) != data.byte(kTurntoface))) {
+ blocknametext();
+ return;
+ } else if (data.byte(kCommandtype) != 3) {
+ if (data.byte(kManspath) != data.byte(kPointerspath)) {
+ walktotext();
return;
- }
- ++sprite->frame;
- if (sprite->frame == 1) {
- al = 2;
- liftnoise();
- }
- sprite->b15 = objData->b17 = objData->b18[sprite->frame];
- } else { //closeLift
- assert(liftFlag == 2);
- if (sprite->frame == 0) {
- data.byte(kLiftflag) = 0;
+ } else if (data.byte(kCommandtype) == 3) {
+ blocknametext();
+ return;
+ } else if (data.byte(kCommandtype) == 5) {
+ personnametext();
+ return;
+ } else {
+ examineobtext();
return;
}
- --sprite->frame;
- if (sprite->frame == 11) {
- al = 3;
- liftnoise();
+ }
+ if (data.byte(kManspath) == data.byte(kPointerspath)) {
+ uint8 flag, flagEx, type, flagX, flagY;
+ checkone(data.byte(kRyanx) + 12, data.byte(kRyany) + 12, &flag, &flagEx, &type, &flagX, &flagY);
+ if (flag < 2) {
+ blocknametext();
+ return;
}
- sprite->b15 = objData->b17 = objData->b18[sprite->frame];
+ }
+
+ getflagunderp();
+ if (data.byte(kLastflag) < 2) {
+ blocknametext();
+ return;
+ } else if (data.byte(kLastflag) >= 128) {
+ blocknametext();
+ return;
+ } else {
+ walktotext();
+ return;
}
}
-void DreamGenContext::modifychar() {
- al = engine->modifyChar(al);
+void DreamGenContext::delpointer() {
+ if (data.word(kOldpointerx) == 0xffff)
+ return;
+ data.word(kDelherex) = data.word(kOldpointerx);
+ data.word(kDelherey) = data.word(kOldpointery);
+ data.byte(kDelxs) = data.byte(kPointerxs);
+ data.byte(kDelys) = data.byte(kPointerys);
+ multiput(segRef(data.word(kBuffers)).ptr(kPointerback, 0), data.word(kDelherex), data.word(kDelherey), data.byte(kPointerxs), data.byte(kPointerys));
}
-void DreamGenContext::lockmon() {
- // Pressing space pauses text output in the monitor. We use the "hard"
- // key because calling readkey() drains characters from the input
- // buffer, we we want the user to be able to type ahead while the text
- // is being printed.
- if (data.byte(kLasthardkey) == 57) {
- // Clear the keyboard buffer. Otherwise the space that caused
- // the pause will be read immediately unpause the game.
- do {
- readkey();
- } while (data.byte(kCurrentkey) != 0);
+void DreamGenContext::showblink() {
+ if (data.byte(kManisoffscreen) == 1)
+ return;
+ ++data.byte(kBlinkcount);
+ if (data.byte(kShadeson) != 0)
+ return;
+ if (data.byte(kReallocation) >= 50) // eyesshut
+ return;
+ if (data.byte(kBlinkcount) != 3)
+ return;
+ data.byte(kBlinkcount) = 0;
+ uint8 blinkFrame = data.byte(kBlinkframe);
+ ++blinkFrame; // Implicit %256
+ data.byte(kBlinkframe) = blinkFrame;
+ if (blinkFrame > 6)
+ blinkFrame = 6;
+ static const uint8 blinkTab[] = { 16,18,18,17,16,16,16 };
+ uint8 width, height;
+ showframe((Frame *)segRef(data.word(kIcons1)).ptr(0, 0), 44, 32, blinkTab[blinkFrame], 0, &width, &height);
+}
+
+void DreamGenContext::dumpblink() {
+ if (data.byte(kShadeson) != 0)
+ return;
+ if (data.byte(kBlinkcount) != 0)
+ return;
+ if (data.byte(kBlinkframe) >= 6)
+ return;
+ multidump(44, 32, 16, 12);
+}
- locklighton();
- while (!engine->shouldQuit()) {
- engine->waitForVSync();
- readkey();
- if (data.byte(kCurrentkey) == ' ')
- break;
+void DreamGenContext::dumppointer() {
+ dumpblink();
+ multidump(data.word(kDelherex), data.word(kDelherey), data.byte(kDelxs), data.byte(kDelys));
+ if ((data.word(kOldpointerx) != data.word(kDelherex)) || (data.word(kOldpointery) != data.word(kDelherey)))
+ multidump(data.word(kOldpointerx), data.word(kOldpointery), data.byte(kPointerxs), data.byte(kPointerys));
+}
+
+void DreamGenContext::checkcoords() {
+ checkcoords((const RectWithCallback *)cs.ptr(bx, 0));
+}
+
+void DreamGenContext::checkcoords(const RectWithCallback *rectWithCallbacks) {
+ if (data.byte(kNewlocation) != 0xff)
+ return;
+
+ const RectWithCallback *rectWithCallback = rectWithCallbacks;
+ while (rectWithCallback->xMin() != 0xffff) {
+ if (rectWithCallback->contains(data.word(kMousex), data.word(kMousey))) {
+ uint16 callback = rectWithCallback->callback();
+
+ // common
+ if(callback == addr_blank)
+ blank();
+ else if(callback == addr_getbackfromob)
+ getbackfromob();
+ else if(callback == addr_incryanpage)
+ incryanpage();
+ else if(callback == addr_getback1)
+ getback1();
+ else if(callback == addr_quitkey)
+ quitkey();
+ else if(callback == addr_dosreturn)
+ dosreturn();
+ else if(callback == addr_getbacktoops)
+ getbacktoops();
+ else if(callback == addr_selectslot)
+ selectslot();
+ // examlist
+ else if(callback == addr_useobject)
+ useobject();
+ else if(callback == addr_selectopenob)
+ selectopenob();
+ else if(callback == addr_setpickup)
+ setpickup();
+ else if(callback == addr_examinventory)
+ examinventory();
+ // invlist1
+ else if(callback == addr_dropobject)
+ dropobject();
+ else if(callback == addr_useopened)
+ useopened();
+ else if(callback == addr_setpickup)
+ setpickup();
+ else if(callback == addr_intoinv)
+ intoinv();
+ // withlist1
+ else if(callback == addr_selectob)
+ selectob();
+ // talklist
+ else if(callback == addr_moretalk)
+ moretalk();
+ // quitlist
+ // destlist
+ else if(callback == addr_nextdest)
+ nextdest();
+ else if(callback == addr_lastdest)
+ lastdest();
+ else if(callback == addr_lookatplace)
+ lookatplace();
+ else if(callback == addr_destselect)
+ destselect();
+ // keypadlist
+ else if(callback == addr_buttonone)
+ buttonone();
+ else if(callback == addr_buttontwo)
+ buttontwo();
+ else if(callback == addr_buttonthree)
+ buttonthree();
+ else if(callback == addr_buttonfour)
+ buttonfour();
+ else if(callback == addr_buttonfive)
+ buttonfive();
+ else if(callback == addr_buttonsix)
+ buttonsix();
+ else if(callback == addr_buttonseven)
+ buttonseven();
+ else if(callback == addr_buttoneight)
+ buttoneight();
+ else if(callback == addr_buttonnine)
+ buttonnine();
+ else if(callback == addr_buttonnought)
+ buttonnought();
+ else if(callback == addr_buttonenter)
+ buttonenter();
+ // menulist
+ // folderlist
+ else if(callback == addr_nextfolder)
+ nextfolder();
+ else if(callback == addr_lastfolder)
+ lastfolder();
+ // symbollist
+ else if(callback == addr_quitsymbol)
+ quitsymbol();
+ else if(callback == addr_settopleft)
+ settopleft();
+ else if(callback == addr_settopright)
+ settopright();
+ else if(callback == addr_setbotleft)
+ setbotleft();
+ else if(callback == addr_setbotright)
+ setbotright();
+ // diarylist
+ else if(callback == addr_diarykeyn)
+ diarykeyn();
+ else if(callback == addr_diarykeyp)
+ diarykeyp();
+ else if(callback == addr_quitkey)
+ quitkey();
+ // opslist
+ else if(callback == addr_getbackfromops)
+ getbackfromops();
+ else if(callback == addr_discops)
+ discops();
+ // discopslist
+ else if(callback == addr_loadgame)
+ loadgame();
+ else if(callback == addr_savegame)
+ savegame();
+ // mainlist, mainlist2
+ else if(callback == addr_look)
+ look();
+ else if(callback == addr_inventory)
+ inventory();
+ else if(callback == addr_zoomonoff)
+ zoomonoff();
+ else if(callback == addr_saveload)
+ saveload();
+ else if(callback == addr_madmanrun)
+ madmanrun();
+ else if(callback == addr_identifyob)
+ identifyob();
+ // decidelist
+ else if(callback == addr_newgame)
+ newgame();
+ else if(callback == addr_loadold)
+ loadold();
+ // loadlist
+ else if(callback == addr_actualload)
+ actualload();
+ // savelist
+ else if(callback == addr_actualsave)
+ actualsave();
+ else {
+ debug("__dispatch_call remaining in checkcoords! %d", (int)callback);
+ __dispatch_call(callback);
+ }
+ return;
}
- // Forget the last "hard" key, otherwise the space that caused
- // the unpausing will immediately re-pause the game.
- data.byte(kLasthardkey) = 0;
- locklightoff();
+ ++rectWithCallback;
}
}
-void DreamGenContext::cancelch0() {
- data.byte(kCh0repeat) = 0;
- data.word(kCh0blockstocopy) = 0;
- data.byte(kCh0playing) = 255;
- engine->stopSound(0);
+void DreamGenContext::showpointer() {
+ showblink();
+ const Frame *icons1 = ((const Frame *)segRef(data.word(kIcons1)).ptr(0, 0));
+ uint16 x = data.word(kMousex);
+ data.word(kOldpointerx) = data.word(kMousex);
+ uint16 y = data.word(kMousey);
+ data.word(kOldpointery) = data.word(kMousey);
+ if (data.byte(kPickup) == 1) {
+ const Frame *frames;
+ if (data.byte(kObjecttype) != 4)
+ frames = (const Frame *)segRef(data.word(kFreeframes)).ptr(0, 0);
+ else
+ frames = (const Frame *)segRef(data.word(kExtras)).ptr(0, 0);
+ const Frame *frame = frames + (3 * data.byte(kItemframe) + 1);
+ uint8 width = frame->width;
+ uint8 height = frame->height;
+ if (width < 12)
+ width = 12;
+ if (height < 12)
+ height = 12;
+ data.byte(kPointerxs) = width;
+ data.byte(kPointerys) = height;
+ data.word(kOldpointerx) -= width / 2;
+ data.word(kOldpointery) -= height / 2;
+ multiget(segRef(data.word(kBuffers)).ptr(kPointerback, 0), x - width / 2, y - height / 2, width, height);
+ showframe(frames, x, y, 3 * data.byte(kItemframe) + 1, 128);
+ showframe(icons1, x, y, 3, 128);
+ } else {
+ const Frame *frame = icons1 + (data.byte(kPointerframe) + 20);
+ uint8 width = frame->width;
+ uint8 height = frame->height;
+ if (width < 12)
+ width = 12;
+ if (height < 12)
+ height = 12;
+ data.byte(kPointerxs) = width;
+ data.byte(kPointerys) = height;
+ multiget(segRef(data.word(kBuffers)).ptr(kPointerback, 0), x, y, width, height);
+ showframe(icons1, x, y, data.byte(kPointerframe) + 20, 0);
+ }
}
-void DreamGenContext::cancelch1() {
- data.word(kCh1blockstocopy) = 0;
- data.byte(kCh1playing) = 255;
- engine->stopSound(1);
+void DreamGenContext::animpointer() {
+
+ if (data.byte(kPointermode) == 2) {
+ data.byte(kPointerframe) = 0;
+ if ((data.byte(kReallocation) == 14) && (data.byte(kCommandtype) == 211))
+ data.byte(kPointerframe) = 5;
+ return;
+ } else if (data.byte(kPointermode) == 3) {
+ if (data.byte(kPointerspeed) != 0) {
+ --data.byte(kPointerspeed);
+ } else {
+ data.byte(kPointerspeed) = 5;
+ ++data.byte(kPointercount);
+ if (data.byte(kPointercount) == 16)
+ data.byte(kPointercount) = 0;
+ }
+ static const uint8 flashMouseTab[] = { 1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2 };
+ data.byte(kPointerframe) = flashMouseTab[data.byte(kPointercount)];
+ return;
+ }
+ if (data.word(kWatchingtime) != 0) {
+ data.byte(kPointerframe) = 11;
+ return;
+ }
+ data.byte(kPointerframe) = 0;
+ if (data.byte(kInmaparea) == 0)
+ return;
+ if (data.byte(kPointerfirstpath) == 0)
+ return;
+ uint8 flag, flagEx;
+ getflagunderp(&flag, &flagEx);
+ if (flag < 2)
+ return;
+ if (flag >= 128)
+ return;
+ if (flag & 4) {
+ data.byte(kPointerframe) = 3;
+ return;
+ }
+ if (flag & 16) {
+ data.byte(kPointerframe) = 4;
+ return;
+ }
+ if (flag & 2) {
+ data.byte(kPointerframe) = 5;
+ return;
+ }
+ if (flag & 8) {
+ data.byte(kPointerframe) = 6;
+ return;
+ }
+ data.byte(kPointerframe) = 8;
}
+bool DreamGenContext::isCD() {
+ // The original sources has two codepaths depending if the game is 'if cd' or not
+ // This is a hack to guess which version to use with the assumption that if we have a cd version
+ // we managed to load the speech. At least it is isolated in this function and can be changed.
+ // Maybe detect the version during game id?
+ return (data.byte(kSpeechloaded) == 1);
+}
} /*namespace dreamgen */