PSP: save through the real sceUtilitySavedata API, not raw file I/O
Rewrote savepsp.c/savestreampsp.c to use sceUtilitySavedataInitStart/ Update/GetStatus/ShutdownStart instead of sceIoOpen/Read/Write, so PSP saves get a proper OS-generated PARAM.SFO (title/savedataTitle/detail) and show up correctly in the native save browser. This dialog spans multiple frames and, per this project's prior experience with the network config dialog, must be pumped non-blocking one step per real engine frame rather than blocked on synchronously - a raw-sceGu blocking loop already froze the app on real hardware for that dialog, since pspGL owns the GU context. So save.h's saveWrite()/saveLoad() are now callback-based (savecallback_t onComplete) instead of returning a result directly, mirroring networkRequestConnection()'s shape, with a new saveUpdate() (wired into engineUpdate()) pumping the active op each frame. Linux/Dolphin behavior is unchanged - their fallback path in save.c still completes synchronously, just via an immediate callback call instead of a direct return. Two real bugs found via PPSSPP testing (not just code review): SAVE/LOAD modes show a confirm screen even for brand-new data, which blocks forever headlessly - switched to AUTOSAVE/AUTOLOAD, which write/read silently and generate the identical PARAM.SFO. And PPSSPP's dialog status goes straight from QUIT to NONE without a separately observable FINISHED in between, which the first version misread as "disappeared without a result" even on a successful save - fixed by tracking whether QUIT was already seen. Confirmed end-to-end in PPSSPP: write, dialog completes, PARAM.SFO + encrypted save.bin appear on the virtual memory stick, and a subsequent load decrypts/deserializes back to the exact original data. Not tested on real PSP hardware.
This commit is contained in:
@@ -7,71 +7,49 @@
|
||||
|
||||
#pragma once
|
||||
#include "error/error.h"
|
||||
#include <pspiofilemgr.h>
|
||||
#include <stddef.h>
|
||||
|
||||
// Backed by SAVE.platform.dataBuffer (see savepsp.h) rather than owning its
|
||||
// own memory - the buffer has to outlive a single saveFileWrite()/Load()
|
||||
// call, since the actual save/load dialog it's handed to only completes
|
||||
// several frames later.
|
||||
typedef struct {
|
||||
SceUID fd;
|
||||
uint8_t *buffer;
|
||||
size_t bufferSize;
|
||||
size_t position;
|
||||
size_t length;
|
||||
} savestreampsp_t;
|
||||
|
||||
/**
|
||||
* Opens a PSP save data file for reading.
|
||||
*
|
||||
* @param p Stream to initialize.
|
||||
* @param found Set to true if the file exists, false if it does not.
|
||||
* @param slot Save slot index.
|
||||
* @return An error if the open fails for a reason other than missing file.
|
||||
*/
|
||||
errorret_t saveStreamOpenReadPSP(
|
||||
savestreampsp_t *p, bool_t *found, const uint8_t slot
|
||||
);
|
||||
|
||||
/**
|
||||
* Opens a PSP save data file for writing, creating or truncating it.
|
||||
* Creates the save data directory if it does not already exist.
|
||||
*
|
||||
* @param p Stream to initialize.
|
||||
* @param slot Save slot index.
|
||||
* @return An error if the file cannot be opened for writing.
|
||||
*/
|
||||
errorret_t saveStreamOpenWritePSP(savestreampsp_t *p, const uint8_t slot);
|
||||
|
||||
/**
|
||||
* Closes the file descriptor held by the stream.
|
||||
*
|
||||
* @param p Stream to close.
|
||||
*/
|
||||
void saveStreamClosePSP(savestreampsp_t *p);
|
||||
|
||||
/**
|
||||
* Reads len bytes from the stream into buf.
|
||||
* Copies len bytes from the buffer at the current position into buf.
|
||||
*
|
||||
* @param p Active stream.
|
||||
* @param buf Destination buffer.
|
||||
* @param len Number of bytes to read.
|
||||
* @return An error if fewer than len bytes are available.
|
||||
* @return An error if the read would exceed the populated data length.
|
||||
*/
|
||||
errorret_t saveStreamReadBytesPSP(
|
||||
savestreampsp_t *p, void *buf, const size_t len
|
||||
);
|
||||
|
||||
/**
|
||||
* Writes len bytes from buf into the stream.
|
||||
* Copies len bytes from buf into the buffer at the current position,
|
||||
* growing p->length if this write extends past it.
|
||||
*
|
||||
* @param p Active stream.
|
||||
* @param buf Source buffer.
|
||||
* @param len Number of bytes to write.
|
||||
* @return An error if the write fails.
|
||||
* @return An error if the write would exceed bufferSize.
|
||||
*/
|
||||
errorret_t saveStreamWriteBytesPSP(
|
||||
savestreampsp_t *p, const void *buf, const size_t len
|
||||
);
|
||||
|
||||
/**
|
||||
* Seeks to an absolute byte position within the stream.
|
||||
* Sets the current read/write position within the buffer.
|
||||
*
|
||||
* @param p Active stream.
|
||||
* @param pos Target byte offset from the start of the file.
|
||||
* @return An error if the seek fails.
|
||||
* @param pos Target byte offset from the start of the buffer.
|
||||
* @return An error if pos is out of range.
|
||||
*/
|
||||
errorret_t saveStreamSeekPSP(savestreampsp_t *p, const size_t pos);
|
||||
|
||||
Reference in New Issue
Block a user