// Copyright 2011-2012 Paulo Augusto Peccin. See licence.txt distributed with this file.
package org.javatari.pc.savestate;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.AccessControlException;
import org.javatari.atari.cartridge.formats.CartridgeSavestate;
import org.javatari.atari.console.savestate.ConsoleState;
import org.javatari.atari.console.savestate.SaveStateMedia;
import org.javatari.atari.console.savestate.SaveStateSocket;
import org.javatari.pc.cartridge.FileROMChooser;
import org.javatari.pc.cartridge.ROMLoader;
public final class FileSaveStateMedia implements SaveStateMedia {
public void connect(SaveStateSocket socket) {
socket.connectMedia(this);
}
@Override
public boolean saveStateFile(ConsoleState state) {
try {
File file = FileROMChooser.chooseFileToSavestate();
if (file == null) return false;
return internalSaveToFile(file.toString(), state, true, false);
} catch (AccessControlException e) {
// No option if in Sandboxed mode
return false;
}
}
@Override
public boolean saveState(int slot, ConsoleState state) {
return internalSaveToFile("javatarisave" + slot + "." + ROMLoader.VALID_STATE_FILE_EXTENSION, state, true, true);
}
@Override
public ConsoleState loadState(int slot) {
try{
return (ConsoleState)internalLoadFromFile("javatarisave" + slot + "." + ROMLoader.VALID_STATE_FILE_EXTENSION, true, true);
} catch (Exception ex) {
// ClassCast or any other error
return null;
}
}
@Override
public boolean saveResourceToFile(String fileName, Object data) {
return internalSaveToFile(fileName, data, false, true);
}
@Override
public Object loadResourceFromFile(String fileName) {
return internalLoadFromFile(fileName, false, true);
}
private boolean internalSaveToFile(String fileName, Object data, boolean isSavestate, boolean insideSavesDirectory) {
try {
// Create the savestate directory if needed
File dir = new File(savesDirectory());
if (!dir.isDirectory())
dir.mkdir();
FileOutputStream file = null;
try {
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
// Begin the file with the identifier if asked
if (isSavestate) {
byteStream.write(CartridgeSavestate.contentIdentifier);
byteStream.flush();
}
// Then the Savestate data
ObjectOutputStream stream = new ObjectOutputStream(byteStream);
stream.writeObject(data);
file = new FileOutputStream(insideSavesDirectory ? insideSavesDirectory(fileName) : fileName);
file.write(byteStream.toByteArray());
} finally {
if (file != null) file.close();
}
return true;
} catch (Exception ex) {
// No permissions or any other IO error
ex.printStackTrace();
return false;
}
}
private Object internalLoadFromFile(String fileName, boolean isSavestate, boolean insideSavesDirectory) {
try{
FileInputStream file = null;
try{
file = new FileInputStream(insideSavesDirectory ? insideSavesDirectory(fileName) : fileName);
// Load the state
byte[] data = new byte[file.available()];
file.read(data);
ByteArrayInputStream byteStream = new ByteArrayInputStream(data);
// If asked, check the Savestate identifier that should be present at the beginning of the file
if (isSavestate) {
if (!CartridgeSavestate.checkIdentifier(data))
throw new IllegalStateException("Invalid Javatari Savestate file");
// Skips the Savestate identifier
byteStream.skip(CartridgeSavestate.contentIdentifier.length);
}
ObjectInputStream objStream = new ObjectInputStream(byteStream);
return objStream.readObject();
} finally {
if (file != null) file.close();
}
} catch (Exception ex) {
// No permissions or any other IO error
ex.printStackTrace();
return null;
}
}
private String insideSavesDirectory(String fileName) {
return savesDirectory() + File.separator + fileName;
}
private String savesDirectory() {
if (savesDirectory != null) return savesDirectory;
try {
String userHome = System.getProperty("user.home");
if (userHome != null && !userHome.isEmpty())
return savesDirectory = userHome + File.separator + BASE_DIR;
} catch(SecurityException ex) {
// No permissions... Ignore and use default directory
}
return savesDirectory = BASE_DIR;
}
private String savesDirectory;
private static final String BASE_DIR = "javatarisaves";
}