Write support for NTR saves

Why does this work? We are writing flash memories without erasing them,
and writing pages without regard to alignment. Yet it works?
This commit is contained in:
Balint Kovacs 2019-07-13 02:14:46 +02:00 committed by d0k3
parent 38d9a23427
commit fa741b265b
9 changed files with 26 additions and 12 deletions

View File

@ -69,7 +69,7 @@ bool CheckWritePermissions(const char* path) {
snprintf(area_name, 16, "game images");
} else if (drvtype & DRV_CART) {
perm = PERM_CART;
snprintf(area_name, 16, "gamecarts");
snprintf(area_name, 16, "gamecart saves");
} else if (drvtype & DRV_VRAM) {
perm = PERM_VRAM;
snprintf(area_name, 16, "vram0");
@ -100,7 +100,7 @@ bool CheckWritePermissions(const char* path) {
return true;
// offer unlock if possible
if (!(perm & (PERM_VRAM|PERM_CART|PERM_GAME|PERM_XORPAD))) {
if (!(perm & (PERM_VRAM|PERM_GAME|PERM_XORPAD))) {
// ask the user
if (!ShowPrompt(true, "Writing to %s is locked!\nUnlock it now?", area_name))
return false;
@ -169,6 +169,10 @@ bool SetWritePermissions(u32 perm, bool add_perm) {
if (!ShowUnlockSequence(2, "You want to enable SD data\nwriting permissions.\n \nThis enables you to modify\ninstallations, user data &\nsavegames."))
return false;
break;
case PERM_CART:
if (!ShowUnlockSequence(2, "You want to enable gamecart\nsave writing permissions."))
return false;
break;
#ifndef SAFEMODE
case PERM_SYS_LVL2:
if (!ShowUnlockSequence(3, "!Better be careful!\n \nYou want to enable SysNAND\nlvl2 writing permissions.\n \nThis enables you to modify\nirrecoverable system data!"))

View File

@ -16,7 +16,7 @@
#define PERM_MEMORY (1UL<<10)
#define PERM_GAME (1UL<<11) // can't be enabled, placeholder
#define PERM_XORPAD (1UL<<12) // can't be enabled, placeholder
#define PERM_CART (1UL<<13) // can't be enabled, placeholder
#define PERM_CART (1UL<<13)
#define PERM_VRAM (1UL<<14) // can't be enabled, placeholder
#define PERM_BASE (PERM_SDCARD | PERM_IMAGE | PERM_RAMDRIVE | PERM_EMU_LVL0 | PERM_SYS_LVL0)
@ -24,7 +24,7 @@
#define PERM_BLUE (GetWritePermissions()&PERM_MEMORY)
#define PERM_RED (GetWritePermissions()&(PERM_SYS_LVL3&~PERM_SYS_LVL2))
#define PERM_ORANGE (GetWritePermissions()&(PERM_SYS_LVL2&~PERM_SYS_LVL1))
#define PERM_YELLOW (GetWritePermissions()&((PERM_SYS_LVL1&~PERM_SYS_LVL0)|(PERM_EMU_LVL1&~PERM_EMU_LVL0)|(PERM_SDDATA&~PERM_SDCARD)))
#define PERM_YELLOW (GetWritePermissions()&((PERM_SYS_LVL1&~PERM_SYS_LVL0)|(PERM_EMU_LVL1&~PERM_EMU_LVL0)|(PERM_SDDATA&~PERM_SDCARD)|PERM_CART))
#define PERM_GREEN (GetWritePermissions()&(PERM_SDCARD|PERM_IMAGE|PERM_RAMDRIVE|PERM_EMU_LVL0|PERM_SYS_LVL0))
/** Check if writing to this path is allowed **/

View File

@ -247,7 +247,7 @@ u32 ReadCartSave(u8* buffer, u64 offset, u64 count, CartData* cdata) {
return (SPIReadSaveData((CardType) cdata->save_type, offset, buffer, count) == 0) ? 0 : 1;
}
u32 WriteCartSave(u8* buffer, u64 offset, u64 count, CartData* cdata) {
u32 WriteCartSave(const u8* buffer, u64 offset, u64 count, CartData* cdata) {
if (offset >= cdata->save_size) return 1;
if (offset + count > cdata->save_size) count = cdata->save_size - offset;
return (SPIWriteSaveData((CardType) cdata->save_type, offset, buffer, count) == 0) ? 0 : 1;

View File

@ -30,5 +30,5 @@ u32 ReadCartSectors(void* buffer, u32 sector, u32 count, CartData* cdata);
u32 ReadCartBytes(void* buffer, u64 offset, u64 count, CartData* cdata);
u32 ReadCartPrivateHeader(void* buffer, u64 offset, u64 count, CartData* cdata);
u32 ReadCartSave(u8* buffer, u64 offset, u64 count, CartData* cdata);
u32 WriteCartSave(u8* buffer, u64 offset, u64 count, CartData* cdata);
u32 WriteCartSave(const u8* buffer, u64 offset, u64 count, CartData* cdata);
u32 ReadCartSaveJedecId(u8* buffer, u64 offset, u64 count, CartData* cdata);

View File

@ -106,7 +106,7 @@ u32 SPIGetCapacity(CardType type) {
else return 1 << sz[(int) type];
}
int SPIWriteSaveData(CardType type, u32 offset, void* data, u32 size) {
int SPIWriteSaveData(CardType type, u32 offset, const void* data, u32 size) {
u8 cmd[4] = { 0 };
u32 cmdSize = 4;
@ -167,7 +167,7 @@ int SPIWriteSaveData(CardType type, u32 offset, void* data, u32 size) {
case FLASH_8MB:
return 0xC8E13404; // writing is unsupported (so is reading? need to test)
default:
return 0; // never happens
return -1; // never happens
}
u32 remaining = end - pos;

View File

@ -89,7 +89,7 @@ int SPIGetCardType(CardType* type, int infrared);
u32 SPIGetPageSize(CardType type);
u32 SPIGetCapacity(CardType type);
int SPIWriteSaveData(CardType type, u32 offset, void* data, u32 size);
int SPIWriteSaveData(CardType type, u32 offset, const void* data, u32 size);
int SPIReadSaveData(CardType type, u32 offset, void* data, u32 size);
// int SPIEraseSector(CardType type, u32 offset);

View File

@ -65,7 +65,7 @@ bool ReadVCartDir(VirtualFile* vfile, VirtualDir* vdir) {
} else if (vdir->index == 7) { // JEDEC id and status register
strcpy(vfile->name, "jedecid_and_sreg.bin");
vfile->size = JEDECID_AND_SREG_SIZE;
vfile->flags = VFLAG_JEDECID_AND_SRFG;
vfile->flags |= VFLAG_JEDECID_AND_SRFG;
return true;
}
}
@ -85,6 +85,14 @@ int ReadVCartFile(const VirtualFile* vfile, void* buffer, u64 offset, u64 count)
else return ReadCartBytes(buffer, foffset, count, cdata);
}
int WriteVCartFile(const VirtualFile* vfile, const void* buffer, u64 offset, u64 count) {
if (!cdata) return -1;
if (vfile->flags & VFLAG_SAVEGAME) {
return WriteCartSave(buffer, offset, count, cdata);
}
return -1;
}
u64 GetVCartDriveSize(void) {
return cart_init ? cdata->cart_size : 0;
}

View File

@ -6,6 +6,6 @@
u32 InitVCartDrive(void);
bool ReadVCartDir(VirtualFile* vfile, VirtualDir* vdir);
int ReadVCartFile(const VirtualFile* vfile, void* buffer, u64 offset, u64 count);
// int WriteVCartFile(const VirtualFile* vfile, const void* buffer, u64 offset, u64 count); // no writes
int WriteVCartFile(const VirtualFile* vfile, const void* buffer, u64 offset, u64 count);
u64 GetVCartDriveSize(void);
void GetVCartTypeString(char* typestr);

View File

@ -204,7 +204,9 @@ int WriteVirtualFile(const VirtualFile* vfile, const void* buffer, u64 offset, u
return WriteVMemFile(vfile, buffer, offset, count);
} else if (vfile->flags & VRT_DISADIFF) {
return WriteVDisaDiffFile(vfile, buffer, offset, count);
} // no write support for virtual game / tickdb / keydb / cart / vram files
} else if (vfile->flags & VRT_CART) {
return WriteVCartFile(vfile, buffer, offset, count);
} // no write support for virtual game / tickdb / keydb / vram files
return -1;
}