private static string GetKeyDescription(int key)
        {
            const int startOfKeyObjects = 0x51;

            if (key < 0 || key > 7)
            {
                throw new ArgumentOutOfRangeException(nameof(key));
            }
            var result       = key.ToString();
            int objectType   = startOfKeyObjects + key;
            var objectSprite = SpriteBuilder.ObjectSpriteLookup[objectType];

            if (objectSprite != 0x4d)
            {
                result += " - does not exist";
                return(result);
            }

            var colourScheme = SquarePalette.FromByte(SpriteBuilder.ObjectPaletteLookup[objectType]);

            result += $" {colourScheme}";
            return(result);
        }
Exemple #2
0
        public void BuildBackgroundSprite(byte backgroundAndOrientation, SquarePalette palette)
        {
            byte background = (byte)(backgroundAndOrientation & 0x3f);
            bool flipHorizontallyAndRightAlign = (backgroundAndOrientation & 0x80) != 0;
            bool flipVerticallyAndBottomAlign  = (backgroundAndOrientation & 0x40) != 0;

            byte sprite       = BackgroundSpriteLookup[background];
            byte offsetAlongY = (byte)(BackgroundYOffsetLookup[background] & 0xf0);

            var  sourceRectangle             = SpritePositions[sprite];
            bool isSourceFlippedHorizontally = FlipSpriteHorizontally[sprite];
            bool isSourceFlippedVertically   = FlipSpriteVertically[sprite];

            Func <int, int> toX;

            if (!flipHorizontallyAndRightAlign && !isSourceFlippedHorizontally)
            {
                toX = x => x;
            }
            else if (!flipHorizontallyAndRightAlign) // && isSourceFlippedHorizontally
            {
                int right = sourceRectangle.Width - 1;
                toX = x => right - x;
            }
            else if (!isSourceFlippedHorizontally) // && flipHorizontallyAndRightAlign
            {
                int width = SquareSize.Width - 1;
                toX = x => width - x;
            }
            else // if flipHorizontallyAndRightAlign && isSourceFlippedHorizontally
            {
                var left = SquareSize.Width - sourceRectangle.Width;
                toX = x => left + x;
            }

            if (flipVerticallyAndBottomAlign)
            {
                offsetAlongY += SpriteHeightLookup[sprite];
                offsetAlongY |= 7;
                offsetAlongY ^= 0xff;
            }
            offsetAlongY >>= 3;

            Func <int, int> toY;

            if (flipVerticallyAndBottomAlign ^ isSourceFlippedVertically)
            {
                int height = sourceRectangle.Height - 1;
                toY = y => (height - y) + offsetAlongY;
            }
            else
            {
                toY = y => y + offsetAlongY;
            }

            for (int y = 0; y < sourceRectangle.Height; y++)
            {
                for (int x = 0; x < sourceRectangle.Width; x++)
                {
                    int   paletteIndex = GetPixelColour(x + sourceRectangle.X, y + sourceRectangle.Y);
                    Color pixelColour  = palette[paletteIndex];
                    if (paletteIndex == 0)
                    {
                        Debug.Assert(pixelColour == Color.Black);
                        continue;
                    }
                    int x2 = toX(x);
                    int y2 = toY(y);
                    this.Sprite.SetPixel(x2, y2, pixelColour);
                }
            }
        }
        internal static PaletteData GetPalette(ref byte background, ref byte orientation, byte squareX, byte squareY)
        {
            if (background > 0x3f)
            {
                throw new ArgumentOutOfRangeException();
            }
            if ((orientation & 0x3f) != 0)
            {
                throw new ArgumentOutOfRangeException();
            }

            // ReSharper disable InlineOutVariableDeclaration
            byte accumulator;
            // ReSharper restore InlineOutVariableDeclaration
            Flags flags = new Flags();

            Load(out accumulator, BackgroundPaletteLookup[background], ref flags);
            var backgroundPalette = accumulator;

            if (!flags.Zero)
            {
                goto palette_not_zero;
            }

// palette 0
            Load(out accumulator, squareY, ref flags);
            flags.Carry = true;
            SubtractWithBorrow(ref accumulator, 0x54, ref flags);
            LogicalShiftRight(ref accumulator, ref flags);
            LogicalShiftRight(ref accumulator, ref flags);
            LogicalShiftRight(ref accumulator, ref flags);
            LogicalShiftRight(ref accumulator, ref flags);
            byte index = accumulator;

            Load(out accumulator, WallPaletteZeroLookup[index], ref flags);

palette_not_zero:
            Compare(accumulator, 0x03, ref flags);
            if (flags.Carry)
            {
                goto palette_not_one_or_two;
            }

// palette 1 or 2
            AddWithCarry(ref accumulator, 0xb1, ref flags);
            BitTest(accumulator, squareY, ref flags);
            if (!flags.Negative)
            {
                goto palette_not_six;
            }
            ArithmeticShiftLeft(ref accumulator, ref flags);
            AddWithCarry(ref accumulator, 0x90, ref flags);

palette_not_one_or_two:
            Compare(accumulator, 0x03, ref flags);
            if (!flags.Zero)
            {
                goto palette_not_three;
            }

// palette 3
            Load(out accumulator, orientation, ref flags);
            RotateLeft(ref accumulator, ref flags);
            RotateLeft(ref accumulator, ref flags);
            RotateLeft(ref accumulator, ref flags);
            SubtractWithBorrow(ref accumulator, squareY, ref flags);
            RotateRight(ref accumulator, ref flags);
            flags.Carry = false;
            AddWithCarry(ref accumulator, squareX, ref flags);
            And(ref accumulator, 0x03, ref flags);
            index       = accumulator;
            accumulator = WallPaletteThreeLookup[index];

palette_not_three:
            Compare(accumulator, 0x04, ref flags);
            if (!flags.Zero)
            {
                goto palette_not_four;
            }

// palette 4
            Load(out accumulator, squareY, ref flags);
            RotateLeft(ref accumulator, ref flags);
            RotateLeft(ref accumulator, ref flags);
            RotateLeft(ref accumulator, ref flags);
            RotateLeft(ref accumulator, ref flags);
            And(ref accumulator, 0x7, ref flags);
            index       = accumulator;
            accumulator = WallPaletteFourLookup[index];

palette_not_four:
            Compare(accumulator, 0x05, ref flags);
            if (!flags.Zero)
            {
                goto palette_not_five;
            }

// palette 5
            Load(out accumulator, squareY, ref flags);
            RotateRight(ref accumulator, ref flags);
            RotateRight(ref accumulator, ref flags);
            Eor(ref accumulator, squareY, ref flags);
            RotateRight(ref accumulator, ref flags);
            if (flags.Carry)
            {
                background = 0x19;
            }
            RotateRight(ref accumulator, ref flags);
            SubtractWithBorrow(ref accumulator, squareY, ref flags);
            And(ref accumulator, 0x40, ref flags);
            Eor(ref accumulator, orientation, ref flags);
            BitTest(accumulator, orientation, ref flags);
            orientation = accumulator;
            Load(out accumulator, 0xB1, ref flags);
            if (!flags.Overflow)
            {
                goto palette_not_six;
            }
            AddWithCarry(ref accumulator, 0x0a, ref flags);

palette_not_five:
            Compare(accumulator, 0x06, ref flags);
            if (!flags.Zero)
            {
                goto palette_not_six;
            }

// palette 6
            Load(out accumulator, 0x9c, ref flags);
            BitTest(accumulator, orientation, ref flags);
            if (!flags.Overflow)
            {
                goto palette_not_six;
            }
            Load(out accumulator, 0xcf, ref flags);

palette_not_six:
            var displayedPalette = accumulator;
            var result = new PaletteData {
                BackgroundPalette = backgroundPalette, Palette = SquarePalette.FromByte(displayedPalette)
            };

            return(result);
        }
