예제 #1
0
        /*
        ======================
        =
        = HuffExpand
        =
        ======================
        */
        public static void HuffExpand(byte[] sourceBuffer, int sourceIndex, byte[] destBuffer, int destIndex, int length, huffnode hufftable)
        {
            memptr source = new memptr(sourceBuffer, sourceIndex);
            memptr dest = new memptr(destBuffer, destIndex);

            ushort bit, _byte, code;
            huffnode nodeon, headptr;

            headptr = new huffnode(hufftable, 254); // head node is allways node 254

            // as: The disabled C code that was in this function appears to be the C version of the asm code
            // this came in handy during the conversion

            nodeon = new huffnode(headptr);

            // as: bugfix - refactored to prevent the out of bounds read that can occur occasionally with the final byte
            bit = 256;
            _byte = 0;
            while(length != 0)
            {
                if(bit == 256)
                {
                    bit = 1;
                    _byte = source.GetUInt8(0);
                    source.Offset(1);
                }

                if((_byte & bit) != 0)
                    code = nodeon.bit1;
                else
                    code = nodeon.bit0;

                bit <<= 1;

                if(code < 256)
                {
                    dest.SetUInt8(0, (byte) code);
                    dest.Offset(1);
                    nodeon = headptr;
                    length--;
                }
                else
                {
                    nodeon = new huffnode(hufftable, code - 256);
                }
            }
        }
예제 #2
0
        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);
        }
예제 #3
0
        //==========================================================================

        /////////////////////////////////////////////////////////
        //
        // InitGrFile
        //
        /////////////////////////////////////////////////////////
        private void InitGrFile()
        {
            //
            // calculate some offsets in the header
            //
            grhuffman = new huffnode(grhead);
            grstarts = new memptr(grhead.Buffer, grhead.dataoffsets);

            OptimizeNodes(grhuffman);

            //
            // Open the graphics file, leaving it open until the game is finished
            //
            grhandle = _sys.open("EGAGRAPH." + EXTENSION);
            if(grhandle.IsNull)
                Quit("Cannot open EGAGRAPH." + EXTENSION + "!");

            memptr buffer = new memptr();

            //
            // load the pic and sprite headers into the data segment
            //
            needgr[STRUCTPIC] = 1; // make sure this chunk never reloads
            grsegs[STRUCTPIC] = new memptr(null, 0xffff);
            GetChunkLength(STRUCTPIC); // position file pointer
            MMGetPtr(ref buffer, chunkcomplen);
            SegRead(ref grhandle, buffer, chunkcomplen);

            // as: Added temp pointer
            memptr temp = new memptr(new byte[pictable.Length * pictype.SizeOf], 0);

            HuffExpand(buffer.Buffer, buffer.BaseIndex, temp.Buffer, 0, temp.Buffer.Length, grhuffman);

            // as: Initialise pictypes
            for(int i = 0; i < pictable.Length; i++)
            {
                pictable[i] = new pictype(temp);
                temp.Offset(pictype.SizeOf);
            }

            MMFreePtr(ref buffer);
        }
예제 #4
0
        private void SaveCtrls()
        {
            memptr handle = new memptr(new byte[key.Length + 2 + 4 + 2]);
            for(int i = 0; i < key.Length; i++)
                handle.SetInt8(i, key[i]);

            handle.Offset(key.Length);

            handle.SetInt8(0, keyB1);
            handle.Offset(1);

            handle.SetInt8(0, keyB2);
            handle.Offset(1);

            handle.SetInt32(0, highscore);
            handle.Offset(4);

            handle.SetInt16(0, bestlevel);
            handle.Offset(2);

            _sys.SaveControls(handle); // as: Handled separately now
        }
예제 #5
0
        //==========================================================================

        /*
        ==========================
        =
        = SegRead
        =
        = Read from a file to a segment pointer
        =
        ==========================
        */
        private void SegRead(ref memptr handle, memptr dest, int length)
        {
            if(length > 0xffff)
                Quit("SegRead doesn't support 64K reads yet!");

            Array.Copy(handle.Buffer, handle.BaseIndex, dest.Buffer, dest.BaseIndex, length);
            handle.Offset(length);
        }
예제 #6
0
        /// <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();
        }
예제 #7
0
 public scaleseg(memptr pointer, ushort offset)
 {
     _pointer = pointer;
     _pointer.Offset(offset);
 }
