feat: Menu option for swapping game file and first saved state

To fix PAL/NTSC issue
This commit is contained in:
lantzelot-swe 2021-11-26 21:24:40 +01:00
parent b472d0e97a
commit 4d6bda5493
5 changed files with 132 additions and 3 deletions

View File

@ -116,11 +116,13 @@ public class GameDetailsBackgroundPanel extends JPanel
if (data == null)
{
cardLayout.show(this, EMPTY);
model.checkEnablementOfPalNtscMenuItem(false);
}
else
{
cardLayout.show(this, DETAILS);
model.readGameDetails(data);
model.checkEnablementOfPalNtscMenuItem(true);
}
}

View File

@ -12,11 +12,14 @@ import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import javax.swing.JEditorPane;
import javax.swing.JFileChooser;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.event.HyperlinkEvent;
import javax.swing.filechooser.FileNameExtensionFilter;
import se.lantz.gamebase.GamebaseImporter;
@ -102,6 +105,7 @@ public class MenuManager
private JMenuItem convertScreensItem;
private JMenuItem checkDescrItem;
private JMenuItem palNtscFixItem;
private JMenuItem helpItem;
private JMenuItem aboutItem;
@ -126,7 +130,7 @@ public class MenuManager
this.exportManager = new ExportManager(uiModel);
this.backupManager = new BackupManager(uiModel);
this.restoreManager = new RestoreManager(uiModel);
this.savedStatesManager = new SavedStatesManager(uiModel);
this.savedStatesManager = new SavedStatesManager(uiModel, getPalNtscFixMenuItem());
uiModel.setSavedStatesManager(savedStatesManager);
setupMenues();
}
@ -194,6 +198,9 @@ public class MenuManager
toolsMenu.addSeparator();
toolsMenu.add(getConvertScreensItem());
toolsMenu.add(getCheckDescriptionsItem());
toolsMenu.addSeparator();
toolsMenu.add(getPalNtscFixMenuItem());
helpMenu = new JMenu("Help");
helpMenu.setMnemonic('H');
helpMenu.add(getHelpItem());
@ -658,6 +665,17 @@ public class MenuManager
checkDescrItem.addActionListener(e -> fixInvalidCharsInDescriptions());
return checkDescrItem;
}
private JMenuItem getPalNtscFixMenuItem()
{
if (palNtscFixItem == null)
{
palNtscFixItem = new JMenuItem("Swap game file and first saved state to fix NTSC/PAL issue");
palNtscFixItem.setMnemonic('s');
palNtscFixItem.addActionListener(e -> fixPalNtscIssue());
}
return palNtscFixItem;
}
private JMenuItem getHelpItem()
{
@ -976,6 +994,49 @@ public class MenuManager
dialog.setVisible(true);
}
}
private void fixPalNtscIssue()
{
int option = JOptionPane.showConfirmDialog(MainWindow.getInstance()
.getMainPanel(), getPalNtscEditorPane(), "Swap game file and first saved state", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
if (option == JOptionPane.YES_OPTION)
{
if (savedStatesManager.swapGameFileAndSavedState())
{
JOptionPane.showMessageDialog(MainWindow.getInstance()
.getMainPanel(), "Game file and saved state successfully swapped. System type was also switched.", "Swap game file and first saved state", JOptionPane.INFORMATION_MESSAGE);
}
}
}
private JEditorPane getPalNtscEditorPane()
{
String message =
"<html>Some VICE snapshots of games made for NTSC does not run properly on a PAL machine, and vice versa. You need to start them twice from the carousel." +
"<br>See this thread on <a href=\"https://thec64community.online/thread/790/pcuae-problem-starting-games-first\">TheC64 Community forum</a>." +
"<br><br>Do you want to swap the game file with the first saved state and change system type for the selected game?</html>";
JEditorPane infoEditorPane = new JEditorPane("text/html", message);
infoEditorPane.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE);
infoEditorPane.setFont(UIManager.getDefaults().getFont("Label.font"));
infoEditorPane.setEditable(false);
infoEditorPane.setOpaque(false);
infoEditorPane.addHyperlinkListener((hle) -> {
if (HyperlinkEvent.EventType.ACTIVATED.equals(hle.getEventType()) && Desktop.isDesktopSupported() &&
Desktop.getDesktop().isSupported(Desktop.Action.BROWSE))
{
try
{
Desktop.getDesktop().browse(hle.getURL().toURI());
}
catch (IOException | URISyntaxException e)
{
ExceptionHandler.handleException(e, "Could not open default browser");
}
}
});
return infoEditorPane;
}
private void clearFavorites(int number)
{

View File

@ -18,6 +18,7 @@ import java.util.TimeZone;
import java.util.stream.Stream;
import javax.imageio.ImageIO;
import javax.swing.JMenuItem;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
@ -67,9 +68,12 @@ public class SavedStatesManager
*/
private Map<String, Integer> savedStatesMap = new HashMap<>();
public SavedStatesManager(MainViewModel model)
private JMenuItem palNtscFixMenuItem;
public SavedStatesManager(MainViewModel model, JMenuItem palNtscFixMenuItem)
{
this.model = model;
this.palNtscFixMenuItem = palNtscFixMenuItem;
this.savedStatesModel = model.getSavedStatesModel();
readSavedStatesAndUpdateMap();
}
@ -553,4 +557,61 @@ public class SavedStatesManager
{
return savedStatesMap.get(gameFileName) != null ? savedStatesMap.get(gameFileName) : 0;
}
public void checkEnablementOfPalNtscMenuItem(boolean check)
{
boolean palNtscItemEnabled = false;
if (check)
{
//Check if current game has a 0.vsf file and the current game file is a snapshot
String fileName = model.getInfoModel().getGamesFile();
if (!fileName.isEmpty() && fileName.contains(".vsf"))
{
//Check if folder is available
Path saveFolder = new File(SAVES + fileName).toPath();
if (Files.exists(saveFolder))
{
//Check which ones are available
Path vsz0Path = saveFolder.resolve(VSZ0);
if (Files.exists(vsz0Path))
{
palNtscItemEnabled = true;
}
}
}
}
palNtscFixMenuItem.setEnabled(palNtscItemEnabled);
}
public boolean swapGameFileAndSavedState()
{
String gamesFile = model.getInfoModel().getGamesFile();
Path gameFilePath = new File(FileManager.GAMES + gamesFile).toPath();
Path firstSavedStatePath = new File(SAVES + gamesFile).toPath().resolve(VSZ0);
Path tempFilePath = new File(FileManager.GAMES + "temp.gz").toPath();
try
{
Files.copy(gameFilePath, tempFilePath, StandardCopyOption.REPLACE_EXISTING);
Files.copy(firstSavedStatePath, gameFilePath, StandardCopyOption.REPLACE_EXISTING);
Files.copy(tempFilePath, firstSavedStatePath, StandardCopyOption.REPLACE_EXISTING);
Files.delete(tempFilePath);
if (model.getSystemModel().isPal())
{
model.getSystemModel().setNtsc(true);
}
else
{
model.getSystemModel().setPal(true);
}
model.saveData();
return true;
}
catch (IOException e)
{
ExceptionHandler.handleException(e, "Could not swap game file and first saved state.");
}
return false;
}
}

View File

@ -840,4 +840,9 @@ public class MainViewModel extends AbstractModel
{
fileManager.runSnapshotInVice(saveState);
}
public void checkEnablementOfPalNtscMenuItem(boolean check)
{
stateManager.checkEnablementOfPalNtscMenuItem(check);
}
}

View File

@ -58,7 +58,7 @@ public class FileManager
public static BufferedImage emptyC64Screenshot;
public static BufferedImage emptyVic20Screenshot;
private static final String GAMES = "./games/";
public static final String GAMES = "./games/";
private static final String SCREENS = "./screens/";
private static final String COVERS = "./covers/";
private static final String SAVES = "./saves/";