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.
250 lines
7.5 KiB
250 lines
7.5 KiB
3 years ago
|
/*
|
||
|
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;
|
||
|
}
|