public ObjController(GameboyAdvance gba) { this.gba = gba; Obj = new Obj[Max_Sprites]; for (int i = 0; i < Max_Sprites; i++) { Obj[i] = new Obj(gba, new ObjAttributes(gba, i * 8, gba.Memory.OamRam)); } OamAffineMatrices = new OamAffineMatrix[Max_OAM_Matrices]; UInt32 address = 0x00000006; for (int i = 0; i < 32; i++) { OamAffineMatrices[i] = new OamAffineMatrix(gba.Memory.OamRam, address); address += 0x20; } for (int i = 0; i < 4; i++) { priorityObjList[i] = new List <Obj>(); } }
public LcdController(GameboyAdvance gba) { this.gba = gba; frameBuffer0 = new DirectBitmap(Screen_X_Resolution, Screen_Y_Resolution); frameBuffer1 = new DirectBitmap(Screen_X_Resolution, Screen_Y_Resolution); FrameBuffer = frameBuffer0; drawBuffer = frameBuffer1; this.Palettes = new Palettes(); DisplayControlRegister = new DisplayControlRegister(this); DispStatRegister = new DisplayStatusRegister(this); BgControlRegisters = new BgControlRegister[4]; Bg = new Background[4]; for (int i = 0; i < 4; i++) { BgControlRegisters[i] = new BgControlRegister(this, i); Bg[i] = new Background(gba, i, BgControlRegisters[i]); priorityObjList[i] = new List<Obj>(); } Obj = new Obj[Max_Sprites]; for (int i = 0; i < Max_Sprites; i++) { Obj[i] = new Obj(gba, new ObjAttributes(gba, i * 8, gba.Memory.OamRam)); } OamAffineMatrices = new OamAffineMatrix[Max_OAM_Matrices]; UInt32 address = 0x00000006; for (int i = 0; i < 32; i++) { OamAffineMatrices[i] = new OamAffineMatrix(gba.Memory.OamRam, address); address += 0x20; } Windows = new Window[4]; for (int i = 0; i < 4; i++) { Windows[i] = new Window(gba); } #if THREADED_SCANLINE drawScanline = false; exitThread = false; scanlineThread = new Thread(new ThreadStart(ScanlineThread)); scanlineThread.Start(); #endif }
bool RenderSpritePixel(int screenX, int screenY, int priority, bool windowing, int windowRegion, ref int bgVisibleOverride) { int paletteIndex; // If a sprite has the same priority as a bg, the sprite is drawn on top, therefore we check sprites first foreach (var obj in priorityObjList[priority]) { if (obj.Attributes.RotationAndScaling) { // Clip against the bounding box which can be DoubleSize. This is the only time doublesize is actually checed if (obj.BoundingBoxScreenSpace.ContainsPoint(screenX, screenY) == false) { continue; } int sourceWidth = obj.Attributes.Dimensions.Width; int sourceHeight = obj.Attributes.Dimensions.Height; // The game will have set up the matrix to be the inverse texture mapping matrix. I.E it maps from screen space to texture space. Just what we need! OamAffineMatrix rotScaleMatrix = obj.Attributes.AffineMatrix(); // NB: Order of operations counts here! // Transform with the origin set to the centre of the sprite (that's what the - width/height /2 below is for) int originX = screenX - obj.Attributes.XPosition - (sourceWidth / 2); int originY = screenY - obj.Attributes.YPosition - (sourceHeight / 2); // Not well documented anywhere but when double size is enabled we render offset by half the original source width / height if(obj.Attributes.DoubleSize) { originX -= sourceWidth / 2; originY -= sourceHeight / 2; } int transformedX, transformedY; rotScaleMatrix.Multiply(originX , originY, out transformedX, out transformedY); // Transform back from centre of sprite transformedX += (sourceWidth / 2); transformedY += (sourceHeight / 2); paletteIndex = obj.PixelValue(transformedX, transformedY); } else { if (obj.BoundingBoxScreenSpace.ContainsPoint(screenX, screenY) == false) { continue; } //paletteIndex = obj.PixelScreenValue(x, scanline); paletteIndex = obj.PixelValue(screenX - obj.Attributes.XPositionAdjusted(), screenY - obj.Attributes.YPositionAdjusted()); } // Pal 0 == Transparent if (paletteIndex == 0) { continue; } // TODO: I *think* this will render the Obj window correctly but i cannot test it yet // This pixel belongs to a sprite in the Obj Window and Win 0 & 1 are not enclosing this pixel if (windowing && DisplayControlRegister.DisplayObjWin && obj.Attributes.Mode == ObjAttributes.ObjMode.ObjWindow && ((windowRegion & (int)TileHelpers.WindowRegion.WindowIn) == 0)) { bgVisibleOverride = Windows[(int)Window.WindowName.WindowObj].DisplayBg0 | Windows[(int)Window.WindowName.WindowObj].DisplayBg1 | Windows[(int)Window.WindowName.WindowObj].DisplayBg2 | Windows[(int)Window.WindowName.WindowObj].DisplayBg3; return false; } drawBuffer.SetPixel(screenX, screenY, Palettes.Palette1[paletteIndex]); return true; } return false; }