Files
2014-08-09 08:46:27 -07:00

619 lines
22 KiB
C
Executable File

/*****************************************************************************
** $Source: /cvsroot/bluemsx/blueMSX/Src/Emulator/FileHistory.c,v $
**
** $Revision: 1.39 $
**
** $Date: 2008/10/26 19:48:18 $
**
** More info: http://www.bluemsx.com
**
** Copyright (C) 2003-2006 Daniel Vik
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**
******************************************************************************
*/
#define USE_ARCH_GLOB
#include "FileHistory.h"
#include "Properties.h"
#include "ziphelper.h"
#include "RomLoader.h"
#include "MsxTypes.h"
#include "ArchNotifications.h"
#include "Disk.h"
#include "AppConfig.h"
#ifdef USE_ARCH_GLOB
#include "ArchGlob.h"
#include "ArchFile.h"
#endif
#include <stdio.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
static char extendedName[PROP_MAX_CARTS][256];
static char extendedDiskName[PROP_MAX_DISKS][256];
static char extendedCasName[PROP_MAX_TAPES][256];
const char* stripPathExt(const char* filename) {
static char buffer[128];
strcpy(buffer, stripPath(filename));
if (buffer[strlen(buffer) - 4] == '.') {
buffer[strlen(buffer) - 4] = 0;
}
return buffer;
}
const char* stripPath(const char* filename) {
const char* ptr = filename + strlen(filename) - 1;
while (--ptr >= filename) {
if (*ptr == '/' || *ptr == '\\') {
return ptr + 1;
}
}
return filename;
}
#ifndef NO_FILE_HISTORY
void updateFileHistory(char* history, RomType* historyType, char* filename, RomType romType) {
char fname[PROP_MAXPATH];
int i = 0;
if (appConfigGetInt("filehistory", 1) == 0) {
return;
}
if (strcmp(filename, CARTNAME_GAMEREADER) == 0) {
return;
}
strcpy(fname, filename);
for (i = 0; i < MAX_HISTORY - 1; i++) {
if (*(history + PROP_MAXPATH * i) == 0 || 0 == strcmp(history + PROP_MAXPATH * i, fname)) {
break;
}
}
while (i > 0) {
strcpy(history + PROP_MAXPATH * i, history + PROP_MAXPATH * (i - 1));
if (historyType) historyType[i] = historyType[i - 1];
i--;
}
strcpy(history, fname);
if (historyType) historyType[0] = romType;
}
void verifyFileHistory(char* history, RomType* historyType) {
int i, j;
if (appConfigGetInt("filehistory", 1) == 0) {
return;
}
for (i = 0; i < MAX_HISTORY; i++) {
char *fname = history + PROP_MAXPATH * i;
if (fname[0] != '\0' &&
strcmp(fname, CARTNAME_SNATCHER) &&
strcmp(fname, CARTNAME_SDSNATCHER) &&
strcmp(fname, CARTNAME_SCCMIRRORED) &&
strcmp(fname, CARTNAME_SCCEXPANDED) &&
strcmp(fname, CARTNAME_SCC) &&
strcmp(fname, CARTNAME_SCCPLUS) &&
strcmp(fname, CARTNAME_JOYREXPSG) &&
strcmp(fname, CARTNAME_FMPAC) &&
strcmp(fname, CARTNAME_PAC) &&
strcmp(fname, CARTNAME_GAMEREADER) &&
strcmp(fname, CARTNAME_SUNRISEIDE) &&
strcmp(fname, CARTNAME_BEERIDE) &&
strcmp(fname, CARTNAME_GIDE) &&
strcmp(fname, CARTNAME_NMS1210) &&
strcmp(fname, CARTNAME_GOUDASCSI) &&
strcmp(fname, CARTNAME_SONYHBI55) &&
strcmp(fname, CARTNAME_EXTRAM16KB) &&
strcmp(fname, CARTNAME_EXTRAM32KB) &&
strcmp(fname, CARTNAME_EXTRAM48KB) &&
strcmp(fname, CARTNAME_EXTRAM64KB) &&
strcmp(fname, CARTNAME_EXTRAM512KB) &&
strcmp(fname, CARTNAME_EXTRAM1MB) &&
strcmp(fname, CARTNAME_EXTRAM2MB) &&
strcmp(fname, CARTNAME_EXTRAM4MB) &&
strcmp(fname, CARTNAME_MEGARAM128) &&
strcmp(fname, CARTNAME_MEGARAM256) &&
strcmp(fname, CARTNAME_MEGARAM512) &&
strcmp(fname, CARTNAME_MEGARAM768) &&
strcmp(fname, CARTNAME_MEGARAM2M) &&
strcmp(fname, CARTNAME_MEGASCSI128) &&
strcmp(fname, CARTNAME_MEGASCSI256) &&
strcmp(fname, CARTNAME_MEGASCSI512) &&
strcmp(fname, CARTNAME_MEGASCSI1MB) &&
strcmp(fname, CARTNAME_NOWINDDOS1) &&
strcmp(fname, CARTNAME_NOWINDDOS2) &&
strcmp(fname, CARTNAME_ESERAM128) &&
strcmp(fname, CARTNAME_ESERAM256) &&
strcmp(fname, CARTNAME_ESERAM512) &&
strcmp(fname, CARTNAME_ESERAM1MB) &&
strcmp(fname, CARTNAME_MEGAFLSHSCC) &&
strcmp(fname, CARTNAME_MEGAFLSHSCCPLUS) &&
strcmp(fname, CARTNAME_WAVESCSI128) &&
strcmp(fname, CARTNAME_WAVESCSI256) &&
strcmp(fname, CARTNAME_WAVESCSI512) &&
strcmp(fname, CARTNAME_WAVESCSI1MB) &&
strcmp(fname, CARTNAME_ESESCC128) &&
strcmp(fname, CARTNAME_ESESCC256) &&
strcmp(fname, CARTNAME_ESESCC512))
{
struct stat s;
int rv = archFileExists(fname);
if (rv) {
rv = stat(fname, &s) == 0;
}
if (rv && (s.st_mode & S_IFDIR)) {
}
else {
if (!archFileExists(fname)) {
if (i == MAX_HISTORY - 1) {
*(history + PROP_MAXPATH * i) = 0;
}
else {
for (j = i + 1; j < MAX_HISTORY; j++) {
strcpy(history + PROP_MAXPATH * (j - 1), history + PROP_MAXPATH * j);
if (historyType) historyType[j - 1] = historyType[j];
*(history + PROP_MAXPATH * j) = 0;
}
i--;
}
}
}
}
}
}
#endif
int fileExist(char* fileName, char* zipFile) {
if (fileName == NULL || *fileName == 0) {
return 0;
}
if (zipFile == NULL || *zipFile == 0) {
return archFileExists(fileName);
return 0;
}
else {
if (archFileExists(zipFile)) {
if( zipFileExists(zipFile, fileName) ) {
return 1;
}
}
return 0;
}
return 0;
}
char* fileGetNext(char* filename, char* zipFile) {
static char name[512];
static int pos = -1;
int c;
int j;
strcpy(name, filename);
pos = strlen(name) - 5;
if (pos < 0) {
return name;
}
while (pos >= 0) {
c = name[pos];
if (c >= '0' && c <= '9') {
if (c < '9') {
name[pos] = c + 1;
if (fileExist(name, zipFile)) {
return name;
}
}
for (j = '0'; j < c; j++) {
name[pos] = j;
if (fileExist(name, zipFile)) {
return name;
}
}
name[pos] = c;
}
pos--;
}
pos = strlen(name) - 5;
c = name[pos];
if (c >= 'A' && c <= 'Z') {
if (c < 'Z') {
name[pos] = c + 1;
if (fileExist(name, zipFile)) {
pos = -1;
return name;
}
}
for (j = 'A'; j <= c; j++) {
name[pos] = j;
if (fileExist(name, zipFile)) {
pos = -1;
return name;
}
}
}
if (c >= 'a' && c <= 'z') {
if (c < 'z') {
name[pos] = c + 1;
if (fileExist(name, zipFile)) {
pos = -1;
return name;
}
}
for (j = 'a'; j <= c; j++) {
name[pos] = j;
if (fileExist(name, zipFile)) {
pos = -1;
return name;
}
}
}
return name;
}
void updateExtendedRomName(int drive, char* filename, char* zipFile) {
int size;
char* buf = romLoad(filename, zipFile[0] ? zipFile : NULL, &size);
if (buf != NULL) {
strcpy(extendedName[drive], mediaDbGetPrettyString(mediaDbLookupRom(buf, size)));
free(buf);
if (extendedName[drive][0] == 0) {
strcpy(extendedName[drive], stripPathExt(zipFile[0] ? zipFile : filename));
}
}
}
void updateExtendedDiskName(int drive, char* filename, char* zipFile) {
int size;
char* buf;
char* name;
extendedDiskName[drive][0] = 0;
#ifndef WII
if (drive < MAX_FDC_COUNT) {
buf = romLoad(filename, zipFile[0] ? zipFile : NULL, &size);
if (buf != NULL) {
strcpy(extendedDiskName[drive], mediaDbGetPrettyString(mediaDbLookupDisk(buf, size)));
free(buf);
if (extendedDiskName[drive][0] == 0) {
strcpy(extendedDiskName[drive], stripPathExt(zipFile[0] ? zipFile : filename));
}
}
} else {
#else
{
#endif
name = zipFile[0] ? zipFile : filename;
if ((name != NULL) && name[0]) {
archFileExists(name);
strcpy(extendedDiskName[drive], stripPathExt(name));
}
}
/*
int size;
char* buf = romLoad(filename, zipFile[0] ? zipFile : NULL, &size);
extendedDiskName[drive][0] = 0;
if (buf != NULL) {
strcpy(extendedDiskName[drive], mediaDbGetPrettyString(mediaDbLookupDisk(buf, size)));
free(buf);
if (extendedDiskName[drive][0] == 0) {
strcpy(extendedDiskName[drive], stripPathExt(zipFile[0] ? zipFile : filename));
}
}
*/
}
void updateExtendedCasName(int drive, char* filename, char* zipFile) {
int size;
char* buf = romLoad(filename, zipFile[0] ? zipFile : NULL, &size);
extendedCasName[drive][0] = 0;
if (buf != NULL) {
strcpy(extendedCasName[drive], mediaDbGetPrettyString(mediaDbLookupCas(buf, size)));
free(buf);
if (extendedCasName[drive][0] == 0) {
strcpy(extendedCasName[drive], stripPathExt(zipFile[0] ? zipFile : filename));
}
}
}
void setExtendedRomName(int drive, const char* name) {
strcpy(extendedName[drive], name);
}
int createSaveFileBaseName(char* fileBase,Properties* properties, int useExtendedName)
{
int done = 0;
int i;
fileBase[0]=0;
for (i = 0; !done && i < PROP_MAX_CARTS; i++) {
if (properties->media.carts[i].fileName[0]) {
if (useExtendedName && extendedName[i][0]) {
strcpy(fileBase, extendedName[i]);
}
else if (*properties->media.carts[i].fileNameInZip) {
strcpy(fileBase, stripPathExt(properties->media.carts[i].fileNameInZip));
}
else {
strcpy(fileBase, stripPathExt(properties->media.carts[i].fileName));
}
if (strcmp(properties->media.carts[i].fileName, CARTNAME_SNATCHER) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_SDSNATCHER) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_SCCMIRRORED) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_SCCEXPANDED) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_SCC) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_SCCPLUS) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_JOYREXPSG) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_FMPAC) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_PAC) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_GAMEREADER) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_SUNRISEIDE) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_BEERIDE) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_GIDE) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_NMS1210) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_GOUDASCSI) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_SONYHBI55) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_EXTRAM512KB) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_EXTRAM16KB) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_EXTRAM32KB) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_EXTRAM48KB) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_EXTRAM64KB) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_EXTRAM512KB) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_EXTRAM1MB) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_EXTRAM2MB) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_EXTRAM4MB) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_MEGARAM128) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_MEGARAM256) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_MEGARAM512) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_MEGARAM768) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_MEGARAM2M) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_MEGASCSI128) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_MEGASCSI256) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_MEGASCSI512) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_MEGASCSI1MB) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_NOWINDDOS1) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_NOWINDDOS2) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_ESERAM128) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_ESERAM256) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_ESERAM512) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_ESERAM1MB) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_MEGAFLSHSCC) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_MEGAFLSHSCCPLUS) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_WAVESCSI128) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_WAVESCSI256) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_WAVESCSI512) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_WAVESCSI1MB) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_ESESCC128) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_ESESCC256) &&
strcmp(properties->media.carts[i].fileName, CARTNAME_ESESCC512) &&
properties->media.carts[i].type != ROM_FMPAC &&
properties->media.carts[i].type != ROM_PAC &&
properties->media.carts[i].type != ROM_GAMEREADER &&
properties->media.carts[i].type != ROM_SUNRISEIDE &&
properties->media.carts[i].type != ROM_BEERIDE &&
properties->media.carts[i].type != ROM_GIDE &&
properties->media.carts[i].type != ROM_GOUDASCSI &&
properties->media.carts[i].type != ROM_MSXAUDIO &&
properties->media.carts[i].type != ROM_MOONSOUND &&
properties->media.carts[i].type != ROM_SNATCHER &&
properties->media.carts[i].type != ROM_SDSNATCHER &&
properties->media.carts[i].type != ROM_SCCMIRRORED &&
properties->media.carts[i].type != ROM_SCC &&
properties->media.carts[i].type != ROM_SCCPLUS &&
properties->media.carts[i].type != ROM_SONYHBI55 &&
properties->media.carts[i].type != ROM_YAMAHASFG01 &&
properties->media.carts[i].type != ROM_YAMAHASFG05 &&
properties->media.carts[i].type != ROM_YAMAHANET &&
properties->media.carts[i].type != ROM_SF7000IPL)
{
done = 1;
}
}
}
for (i = 0; !done && i < PROP_MAX_DISKS; i++) {
if (properties->media.disks[i].fileName[0]) {
if (useExtendedName && extendedDiskName[i][0]) {
strcpy(fileBase, extendedDiskName[i]);
}
else if (*properties->media.disks[i].fileNameInZip) {
#ifdef WII // Use the same name for state files for every disk image within one zip file
strcpy(fileBase, stripPathExt(properties->media.disks[i].fileName));
#else
strcpy(fileBase, stripPathExt(properties->media.disks[i].fileNameInZip));
#endif
}
else {
strcpy(fileBase, stripPathExt(properties->media.disks[i].fileName));
}
done = 1;
}
}
for (i = 0; !done && i < PROP_MAX_TAPES; i++) {
if (properties->media.tapes[0].fileName[0]) {
if (useExtendedName && extendedCasName[i][0]) {
strcpy(fileBase, extendedCasName[i]);
}
else if (*properties->media.tapes[i].fileNameInZip) {
strcpy(fileBase, stripPathExt(properties->media.tapes[i].fileNameInZip));
}
else {
strcpy(fileBase, stripPathExt(properties->media.tapes[i].fileName));
}
done = 1;
}
}
if (fileBase[0] == 0) {
strcpy(fileBase, "unknown");
return 0;
}
return strlen(fileBase);
}
#ifdef USE_ARCH_GLOB
static UInt32 fileWriteTime(const char* filename)
{
struct stat s;
int rv;
rv = stat(filename, &s);
return rv < 0 ? 0 : (UInt32)s.st_mtime;
}
char* generateSaveFilename(Properties* properties, char* directory, char* prefix, char* extension, int digits)
{
ArchGlob* glob;
static char filename[512];
char baseName[128];
int fileIndex = 0;
int extensionLen = strlen(extension);
int i;
int numMod = 1;
char filenameFormat[32] = "%s/%s%s_";
char destfileFormat[32];
for (i = 0; i < digits; i++) {
strcat(filenameFormat, "?");
numMod *= 10;
}
strcat(filenameFormat, "%s");
sprintf(destfileFormat, "%%s/%%s%%s_%%0%di%%s", digits);
createSaveFileBaseName(baseName, properties, 0);
sprintf(filename, filenameFormat, directory, prefix, baseName, extension);
glob = archGlob(filename, ARCH_GLOB_FILES);
if (glob) {
if (glob->count > 0) {
UInt32 writeTime = fileWriteTime(glob->pathVector[0]);
char lastfile[512];
int filenameLen;
strcpy(lastfile, glob->pathVector[0]);
for (i = 1; i < glob->count; i++) {
UInt32 thisWriteTime = fileWriteTime(glob->pathVector[i]);
if (thisWriteTime > 0 && thisWriteTime < writeTime) {
break;
}
writeTime = thisWriteTime;
strcpy(lastfile, glob->pathVector[i]);
}
filenameLen = strlen(lastfile);
if (filenameLen > extensionLen + digits) {
lastfile[filenameLen - extensionLen] = 0;
fileIndex = (atoi(&lastfile[filenameLen - extensionLen - digits]) + 1) % numMod;
}
}
archGlobFree(glob);
}
sprintf(filename, destfileFormat, directory, prefix, baseName, fileIndex, extension);
return filename;
}
#else
char* generateSaveFilename(Properties* properties, char* directory, char* prefix, char* extension, int digits)
{
WIN32_FIND_DATA fileData;
FILETIME writeTime;
HANDLE hFile;
char lastfile[512];
static char filename[512];
char baseName[128];
int fileIndex = 0;
int extensionLen = strlen(extension);
int i;
int numMod = 1;
char filenameFormat[32] = "%s" DIR_SEPARATOR "%s%s_";
char destfileFormat[32];
for (i = 0; i < digits; i++) {
strcat(filenameFormat, "?");
numMod *= 10;
}
strcat(filenameFormat, "%s");
sprintf(destfileFormat, "%%s" DIR_SEPARATOR "%%s%%s_%%0%di%%s", digits);
createSaveFileBaseName(baseName, properties, 0);
sprintf(filename, filenameFormat, directory, prefix, baseName, extension);
hFile = FindFirstFile(filename,&fileData);
if (hFile != INVALID_HANDLE_VALUE) {
int filenameLen;
writeTime = fileData.ftLastWriteTime;
strcpy(lastfile, fileData.cFileName);
while (FindNextFile(hFile, &fileData ) != 0) {
if (CompareFileTime(&fileData.ftLastWriteTime, &writeTime) < 0) {
break;
}
writeTime = fileData.ftLastWriteTime;
strcpy(lastfile, fileData.cFileName);
}
filenameLen = strlen(lastfile);
if (filenameLen > extensionLen + digits) {
lastfile[filenameLen - extensionLen] = 0;
fileIndex = (atoi(&lastfile[filenameLen - extensionLen - digits]) + 1) % numMod;
}
FindClose(hFile);
}
sprintf(filename, destfileFormat, directory, prefix, baseName, fileIndex, extension);
return filename;
}
#endif