public static void RLEWExpand(memptr source, memptr dest) { int length = source.GetInt32(0); memptr end = new memptr(dest, length); source.Offset(4); // skip length words // // expand it // do { ushort value = source.GetUInt16(0); source.Offset(2); if(value != RLETAG) { // // uncompressed // dest.SetUInt16(0, value); dest.Offset(2); } else { // // compressed string // ushort count = source.GetUInt16(0); source.Offset(2); value = source.GetUInt16(0); source.Offset(2); if(dest.BaseIndex + count * 2 > end.BaseIndex) throw new Exception("RLEWExpand error!"); for(ushort i = 1; i <= count; i++) { dest.SetUInt16(0, value); dest.Offset(2); } } } while(dest.BaseIndex < end.BaseIndex); }
/// <summary>Returns a byte array containing 16-bit signed samples for the specified speaker sound.</summary> /// <param name="speakerSound">The speaker sound.</param> /// <param name="soundsPointer">The speaker sounds pointer.</param> /// <param name="sampleFrequency">The sample frequency in Hz.</param> /// <param name="amplitude">The peak amplitude (0 to 1).</param> /// <returns>A byte array.</returns> public static byte[] GetSpeakerSamplesS16(spksndtype speakerSound, memptr soundsPointer, double sampleFrequency, double amplitude) { soundsPointer.Offset(speakerSound.start); PCSpeaker pcSpeaker = new PCSpeaker(sampleFrequency, amplitude); // as: Added checks to catch problems with SOUNDS.HOV files (Demon Hunter v1.1): // Also, the maximum sample time has been limited to 10s // and: sound generation stops if the end of the soundsPointer buffer is reached double time = 1.0 / spksndtype.Frequency(0x2147); ushort timerValue = soundsPointer.GetUInt16(0); double maxTime = 10.0; while(timerValue != spksndtype.SpeakerData_EndSound) { pcSpeaker.SetTimer((ushort) timerValue); pcSpeaker.WriteSamples(time); soundsPointer.Offset(2); if(soundsPointer.BaseIndex + 1 >= soundsPointer.Buffer.Length) break; timerValue = soundsPointer.GetUInt16(0); if(pcSpeaker.ElapsedTime > maxTime) break; } return pcSpeaker.ToArray(); }
//========================================================================== /* ====================== = = LoadLevel = = Loads LEVEL00.EXT (00 = global variable level) = ====================== */ private void LoadLevel() { // // load the new level in and decompress // string filename, num; if(level < 10) { num = level.ToString(); filename = "LEVEL0"; } else { num = level.ToString(); filename = "LEVEL"; } filename = string.Concat(filename, num); filename = string.Concat(filename, "." + EXTENSION); memptr bufferseg = new memptr(); BloadinMM(filename, ref bufferseg); ushort length = bufferseg.GetUInt16(0); if(levelseg.Buffer != null) MMFreePtr(ref levelseg); MMGetPtr(ref levelseg, length); // as: Made RLEWExpand static try { RLEWExpand(bufferseg, levelseg); } catch(Exception ex) { // as: Quit on failure Quit(ex.Message); } MMFreePtr(ref bufferseg); levelheader = new LevelDef(levelseg); // // copy plane 0 to tilemap // memptr planeptr = new memptr(levelseg, 32); int index = 0; for(short y = 0; y < levelheader.height; y++) for(short x = 0; x < levelheader.width; x++, index += 2) tilemap[x, y] = planeptr.GetUInt16(index); // // spawn tanks // planeptr = new memptr(levelseg, 32 + levelheader.planesize); StartLevel(planeptr); MMFreePtr(ref levelseg); }
//========================================================================== /* ================== = = StartLevel = ================== */ private void StartLevel(memptr plane1) { numrefugees = 0; // as: Enemy stats enemiesKilled = 0; totalEnemies = 0; for(ushort y = 0; y < levelheader.height; y++) { for(ushort x = 0; x < levelheader.width; x++) { ushort tile = plane1.GetUInt16(0); plane1.Offset(2); if(tile > 0) { ushort dir = (ushort) (tile >> 8); // high byte gives starting dir tile &= 0xff; fixed_t gx = x * TILEGLOBAL + TILEGLOBAL / 2; fixed_t gy = y * TILEGLOBAL + TILEGLOBAL / 2; // as: Added LevelObjects switch(tile) { case LevelObjects.MaleRefugee: SpawnRefugee(gx, gy, true); break; case LevelObjects.Drone: SpawnDrone(gx + TILEGLOBAL / 2, gy + TILEGLOBAL / 2); break; case LevelObjects.Tank: SpawnTank(gx + TILEGLOBAL / 2, gy + TILEGLOBAL / 2); break; case LevelObjects.Mutant: SpawnMutant(gx + TILEGLOBAL / 2, gy + TILEGLOBAL / 2); break; case LevelObjects.Shield: SpawnShield(gx, gy); break; case LevelObjects.FemaleRefugee: SpawnRefugee(gx, gy, false); break; case LevelObjects.WarpGate: warpx = gx; // warp gate is spawned when all men are done warpy = gy; break; case LevelObjects.Player: SpawnPlayer(gx, gy); short angle = (short) (ANGLES / 4 - dir * ANGLES / 4); if(angle < 0) angle += ANGLES; objlist[0].angle = angle; break; } } } } totalrefugees = numrefugees; }