예제 #8
0
        /*
        ===========================
        =
        = MakeShape
        =
        = Takes a raw bit map of width bytes by height and creates a scaleable shape
        =
        = Returns the length of the shape in bytes
        =
        ===========================
        */
        private void SC_MakeShape(memptr src, short width, short height, ref memptr shapeseg)
        {
            short pixwidth = (short) (width * 8);

            memptr tempseg_memptr = new memptr(); // as: added
            MMGetPtr(ref tempseg_memptr, pixwidth * (height + 20)); // larger than needed buffer

            scaleshape tempseg = new scaleshape(tempseg_memptr);

            tempseg.width = pixwidth; // pixel dimensions
            tempseg.height = height;

            //
            // convert ega pixels to byte color values in a temp buffer
            //
            // Stored in a collumn format, not rows!
            //
            memptr byteseg = new memptr();
            MMGetPtr(ref byteseg, pixwidth * height);

            memptr byteptr = new memptr(byteseg);

            memptr plane0 = new memptr(src);
            memptr plane1 = new memptr(plane0, width * height);
            memptr plane2 = new memptr(plane1, width * height);
            memptr plane3 = new memptr(plane2, width * height);

            for(short x = 0; x < width; x++)
            {
                for(ushort b = 0; b < 8; b++)
                {
                    ushort shift = (ushort) (8 - b);
                    ushort offset = (ushort) x;

                    for(short y = 0; y < height; y++)
                    {
                        byte by0 = plane0.GetUInt8(offset);
                        byte by1 = plane1.GetUInt8(offset);
                        byte by2 = plane2.GetUInt8(offset);
                        byte by3 = plane3.GetUInt8(offset);
                        offset += (ushort) width;

                        ushort color = 0;

                        // as: converted from asm
                        color |= AsmRotate(by3, shift);
                        color <<= 1;
                        color |= AsmRotate(by2, shift);
                        color <<= 1;
                        color |= AsmRotate(by1, shift);
                        color <<= 1;
                        color |= AsmRotate(by0, shift);

                        byteptr.SetUInt8(0, (byte) color);
                        byteptr.Offset(1);
                    } // Y
                } // B
            } // X

            //
            // convert byte map to sparse scaling format
            //
            memptr saveptr = tempseg.PointerTofirst(pixwidth);

            // start filling in data after all pointers to line segments
            byteptr = new memptr(byteseg); // first pixel in byte array

            for(short x = 0; x < pixwidth; x++)
            {
                //
                // each vertical line can have 0 or more segments of pixels in it
                //
                short y = 0;
                memptr segptr = tempseg.PointerTofirst(x);
                segptr.SetUInt16(0, 0); // in case there are no segments on line
                do
                {
                    // scan for first pixel to be scaled
                    while(y < height && byteptr.GetUInt8(0) == BACKGROUND) // as: bugfix - re-ordered to prevent out of bounds read
                    {
                        byteptr.Offset(1);
                        y++;
                    }

                    if(y == height) // if not, the line is finished
                        continue;

                    //
                    // start a segment by pointing the last link (either shape.first[x] if it
                    // is the first segment, or a seg.next if not) to the current spot in
                    // the tempseg, setting segptr to this segments next link, and copying
                    // all the pixels in the segment
                    //
                    segptr.SetUInt16(0, _sys.FP_OFF(saveptr)); // pointer to start of this segment

                    short start = y;
                    short length = 0;

                    scaleseg scale_seg = new scaleseg(saveptr);

                    memptr dataptr = scale_seg.PointerToData(0);

                    //
                    // copy bytes in the segment to the shape
                    //
                    while(y < height && byteptr.GetUInt8(0) != BACKGROUND) // as: bugfix - re-ordered to prevent out of bounds read
                    {
                        length++;
                        dataptr.SetUInt8(0, byteptr.GetUInt8(0));
                        dataptr.Offset(1);
                        byteptr.Offset(1);
                        y++;
                    }

                    scale_seg.start = start;
                    scale_seg.length = length;
                    scale_seg.next = 0;

                    // get ready for next segment
                    segptr = new memptr(saveptr, scaleseg.FieldOffset_next);

                    saveptr = dataptr; // next free byte to be used

                } while(y < height);
            }

            //
            // allocate exact space needed and copy shape to it, then free buffers
            //
            MMGetPtr(ref shapeseg, _sys.FP_OFF(saveptr));
            Array.Copy(tempseg.Pointer.Buffer, shapeseg.Buffer, _sys.FP_OFF(saveptr));
            MMFreePtr(ref byteseg);
            MMFreePtr(ref tempseg_memptr);
        }
예제 #9
0
        //==========================================================================
        /*
        ==================
        =
        = 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;
        }