private void Stopped() { // waiting for another mega to move or give-up trying // // this mode will always be set up from a special script // that will be one level higher than the script we // would wish to restart from Compact cpt = _skyCompact.FetchCpt(_compact.Core.waitingFor); if (cpt != null) { if (cpt.Core.mood == 0 && Collide(cpt)) { return; } } // we are free, continue processing the script // restart script one level below SkyCompact.GetSub(_compact, _compact.Core.mode - 2).Field = 0; _compact.Core.waitingFor = 0xffff; _compact.Core.logic = L_SCRIPT; LogicScript(); }
private bool FnStartSub(uint scr, uint b, uint c) { _compact.Core.mode += 4; SkyCompact.GetSub(_compact, _compact.Core.mode).Field = (ushort)(scr & 0xffff); SkyCompact.GetSub(_compact, (ushort)(_compact.Core.mode + 2)).Field = (ushort)(scr >> 16); return(false); }
private bool FnGetTo(uint targetPlaceId, uint mode, uint c) { _compact.Core.upFlag = (ushort)mode; // save mode for action script _compact.Core.mode += 4; // next level up Compact cpt = _skyCompact.FetchCpt(_compact.Core.place); if (cpt == null) { // TODO: warning("can't find _compact's getToTable. Place compact is NULL"); return(false); } var raw = _skyCompact.FetchCptRaw(cpt.Core.getToTableId); if (raw == null) { //TODO: warning("Place compact's getToTable is NULL"); return(false); } var getToTable = new UShortAccess(raw, 0); while (getToTable.Value != targetPlaceId) { getToTable.Offset += 4; } // get new script SkyCompact.GetSub(_compact, _compact.Core.mode).Field = getToTable[1]; SkyCompact.GetSub(_compact, (ushort)(_compact.Core.mode + 2)).Field = 0; return(false); // drop out of script }
public AutoRoute(Grid skyGrid, SkyCompact skyCompact) { _grid = skyGrid; _skyCompact = skyCompact; _routeGrid = new byte[RouteGridSize]; _routeBuf = new byte[Logic.ROUTE_SPACE]; }
public Text(Disk disk, SkyCompact skyCompact) { _skyDisk = disk; _skyCompact = skyCompact; InitHuffTree(); _mainCharacterSet = new CharSet { Addr = _skyDisk.LoadFile(CharSetFile), CharHeight = MainCharHeight, CharSpacing = 0 }; FnSetFont(0); if (!SystemVars.Instance.GameVersion.Type.HasFlag(SkyGameType.Demo)) { _controlCharacterSet = new CharSet { Addr = _skyDisk.LoadFile(60520), CharHeight = 12, CharSpacing = 0 }; _linkCharacterSet = new CharSet { Addr = _skyDisk.LoadFile(60521), CharHeight = 12, CharSpacing = 1 }; } }
private void Alt() { // change the current script _compact.Core.logic = L_SCRIPT; SkyCompact.GetSub(_compact, _compact.Core.mode).Field = _compact.Core.alt; SkyCompact.GetSub(_compact, _compact.Core.mode + 2).Field = 0; LogicScript(); }
private bool FnTheyStartSub(uint mega, uint scr, uint c) { Compact cpt = _skyCompact.FetchCpt((ushort)mega); cpt.Core.mode += 4; SkyCompact.GetSub(cpt, cpt.Core.mode).Field = (ushort)(scr & 0xffff); SkyCompact.GetSub(cpt, (ushort)(cpt.Core.mode + 2)).Field = (ushort)(scr >> 16); return(true); }
private bool FnInteract(uint targetId, uint b, uint c) { _compact.Core.mode += 4; // next level up _compact.Core.logic = L_SCRIPT; var cpt = _skyCompact.FetchCpt((ushort)targetId); SkyCompact.GetSub(_compact, _compact.Core.mode).Field = cpt.Core.actionScript; SkyCompact.GetSub(_compact, (ushort)(_compact.Core.mode + 2)).Field = 0; return(false); }
private void StopAndWait() { _compact.Core.mode += 4; var scriptNo = SkyCompact.GetSub(_compact, _compact.Core.mode); var offset = SkyCompact.GetSub(_compact, _compact.Core.mode + 2); scriptNo.Field = _compact.Core.stopScript; offset.Field = 0; _compact.Core.logic = L_SCRIPT; LogicScript(); }
public Mouse(SkySystem system, Disk skyDisk, SkyCompact skyCompact) { _system = system; _skyDisk = skyDisk; _skyCompact = skyCompact; CurrentMouseType = 6; MouseX = Screen.GameScreenWidth / 2; MouseY = Screen.GameScreenHeight / 2; _miceData = _skyDisk.LoadFile(MiceFile); //load in the object mouse file _objectMouseData = _skyDisk.LoadFile(MiceFile + 1); }
public Logic(SkyCompact skyCompact, Screen skyScreen, Disk skyDisk, Text skyText, MusicBase skyMusic, Mouse skyMouse, Sound skySound) { _skyCompact = skyCompact; _skyScreen = skyScreen; _skyDisk = skyDisk; _skyText = skyText; _skyMusic = skyMusic; _skySound = skySound; _skyMouse = skyMouse; _skyGrid = new Grid(this, _skyDisk, _skyCompact); _skyAutoRoute = new AutoRoute(_skyGrid, _skyCompact); SetupLogicTable(); SetupMcodeTable(); _currentSection = 0xFF; //force music & sound reload InitScriptVariables(); }
public Screen(ISystem system, Disk disk, SkyCompact skyCompact) { _system = system; _skyDisk = disk; _skyCompact = skyCompact; _gameGrid = new byte[GridX * GridY * 2]; ForceRefresh(); //blank the first 240 colors of the palette var tmpPal = new Color[VgaColors]; //set the remaining colors for (var i = 0; i < VgaColors - GameColors; i++) { tmpPal[GameColors + i] = Color.FromRgb( (Top16Colors[i].R << 2) + (Top16Colors[i].R >> 4) , (Top16Colors[i].G << 2) + (Top16Colors[i].G >> 4) , (Top16Colors[i].B << 2) + (Top16Colors[i].B >> 4)); } //set the palette _system.GraphicsManager.SetPalette(tmpPal, 0, VgaColors); }
/// <summary> /// This function is basicly a wrapper around the real script engine. It runs /// the script engine until a script has finished. /// </summary> private void LogicScript() { // Process the current mega's script // If the script finishes then drop back a level for (;;) { ushort mode = _compact.Core.mode; // get pointer to current script var scriptNo = SkyCompact.GetSub(_compact, mode); var offset = SkyCompact.GetSub(_compact, (ushort)(mode + 2)); offset.Field = Script(scriptNo.Field, offset.Field); if (offset.Field == 0) // script finished { _compact.Core.mode -= 4; } else if (_compact.Core.mode == mode) { return; } } }
public Grid(Logic logic, Disk disk, SkyCompact skyCompact) { _skyLogic = logic; _skyDisk = disk; _skyCompact = skyCompact; }
public ushort DoAutoRoute(Compact cpt) { var cptScreen = (byte)cpt.Core.screen; var cptWidth = (byte)SkyCompact.GetMegaSet(cpt).gridWidth; InitWalkGrid(cptScreen, cptWidth); byte startX, startY, destX, destY; short initStaX, initStaY, initDestX, initDestY; ClipCoordX(cpt.Core.xcood, out startX, out initStaX); ClipCoordY(cpt.Core.ycood, out startY, out initStaY); ClipCoordX(cpt.Core.arTargetX, out destX, out initDestX); ClipCoordY(cpt.Core.arTargetY, out destY, out initDestY); var raw = _skyCompact.FetchCptRaw(cpt.Core.animScratchId); Array.Clear(raw, 0, 64); var routeDest = new UShortAccess(raw, 0); if ((startX == destX) && (startY == destY)) { return(2); } var routeGrid = new UShortAccess(_routeGrid, 0); if (routeGrid[(destY + 1) * RouteGridWidth + destX + 1] != 0) { //if ((cpt == &Sky::SkyCompact::foster) && (cptScreen == 12) && (destX == 2) && (destY == 14)) { if (_skyCompact.CptIsId(cpt, (ushort)CptIds.Foster) && (cptScreen == 12) && (destX == 2) && (destY == 14)) { /* workaround for Scriptbug #1043047 * In screen 12 (the pipe factory) Joey can block Foster's target * coordinates (2/14). This is normally not too tragic, but in the * scene when foster gets thrown out by Lamb (first time you enter * the pipe factory), the game would enter an infinite loop. */ routeGrid[(destY + 1) * RouteGridWidth + destX + 1] = 0; // hide this part joey from the grid } else { return(1); // AR destination is an unaccessible block } } if (!CalcWalkGrid(startX, startY, destX, destY)) { return(1); // can't find route to block } var routeData = MakeRouteData(destX, destY); // the route is done. // if there was an initial x movement (due to clipping) tag it onto the start routeData = CheckInitMove(routeData, initStaX); byte cnt = 0; do { routeDest[cnt] = routeData[cnt]; routeDest[cnt + 1] = routeData[cnt + 1]; cnt += 2; } while (routeData[cnt - 2] != 0); return(0); }
private bool Collide(Compact cpt) { MegaSet m1 = SkyCompact.GetMegaSet(_compact); MegaSet m2 = SkyCompact.GetMegaSet(cpt); // target's base coordinates ushort x = (ushort)(cpt.Core.xcood & 0xfff8); ushort y = (ushort)(cpt.Core.ycood & 0xfff8); // The collision is direction dependent switch (_compact.Core.dir) { case 0: // looking up x -= m1.colOffset; // compensate for inner x offsets x += m2.colOffset; if (x + m2.colWidth < _compact.Core.xcood) // their rightmost { return(false); } x -= m1.colWidth; // our left, their right if (x >= _compact.Core.xcood) { return(false); } y += 8; // bring them down a line if (y == _compact.Core.ycood) { return(true); } y += 8; // bring them down a line if (y == _compact.Core.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.Core.xcood) // their rightmoast { return(false); } x -= m1.colWidth; // our left, their right if (x >= _compact.Core.xcood) { return(false); } y -= 8; // bring them up a line if (y == _compact.Core.ycood) { return(true); } y -= 8; // bring them up a line if (y == _compact.Core.ycood) { return(true); } return(false); case 2: // looking left if (y != _compact.Core.ycood) { return(false); } x += m2.lastChr; if (x == _compact.Core.xcood) { return(true); } x -= 8; // out another one if (x == _compact.Core.xcood) { return(true); } return(false); case 3: // looking right case 4: // talking (not sure if this makes sense...) if (y != _compact.Core.ycood) { return(false); } x -= m1.lastChr; // last block if (x == _compact.Core.xcood) { return(true); } x -= 8; // out another block if (x != _compact.Core.xcood) { return(false); } return(true); default: throw new InvalidOperationException(string.Format("Unknown Direction: {0}", _compact.Core.dir)); } }
public SkyEngine(GameSettings settings, IGraphicsManager gfxManager, IInputManager inputManager, IAudioOutput output, ISaveFileManager saveFileManager, bool debugMode = false) { _system = new SkySystem(gfxManager, inputManager, saveFileManager); _mixer = new Mixer(44100); // HACK: _mixer.Read(new byte[0], 0); output.SetSampleProvider(_mixer); var directory = ServiceLocator.FileStorage.GetDirectoryName(settings.Game.Path); _skyDisk = new Disk(directory); _skySound = new Sound(_mixer, _skyDisk, Mixer.MaxChannelVolume); SystemVars.Instance.GameVersion = _skyDisk.DetermineGameVersion(); // TODO: music var dev = MidiDriver.DetectDevice(MusicDriverTypes.AdLib | MusicDriverTypes.Midi /*| MDT_PREFER_MT32*/, settings.AudioDevice); if (MidiDriver.GetMusicType(dev) == MusicType.AdLib) { SystemVars.Instance.SystemFlags |= SystemFlags.Sblaster; _skyMusic = new AdLibMusic(_mixer, _skyDisk); } else { SystemVars.Instance.SystemFlags |= SystemFlags.Roland; if ((MidiDriver.GetMusicType(dev) == MusicType.MT32)/* || ConfMan.getBool("native_mt32")*/) _skyMusic = new Mt32Music((MidiDriver)MidiDriver.CreateMidi(_mixer, dev), _mixer, _skyDisk); else _skyMusic = new GmMusic((MidiDriver)MidiDriver.CreateMidi(_mixer, dev), _mixer, _skyDisk); } if (IsCDVersion) { // TODO: configuration //if (ConfMan.hasKey("nosubtitles")) //{ // warning("Configuration key 'nosubtitles' is deprecated. Use 'subtitles' instead"); // if (!ConfMan.getBool("nosubtitles")) // _systemVars.systemFlags |= SF_ALLOW_TEXT; //} //if (ConfMan.getBool("subtitles")) // _systemVars.systemFlags |= SF_ALLOW_TEXT; //if (!ConfMan.getBool("speech_mute")) // _systemVars.systemFlags |= SF_ALLOW_SPEECH; } else SystemVars.Instance.SystemFlags |= SystemFlags.AllowText; SystemVars.Instance.SystemFlags |= SystemFlags.PlayVocs; SystemVars.Instance.GameSpeed = 80; _skyCompact = new SkyCompact(); _skyText = new Text(_skyDisk, _skyCompact); _skyMouse = new Mouse(_system, _skyDisk, _skyCompact); _skyScreen = new Screen(_system, _skyDisk, _skyCompact); InitVirgin(); InitItemList(); LoadFixedItems(); _skyLogic = new Logic(_skyCompact, _skyScreen, _skyDisk, _skyText, _skyMusic, _skyMouse, _skySound); _skyMouse.Logic = _skyLogic; _skyScreen.Logic = _skyLogic; _skySound.Logic = _skyLogic; _skyText.Logic = _skyLogic; _skyControl = new Control(_skyScreen, _skyDisk, _skyMouse, _skyText, _skyMusic, _skyLogic, _skySound, _skyCompact, _system); _skyLogic.Control = _skyControl; // TODO: language // TODO: Setup mixer //SyncSoundSettings(); // TODO: debugger //_debugger = new Debugger(_skyLogic, _skyMouse, _skyScreen, _skyCompact); }
public Control(Screen screen, Disk disk, Mouse mouse, Text text, MusicBase music, Logic logic, Sound sound, SkyCompact skyCompact, ISystem system) { _saveFileMan = system.SaveFileManager; _skyScreen = screen; _skyDisk = disk; _skyMouse = mouse; _skyText = text; _skyMusic = music; _skyLogic = logic; _skySound = sound; _skyCompact = skyCompact; _system = system; }
private bool GetGridValues(Compact cpt, out byte resGrid, out int resBitNum, out uint resWidth) { var width = SkyCompact.GetMegaSet(cpt).gridWidth; return(GetGridValues(cpt.Core.xcood, cpt.Core.ycood, width, cpt, out resGrid, out resBitNum, out resWidth)); }
private void ArAnim() { // Follow a route // Mega should be in getToMode // only check collisions on character boundaries if (((_compact.Core.xcood & 7) != 0) || ((_compact.Core.ycood & 7) != 0)) { MainAnim(); return; } // On character boundary. Have we been told to wait? // if not - are WE colliding? if (_compact.Core.waitingFor == 0xffff) { // 1st cycle of re-route does not require collision checks MainAnim(); return; } if (_compact.Core.waitingFor != 0) { // 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(_skyCompact.FetchCpt(_compact.Core.waitingFor))) { StopAndWait(); return; } // we are not in fact hitting this person so clr & continue // it must have registered some time ago _compact.Core.waitingFor = 0; // clear id flag } // ok, our turn to check for collisions var logicList = new UShortAccess(_skyCompact.FetchCptRaw((ushort)_scriptVariables[LOGIC_LIST_NO]), 0); ushort id; while ((id = logicList[0]) != 0) { // get an id logicList.Offset += 2; if (id == 0xffff) { // address change? logicList = new UShortAccess(_skyCompact.FetchCptRaw(logicList[0]), 0); // get new logic list continue; } if (id == (ushort)(_scriptVariables[CUR_ID] & 0xffff)) // is it us? { continue; } _scriptVariables[HIT_ID] = id; // save target id for any possible c_mini_bump var cpt = _skyCompact.FetchCpt(id); if ((cpt.Core.status & (1 << ST_COLLISION_BIT)) == 0) // can it collide? { continue; } if (cpt.Core.screen != _compact.Core.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.Core.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.Core.waitingFor = 0xffff; // effect 1 cycle collision skip // tell it it is waiting for us cpt.Core.waitingFor = (ushort)(_scriptVariables[CUR_ID] & 0xffff); // restart current script SkyCompact.GetSub(_compact, _compact.Core.mode + 2).Field = 0; _compact.Core.logic = L_SCRIPT; LogicScript(); return; } Script(_compact.Core.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.Core.request != 0) { _compact.Core.mode = C_ACTION_MODE; // put into action mode _compact.Core.actionSub = _compact.Core.request; _compact.Core.actionSub_off = 0; _compact.Core.request = 0; // trash request _compact.Core.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.Core.atWatch == 0) { // any flag set? MainAnim(); return; } // ok, there is an at watch - see if it's changed if (_compact.Core.atWas == _scriptVariables[_compact.Core.atWatch / 4]) { // still the same? MainAnim(); return; } // changed so restart the current script // *not suitable for base initiated ARing SkyCompact.GetSub(_compact, _compact.Core.mode + 2).Field = 0; _compact.Core.logic = L_SCRIPT; LogicScript(); }
public SkyEngine(GameSettings settings, IGraphicsManager gfxManager, IInputManager inputManager, IAudioOutput output, ISaveFileManager saveFileManager, bool debugMode = false) { _system = new SkySystem(gfxManager, inputManager, saveFileManager); _mixer = new Mixer(44100); // HACK: _mixer.Read(new byte[0], 0); output.SetSampleProvider(_mixer); var directory = ServiceLocator.FileStorage.GetDirectoryName(settings.Game.Path); _skyDisk = new Disk(directory); _skySound = new Sound(_mixer, _skyDisk, Mixer.MaxChannelVolume); SystemVars.Instance.GameVersion = _skyDisk.DetermineGameVersion(); // TODO: music var dev = MidiDriver.DetectDevice(MusicDriverTypes.AdLib | MusicDriverTypes.Midi /*| MDT_PREFER_MT32*/, settings.AudioDevice); if (MidiDriver.GetMusicType(dev) == MusicType.AdLib) { SystemVars.Instance.SystemFlags |= SystemFlags.Sblaster; _skyMusic = new AdLibMusic(_mixer, _skyDisk); } else { SystemVars.Instance.SystemFlags |= SystemFlags.Roland; if ((MidiDriver.GetMusicType(dev) == MusicType.MT32) /* || ConfMan.getBool("native_mt32")*/) { _skyMusic = new Mt32Music((MidiDriver)MidiDriver.CreateMidi(_mixer, dev), _mixer, _skyDisk); } else { _skyMusic = new GmMusic((MidiDriver)MidiDriver.CreateMidi(_mixer, dev), _mixer, _skyDisk); } } if (IsCDVersion) { // TODO: configuration //if (ConfMan.hasKey("nosubtitles")) //{ // warning("Configuration key 'nosubtitles' is deprecated. Use 'subtitles' instead"); // if (!ConfMan.getBool("nosubtitles")) // _systemVars.systemFlags |= SF_ALLOW_TEXT; //} //if (ConfMan.getBool("subtitles")) // _systemVars.systemFlags |= SF_ALLOW_TEXT; //if (!ConfMan.getBool("speech_mute")) // _systemVars.systemFlags |= SF_ALLOW_SPEECH; } else { SystemVars.Instance.SystemFlags |= SystemFlags.AllowText; } SystemVars.Instance.SystemFlags |= SystemFlags.PlayVocs; SystemVars.Instance.GameSpeed = 80; _skyCompact = new SkyCompact(); _skyText = new Text(_skyDisk, _skyCompact); _skyMouse = new Mouse(_system, _skyDisk, _skyCompact); _skyScreen = new Screen(_system, _skyDisk, _skyCompact); InitVirgin(); InitItemList(); LoadFixedItems(); _skyLogic = new Logic(_skyCompact, _skyScreen, _skyDisk, _skyText, _skyMusic, _skyMouse, _skySound); _skyMouse.Logic = _skyLogic; _skyScreen.Logic = _skyLogic; _skySound.Logic = _skyLogic; _skyText.Logic = _skyLogic; _skyControl = new Control(_skyScreen, _skyDisk, _skyMouse, _skyText, _skyMusic, _skyLogic, _skySound, _skyCompact, _system); _skyLogic.Control = _skyControl; // TODO: language // TODO: Setup mixer //SyncSoundSettings(); // TODO: debugger //_debugger = new Debugger(_skyLogic, _skyMouse, _skyScreen, _skyCompact); }