Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -281,4 +281,6 @@ __pycache__/
.vscode/settings.json

BenchmarkDotNet.Artifacts/

/src/apps/Highbyte.DotNet6502.App.SadConsole/appsettings.Development.json
/src/apps/Highbyte.DotNet6502.App.SilkNetNative/appsettings.Development.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,56 @@ public C64ConfigUIConsole(SadConsoleHostApp sadConsoleHostApp, IConfiguration co

private void DrawUIItems()
{
// Automatic download of C64 ROMs
var autoDownloadROMButton = new Button("Auto download ROM files")
{
Name = "autoDownloadROMButton",
Position = (1, 2),
};
autoDownloadROMButton.Click += async (s, e) =>
{
var autoDownloadROMInfoLabel = Controls["autoDownloadROMInfoLabel"] as Label;
try
{
await AutoDownloadROMs();
autoDownloadROMInfoLabel.DisplayText = "ROMs downloaded OK";
autoDownloadROMInfoLabel.TextColor = Color.Green;
}
catch (Exception ex)
{
autoDownloadROMInfoLabel.DisplayText = ex.Message;
autoDownloadROMInfoLabel.TextColor = Color.Red;
}
finally
{
IsDirty = true; // Mark as dirty to update the UI
}
};
Controls.Add(autoDownloadROMButton);

// Manual download link
var openROMDownloadURLButton = new Button("Manual ROM download link")
{
Name = "openROMDownloadURLButton",
Position = (31, autoDownloadROMButton.Position.Y),
};
openROMDownloadURLButton.Click += (s, e) => OpenURL(new Uri(C64SystemConfig.ROMDownloadUrls[C64SystemConfig.KERNAL_ROM_NAME]).GetLeftPart(UriPartial.Authority));
Controls.Add(openROMDownloadURLButton);

// Auto ROM download status label
var autoDownloadROMInfoLabel = new Label(Width - 10)
{
Name = "autoDownloadROMInfoLabel",
Position = (1, autoDownloadROMButton.Bounds.MaxExtentY + 1),
IsEnabled = false,
DisplayText = "",
TextColor = Controls.GetThemeColors().Appearance_ControlDisabled.Foreground
};
Controls.Add(autoDownloadROMInfoLabel);


// ROM directory
var romDirectoryLabel = CreateLabel("ROM directory", 1, 1);
var romDirectoryLabel = CreateLabel("ROM directory", 1, autoDownloadROMInfoLabel.Position.Y + 2);
var romDirectoryTextBox = new TextBox(Width - 10)
{
Name = "romDirectoryTextBox",
Expand Down Expand Up @@ -118,27 +166,8 @@ private void DrawUIItems()
Controls.Add(selectChargenROMButton);


// URL for downloading C64 ROMs
var romDownloadsLabel = CreateLabel("ROM download link", 1, chargenROMTextBox.Bounds.MaxExtentY + 2);
var romDownloadLinkTextBox = new TextBox(Width - 10)
{
Name = "romDownloadLinkTextBox",
Position = (1, romDownloadsLabel.Bounds.MaxExtentY + 1),
IsEnabled = false,
Text = "https://www.commodore.ca/manuals/funet/cbm/firmware/computers/c64/index-t.html",
};
Controls.Add(romDownloadLinkTextBox);

var openROMDownloadURLButton = new Button("...")
{
Name = "openROMDownloadURLButton",
Position = (romDownloadLinkTextBox.Bounds.MaxExtentX + 2, romDownloadLinkTextBox.Position.Y),
};
openROMDownloadURLButton.Click += (s, e) => OpenURL(romDownloadLinkTextBox.Text);
Controls.Add(openROMDownloadURLButton);

// AI coding assistant selection
var codingAssistantLabel = CreateLabel("Basic AI assistant: ", 1, romDownloadLinkTextBox.Bounds.MaxExtentY + 3);
var codingAssistantLabel = CreateLabel("Basic AI assistant: ", 1, selectChargenROMButton.Bounds.MaxExtentY + 2);
var codingAssistantValue = CreateLabel($"{C64HostConfig.CodeSuggestionBackendType}", codingAssistantLabel.Bounds.MaxExtentX + 1, codingAssistantLabel.Position.Y);
codingAssistantValue.TextColor = Controls.GetThemeColors().White;

Expand Down Expand Up @@ -289,6 +318,46 @@ private void ShowROMFolderPickerDialog()
window.Show(true);
}

private async Task AutoDownloadROMs()
{
var romFolder = PathHelper.ExpandOSEnvironmentVariables(C64SystemConfig.ROMDirectory);
if (!Directory.Exists(romFolder))
{
Directory.CreateDirectory(romFolder);
}

using var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36");
//httpClient.DefaultRequestHeaders.Accept.ParseAdd("text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
httpClient.DefaultRequestHeaders.Accept.ParseAdd("*/*");

foreach (var romDownload in C64SystemConfig.ROMDownloadUrls)
{
var romName = romDownload.Key;
var romUrl = romDownload.Value;
var filename = Path.GetFileName(new Uri(romUrl).LocalPath);
var dest = Path.Combine(romFolder, filename);
try
{
using var response = await httpClient.GetAsync(romUrl);
if (!response.IsSuccessStatusCode)
throw new Exception($"Failed to get '{romUrl}' ({(int)response.StatusCode})");
await using var fs = new FileStream(dest, FileMode.Create, FileAccess.Write, FileShare.None);
await response.Content.CopyToAsync(fs);
System.Console.WriteLine($"Downloaded {filename} to {dest}");

// Update the C64SystemConfig with the downloaded ROM file
C64SystemConfig.SetROM(romName, filename);
}
catch (Exception ex)
{
if (File.Exists(dest))
File.Delete(dest);
throw new Exception($"Error downloading {romUrl}: {ex.Message}", ex);
}
}
}

protected override void OnIsDirtyChanged()
{
if (IsDirty)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,7 @@
</ItemGroup>

<ItemGroup>
<None Update="appsettings.Development.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>

<None Update="appsettings.Development.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Expand Down
3 changes: 0 additions & 3 deletions src/apps/Highbyte.DotNet6502.App.SadConsole/InfoConsole.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
using System.Text;
using Highbyte.DotNet6502.Systems.Commodore64;
using Highbyte.DotNet6502.Systems.Commodore64.Video;
using Highbyte.DotNet6502.Systems.Generic;
using Highbyte.DotNet6502.Systems.Logging.InMem;
using Highbyte.DotNet6502.Utils;
using Microsoft.Extensions.Logging;
using SadConsole.UI;
using SadConsole.UI.Controls;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Highbyte.DotNet6502.Systems.Commodore64;
using Highbyte.DotNet6502.Systems;
using Highbyte.DotNet6502.Systems.Commodore64.Config;
using Highbyte.DotNet6502.Utils;

namespace Highbyte.DotNet6502.App.SilkNetNative.ConfigUI;

Expand Down Expand Up @@ -35,8 +36,14 @@ public class SilkNetImGuiC64Config

private List<string> _validationErrors = new();

// ROM download state
private bool _isDownloadingRoms = false;
private string _downloadStatusMessage = "";
private bool _downloadSuccess = false;

//private static Vector4 s_informationColor = new Vector4(1.0f, 1.0f, 1.0f, 1.0f);
private static Vector4 s_errorColor = new Vector4(1.0f, 0.0f, 0.0f, 1.0f);
private static Vector4 s_successColor = new Vector4(0.0f, 1.0f, 0.0f, 1.0f);
//private static Vector4 s_warningColor = new Vector4(0.5f, 0.8f, 0.8f, 1);
private static Vector4 s_okButtonColor = new Vector4(0.0f, 0.6f, 0.0f, 1.0f);

Expand All @@ -60,11 +67,16 @@ internal void Init(C64HostConfig c64HostConfig)

_romDirectory = _systemConfig.ROMDirectory;
_kernalRomFile = _systemConfig.HasROM(C64SystemConfig.KERNAL_ROM_NAME) ? _systemConfig.GetROM(C64SystemConfig.KERNAL_ROM_NAME).File! : "";
_basicRomFile = _systemConfig.HasROM(C64SystemConfig.KERNAL_ROM_NAME) ? _systemConfig.GetROM(C64SystemConfig.BASIC_ROM_NAME).File! : "";
_chargenRomFile = _systemConfig.HasROM(C64SystemConfig.KERNAL_ROM_NAME) ? _systemConfig.GetROM(C64SystemConfig.CHARGEN_ROM_NAME).File! : "";
_basicRomFile = _systemConfig.HasROM(C64SystemConfig.BASIC_ROM_NAME) ? _systemConfig.GetROM(C64SystemConfig.BASIC_ROM_NAME).File! : "";
_chargenRomFile = _systemConfig.HasROM(C64SystemConfig.CHARGEN_ROM_NAME) ? _systemConfig.GetROM(C64SystemConfig.CHARGEN_ROM_NAME).File! : "";

_selectedRenderer = _availableRenderers.ToList().IndexOf(_hostConfig.Renderer.ToString());
_openGLFineScrollPerRasterLineEnabled = _hostConfig.SilkNetOpenGlRendererConfig.UseFineScrollPerRasterLine;

// Reset download status
_isDownloadingRoms = false;
_downloadStatusMessage = "";
_downloadSuccess = false;
}

public void PostOnRender(string dialogLabel)
Expand All @@ -77,6 +89,31 @@ public void PostOnRender(string dialogLabel)
//ImGui.LabelText("VIC2 model", $"{_config!.Vic2Model}");

ImGui.Text("ROMs");

// ROM auto-download button
ImGui.BeginDisabled(_isDownloadingRoms);
if (ImGui.Button("Auto download ROM files"))
{
_ = Task.Run(async () => await AutoDownloadROMs());
}
ImGui.EndDisabled();

ImGui.SameLine();
if (ImGui.Button("Manual ROM download link"))
{
var url = new Uri(_systemConfig.ROMDownloadUrls[C64SystemConfig.KERNAL_ROM_NAME]).GetLeftPart(UriPartial.Authority);
OpenURL(url);
}

// Download status message
if (!string.IsNullOrEmpty(_downloadStatusMessage))
{
var color = _downloadSuccess ? s_successColor : s_errorColor;
ImGui.PushStyleColor(ImGuiCol.Text, color);
ImGui.TextWrapped(_downloadStatusMessage);
ImGui.PopStyleColor();
}

if (ImGui.InputText("Directory", ref _romDirectory, 255))
{
_systemConfig!.ROMDirectory = _romDirectory;
Expand Down Expand Up @@ -201,4 +238,89 @@ public void PostOnRender(string dialogLabel)
ImGui.EndPopup();
}
}

private async Task AutoDownloadROMs()
{
_isDownloadingRoms = true;
_downloadStatusMessage = "Downloading ROMs...";
_downloadSuccess = false;

try
{
var romFolder = PathHelper.ExpandOSEnvironmentVariables(_systemConfig.ROMDirectory);
await DownloadC64RomsAsync(_systemConfig.ROMDownloadUrls, romFolder);

// Update the system config with the downloaded ROM files
foreach (var romDownload in _systemConfig.ROMDownloadUrls)
{
var romName = romDownload.Key;
var romUrl = romDownload.Value;
var filename = Path.GetFileName(new Uri(romUrl).LocalPath);
_systemConfig.SetROM(romName, filename);
}

// Update the UI variables
_romDirectory = _systemConfig.ROMDirectory;
_kernalRomFile = _systemConfig.HasROM(C64SystemConfig.KERNAL_ROM_NAME) ? _systemConfig.GetROM(C64SystemConfig.KERNAL_ROM_NAME).File! : "";
_basicRomFile = _systemConfig.HasROM(C64SystemConfig.BASIC_ROM_NAME) ? _systemConfig.GetROM(C64SystemConfig.BASIC_ROM_NAME).File! : "";
_chargenRomFile = _systemConfig.HasROM(C64SystemConfig.CHARGEN_ROM_NAME) ? _systemConfig.GetROM(C64SystemConfig.CHARGEN_ROM_NAME).File! : "";

_downloadStatusMessage = "ROMs downloaded successfully!";
_downloadSuccess = true;
}
catch (Exception ex)
{
_downloadStatusMessage = $"Error downloading ROMs: {ex.Message}";
_downloadSuccess = false;
}
finally
{
_isDownloadingRoms = false;
}
}

private async Task DownloadC64RomsAsync(Dictionary<string, string> romDownloadUrls, string destinationDirectory)
{
if (!Directory.Exists(destinationDirectory))
{
Directory.CreateDirectory(destinationDirectory);
}

using var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36");
httpClient.DefaultRequestHeaders.Accept.ParseAdd("text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");

foreach (var romDownload in romDownloadUrls)
{
var romName = romDownload.Key;
var romUrl = romDownload.Value;
var filename = Path.GetFileName(new Uri(romUrl).LocalPath);
var dest = Path.Combine(destinationDirectory, filename);

try
{
using var response = await httpClient.GetAsync(romUrl);
if (!response.IsSuccessStatusCode)
throw new Exception($"Failed to get '{romUrl}' ({(int)response.StatusCode})");

await using var fs = new FileStream(dest, FileMode.Create, FileAccess.Write, FileShare.None);
await response.Content.CopyToAsync(fs);
Console.WriteLine($"Downloaded {filename} to {dest}");
}
catch (Exception ex)
{
if (File.Exists(dest))
File.Delete(dest);
throw new Exception($"Error downloading {romUrl}: {ex.Message}", ex);
}
}
}

private void OpenURL(string url)
{
if (!Uri.TryCreate(url, UriKind.Absolute, out var uri))
throw new Exception($"Invalid URL: {url}");
// Launch the URL in the default browser
Process.Start(new ProcessStartInfo(uri.AbsoluteUri) { UseShellExecute = true });
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
</ItemGroup>

<ItemGroup>
<None Update="appsettings.Development.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Expand Down
4 changes: 3 additions & 1 deletion src/apps/Highbyte.DotNet6502.App.SilkNetNative/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
// ----------
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json");
.AddJsonFile("appsettings.json")
.AddJsonFile("appsettings.Development.json", optional: true);

IConfiguration Configuration = builder.Build();

// ----------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ public class C64HostConfig : IHostSystemConfig, ICloneable
{
public const string ConfigSectionName = "Highbyte.DotNet6502.C64.WASM";

//public const string DefaultCorsProxyURL = "https://api.allorigins.win/raw?url=";
public const string DefaultCorsProxyURL = "https://thingproxy.freeboard.io/fetch/";

private C64SystemConfig _systemConfig;
ISystemConfig IHostSystemConfig.SystemConfig => _systemConfig;

Expand All @@ -44,6 +47,8 @@ public void ClearDirty()

public C64AspNetInputConfig InputConfig { get; set; } = new C64AspNetInputConfig();

public string CorsProxyURL { get; set; } = DefaultCorsProxyURL;

private bool _basicAIAssistantDefaultEnabled;
[JsonIgnore]
public bool BasicAIAssistantDefaultEnabled
Expand Down
Loading
Loading