
Originally Posted by
limnique
squarepusher2, how about save states?
Tried to implement it - crashed it horribly - I posted details on the other forum - if somebody can help me with that, I would appreciate it.
Looks to have something to do with the libc-method of opening files that SNES9x relies upon -
Let's put this out there so other developers can chime in and perhaps comment on what I am doing wrong:
First we give Snes9x two button mappings for saving (in cell.cpp):
Code:
#define BTN_QUICKSAVE 13
#define BTN_QUICKLOAD 14
MAP_BUTTON(MAKE_BUTTON(PAD_1, BTN_QUICKSAVE), "QuickSave010");
MAP_BUTTON(MAKE_BUTTON(PAD_1, BTN_QUICKLOAD), "QuickLoad010");
Then we go to the main input loop (read_pad) and insert the following in there:
Code:
S9xReportButton(MAKE_BUTTON(pad_id, BTN_QUICKSAVE), (cellPadUtilButtonPressed(i,CTRL_R2)));
S9xReportButton(MAKE_BUTTON(pad_id, BTN_QUICKLOAD), (cellPadUtilButtonPressed(i,CTRL_L2)));
So you can see that at the moment I had mapped it to L2 and R2 for simple convenience and testing's sake. Now, the way this works is, if you trigger this Snes9x command 'QuickSave010', it goes to controls.cpp (specifically this code snippet:
controls.cpp
Code:
case QuickSave010:
{
char filename[PATH_MAX + 1];
char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[_MAX_FNAME + 1], ext[_MAX_EXT + 1];
_splitpath(Memory.ROMFilename, drive, dir, def, ext);
snprintf(filename, PATH_MAX + 1, "%s%s%s.%03d", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, i - QuickSave000);
sprintf(buf, "%s.%03d saved", def, i - QuickSave000);
S9xSetInfoString(buf);
S9xFreezeGame(filename);
break;
} _splitpath and _makepath are function calls provided by SNES9x.
From there you can see it makes a call to S9xFreezeGame - this is a function call that is in snapshot.cpp.
snapshot.cpp
Code:
bool8 S9xFreezeGame (const char *filename)
{
STREAM stream = NULL;
if (S9xOpenSnapshotFile(filename, FALSE, &stream))
{
S9xFreezeToStream(stream);
S9xCloseSnapshotFile(stream);
S9xResetSaveTimer(TRUE);
const char *base = S9xBasename(filename);
if (S9xMovieActive())
sprintf(String, MOVIE_INFO_SNAPSHOT " %s", base);
else
sprintf(String, SAVE_INFO_SNAPSHOT " %s", base);
S9xMessage(S9X_INFO, S9X_FREEZE_FILE_INFO, String);
return (TRUE);
}
return (FALSE);
} Alright, so then S9xFreezeGame makes a function call to S9xOpenSnapshotFile (which, of course, we, as porters, have to implement). So since it already splits/makes the correct filename path while inside controls.cpp, I don't think I have to do this again in my implementation of S9xOpenSnapshotFile.
This is basically what I thought should work (in cell.cpp):
cell.cpp
Code:
bool8 S9xOpenSnapshotFile (const char *filepath, bool8 read_only, STREAM *file) {
if (read_only)
{
if ((*file = OPEN_STREAM (filepath, "rb")))
return (TRUE);
}
else
{
if ((*file = OPEN_STREAM (filepath, "wb")))
{
return (TRUE);
}
}
return (FALSE);
}
void S9xCloseSnapshotFile (STREAM file) {
CLOSE_STREAM (file);
} This causes it to crash each and every time I trigger the 'QuickSave' command. I also tried out another variant on this - basically doing the _splitpath stuff first. You can see an example of what I based it on if you go to this page:
http://snes-sdk.googlecode.com/svn-history/r68/trunk/snes9x/unix/unix.cpp
Perhaps I need to use libFS' streaming methods for the job instead of going with the standard C++ stuff? (OPEN_STREAM is a SNES9x shorthand to fopen IIRC)