aboutsummaryrefslogtreecommitdiff
path: root/sky
diff options
context:
space:
mode:
authorOliver Kiehl2003-05-01 14:05:10 +0000
committerOliver Kiehl2003-05-01 14:05:10 +0000
commit8e606a99ff4fd61e74b73f1e6883b5c27178c34b (patch)
treead27cffe6e90092eaeb1191a120d396e309da14d /sky
parentfb36c0ad302c4f023b20576ec0882d57a7803532 (diff)
downloadscummvm-rg350-8e606a99ff4fd61e74b73f1e6883b5c27178c34b.tar.gz
scummvm-rg350-8e606a99ff4fd61e74b73f1e6883b5c27178c34b.tar.bz2
scummvm-rg350-8e606a99ff4fd61e74b73f1e6883b5c27178c34b.zip
Commiting some of my stuff. Rather untested still buggy
svn-id: r7249
Diffstat (limited to 'sky')
-rw-r--r--sky/logic.cpp342
-rw-r--r--sky/logic.h2
-rw-r--r--sky/skydefs.h17
3 files changed, 334 insertions, 27 deletions
diff --git a/sky/logic.cpp b/sky/logic.cpp
index 5c72b38549..18df4a4add 100644
--- a/sky/logic.cpp
+++ b/sky/logic.cpp
@@ -71,7 +71,7 @@ void SkyLogic::engine() {
continue;
}
- //cur_id = compact2->logic;
+ _scriptVariables[CUR_ID] = compact2->logic;
_compact = SkyState::fetchCompact(compact2->logic);
// check the id actually wishes to be processed
@@ -110,10 +110,6 @@ void SkyLogic::logicScript() {
uint16 *scriptNo = (uint16 *)SkyCompact::getCompactElem(_compact, C_BASE_SUB + mode);
uint16 *offset = (uint16 *)SkyCompact::getCompactElem(_compact, C_BASE_SUB + mode + 2);
- // FIXME: HACK ALERT!!!!
- if (*scriptNo == 0x27 && *offset == 0)
- *offset = 0x9fa;
-
uint32 scr = script(_compact, *scriptNo, *offset);
*scriptNo = (uint16)(scr & 0xffff);
*offset = (uint16)(scr >> 16);
@@ -145,7 +141,187 @@ void SkyLogic::autoRoute() {
}
void SkyLogic::arAnim() {
- error("Stub: SkyLogic::arAnim");
+ // Follow a route
+ // Mega should be in getToMode
+
+ // only check collisions on character boundaries
+ if ((_compact->xcood & 7) || (_compact->ycood & 7)) {
+ mainAnim();
+ return;
+ }
+
+ // On character boundary. Have we been told to wait?
+ // if not - are WE colliding?
+
+ if (_compact->extCompact->waitingFor == 0xffff) { // 1st cycle of re-route does
+ mainAnim();
+ return;
+ }
+
+ if (_compact->extCompact->waitingFor) {
+ // ok, we've been told we've hit someone
+ // we will wait until we are no longer colliding
+ // with them. here we check to see if we are (still) colliding.
+ // if we are then run the stop script. if not clear the flag
+ // and continue.
+
+ // remember - this could be the first ar cycle for some time,
+ // we might have been told to wait months ago. if we are
+ // waiting for one person then another hits us then
+ // c_waiting_for will be replaced by the new mega - this is
+ // fine because the later collision will almost certainly
+ // take longer to clear than the earlier one.
+
+ if (!collide(SkyState::fetchCompact(_compact->extCompact->waitingFor)))
+ error("stop_and_wait not implemented\n");
+
+ // we are not in fact hitting this person so clr & continue
+ // it must have registered some time ago
+
+ _compact->extCompact->waitingFor = 0; // clear id flag
+ }
+
+ // ok, our turn to check for collisions
+
+#define logic_list_no 141
+ uint16 *logicList = (uint16 *)SkyState::fetchCompact(logic_list_no);
+ Compact *cpt = 0;
+
+ for (;;) {
+ uint16 id = *logicList++; // get an id
+ if (!id) // 0 is list end
+ break;
+
+ if (id == 0xffff) { // address change?
+ logicList = (uint16 *)SkyState::fetchCompact(*logicList); // get new logic list
+ continue;
+ }
+
+ if (id == (uint16)(_scriptVariables[CUR_ID] & 0xffff)) // is it us?
+ continue;
+
+ _scriptVariables[HIT_ID] = id; // save target id for any possible c_mini_bump
+ cpt = SkyState::fetchCompact(id); // let's have a closer look
+
+ if (!(cpt->status & (1 << ST_COLLISION_BIT))) // can it collide?
+ continue;
+
+ if (cpt->screen != _compact->screen) // is it on our screen?
+ continue;
+
+ if (collide(cpt)) { // check for a hit
+ // ok, we've hit a mega
+ // is it moving... or something else?
+
+ if (cpt->logic != L_AR_ANIM) { // check for following route
+ // it is doing something else
+ // we restart our get-to script
+ // first tell it to wait for us - in case it starts moving
+ // ( *it may have already hit us and stopped to wait )
+
+ _compact->extCompact->waitingFor = 0xffff; // effect 1 cycle collision skip
+ // tell it it is waiting for us
+ cpt->extCompact->waitingFor = (uint16)(_scriptVariables[CUR_ID] & 0xffff);
+ // restart current script
+ *(uint16 *)SkyCompact::getCompactElem(_compact, C_BASE_SUB + _compact->mode + 2) = 0;
+ _compact->logic = L_SCRIPT;
+ logicScript();
+ return;
+ }
+
+ script(_compact, _compact->extCompact->miniBump, 0);
+ return;
+ }
+ }
+
+ // ok, there was no collisions
+ // now check for interaction request
+ // *note: the interaction is always set up as an action script
+
+ if (_compact->extCompact->request) {
+ _compact->mode = C_ACTION_MODE; // put into action mode
+ _compact->extCompact->actionSub = _compact->extCompact->request;
+ _compact->extCompact->request = 0; // trash request
+ _compact->logic = L_SCRIPT;
+ logicScript();
+ return;
+ }
+
+ // any flag? - or any change?
+ // if change then re-run the current script, which must be
+ // a position independent get-to ----
+
+ if (_compact->extCompact->atWatch) { // any flag set?
+ mainAnim();
+ return;
+ }
+
+ // ok, there is an at watch - see if it's changed
+
+ if (_compact->extCompact->atWas == _scriptVariables[_compact->extCompact->atWatch/4]) { // still the same?
+ mainAnim();
+ return;
+ }
+
+ // changed so restart the current script
+ // *not suitable for base initiated ARing
+ *(uint16 *)SkyCompact::getCompactElem(_compact, C_BASE_SUB + _compact->mode + 2) = 0;
+
+ _compact->logic = L_SCRIPT;
+ logicScript();
+}
+
+void SkyLogic::mainAnim() {
+ _compact->extCompact->waitingFor = 0; // clear possible zero-zero skip
+
+ uint16 *sequence = _compact->grafixProg;
+ if (!*sequence) {
+ // ok, move to new anim segment
+ sequence += 2;
+ if (!*sequence) { // end of route?
+ // ok, sequence has finished
+
+ _compact->extCompact->arAnimIndex = 0; // will start afresh if new sequence continues in last direction
+ _compact->downFlag = 0; // pass back ok to script
+ _compact->logic = L_SCRIPT;
+ logicScript();
+ return;
+ }
+
+ _compact->grafixProg = sequence;
+ _compact->extCompact->arAnimIndex = 0; // reset position
+ }
+
+ uint16 dir = 0;
+ while ((dir = _compact->extCompact->dir) != *(sequence + 1)) {
+ // ok, setup turning
+ _compact->extCompact->dir = *(sequence + 1);
+
+ uint16 **tt = (uint16 **)SkyCompact::getCompactElem(_compact,
+ C_TURN_TABLE + _compact->extCompact->megaSet + dir * 20);
+ if (tt[_compact->extCompact->dir]) {
+ _compact->extCompact->turnProg = tt[_compact->extCompact->dir];
+ _compact->logic = L_AR_TURNING;
+ arTurn();
+ return;
+ }
+ };
+
+ uint16 *animUp = (uint16 *)SkyCompact::getCompactElem(_compact,
+ C_ANIM_UP + _compact->extCompact->megaSet + (dir << 4));
+
+ uint16 arAnimIndex = _compact->extCompact->arAnimIndex;
+ if (!animUp[arAnimIndex/2]) {
+ arAnimIndex = 0;
+ _compact->extCompact->arAnimIndex = 0; // reset
+ }
+
+ _compact->extCompact->arAnimIndex += S_LENGTH;
+
+ *sequence -= animUp[(S_COUNT + arAnimIndex)/2]; // reduce the distance to travel
+ _compact->frame = animUp[(S_FRAME + arAnimIndex)/2]; // new graphic frame
+ _compact->xcood += animUp[(S_AR_X + arAnimIndex)/2]; // update x coordinate
+ _compact->ycood += animUp[(S_AR_Y + arAnimIndex)/2]; // update y coordinate
}
void SkyLogic::arTurn() {
@@ -181,7 +357,6 @@ void SkyLogic::turn() {
}
// turn_to_script:
-
_compact->extCompact->arAnimIndex = 0;
_compact->logic = L_SCRIPT;
@@ -213,7 +388,12 @@ void SkyLogic::frames() {
}
void SkyLogic::pause() {
- error("Stub: SkyLogic::pause");
+ if (--_compact->flag)
+ return;
+
+ _compact->logic = L_SCRIPT;
+ logicScript();
+ return;
}
void SkyLogic::waitSync() {
@@ -258,6 +438,90 @@ void SkyLogic::simpleAnim() {
logicScript();
}
+bool SkyLogic::collide(Compact *cpt) {
+ MegaSet *m1 = (MegaSet *)SkyCompact::getCompactElem(_compact, C_GRID_WIDTH + _compact->extCompact->megaSet);
+ MegaSet *m2 = (MegaSet *)SkyCompact::getCompactElem(cpt, C_GRID_WIDTH + cpt->extCompact->megaSet);
+
+ uint16 x = cpt->xcood; // target's base coordinates
+ x &= 0xfff8;
+ uint16 y = cpt->ycood;
+ y &= 0xfff8;
+
+ // The collision is direction dependant
+ switch (_compact->extCompact->dir) {
+ case 0: // looking up
+ x -= m1->colOffset; // compensate for inner x offsets
+ x += m2->colOffset;
+
+ if ((x + m2->colWidth) < _compact->xcood) // their rightmost
+ return false;
+
+ x -= m1->colWidth; // our left, their right
+ if (x >= _compact->xcood)
+ return false;
+
+ y += 8; // bring them down a line
+ if (y == _compact->ycood)
+ return true;
+
+ y += 8; // bring them down a line
+ if (y == _compact->ycood)
+ return true;
+
+ return false;
+ case 1: // looking down
+ x -= m1->colOffset; // compensate for inner x offsets
+ x += m2->colOffset;
+
+ if ((x + m2->colWidth) >= _compact->xcood) // their rightmoast
+ return false;
+
+ x -= m1->colWidth; // our left, their right
+ if (x >= _compact->xcood)
+ return false;
+
+ y -= 8; // bring them up a line
+ if (y == _compact->ycood)
+ return true;
+
+ y -= 8; // bring them up a line
+ if (y == _compact->ycood)
+ return true;
+
+ return false;
+ case 2: // looking left
+
+ if (y != _compact->ycood)
+ return false;
+
+ x += m2->lastChr;
+ if (x == _compact->xcood)
+ return true;
+
+ x -= 8; // out another one
+ if (x == _compact->xcood)
+ return true;
+
+ return false;
+ case 3: // looking right
+
+ if (y != _compact->ycood)
+ return false;
+
+ x -= m1->lastChr; // last block
+ if (x == _compact->xcood)
+ return true;
+
+ x -= 8; // out another block
+ if (x != _compact->xcood)
+ return false;
+
+ return true;
+ default:
+ error("Unknown Direction: %d", _compact->extCompact->dir);
+ }
+}
+
void SkyLogic::checkModuleLoaded(uint16 moduleNo) {
if (!_moduleList[moduleNo])
_moduleList[moduleNo] = (uint16 *)_skyDisk->loadFile((uint16)moduleNo + F_MODULE_0, NULL);
@@ -520,8 +784,6 @@ static const uint32 forwardList5b[] = {
RIGHT_MOUSE,
};
-#define RESULT 1
-#define TEXT1 54
void SkyLogic::initScriptVariables() {
for (uint i = 0; i < sizeof(_scriptVariables)/sizeof(uint32); i++)
_scriptVariables[i] = 0;
@@ -571,7 +833,7 @@ script:
// Bit 12-15 - Module number
uint16 moduleNo = (uint16)((scriptNo & 0xff00) >> 12);
- printf("scriptNo: %d, moduleNo: %d, offset: %d\n", scriptNo, moduleNo, offset);
+ printf("Doing Script %x\n", (offset << 16) | scriptNo);
uint16 *scriptData = _moduleList[moduleNo]; // get module address
printf("File: %d\n", moduleNo + F_MODULE_0);
@@ -684,7 +946,7 @@ script:
a = (this->*mcodeTable[mcode]) (a, b, c);
- if (!(a & 0xffff))
+ if (!a)
return (((scriptData - moduleStart) << 16) | scriptNo);
break;
case 12: // more_than
@@ -717,7 +979,6 @@ script:
// Push a compact access
s = READ_LE_UINT16(scriptData++);
tmp = (uint16 *)SkyCompact::getCompactElem(compact, s);
- printf("push_offset: %d\n", *tmp);
push(*tmp);
break;
case 16: // pop_offset
@@ -752,15 +1013,18 @@ script:
}
uint32 SkyLogic::fnCacheChip(uint32 a, uint32 b, uint32 c) {
- error("Stub: fnCacheChip");
+ warning("Stub: fnCacheChip");
+ return 1;
}
uint32 SkyLogic::fnCacheFast(uint32 a, uint32 b, uint32 c) {
- error("Stub: fnCacheFast");
+ warning("Stub: fnCacheFast");
+ return 1;
}
uint32 SkyLogic::fnDrawScreen(uint32 a, uint32 b, uint32 c) {
- error("Stub: fnDrawScreen");
+ warning("Stub: fnDrawScreen");
+ return 1;
}
uint32 SkyLogic::fnAr(uint32 x, uint32 y, uint32 c) {
@@ -843,8 +1107,8 @@ uint32 SkyLogic::fnCloseHand(uint32 a, uint32 b, uint32 c) {
uint32 SkyLogic::fnGetTo(uint32 targetPlaceId, uint32 mode, uint32 c) {
_compact->upFlag = (uint16)mode; // save mode for action script
_compact->mode += 4; // next level up
- Compact *compact2 = SkyState::fetchCompact(_compact->place);
- uint16 *getToTable = compact2->getToTable;
+ Compact *cpt = SkyState::fetchCompact(_compact->place);
+ uint16 *getToTable = cpt->getToTable;
while (*getToTable != targetPlaceId)
getToTable += 2;
@@ -870,8 +1134,24 @@ uint32 SkyLogic::fnSetToStand(uint32 a, uint32 b, uint32 c) {
return 0; // drop out of script
}
-uint32 SkyLogic::fnTurnTo(uint32 direction, uint32 b, uint32 c) {
- error("Stub: fnTurnTo");
+uint32 SkyLogic::fnTurnTo(uint32 dir, uint32 b, uint32 c) {
+ // turn compact to direction dir
+
+ uint16 curDir = _compact->extCompact->dir * 20; // get current direction
+ _compact->extCompact->dir = (uint16)(dir & 0xffff); // set new direction
+
+ uint16 **tt = (uint16 **)SkyCompact::getCompactElem(_compact,
+ C_TURN_TABLE + _compact->extCompact->megaSet + curDir);
+
+ if (!tt[dir])
+ return 1; // keep going
+
+ _compact->extCompact->turnProg = tt[dir]; // put turn program in
+ _compact->logic = L_TURNING;
+
+ turn();
+
+ return 0; // drop out of script
}
uint32 SkyLogic::fnArrived(uint32 a, uint32 b, uint32 c) {
@@ -920,7 +1200,8 @@ uint32 SkyLogic::fnNoButtons(uint32 a, uint32 b, uint32 c) {
}
uint32 SkyLogic::fnSetStop(uint32 a, uint32 b, uint32 c) {
- error("Stub: fnSetStop");
+ warning("Stub: fnSetStop");
+ return 1;
}
uint32 SkyLogic::fnClearStop(uint32 a, uint32 b, uint32 c) {
@@ -932,7 +1213,7 @@ uint32 SkyLogic::fnPointerText(uint32 a, uint32 b, uint32 c) {
}
uint32 SkyLogic::fnQuit(uint32 a, uint32 b, uint32 c) {
- error("Stub: fnQuit");
+ return 0;
}
uint32 SkyLogic::fnSpeakMe(uint32 a, uint32 b, uint32 c) {
@@ -959,7 +1240,7 @@ uint32 SkyLogic::fnChooser(uint32 a, uint32 b, uint32 c) {
// systemFlags |= 1 << SF_CHOOSING; // can't save/restore while choosing
-// theChosenOne = 0; // clear result
+ _scriptVariables[THE_CHOSEN_ONE] = 0; // clear result
uint32 *p = _scriptVariables + TEXT1;
uint16 ycood = TOP_LEFT_Y; // rolling coordinate
@@ -1066,8 +1347,12 @@ uint32 SkyLogic::fnFaceId(uint32 a, uint32 b, uint32 c) {
error("Stub: fnFaceId");
}
-uint32 SkyLogic::fnForeground(uint32 a, uint32 b, uint32 c) {
- error("Stub: fnForeground");
+uint32 SkyLogic::fnForeground(uint32 sprite, uint32 b, uint32 c) {
+ // Make sprite a foreground sprite
+ Compact *cpt = SkyState::fetchCompact(sprite);
+ cpt->status &= 0xfff8;
+ cpt->status |= ST_FOREGROUND;
+ return 1;
}
uint32 SkyLogic::fnBackground(uint32 a, uint32 b, uint32 c) {
@@ -1098,8 +1383,11 @@ uint32 SkyLogic::fnToggleGrid(uint32 a, uint32 b, uint32 c) {
error("Stub: fnToggleGrid");
}
-uint32 SkyLogic::fnPause(uint32 a, uint32 b, uint32 c) {
- error("Stub: fnPause");
+uint32 SkyLogic::fnPause(uint32 cycles, uint32 b, uint32 c) {
+ // Set mega to l_pause
+ _compact->flag = (uint16)(cycles & 0xffff);
+ _compact->logic = L_PAUSE;
+ return 0; // drop out of script
}
uint32 SkyLogic::fnRunAnimMod(uint32 a, uint32 b, uint32 c) {
diff --git a/sky/logic.h b/sky/logic.h
index 40ac2aa717..3a088af047 100644
--- a/sky/logic.h
+++ b/sky/logic.h
@@ -174,7 +174,9 @@ protected:
uint32 pop();
void checkModuleLoaded(uint16 moduleNo);
uint32 script(Compact *compact, uint16 scriptNo, uint16 offset);
+ bool collide(Compact *cpt);
void initScriptVariables();
+ void mainAnim();
uint16 *_moduleList[16];
uint32 _stack[20];
diff --git a/sky/skydefs.h b/sky/skydefs.h
index b4c0c4b3b4..52e75c173d 100644
--- a/sky/skydefs.h
+++ b/sky/skydefs.h
@@ -23,11 +23,26 @@
//This file is incomplete, several flags still missing.
+#define ST_COLLISION_BIT 5
+
+#define S_COUNT 0
+#define S_FRAME 2
+#define S_AR_X 4
+#define S_AR_Y 6
+#define S_LENGTH 8
+
#define KEY_BUFFER_SIZE 80
#define SEQUENCE_COUNT 3
#define FIRST_TEXT_COMPACT 23
+// scriptVariable offsets
+#define RESULT 1
+#define CUR_ID 13
+#define HIT_ID 38
+#define THE_CHOSEN_ONE 52
+#define TEXT1 54
+
//screen/grid defines
#define GAME_SCREEN_WIDTH 320
#define GAME_SCREEN_HEIGHT 192
@@ -59,7 +74,9 @@
#define C_SP_COLOUR 90
#define C_MEGA_SET 112
#define C_GRID_WIDTH 114
+#define C_ANIM_UP 122
#define C_STAND_UP 138
+#define C_TURN_TABLE 158
#define SECTION_0_ITEM 119 //item number of first item section
#define NEXT_MEGA_SET (258 - C_GRID_WIDTH)