You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

249 lines
7.5 KiB

/*
Copyright 2020-2021 Brad Parker
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <iostream>
#include "core.h"
bool Core::saveSRAM() {
if(m_isInited) {
if(m_library.isLoaded()) {
void *data = m_retroGetMemoryData(RETRO_MEMORY_SAVE_RAM);
size_t size = m_retroGetMemorySize(RETRO_MEMORY_SAVE_RAM);
QDir saveDir(m_savePath);
saveDir.mkpath(m_info.library_name);
if(!saveDir.cd(m_info.library_name)) {
std::cerr << "could not change directory to core name!" << std::endl;
// save anyway in the current dir, never throw away a user's work
}
if(saveDir.exists()) {
QString saveFileString = QFileInfo(m_path).fileName();
int index = saveFileString.lastIndexOf('.');
if(index > -1) {
saveFileString.remove(index, saveFileString.size() - index);
saveFileString += ".srm";
}
QFile saveFile(saveDir.filePath(saveFileString));
if(saveFile.open(QIODevice::WriteOnly)) {
saveFile.write((const char*)data, size);
saveFile.close();
std::cout << "wrote save file successfully to: " << qUtf8Printable(QFileInfo(saveFile).absoluteFilePath()) << std::endl;
}else{
std::cerr << "cannot open save file for writing." << std::endl;
// TODO: should we try to save SRAM somewhere else instead of abandoning it?
return false;
}
}else{
std::cerr << "save directory does not exist." << std::endl;
// TODO: should we try to save SRAM somewhere else instead of abandoning it?
return false;
}
}
}else{
return false;
}
return true;
}
bool Core::loadSRAM() {
// load SRAM if any
QDir saveDir(m_savePath);
saveDir.mkpath(m_info.library_name);
saveDir.cd(m_info.library_name);
if(saveDir.exists()) {
QString saveFileString = QFileInfo(m_path).fileName();
int index = saveFileString.lastIndexOf('.');
if(index > -1) {
saveFileString.remove(index, saveFileString.size() - index);
saveFileString += ".srm";
}
QFile saveFile(saveDir.filePath(saveFileString));
if(saveFile.exists()) {
if(saveFile.open(QIODevice::ReadOnly)) {
QByteArray sramArray = saveFile.readAll();
saveFile.close();
const char *sramData = sramArray.constData();
void *data = m_retroGetMemoryData(RETRO_MEMORY_SAVE_RAM);
size_t size = m_retroGetMemorySize(RETRO_MEMORY_SAVE_RAM);
if(sramArray.size() == static_cast<ssize_t>(size)) {
memcpy(data, sramData, qMin(static_cast<size_t>(sramArray.size()), size));
std::cout << "save file loaded successfully from: " << qUtf8Printable(QFileInfo(saveFile).absoluteFilePath()) << std::endl;
}else{
std::cerr << "save file size is incorrect! not loading it." << std::endl;
return false;
}
}else{
std::cerr << "cannot open save file for reading." << std::endl;
return false;
}
}else{
std::cerr << "no existing save file found for this game." << std::endl;
return false;
}
}else{
std::cerr << "save directory does not exist." << std::endl;
return false;
}
return true;
}
void Core::reset() {
m_retroReset();
}
bool Core::saveState() {
size_t size = m_retroSerializeSize();
if(size == 0) {
std::cerr << "required state size is zero! not saving anything." << std::endl;
return false;
}
if(m_saveStateData) {
delete[] m_saveStateData;
m_saveStateData = nullptr;
m_saveStateDataSize = 0;
}
m_saveStateData = new char[size];
m_saveStateDataSize = size;
bool success = m_retroSerialize(m_saveStateData, m_saveStateDataSize);
if(!success) {
std::cerr << "core failed to save state." << std::endl;
return false;
}
QDir stateDir(m_statePath);
stateDir.mkpath(m_info.library_name);
if(!stateDir.cd(m_info.library_name)) {
std::cerr << "could not change directory to core name!" << std::endl;
// save anyway in the current dir, never throw away a user's work
}
if(stateDir.exists()) {
QString stateFileString = QFileInfo(m_path).fileName();
int index = stateFileString.lastIndexOf('.');
if(index > -1) {
stateFileString.remove(index, stateFileString.size() - index);
stateFileString += ".state";
}
QFile stateFile(stateDir.filePath(stateFileString));
if(stateFile.open(QIODevice::WriteOnly)) {
stateFile.write((const char*)m_saveStateData, m_saveStateDataSize);
stateFile.close();
std::cout << "wrote state file successfully to: " << qUtf8Printable(QFileInfo(stateFile).absoluteFilePath()) << std::endl;
return true;
}else{
std::cerr << "cannot open state file for writing." << std::endl;
return false;
}
}else{
std::cerr << "state directory does not exist." << std::endl;
return false;
}
return false;
}
bool Core::loadState() {
size_t size = m_retroSerializeSize();
if(size == 0) {
std::cerr << "required state size is zero! not loading anything." << std::endl;
return false;
}
QDir stateDir(m_statePath);
stateDir.mkpath(m_info.library_name);
stateDir.cd(m_info.library_name);
if(stateDir.exists()) {
QString stateFileString = QFileInfo(m_path).fileName();
int index = stateFileString.lastIndexOf('.');
if(index > -1) {
stateFileString.remove(index, stateFileString.size() - index);
stateFileString += ".state";
}
QFile stateFile(stateDir.filePath(stateFileString));
if(stateFile.exists()) {
if(stateFile.open(QIODevice::ReadOnly)) {
QByteArray stateArray = stateFile.readAll();
stateFile.close();
const char *stateData = stateArray.constData();
if(stateArray.size() == static_cast<ssize_t>(size)) {
if(m_retroUnserialize(stateData, size)) {
std::cout << "state with size of " << size << " bytes loaded successfully from: " << qUtf8Printable(QFileInfo(stateFile).absoluteFilePath()) << std::endl;
return true;
}
std::cerr << "failed to load state." << std::endl;
return false;
}else{
std::cerr << "state file size is incorrect! (" << stateArray.size() << " != " << size << ") trying anyway. (note: some cores store the file path in the state so they will always be a false positive if the file is moved or renamed)" << std::endl;
if(m_retroUnserialize(stateData, size)) {
std::cout << "state with size of " << stateArray.size() << " (not " << size << ") bytes loaded successfully from: " << qUtf8Printable(QFileInfo(stateFile).absoluteFilePath()) << std::endl;
return true;
}
}
}else{
std::cerr << "cannot open state file for reading." << std::endl;
return false;
}
}else{
std::cerr << "no existing state file found for this game. " << qUtf8Printable(QFileInfo(stateFile).absoluteFilePath()) << std::endl;
return false;
}
}else{
std::cerr << "state directory does not exist." << std::endl;
return false;
}
return false;
}