Exemple #4
0
        public void BuildObjectFromDataSprite(byte data, byte orientation)
        {
            data = (byte)(data & 0x7f);
            byte sprite        = ObjectSpriteLookup[data];
            byte objectPalette = ObjectPaletteLookup[data];
            var  palette       = SquarePalette.FromByte(objectPalette);

            var  sourceRectangle = SpritePositions[sprite];
            bool flipHorizontallyAndRightAlign = (orientation & 0x80) != 0;
            bool flipVerticallyAndTopAlign     = (orientation & 0x40) != 0;
            bool isSourceFlippedHorizontally   = FlipSpriteHorizontally[sprite];
            bool isSourceFlippedVertically     = FlipSpriteVertically[sprite];

            Func <int, int> toX;

            if (!flipHorizontallyAndRightAlign && !isSourceFlippedHorizontally)
            {
                toX = x => x;
            }
            else if (!flipHorizontallyAndRightAlign) // && isSourceFlippedHorizontally
            {
                int right = sourceRectangle.Width - 1;
                toX = x => right - x;
            }
            else if (!isSourceFlippedHorizontally) // && flipHorizontallyAndRightAlign
            {
                int width = SquareSize.Width - 1;
                toX = x => width - x;
            }
            else // if flipHorizontallyAndRightAlign && isSourceFlippedHorizontally
            {
                var left = SquareSize.Width - sourceRectangle.Width;
                toX = x => left + x;
            }

            Func <int, int> toY;

            if (!flipVerticallyAndTopAlign && !isSourceFlippedVertically)     // so bottom aligned and no flip
            {
                int yOffset = SquareSize.Height - sourceRectangle.Height;
                toY = y => y + yOffset;
            }
            else if (!isSourceFlippedVertically) // so top align with flip
            {
                var height = sourceRectangle.Height - 1;
                toY = y => height - y;
            }
            else if (!flipVerticallyAndTopAlign) // so bottom align with flip
            {
                int bottom = sourceRectangle.Height - 1;
                toY = y => bottom - y;
            }
            else            // so top align with flip
            {
                toY = y => y;
            }

            for (int y = 0; y < sourceRectangle.Height; y++)
            {
                for (int x = 0; x < sourceRectangle.Width; x++)
                {
                    int   paletteIndex = GetPixelColour(x + sourceRectangle.X, y + sourceRectangle.Y);
                    Color pixelColour  = palette[paletteIndex];
                    if (paletteIndex == 0)
                    {
                        Debug.Assert(pixelColour == Color.Black);
                        continue;
                    }
                    int x2 = toX(x);
                    int y2 = toY(y);
                    this.Sprite.SetPixel(x2, y2, pixelColour);
                }
            }
        }