public ObjectRenderer(MathboxRenderer mathboxRenderer)
            {
                Parent             = mathboxRenderer;
                DisplayListManager = Parent.DisplayListManager;
                Memory             = Parent.Memory;

#if WIDESCREEN_STARS
                // load 123 stars from ROM starfield
                byte[] table = Parent.Machine.Mathbox.ROM[2];
                for (int n = 0; n < 123; n++)
                {
                    int   addr = 0x3140 + n * 8;
                    Int16 x    = (Int16)(table[addr & 0x1FFF] * 256 + table[(addr + 1) & 0x1FFF]); addr += 2;
                    Int16 y    = (Int16)(table[addr & 0x1FFF] * 256 + table[(addr + 1) & 0x1FFF]); addr += 2;
                    Int16 z    = (Int16)(table[addr & 0x1FFF] * 256 + table[(addr + 1) & 0x1FFF]); addr += 2;
                    Stars[n] = new Vector3(x, y, z);
                }

                // fill in the blanks with some more random stars
                PRNG r = new PRNG(0xDEAD);
                for (int n = 123; n < Stars.Length;)
                {
                    const int size  = 10000;
                    double    theta = 2 * Math.PI * r.NextDouble;
                    double    phi   = Math.Acos(1 - 2 * r.NextDouble);
                    double    x     = size * Math.Sin(phi) * Math.Cos(theta);
                    double    y     = size * Math.Sin(phi) * Math.Sin(theta);
                    double    z     = size * Math.Abs(Math.Cos(phi));
                    if (x < -3000 || x > 3500)
                    {
                        Vector3 v = new Vector3((float)x, (float)y, (float)z);
                        v.Normalize();
                        v         *= 10000;
                        Stars[n++] = v;
                    }
                }
#endif
            }
        MathboxRenderer(Machine machine, ScreenManager screenManager)
        {
            Machine       = machine;
            Memory        = Machine.Mathbox.Memory16;
            ScreenManager = screenManager;

            if (!(screenManager.Game is I_Robot.Game game))
            {
                throw new Exception("VideoInterpreter can only be used with I_Robot.Game");
            }
            Game = game;

            DisplayListManager = new DisplayList.Manager(this);
            Object             = new ObjectRenderer(this);
            Terrain            = new TerrainRenderer(this);

            // create our scene buffer
            // this buffer has a z-buffer
            SceneBuffer = new RenderTarget2D(
                Game.GraphicsDevice,
                Game.GraphicsDevice.Viewport.Width,
                Game.GraphicsDevice.Viewport.Height,
                false,
                Game.GraphicsDevice.PresentationParameters.BackBufferFormat,
                DepthFormat.None,
                8,
                RenderTargetUsage.DiscardContents);

            // create our two screen buffers
            // these buffers do not require depth sorting, they are simply raw bitmaps
            // however the contents need to be preserved when rendering context is reset
            for (int n = 0; n < ScreenBuffers.Length; n++)
            {
                ScreenBuffers[n] = new RenderTarget2D(
                    Game.GraphicsDevice,
                    Game.GraphicsDevice.Viewport.Width,
                    Game.GraphicsDevice.Viewport.Height,
                    false,
                    Game.GraphicsDevice.PresentationParameters.BackBufferFormat,
                    DepthFormat.None,
                    0,
                    RenderTargetUsage.PreserveContents);
            }

            camTarget   = new Vector3(0f, 0f, 0f);
            camPosition = new Vector3(0f, 0f, -1f);

            double scaleToMonitor = Emulation.Machine.MonitorAspectRatio / Emulation.Machine.NativeAspectRatio;

            projectionMatrix = Matrix.CreatePerspectiveFieldOfView(
                MathHelper.ToRadians(45f),
                (float)(Game.GraphicsDevice.Viewport.AspectRatio / scaleToMonitor),
                0.1f,
                65536f);

            // it's important to move the projection matrix down a bit, this matches what I, Robot seems to do
            projectionMatrix = projectionMatrix * Matrix.CreateTranslation(new Vector3(0, -0.1f, 0));
            viewMatrix       = Matrix.CreateLookAt(camPosition, camTarget, Vector3.Up);
            worldMatrix      = Matrix.CreateWorld(Vector3.Zero, Vector3.Forward, Vector3.Down);

            basicEffect       = new BasicEffect(Game.GraphicsDevice);
            basicEffect.Alpha = 1f;
            basicEffect.VertexColorEnabled = true; // Want to see the colors of the vertices, this needs to be on
            // Lighting requires normal information which VertexPositionColor does not have
            // If you want to use lighting and VPC you need to create a custom def
            basicEffect.LightingEnabled = false;
        }
 public TerrainRenderer(MathboxRenderer mathboxRenderer)
 {
     Parent             = mathboxRenderer;
     Memory             = Parent.Memory;
     DisplayListManager = Parent.DisplayListManager;
 }