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); }
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); }
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); } } }