@@ -322,7 +322,7 @@ try {
322322 $colDefine.Name = " Define"
323323 $colDefine.HeaderText = " Define"
324324 $colDefine.ReadOnly = $true
325- $colDefine.Width = 420
325+ $colDefine.Width = 454
326326
327327 $colFuture = New-Object Windows.Forms.DataGridViewComboBoxColumn
328328 $colFuture.Name = " Will Be After Apply"
@@ -418,7 +418,15 @@ try {
418418 $btnRestore.Location = New-Object Drawing.Point(550 , 10 )
419419 $btnRestore.BackColor = [System.Drawing.Color ]::LightCoral
420420 $btnRestore.FlatStyle = " Flat"
421-
421+
422+ # --- Copy to SD Button ---
423+ $btnCopyToSD = New-Object Windows.Forms.Button
424+ $btnCopyToSD.Text = " Copy to SD"
425+ $btnCopyToSD.Size = New-Object Drawing.Size(80 , 35 )
426+ $btnCopyToSD.Location = New-Object Drawing.Point(640 , 10 )
427+ $btnCopyToSD.BackColor = [System.Drawing.Color ]::LightCyan
428+ $btnCopyToSD.FlatStyle = " Flat"
429+
422430 # Create tooltips for buttons
423431 $tooltip = New-Object Windows.Forms.ToolTip
424432 $tooltip.SetToolTip ($btnRefreshCOM , " Searches for available COM ports" )
@@ -427,6 +435,7 @@ try {
427435 $tooltip.SetToolTip ($btnApply , " Writes the changes colored in red to the config.h" )
428436 $tooltip.SetToolTip ($btnArduinoIDE , " Launches the Arduino IDE so you can compile and flash the code" )
429437 $tooltip.SetToolTip ($btnRestore , " Restores the saved firmware in case something went wrong" )
438+ $tooltip.SetToolTip ($btnCopyToSD , " Copies the game databases to the SD card and hides them" )
430439
431440 # Status label
432441 $statusLabel = New-Object Windows.Forms.Label
@@ -727,7 +736,8 @@ try {
727736 Invoke-WebRequest " https://github.com/sanni/cartreader/archive/refs/heads/master.zip" - OutFile " master.zip"
728737
729738 # Extracting
730- Expand-Archive - Path " master.zip" - DestinationPath " master"
739+ Add-Type - AssemblyName System.IO.Compression.FileSystem
740+ [System.IO.Compression.ZipFile ]::ExtractToDirectory(" master.zip" , " master" )
731741
732742 # Moving to sub-folders
733743 Move-Item " master\cartreader-master\Cart_Reader" " Arduino IDE\portable\sketchbook\Cart_Reader"
@@ -745,8 +755,6 @@ try {
745755 if (Test-Path " master" ) { Remove-Item " master" - Recurse - Force }
746756 if (Test-Path " master.zip" ) { Remove-Item " master.zip" - Force }
747757
748- Clear-Host
749-
750758 # Reload config data after update
751759 $script :configDefs = Get-ConfigData
752760 $script :applyChanges = @ {}
@@ -861,6 +869,7 @@ try {
861869 }
862870 })
863871
872+ # Apply button click handler
864873 $btnApply.Add_Click ({
865874 try {
866875 $newConfigDefs = @ {}
@@ -1080,6 +1089,153 @@ try {
10801089 }
10811090 })
10821091
1092+ # Copy to SD button click handler
1093+ $btnCopyToSD.Add_Click ({
1094+ try {
1095+ # Get current script directory more defensively
1096+ $scriptDir = $null
1097+ if ($PSScriptRoot ) {
1098+ $scriptDir = $PSScriptRoot
1099+ } elseif ($MyInvocation.MyCommand.Path ) {
1100+ $scriptDir = Split-Path $MyInvocation.MyCommand.Path - Parent
1101+ } else {
1102+ $scriptDir = Get-Location
1103+ }
1104+
1105+ # Ask user to select SD card root
1106+ $folderBrowser = New-Object System.Windows.Forms.FolderBrowserDialog
1107+ $folderBrowser.Description = " Select the root of your SD card"
1108+ $folderBrowser.ShowNewFolderButton = $false
1109+ $folderBrowser.RootFolder = [System.Environment + SpecialFolder ]::MyComputer
1110+
1111+ $dialogResult = $folderBrowser.ShowDialog ()
1112+
1113+ if ($dialogResult -eq [System.Windows.Forms.DialogResult ]::OK) {
1114+ $sdPath = $folderBrowser.SelectedPath
1115+
1116+ # Validate SD path
1117+ if (-not $sdPath -or $sdPath.Trim () -eq " " ) {
1118+ [System.Windows.Forms.MessageBox ]::Show(" No SD card path selected." , " Error" , [System.Windows.Forms.MessageBoxButtons ]::OK, [System.Windows.Forms.MessageBoxIcon ]::Error)
1119+ return
1120+ }
1121+
1122+ # Build source path
1123+ $sourcePath = $null
1124+ if ($scriptDir ) {
1125+ $sourcePath = [System.IO.Path ]::Combine($scriptDir , " SD Card" )
1126+ }
1127+
1128+ if (-not $sourcePath -or $sourcePath.Trim () -eq " " ) {
1129+ [System.Windows.Forms.MessageBox ]::Show(" Could not determine source path." , " Error" , [System.Windows.Forms.MessageBoxButtons ]::OK, [System.Windows.Forms.MessageBoxIcon ]::Error)
1130+ return
1131+ }
1132+
1133+ # Check if source folder exists
1134+ if (-not (Test-Path - Path $sourcePath - PathType Container)) {
1135+ [System.Windows.Forms.MessageBox ]::Show(" The folder 'SD Card' was not found at: $sourcePath " , " Error" , [System.Windows.Forms.MessageBoxButtons ]::OK, [System.Windows.Forms.MessageBoxIcon ]::Error)
1136+ return
1137+ }
1138+
1139+ # Get all items recursively, excluding config.txt
1140+ $allItems = @ ()
1141+
1142+ try {
1143+ $allItems = Get-ChildItem - Path $sourcePath - Recurse - Force - ErrorAction Stop | Where-Object {
1144+ $_.Name.ToLower () -ne " config.txt"
1145+ }
1146+ } catch {
1147+ [System.Windows.Forms.MessageBox ]::Show(" Failed to scan source directory: $ ( $_.Exception.Message ) " , " Error" , [System.Windows.Forms.MessageBoxButtons ]::OK, [System.Windows.Forms.MessageBoxIcon ]::Error)
1148+ return
1149+ }
1150+
1151+ if (-not $allItems -or $allItems.Count -eq 0 ) {
1152+ [System.Windows.Forms.MessageBox ]::Show(" No files found to copy." , " Information" , [System.Windows.Forms.MessageBoxButtons ]::OK, [System.Windows.Forms.MessageBoxIcon ]::Information)
1153+ return
1154+ }
1155+
1156+ $fileItems = $allItems | Where-Object { -not $_.PSIsContainer }
1157+ $totalFiles = if ($fileItems ) { $fileItems.Count } else { 0 }
1158+ $currentFile = 0
1159+
1160+ # Process each item
1161+ foreach ($item in $allItems ) {
1162+ try {
1163+ if (-not $item -or -not $item.FullName ) {
1164+ Write-Host " Skipping invalid item" - ForegroundColor Yellow
1165+ continue
1166+ }
1167+
1168+ # Calculate relative path using .NET methods for better reliability
1169+ $itemFullPath = $item.FullName
1170+ $sourceFullPath = (Get-Item $sourcePath ).FullName
1171+
1172+ if (-not $itemFullPath.StartsWith ($sourceFullPath )) {
1173+ Write-Host " Skipping item outside source path: $itemFullPath " - ForegroundColor Yellow
1174+ continue
1175+ }
1176+
1177+ $relativePath = $itemFullPath.Substring ($sourceFullPath.Length ).TrimStart([System.IO.Path ]::DirectorySeparatorChar)
1178+
1179+ if (-not $relativePath -or $relativePath.Trim () -eq " " ) {
1180+ Write-Host " Skipping item with empty relative path" - ForegroundColor Yellow
1181+ continue
1182+ }
1183+
1184+ $targetPath = [System.IO.Path ]::Combine($sdPath , $relativePath )
1185+
1186+ if ($item.PSIsContainer ) {
1187+ # Create directory
1188+ if (-not (Test-Path - Path $targetPath - PathType Container)) {
1189+ New-Item - ItemType Directory - Path $targetPath - Force - ErrorAction Stop | Out-Null
1190+ Write-Host " Created directory: $relativePath " - ForegroundColor Blue
1191+ }
1192+ } else {
1193+ # Copy file
1194+ $targetDir = [System.IO.Path ]::GetDirectoryName($targetPath )
1195+
1196+ if ($targetDir -and -not (Test-Path - Path $targetDir - PathType Container)) {
1197+ New-Item - ItemType Directory - Path $targetDir - Force - ErrorAction Stop | Out-Null
1198+ }
1199+
1200+ Copy-Item - Path $itemFullPath - Destination $targetPath - Force - ErrorAction Stop
1201+
1202+ # Set file as hidden
1203+ if (Test-Path - Path $targetPath - PathType Leaf) {
1204+ try {
1205+ $file = Get-Item - Path $targetPath - Force - ErrorAction SilentlyContinue
1206+ if ($file ) {
1207+ $file.Attributes = $file.Attributes -bor [System.IO.FileAttributes ]::Hidden
1208+ }
1209+ } catch {
1210+ Write-Host " Warning: Could not hide file $relativePath " - ForegroundColor Yellow
1211+ }
1212+ }
1213+
1214+ $currentFile ++
1215+ if ($totalFiles -gt 0 ) {
1216+ Write-Progress - Activity " Copying to SD Card" - Status " File $currentFile of $totalFiles " - PercentComplete (($currentFile / $totalFiles ) * 100 )
1217+ }
1218+ Write-Host " Copied and hid: $relativePath "
1219+ }
1220+ } catch {
1221+ Write-Host " Failed to process item: $ ( $item.Name ) - $ ( $_.Exception.Message ) " - ForegroundColor Red
1222+ }
1223+ }
1224+
1225+ Write-Progress - Activity " Copying to SD Card" - Completed
1226+ Write-Host " Copy operation completed successfully!"
1227+ } else {
1228+ Write-Host " User cancelled SD card selection" - ForegroundColor Yellow
1229+ }
1230+ } catch {
1231+ $errorMessage = " Copy operation failed: $ ( $_.Exception.Message ) "
1232+ Write-Host $errorMessage - ForegroundColor Red
1233+ Write-Host " Stack trace: $ ( $_.ScriptStackTrace ) " - ForegroundColor Red
1234+ [System.Windows.Forms.MessageBox ]::Show($errorMessage , " Error" , [System.Windows.Forms.MessageBoxButtons ]::OK, [System.Windows.Forms.MessageBoxIcon ]::Error)
1235+ }
1236+ })
1237+ $form.Controls.Add ($btnCopyToSD )
1238+
10831239 # Enable vertical scrolling for the panel content
10841240 $panel.AutoScroll = $true
10851241 $panel.HorizontalScroll.Enabled = $false
0 commit comments