Frame rendering.

This commit is contained in:
Washi 2018-07-07 18:04:38 +02:00
parent 9f2094575c
commit 120d9455ba
5 changed files with 233 additions and 0 deletions

View File

@ -0,0 +1,15 @@
#----------------------------- Global Properties ----------------------------#
/outputDir:bin/$(Platform)
/intermediateDir:obj/$(Platform)
/platform:DesktopGL
/config:
/profile:Reach
/compress:False
#-------------------------------- References --------------------------------#
#---------------------------------- Content ---------------------------------#

View File

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<MonoGameContentReference Include="**\*.mgcb" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MonoGame.Content.Builder" Version="3.7.0.4" />
<PackageReference Include="MonoGame.Framework.DesktopGL.Core" Version="3.7.0.7" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Emux.GameBoy\Emux.GameBoy.csproj" />
</ItemGroup>
</Project>

116
Emux.MonoGame/EmuxHost.cs Normal file
View File

@ -0,0 +1,116 @@
using System;
using Emux.GameBoy.Cpu;
using Emux.GameBoy.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Color = Microsoft.Xna.Framework.Color;
namespace Emux.MonoGame
{
public class EmuxHost : Game, IClock, IVideoOutput
{
public new event EventHandler Tick;
private GraphicsDeviceManager _graphics;
private SpriteBatch _spriteBatch;
private Texture2D _video;
private bool _clockEnabled = false;
public EmuxHost()
{
_graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
IsMouseVisible = true;
}
public GameBoy.GameBoy GameBoy
{
get;
set;
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
_spriteBatch = new SpriteBatch(GraphicsDevice);
_video = new Texture2D(GraphicsDevice, 160, 144);
GameBoy.Cpu.Run();
}
protected override void Update(GameTime gameTime)
{
if (_clockEnabled)
Tick?.Invoke(this, EventArgs.Empty);
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed ||
Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
_spriteBatch.Begin();
float aspectRatio = 160f / 144f;
int screenHeight = _graphics.PreferredBackBufferHeight;
int screenWidth = _graphics.PreferredBackBufferWidth;
int frameWidth;
int frameHeight;
if (screenHeight > screenWidth)
{
frameWidth = screenWidth;
frameHeight = (int) (frameWidth / aspectRatio);
}
else
{
frameHeight = screenHeight;
frameWidth = (int) (frameHeight / aspectRatio);
}
_spriteBatch.Draw(_video,
new Rectangle((screenWidth - frameWidth) / 2, (screenHeight - frameHeight) / 2, frameWidth, frameHeight),
Color.White);
_spriteBatch.End();
base.Draw(gameTime);
}
public void Start()
{
_clockEnabled = true;
}
public void Stop()
{
_clockEnabled = false;
}
public void RenderFrame(byte[] pixelData)
{
var rawData = new byte[160 * 144 * sizeof(int)];
for (int i = 0, j = 0; j < pixelData.Length; i+=4, j+=3)
{
rawData[i] = pixelData[j + 2];
rawData[i + 1] = pixelData[j + 1];
rawData[i + 2] = pixelData[j];
rawData[i + 3] = 255;
}
_video.SetData(rawData);
}
}
}

80
Emux.MonoGame/Program.cs Normal file
View File

@ -0,0 +1,80 @@
using System;
using System.IO;
using Emux.GameBoy.Audio;
using Emux.GameBoy.Cartridge;
namespace Emux.MonoGame
{
internal class AudioOutput : IAudioChannelOutput
{
public int SampleRate
{
get { return 1; }
}
public void BufferSoundSamples(float[] sampleData, int offset, int length)
{
}
}
public static class Program
{
private static void PrintAbout()
{
Console.WriteLine("Emux.MonoGame: v{0}, Core: v{1}",
typeof(Program).Assembly.GetName().Version,
typeof(GameBoy.GameBoy).Assembly.GetName().Version);
Console.WriteLine("Copyright © Washi 2017-2018");
Console.WriteLine("Repository and issue tracker: https://www.github.com/Washi1337/Emux");
}
[STAThread]
private static void Main(string[] args)
{
PrintAbout();
string romFile;
string saveFile;
switch (args.Length)
{
default:
Console.WriteLine("Usage: Emux.MonoGame.exe romfile [savefile]");
return;
case 1:
romFile = args[0].Replace("\"", "");
saveFile = Path.ChangeExtension(romFile, ".sav");
break;
case 2:
romFile = args[0].Replace("\"", "");
saveFile = args[1].Replace("\"", "");
break;
}
if (!File.Exists(romFile))
{
Console.WriteLine("ROM could not be found!");
return;
}
using (var game = new EmuxHost())
using (var saveFs = File.Open(saveFile, FileMode.OpenOrCreate))
{
var cartridge = new EmulatedCartridge(File.ReadAllBytes(romFile), new StreamedExternalMemory(saveFs));
var device = new GameBoy.GameBoy(cartridge, game, false);
game.GameBoy = device;
device.Gpu.VideoOutput = game;
for (var i = 0; i < device.Spu.Channels.Count; i++)
{
var channel = device.Spu.Channels[i];
channel.ChannelOutput = new AudioOutput();
channel.ChannelVolume = 0.05f;
}
game.Run();
}
}
}
}

View File

@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emux", "Emux\Emux.csproj",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emux.GameBoy.Tests", "Emux.GameBoy.Tests\Emux.GameBoy.Tests.csproj", "{365C6CF7-99E3-4861-B63B-E9D352E386AF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emux.MonoGame", "Emux.MonoGame\Emux.MonoGame.csproj", "{A8CDE19D-11F0-47AB-8391-EFF20F3532FB}"
EndProject
Global
GlobalSection(Performance) = preSolution
HasPerformanceSessions = true
@ -30,6 +32,10 @@ Global
{365C6CF7-99E3-4861-B63B-E9D352E386AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{365C6CF7-99E3-4861-B63B-E9D352E386AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{365C6CF7-99E3-4861-B63B-E9D352E386AF}.Release|Any CPU.Build.0 = Release|Any CPU
{A8CDE19D-11F0-47AB-8391-EFF20F3532FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A8CDE19D-11F0-47AB-8391-EFF20F3532FB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A8CDE19D-11F0-47AB-8391-EFF20F3532FB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A8CDE19D-11F0-47AB-8391-EFF20F3532FB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE