Added SPU IO mapping to GUI

This commit is contained in:
Washi 2017-08-13 23:12:56 +02:00
parent 1d3c48c602
commit cc09af5349
4 changed files with 166 additions and 19 deletions

View File

@ -10,6 +10,9 @@ EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emux.GameBoy.Tests", "Emux.GameBoy.Tests\Emux.GameBoy.Tests.csproj", "{365C6CF7-99E3-4861-B63B-E9D352E386AF}"
EndProject
Global
GlobalSection(Performance) = preSolution
HasPerformanceSessions = true
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU

View File

@ -6,7 +6,9 @@
xmlns:local="clr-namespace:Emux.Gui"
xmlns:converters="clr-namespace:Emux.Gui.Converters"
mc:Ignorable="d"
Title="IO memory view" Height="523.157" Width="584.81" Closing="IOWindowOnClosing" WindowStyle="ToolWindow" IsVisibleChanged="IOWindowOnIsVisibleChanged">
Title="IO memory view" Height="523.157" Width="581.271" Closing="IOWindowOnClosing" WindowStyle="ToolWindow"
IsVisibleChanged="IOWindowOnIsVisibleChanged"
x:Name="Root">
<Window.CommandBindings>
<CommandBinding Command="Close" CanExecute="CommandBindingOnCanAlwaysExecute" Executed="CloseCommandOnExecuted"/>
<CommandBinding Command="Refresh" CanExecute="CommandBindingOnCanAlwaysExecute"
@ -20,8 +22,12 @@
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TabControl>
<TabControl Grid.ColumnSpan="2">
<TabItem Header="GPU">
<Grid>
<Grid.ColumnDefinitions>
@ -29,7 +35,7 @@
<ColumnDefinition Width="5"/>
<ColumnDefinition Width="263*" />
</Grid.ColumnDefinitions>
<ListView x:Name="GpuRegistersView" d:DataContext="{d:DesignInstance local:RegisterItem}" MouseDoubleClick="GpuRegistersViewOnItemActivate">
<ListView x:Name="GpuRegistersView" d:DataContext="{d:DesignInstance local:RegisterItem}" MouseDoubleClick="RegistersViewOnItemActivate">
<ListView.View>
<GridView>
<GridViewColumn Header="Offset" Width="75" DisplayMemberBinding="{Binding Path=Offset, Converter={StaticResource HexConverter}}"/>
@ -87,13 +93,127 @@
</Grid>
</Grid>
</TabItem>
</TabControl>
<local:TitledOverlay Grid.Row="0" x:Name="DisabledOverlay" Visibility="Hidden"
Title="The emulator is running..."
Subtitle="Changes to IO registers cannot be made right now. "/>
<TabItem Header="SPU">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="5"/>
<ColumnDefinition/>
<ColumnDefinition Width="5"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="5"/>
<RowDefinition/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="1" Margin="5" Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Stretch">
<GroupBox Grid.Row="0" Grid.Column="0" Header="Master">
<ListView x:Name="MasterSoundRegistersView" d:DataContext="{d:DesignInstance local:RegisterItem}" MouseDoubleClick="RegistersViewOnItemActivate">
<ListView.View>
<GridView>
<GridViewColumn Header="Offset" Width="50" DisplayMemberBinding="{Binding Path=Offset, Converter={StaticResource HexConverter}}"/>
<GridViewColumn Header="Name" Width="50" DisplayMemberBinding="{Binding DisplayName}"/>
<GridViewColumn Header="Value" Width="50" DisplayMemberBinding="{Binding Value, Converter={StaticResource HexConverter}}"/>
</GridView>
</ListView.View>
<ListView.Items>
<local:RegisterItem Offset="0xFF24" DisplayName="NR51"/>
<local:RegisterItem Offset="0xFF25" DisplayName="NR52"/>
<local:RegisterItem Offset="0xFF26" DisplayName="NR53"/>
</ListView.Items>
</ListView>
</GroupBox>
<GroupBox Grid.Row="0" Grid.Column="2" Header="#1 (Square + sweep)">
<ListView x:Name="Sound1RegistersView" d:DataContext="{d:DesignInstance local:RegisterItem}" MouseDoubleClick="RegistersViewOnItemActivate">
<ListView.View>
<GridView>
<GridViewColumn Header="Offset" Width="50" DisplayMemberBinding="{Binding Path=Offset, Converter={StaticResource HexConverter}}"/>
<GridViewColumn Header="Name" Width="50" DisplayMemberBinding="{Binding DisplayName}"/>
<GridViewColumn Header="Value" Width="50" DisplayMemberBinding="{Binding Value, Converter={StaticResource HexConverter}}"/>
</GridView>
</ListView.View>
<ListView.Items>
<local:RegisterItem Offset="0xFF10" DisplayName="NR10"/>
<local:RegisterItem Offset="0xFF11" DisplayName="NR11"/>
<local:RegisterItem Offset="0xFF12" DisplayName="NR12"/>
<local:RegisterItem Offset="0xFF13" DisplayName="NR13"/>
<local:RegisterItem Offset="0xFF14" DisplayName="NR14"/>
</ListView.Items>
</ListView>
</GroupBox>
<GridSplitter Grid.Row="0" Grid.Column="3" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>
<GroupBox Grid.Row="0" Grid.Column="4" Header="#2 (Square)">
<ListView x:Name="Sound2RegistersView" d:DataContext="{d:DesignInstance local:RegisterItem}" MouseDoubleClick="RegistersViewOnItemActivate">
<ListView.View>
<GridView>
<GridViewColumn Header="Offset" Width="50" DisplayMemberBinding="{Binding Path=Offset, Converter={StaticResource HexConverter}}"/>
<GridViewColumn Header="Name" Width="50" DisplayMemberBinding="{Binding DisplayName}"/>
<GridViewColumn Header="Value" Width="50" DisplayMemberBinding="{Binding Value, Converter={StaticResource HexConverter}}"/>
</GridView>
</ListView.View>
<ListView.Items>
<local:RegisterItem Offset="0xFF15" DisplayName="NR20"/>
<local:RegisterItem Offset="0xFF16" DisplayName="NR21"/>
<local:RegisterItem Offset="0xFF17" DisplayName="NR22"/>
<local:RegisterItem Offset="0xFF18" DisplayName="NR23"/>
<local:RegisterItem Offset="0xFF19" DisplayName="NR24"/>
</ListView.Items>
</ListView>
</GroupBox>
<GridSplitter Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="5" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>
<GroupBox Grid.Row="2" Grid.Column="2" Header="#3 (Wave)">
<ListView x:Name="Sound3RegistersView" d:DataContext="{d:DesignInstance local:RegisterItem}" MouseDoubleClick="RegistersViewOnItemActivate">
<ListView.View>
<GridView>
<GridViewColumn Header="Offset" Width="50" DisplayMemberBinding="{Binding Path=Offset, Converter={StaticResource HexConverter}}"/>
<GridViewColumn Header="Name" Width="50" DisplayMemberBinding="{Binding DisplayName}"/>
<GridViewColumn Header="Value" Width="50" DisplayMemberBinding="{Binding Value, Converter={StaticResource HexConverter}}"/>
</GridView>
</ListView.View>
<ListView.Items>
<local:RegisterItem Offset="0xFF1A" DisplayName="NR30"/>
<local:RegisterItem Offset="0xFF1B" DisplayName="NR31"/>
<local:RegisterItem Offset="0xFF1C" DisplayName="NR32"/>
<local:RegisterItem Offset="0xFF1D" DisplayName="NR33"/>
<local:RegisterItem Offset="0xFF1E" DisplayName="NR34"/>
</ListView.Items>
</ListView>
</GroupBox>
<GridSplitter Grid.Row="2" Grid.Column="3" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>
<GroupBox Grid.Row="2" Grid.Column="4" Header="#4 (Noise)">
<ListView x:Name="Sound4RegistersView" d:DataContext="{d:DesignInstance local:RegisterItem}" MouseDoubleClick="RegistersViewOnItemActivate">
<ListView.View>
<GridView>
<GridViewColumn Header="Offset" Width="50" DisplayMemberBinding="{Binding Path=Offset, Converter={StaticResource HexConverter}}"/>
<GridViewColumn Header="Name" Width="50" DisplayMemberBinding="{Binding DisplayName}"/>
<GridViewColumn Header="Value" Width="50" DisplayMemberBinding="{Binding Value, Converter={StaticResource HexConverter}}"/>
</GridView>
</ListView.View>
<ListView.Items>
<local:RegisterItem Offset="0xFF1F" DisplayName="NR40"/>
<local:RegisterItem Offset="0xFF20" DisplayName="NR41"/>
<local:RegisterItem Offset="0xFF21" DisplayName="NR42"/>
<local:RegisterItem Offset="0xFF22" DisplayName="NR43"/>
<local:RegisterItem Offset="0xFF23" DisplayName="NR44"/>
</ListView.Items>
</ListView>
</GroupBox>
</Grid>
</TabItem>
</TabControl>
<StackPanel Grid.Row="1" Grid.Column="0" Margin="5" Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Stretch">
<CheckBox Content="Auto-refresh" VerticalAlignment="Center" IsChecked="{Binding ElementName=Root, Path=AutoRefresh}"/>
</StackPanel>
<StackPanel Grid.Row="1" Grid.Column="1" Margin="5" Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Stretch">
<Button Content="Refresh" Padding="20,5" MinWidth="100" Margin="5" Command="Refresh"/>
<Button Content="Close" Padding="20,5" MinWidth="100" Margin="5" IsCancel="True" Command="Close"/>
</StackPanel>

View File

@ -3,7 +3,9 @@ using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Threading;
using Emux.GameBoy.Graphics;
namespace Emux.Gui
@ -13,11 +15,21 @@ namespace Emux.Gui
/// </summary>
public partial class IOWindow : Window
{
private GameBoy.GameBoy _device;
public static readonly DependencyProperty AutoRefreshProperty = DependencyProperty.Register("AutoRefresh",
typeof(bool), typeof(IOWindow), new PropertyMetadata((o, e) => ((IOWindow)o)._refreshTimer.IsEnabled = (bool) e.NewValue));
private GameBoy.GameBoy _device;
private readonly DispatcherTimer _refreshTimer;
public IOWindow()
{
InitializeComponent();
_refreshTimer = new DispatcherTimer(new TimeSpan(0, 0, 0, 0, 50), DispatcherPriority.Background,
(o, e) =>
{
if (Device != null)
RefreshView();
}, Dispatcher);
}
public GameBoy.GameBoy Device
@ -35,7 +47,6 @@ namespace Emux.Gui
value.Cpu.Resumed -= CpuOnResumed;
}
_device = value;
DisabledOverlay.DisableOverlay();
if (_device != null)
{
_device.Cpu.Paused += CpuOnPaused;
@ -45,6 +56,11 @@ namespace Emux.Gui
}
}
}
public bool AutoRefresh
{
get { return (bool) GetValue(AutoRefreshProperty); }
set { SetValue(AutoRefreshProperty, value); }
}
private void CpuOnPaused(object sender, EventArgs eventArgs)
{
@ -52,16 +68,11 @@ namespace Emux.Gui
{
if (IsVisible)
RefreshView();
DisabledOverlay.DisableOverlay();
});
}
private void CpuOnResumed(object sender, EventArgs e)
{
Dispatcher.Invoke(() =>
{
DisabledOverlay.EnableOverlay(500);
});
}
public void RefreshView()
@ -71,6 +82,16 @@ namespace Emux.Gui
foreach (var item in GpuRegistersView.Items.Cast<RegisterItem>())
item.Value = Device.Memory.ReadByte(item.Offset);
foreach (var item in Sound1RegistersView.Items.Cast<RegisterItem>())
item.Value = Device.Memory.ReadByte(item.Offset);
foreach (var item in Sound2RegistersView.Items.Cast<RegisterItem>())
item.Value = Device.Memory.ReadByte(item.Offset);
foreach (var item in Sound3RegistersView.Items.Cast<RegisterItem>())
item.Value = Device.Memory.ReadByte(item.Offset);
foreach (var item in Sound4RegistersView.Items.Cast<RegisterItem>())
item.Value = Device.Memory.ReadByte(item.Offset);
foreach (var item in MasterSoundRegistersView.Items.Cast<RegisterItem>())
item.Value = Device.Memory.ReadByte(item.Offset);
}
private void IOWindowOnClosing(object sender, CancelEventArgs e)
@ -114,12 +135,13 @@ namespace Emux.Gui
StatFlagsListBox.RawValue;
}
private void GpuRegistersViewOnItemActivate(object sender, EventArgs e)
private void RegistersViewOnItemActivate(object sender, EventArgs e)
{
if (GpuRegistersView.SelectedItem == null)
var listView = (ListView) sender;
if (listView.SelectedItem == null)
return;
var item = (RegisterItem) GpuRegistersView.SelectedItem;
var item = (RegisterItem) listView.SelectedItem;
string text = item.Value.ToString("X2");
bool repeat = true;
while (repeat)
@ -145,6 +167,7 @@ namespace Emux.Gui
else
{
item.Value = newValue;
Device.Memory.WriteByte(item.Offset, newValue);
}
}
}

View File

@ -303,6 +303,7 @@ namespace Emux.Gui
_ioWindow.Device = null;
_videoWindow.Close();
_keypadWindow.Close();
_ioWindow.Close();
}
private void EnableSoundCommandOnExecuted(object sender, ExecutedRoutedEventArgs e)