diff options
Diffstat (limited to 'engines/dreamweb/stubs.cpp')
-rw-r--r-- | engines/dreamweb/stubs.cpp | 1981 |
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 */ |