--- /dev/null
+---
+Language: Cpp
+# BasedOnStyle: Mozilla
+AccessModifierOffset: -2
+AlignAfterOpenBracket: true
+AlignConsecutiveAssignments: false
+AlignEscapedNewlinesLeft: false
+AlignOperands: true
+AlignTrailingComments: true
+AllowAllParametersOfDeclarationOnNextLine: false
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: Inline
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: TopLevel
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: true
+BinPackArguments: true
+BinPackParameters: true
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Mozilla
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializersBeforeComma: true
+ColumnLimit: 80
+CommentPragmas: '^ IWYU pragma:'
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: false
+DerivePointerAlignment: false
+DisableFormat: false
+ExperimentalAutoDetectBinPacking: false
+ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
+IndentCaseLabels: true
+IndentWidth: 4
+IndentWrappedFunctionNames: false
+KeepEmptyLinesAtTheStartOfBlocks: true
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+ObjCBlockIndentWidth: 4
+ObjCSpaceAfterProperty: true
+ObjCSpaceBeforeProtocolList: false
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 200
+PointerAlignment: Left
+SpaceAfterCStyleCast: false
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeParens: ControlStatements
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles: false
+SpacesInContainerLiterals: true
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard: Cpp11
+TabWidth: 4
+UseTab: Never
+...
+
.PHONY: a9lh
a9lh: $(dir_out)/arm9loaderhax.bin
+.PHONY: reformat
+reformat:
+ clang-format -i $(dir_source)/*.{c,h} $(dir_source)/*/*.{c,h} external/loader/source/*.{c,h} external/loader/source/*/*.{c,h}
+
host/langemu.conf:
echo "Generating langemu.conf - may take a bit"
cd host && ./generate_langemu_conf.sh
#define CONFIG_MAGIC "OVAN"
// Structure of config file
-struct config_file {
- char magic[4]; // "OVAN" for shits and giggles again.
+struct config_file
+{
+ char magic[4]; // "OVAN" for shits and giggles again.
- uint32_t config_ver; // Config file version.
+ uint32_t config_ver; // Config file version.
- uint8_t options[256]; // Options in the menu - deliberately large to avoid config version bumps.
+ uint8_t options[256]; // Options in the menu - deliberately large to avoid
+ // config version bumps.
- uint64_t patch_ids[256]; // What patches are enabled by UUID. 256 is an arbitrary limit - contact me if you hit it.
-}__attribute__((packed));
+ uint64_t patch_ids[256]; // What patches are enabled by UUID. 256 is an
+ // arbitrary limit - contact me if you hit it.
+} __attribute__((packed));
-#define OPTION_LOADER_CPU_L2 11 // Enable L2 cache.
+#define OPTION_LOADER_CPU_L2 11 // Enable L2 cache.
#define OPTION_LOADER_CPU_800MHZ 12 // Enable 800Mhz mode.
-#define OPTION_LOADER_LANGEMU 13 // Enable 800Mhz mode.
+#define OPTION_LOADER_LANGEMU 13 // Enable 800Mhz mode.
#endif
typedef struct
{
- u8 reserved[5];
- u8 flag;
- u8 remasterversion[2];
+ u8 reserved[5];
+ u8 flag;
+ u8 remasterversion[2];
} PACKED exheader_systeminfoflags;
typedef struct
{
- u32 address;
- u32 nummaxpages;
- u32 codesize;
+ u32 address;
+ u32 nummaxpages;
+ u32 codesize;
} PACKED exheader_codesegmentinfo;
typedef struct
{
- u8 name[8];
- exheader_systeminfoflags flags;
- exheader_codesegmentinfo text;
- u8 stacksize[4];
- exheader_codesegmentinfo ro;
- u8 reserved[4];
- exheader_codesegmentinfo data;
- u32 bsssize;
+ u8 name[8];
+ exheader_systeminfoflags flags;
+ exheader_codesegmentinfo text;
+ u8 stacksize[4];
+ exheader_codesegmentinfo ro;
+ u8 reserved[4];
+ exheader_codesegmentinfo data;
+ u32 bsssize;
} PACKED exheader_codesetinfo;
typedef struct
{
- u64 programid[0x30];
+ u64 programid[0x30];
} PACKED exheader_dependencylist;
typedef struct
{
- u8 savedatasize[4];
- u8 reserved[4];
- u8 jumpid[8];
- u8 reserved2[0x30];
+ u8 savedatasize[4];
+ u8 reserved[4];
+ u8 jumpid[8];
+ u8 reserved2[0x30];
} PACKED exheader_systeminfo;
typedef struct
{
- u8 extsavedataid[8];
- u8 systemsavedataid[8];
- u8 reserved[8];
- u8 accessinfo[7];
- u8 otherattributes;
+ u8 extsavedataid[8];
+ u8 systemsavedataid[8];
+ u8 reserved[8];
+ u8 accessinfo[7];
+ u8 otherattributes;
} PACKED exheader_storageinfo;
// New3DS speed is flags[1]:1
typedef struct
{
- u64 programid;
- u8 flags[8];
- u16 resourcelimitdescriptor[0x10];
- exheader_storageinfo storageinfo;
- u64 serviceaccesscontrol[0x20];
- u8 reserved[0x1f];
- u8 resourcelimitcategory;
+ u64 programid;
+ u8 flags[8];
+ u16 resourcelimitdescriptor[0x10];
+ exheader_storageinfo storageinfo;
+ u64 serviceaccesscontrol[0x20];
+ u8 reserved[0x1f];
+ u8 resourcelimitcategory;
} PACKED exheader_arm11systemlocalcaps;
typedef struct
{
- u32 descriptors[28];
- u8 reserved[0x10];
+ u32 descriptors[28];
+ u8 reserved[0x10];
} PACKED exheader_arm11kernelcapabilities;
typedef struct
{
- u8 descriptors[15];
- u8 descversion;
+ u8 descriptors[15];
+ u8 descversion;
} PACKED exheader_arm9accesscontrol;
typedef struct
{
- exheader_codesetinfo codesetinfo;
- exheader_dependencylist deplist;
- exheader_systeminfo systeminfo;
- exheader_arm11systemlocalcaps arm11systemlocalcaps;
- exheader_arm11kernelcapabilities arm11kernelcaps;
- exheader_arm9accesscontrol arm9accesscontrol;
- struct {
- u8 signature[0x100];
- u8 ncchpubkeymodulus[0x100];
- exheader_arm11systemlocalcaps arm11systemlocalcaps;
- exheader_arm11kernelcapabilities arm11kernelcaps;
- exheader_arm9accesscontrol arm9accesscontrol;
- } PACKED accessdesc;
+ exheader_codesetinfo codesetinfo;
+ exheader_dependencylist deplist;
+ exheader_systeminfo systeminfo;
+ exheader_arm11systemlocalcaps arm11systemlocalcaps;
+ exheader_arm11kernelcapabilities arm11kernelcaps;
+ exheader_arm9accesscontrol arm9accesscontrol;
+ struct
+ {
+ u8 signature[0x100];
+ u8 ncchpubkeymodulus[0x100];
+ exheader_arm11systemlocalcaps arm11systemlocalcaps;
+ exheader_arm11kernelcapabilities arm11kernelcaps;
+ exheader_arm9accesscontrol arm9accesscontrol;
+ } PACKED accessdesc;
} PACKED exheader_header;
static int fsldrRefCount;
// MAKE SURE fsreg has been init before calling this
-static Result fsldrPatchPermissions(void)
+static Result
+fsldrPatchPermissions(void)
{
- u32 pid;
- Result res;
- FS_ProgramInfo info;
- u32 storage[8] = {0};
-
- storage[6] = 0x680; // SDMC access and NAND access flag
- info.programId = 0x0004013000001302LL; // loader PID
- info.mediaType = MEDIATYPE_NAND;
- res = svcGetProcessId(&pid, 0xFFFF8001);
- if (R_SUCCEEDED(res))
- {
- res = FSREG_Register(pid, 0xFFFF000000000000LL, &info, (u8 *)storage);
- }
- return res;
+ u32 pid;
+ Result res;
+ FS_ProgramInfo info;
+ u32 storage[8] = { 0 };
+
+ storage[6] = 0x680; // SDMC access and NAND access flag
+ info.programId = 0x0004013000001302LL; // loader PID
+ info.mediaType = MEDIATYPE_NAND;
+ res = svcGetProcessId(&pid, 0xFFFF8001);
+ if (R_SUCCEEDED(res)) {
+ res = FSREG_Register(pid, 0xFFFF000000000000LL, &info, (u8*)storage);
+ }
+ return res;
}
-Result fsldrInit(void)
+Result
+fsldrInit(void)
{
- Result ret = 0;
-
- if (AtomicPostIncrement(&fsldrRefCount)) return 0;
-
- ret = srvSysGetServiceHandle(&fsldrHandle, "fs:LDR");
- if (R_SUCCEEDED(ret))
- {
- fsldrPatchPermissions();
- ret = FSLDR_InitializeWithSdkVersion(fsldrHandle, SDK_VERSION);
- ret = FSLDR_SetPriority(0);
- if (R_FAILED(ret)) svcBreak(USERBREAK_ASSERT);
- }
- else
- {
- AtomicDecrement(&fsldrRefCount);
- }
-
- return ret;
+ Result ret = 0;
+
+ if (AtomicPostIncrement(&fsldrRefCount))
+ return 0;
+
+ ret = srvSysGetServiceHandle(&fsldrHandle, "fs:LDR");
+ if (R_SUCCEEDED(ret)) {
+ fsldrPatchPermissions();
+ ret = FSLDR_InitializeWithSdkVersion(fsldrHandle, SDK_VERSION);
+ ret = FSLDR_SetPriority(0);
+ if (R_FAILED(ret))
+ svcBreak(USERBREAK_ASSERT);
+ } else {
+ AtomicDecrement(&fsldrRefCount);
+ }
+
+ return ret;
}
-void fsldrExit(void)
+void
+fsldrExit(void)
{
- if (AtomicDecrement(&fsldrRefCount)) return;
- svcCloseHandle(fsldrHandle);
+ if (AtomicDecrement(&fsldrRefCount))
+ return;
+ svcCloseHandle(fsldrHandle);
}
-Result FSLDR_InitializeWithSdkVersion(Handle session, u32 version)
+Result
+FSLDR_InitializeWithSdkVersion(Handle session, u32 version)
{
- u32 *cmdbuf = getThreadCommandBuffer();
+ u32* cmdbuf = getThreadCommandBuffer();
- cmdbuf[0] = IPC_MakeHeader(0x861,1,2); // 0x8610042
- cmdbuf[1] = version;
- cmdbuf[2] = 32;
+ cmdbuf[0] = IPC_MakeHeader(0x861, 1, 2); // 0x8610042
+ cmdbuf[1] = version;
+ cmdbuf[2] = 32;
- Result ret = 0;
- if(R_FAILED(ret = svcSendSyncRequest(session))) return ret;
+ Result ret = 0;
+ if (R_FAILED(ret = svcSendSyncRequest(session)))
+ return ret;
- return cmdbuf[1];
+ return cmdbuf[1];
}
-Result FSLDR_SetPriority(u32 priority)
+Result
+FSLDR_SetPriority(u32 priority)
{
- u32 *cmdbuf = getThreadCommandBuffer();
+ u32* cmdbuf = getThreadCommandBuffer();
- cmdbuf[0] = IPC_MakeHeader(0x862,1,0); // 0x8620040
- cmdbuf[1] = priority;
+ cmdbuf[0] = IPC_MakeHeader(0x862, 1, 0); // 0x8620040
+ cmdbuf[1] = priority;
- Result ret = 0;
- if(R_FAILED(ret = svcSendSyncRequest(fsldrHandle))) return ret;
+ Result ret = 0;
+ if (R_FAILED(ret = svcSendSyncRequest(fsldrHandle)))
+ return ret;
- return cmdbuf[1];
+ return cmdbuf[1];
}
-Result FSLDR_OpenFileDirectly(Handle* out, FS_ArchiveID archiveId, FS_Path archivePath, FS_Path filePath, u32 openFlags, u32 attributes)
+Result
+FSLDR_OpenFileDirectly(Handle* out, FS_ArchiveID archiveId, FS_Path archivePath,
+ FS_Path filePath, u32 openFlags, u32 attributes)
{
- u32 *cmdbuf = getThreadCommandBuffer();
-
- cmdbuf[0] = IPC_MakeHeader(0x803,8,4); // 0x8030204
- cmdbuf[1] = 0;
- cmdbuf[2] = archiveId;
- cmdbuf[3] = archivePath.type;
- cmdbuf[4] = archivePath.size;
- cmdbuf[5] = filePath.type;
- cmdbuf[6] = filePath.size;
- cmdbuf[7] = openFlags;
- cmdbuf[8] = attributes;
- cmdbuf[9] = IPC_Desc_StaticBuffer(archivePath.size, 2);
- cmdbuf[10] = (u32)archivePath.data;
- cmdbuf[11] = IPC_Desc_StaticBuffer(filePath.size, 0);
- cmdbuf[12] = (u32)filePath.data;
-
- Result ret = 0;
- if(R_FAILED(ret = svcSendSyncRequest(fsldrHandle))) return ret;
-
- if(out) *out = cmdbuf[3];
-
- return cmdbuf[1];
+ u32* cmdbuf = getThreadCommandBuffer();
+
+ cmdbuf[0] = IPC_MakeHeader(0x803, 8, 4); // 0x8030204
+ cmdbuf[1] = 0;
+ cmdbuf[2] = archiveId;
+ cmdbuf[3] = archivePath.type;
+ cmdbuf[4] = archivePath.size;
+ cmdbuf[5] = filePath.type;
+ cmdbuf[6] = filePath.size;
+ cmdbuf[7] = openFlags;
+ cmdbuf[8] = attributes;
+ cmdbuf[9] = IPC_Desc_StaticBuffer(archivePath.size, 2);
+ cmdbuf[10] = (u32)archivePath.data;
+ cmdbuf[11] = IPC_Desc_StaticBuffer(filePath.size, 0);
+ cmdbuf[12] = (u32)filePath.data;
+
+ Result ret = 0;
+ if (R_FAILED(ret = svcSendSyncRequest(fsldrHandle)))
+ return ret;
+
+ if (out)
+ *out = cmdbuf[3];
+
+ return cmdbuf[1];
}
void fsldrExit(void);
Result FSLDR_InitializeWithSdkVersion(Handle session, u32 version);
Result FSLDR_SetPriority(u32 priority);
-Result FSLDR_OpenFileDirectly(Handle* out, FS_ArchiveID archiveId, FS_Path archivePath, FS_Path filePath, u32 openFlags, u32 attributes);
\ No newline at end of file
+Result FSLDR_OpenFileDirectly(Handle* out, FS_ArchiveID archiveId,
+ FS_Path archivePath, FS_Path filePath,
+ u32 openFlags, u32 attributes);
\ No newline at end of file
static Handle fsregHandle;
static int fsregRefCount;
-Result fsregInit(void)
+Result
+fsregInit(void)
{
- Result ret = 0;
+ Result ret = 0;
- if (AtomicPostIncrement(&fsregRefCount)) return 0;
+ if (AtomicPostIncrement(&fsregRefCount))
+ return 0;
- ret = srvSysGetServiceHandle(&fsregHandle, "fs:REG");
+ ret = srvSysGetServiceHandle(&fsregHandle, "fs:REG");
- if (R_FAILED(ret)) AtomicDecrement(&fsregRefCount);
- return ret;
+ if (R_FAILED(ret))
+ AtomicDecrement(&fsregRefCount);
+ return ret;
}
-void fsregExit(void)
+void
+fsregExit(void)
{
- if (AtomicDecrement(&fsregRefCount)) return;
- svcCloseHandle(fsregHandle);
+ if (AtomicDecrement(&fsregRefCount))
+ return;
+ svcCloseHandle(fsregHandle);
}
-Result FSREG_CheckHostLoadId(u64 prog_handle)
+Result
+FSREG_CheckHostLoadId(u64 prog_handle)
{
- u32 *cmdbuf = getThreadCommandBuffer();
+ u32* cmdbuf = getThreadCommandBuffer();
- cmdbuf[0] = IPC_MakeHeader(0x406,2,0); // 0x4060080
- cmdbuf[1] = (u32) (prog_handle);
- cmdbuf[2] = (u32) (prog_handle >> 32);
+ cmdbuf[0] = IPC_MakeHeader(0x406, 2, 0); // 0x4060080
+ cmdbuf[1] = (u32)(prog_handle);
+ cmdbuf[2] = (u32)(prog_handle >> 32);
- Result ret = 0;
- if(R_FAILED(ret = svcSendSyncRequest(fsregHandle))) return ret;
+ Result ret = 0;
+ if (R_FAILED(ret = svcSendSyncRequest(fsregHandle)))
+ return ret;
- return cmdbuf[1];
+ return cmdbuf[1];
}
-Result FSREG_LoadProgram(u64 *prog_handle, FS_ProgramInfo *title)
+Result
+FSREG_LoadProgram(u64* prog_handle, FS_ProgramInfo* title)
{
- u32 *cmdbuf = getThreadCommandBuffer();
+ u32* cmdbuf = getThreadCommandBuffer();
- cmdbuf[0] = IPC_MakeHeader(0x404,4,0); // 0x4040100
- memcpy(&cmdbuf[1], &title->programId, sizeof(u64));
- *(u8 *)&cmdbuf[3] = title->mediaType;
- memcpy(((u8 *)&cmdbuf[3])+1, &title->padding, 7);
+ cmdbuf[0] = IPC_MakeHeader(0x404, 4, 0); // 0x4040100
+ memcpy(&cmdbuf[1], &title->programId, sizeof(u64));
+ *(u8*)&cmdbuf[3] = title->mediaType;
+ memcpy(((u8*)&cmdbuf[3]) + 1, &title->padding, 7);
- Result ret = 0;
- if(R_FAILED(ret = svcSendSyncRequest(fsregHandle))) return ret;
- *prog_handle = *(u64 *)&cmdbuf[2];
+ Result ret = 0;
+ if (R_FAILED(ret = svcSendSyncRequest(fsregHandle)))
+ return ret;
+ *prog_handle = *(u64*)&cmdbuf[2];
- return cmdbuf[1];
+ return cmdbuf[1];
}
-Result FSREG_GetProgramInfo(exheader_header *exheader, u32 entry_count, u64 prog_handle)
+Result
+FSREG_GetProgramInfo(exheader_header* exheader, u32 entry_count,
+ u64 prog_handle)
{
- u32 *cmdbuf = getThreadCommandBuffer();
+ u32* cmdbuf = getThreadCommandBuffer();
- cmdbuf[0] = IPC_MakeHeader(0x403,3,0); // 0x40300C0
- cmdbuf[1] = entry_count;
- *(u64 *)&cmdbuf[2] = prog_handle;
- cmdbuf[64] = ((entry_count << 10) << 14) | 2;
- cmdbuf[65] = (u32) exheader;
+ cmdbuf[0] = IPC_MakeHeader(0x403, 3, 0); // 0x40300C0
+ cmdbuf[1] = entry_count;
+ *(u64*)&cmdbuf[2] = prog_handle;
+ cmdbuf[64] = ((entry_count << 10) << 14) | 2;
+ cmdbuf[65] = (u32)exheader;
- Result ret = 0;
- if(R_FAILED(ret = svcSendSyncRequest(fsregHandle))) return ret;
+ Result ret = 0;
+ if (R_FAILED(ret = svcSendSyncRequest(fsregHandle)))
+ return ret;
- return cmdbuf[1];
+ return cmdbuf[1];
}
-Result FSREG_UnloadProgram(u64 prog_handle)
+Result
+FSREG_UnloadProgram(u64 prog_handle)
{
- u32 *cmdbuf = getThreadCommandBuffer();
+ u32* cmdbuf = getThreadCommandBuffer();
- cmdbuf[0] = IPC_MakeHeader(0x405,2,0); // 0x4050080
- cmdbuf[1] = (u32) (prog_handle);
- cmdbuf[2] = (u32) (prog_handle >> 32);
+ cmdbuf[0] = IPC_MakeHeader(0x405, 2, 0); // 0x4050080
+ cmdbuf[1] = (u32)(prog_handle);
+ cmdbuf[2] = (u32)(prog_handle >> 32);
- Result ret = 0;
- if(R_FAILED(ret = svcSendSyncRequest(fsregHandle))) return ret;
+ Result ret = 0;
+ if (R_FAILED(ret = svcSendSyncRequest(fsregHandle)))
+ return ret;
- return cmdbuf[1];
+ return cmdbuf[1];
}
-Result FSREG_Unregister(u32 pid)
+Result
+FSREG_Unregister(u32 pid)
{
- u32 *cmdbuf = getThreadCommandBuffer();
+ u32* cmdbuf = getThreadCommandBuffer();
- cmdbuf[0] = IPC_MakeHeader(0x402,1,0); // 0x4020040
- cmdbuf[1] = pid;
+ cmdbuf[0] = IPC_MakeHeader(0x402, 1, 0); // 0x4020040
+ cmdbuf[1] = pid;
- Result ret = 0;
- if(R_FAILED(ret = svcSendSyncRequest(fsregHandle))) return ret;
+ Result ret = 0;
+ if (R_FAILED(ret = svcSendSyncRequest(fsregHandle)))
+ return ret;
- return cmdbuf[1];
+ return cmdbuf[1];
}
-Result FSREG_Register(u32 pid, u64 prog_handle, FS_ProgramInfo *info, void *storageinfo)
+Result
+FSREG_Register(u32 pid, u64 prog_handle, FS_ProgramInfo* info,
+ void* storageinfo)
{
- u32 *cmdbuf = getThreadCommandBuffer();
+ u32* cmdbuf = getThreadCommandBuffer();
- cmdbuf[0] = IPC_MakeHeader(0x401,0xf,0); // 0x40103C0
- cmdbuf[1] = pid;
- *(u64 *)&cmdbuf[2] = prog_handle;
- memcpy(&cmdbuf[4], &info->programId, sizeof(u64));
- *(u8 *)&cmdbuf[6] = info->mediaType;
- memcpy(((u8 *)&cmdbuf[6])+1, &info->padding, 7);
- memcpy((u8 *)&cmdbuf[8], storageinfo, 32);
+ cmdbuf[0] = IPC_MakeHeader(0x401, 0xf, 0); // 0x40103C0
+ cmdbuf[1] = pid;
+ *(u64*)&cmdbuf[2] = prog_handle;
+ memcpy(&cmdbuf[4], &info->programId, sizeof(u64));
+ *(u8*)&cmdbuf[6] = info->mediaType;
+ memcpy(((u8*)&cmdbuf[6]) + 1, &info->padding, 7);
+ memcpy((u8*)&cmdbuf[8], storageinfo, 32);
- Result ret = 0;
- if(R_FAILED(ret = svcSendSyncRequest(fsregHandle))) return ret;
+ Result ret = 0;
+ if (R_FAILED(ret = svcSendSyncRequest(fsregHandle)))
+ return ret;
- return cmdbuf[1];
+ return cmdbuf[1];
}
Result fsregInit(void);
void fsregExit(void);
Result FSREG_CheckHostLoadId(u64 prog_handle);
-Result FSREG_LoadProgram(u64 *prog_handle, FS_ProgramInfo *title);
-Result FSREG_GetProgramInfo(exheader_header *exheader, u32 entry_count, u64 prog_handle);
+Result FSREG_LoadProgram(u64* prog_handle, FS_ProgramInfo* title);
+Result FSREG_GetProgramInfo(exheader_header* exheader, u32 entry_count,
+ u64 prog_handle);
Result FSREG_UnloadProgram(u64 prog_handle);
Result FSREG_Unregister(u32 pid);
-Result FSREG_Register(u32 pid, u64 prog_handle, FS_ProgramInfo *info, void *storageinfo);
+Result FSREG_Register(u32 pid, u64 prog_handle, FS_ProgramInfo* info,
+ void* storageinfo);
// TODO - What exactly is the point of these? Can't we just use FSFILE directly?
// These are just shitty wrappers.
-Result IFile_Open(IFile *file, FS_ArchiveID archiveId, FS_Path archivePath, FS_Path filePath, u32 flags)
+Result
+IFile_Open(IFile* file, FS_ArchiveID archiveId, FS_Path archivePath,
+ FS_Path filePath, u32 flags)
{
- Result res;
+ Result res;
- res = FSLDR_OpenFileDirectly(&file->handle, archiveId, archivePath, filePath, flags, 0);
- file->pos = 0;
- file->size = 0;
- return res;
+ res = FSLDR_OpenFileDirectly(&file->handle, archiveId, archivePath,
+ filePath, flags, 0);
+ file->pos = 0;
+ file->size = 0;
+ return res;
}
-Result IFile_Close(IFile *file)
+Result
+IFile_Close(IFile* file)
{
- return FSFILE_Close(file->handle);
+ return FSFILE_Close(file->handle);
}
-Result IFile_GetSize(IFile *file, u64 *size)
+Result
+IFile_GetSize(IFile* file, u64* size)
{
- Result res;
+ Result res;
- res = FSFILE_GetSize(file->handle, size);
- file->size = *size;
- return res;
+ res = FSFILE_GetSize(file->handle, size);
+ file->size = *size;
+ return res;
}
-Result IFile_Read(IFile *file, u64 *total, void *buffer, u32 len)
+Result
+IFile_Read(IFile* file, u64* total, void* buffer, u32 len)
{
- u32 read;
- u32 left;
- char *buf;
- u64 cur;
- Result res;
+ u32 read;
+ u32 left;
+ char* buf;
+ u64 cur;
+ Result res;
- if (len == 0)
- {
- *total = 0;
- return 0;
- }
-
- buf = (char *)buffer;
- cur = 0;
- left = len;
- while (1)
- {
- res = FSFILE_Read(file->handle, &read, file->pos, buf, left);
- if (R_FAILED(res))
- {
- break;
+ if (len == 0) {
+ *total = 0;
+ return 0;
}
- cur += read;
- file->pos += read;
- if (read == left)
- {
- break;
+ buf = (char*)buffer;
+ cur = 0;
+ left = len;
+ while (1) {
+ res = FSFILE_Read(file->handle, &read, file->pos, buf, left);
+ if (R_FAILED(res)) {
+ break;
+ }
+
+ cur += read;
+ file->pos += read;
+ if (read == left) {
+ break;
+ }
+ buf += read;
+ left -= read;
}
- buf += read;
- left -= read;
- }
- *total = cur;
- return res;
+ *total = cur;
+ return res;
}
-Result IFile_Write(IFile *file, u64 *total, void *buffer, u32 len) {
- return 1; // FIXME - Not yet implemented.
+Result
+IFile_Write(IFile* file, u64* total, void* buffer, u32 len)
+{
+ return 1; // FIXME - Not yet implemented.
}
typedef struct
{
- Handle handle;
- u64 pos;
- u64 size;
+ Handle handle;
+ u64 pos;
+ u64 size;
} IFile;
-Result IFile_Open(IFile *file, FS_ArchiveID archiveId, FS_Path archivePath, FS_Path filePath, u32 flags);
-Result IFile_Close(IFile *file);
-Result IFile_GetSize(IFile *file, u64 *size);
-Result IFile_Read(IFile *file, u64 *total, void *buffer, u32 len);
-Result IFile_Write(IFile *file, u64 *total, void *buffer, u32 len);
+Result IFile_Open(IFile* file, FS_ArchiveID archiveId, FS_Path archivePath,
+ FS_Path filePath, u32 flags);
+Result IFile_Close(IFile* file);
+Result IFile_GetSize(IFile* file, u64* size);
+Result IFile_Read(IFile* file, u64* total, void* buffer, u32 len);
+Result IFile_Write(IFile* file, u64* total, void* buffer, u32 len);
#pragma once
-// This is a GCC builtin, and so there's no need to carry an implementation here.
+// This is a GCC builtin, and so there's no need to carry an implementation
+// here.
void* memcpy(void* dest, const void* src, size_t len);
#include "lzss.h"
#include "internal.h"
-// TODO - a lot of this is unecessarily verbose and shitty. Clean it up to be tidy.
+// TODO - a lot of this is unecessarily verbose and shitty. Clean it up to be
+// tidy.
#define MAX_SESSIONS 1
-const char CODE_PATH[] = {0x01, 0x00, 0x00, 0x00, 0x2E, 0x63, 0x6F, 0x64, 0x65, 0x00, 0x00, 0x00};
+const char CODE_PATH[] = { 0x01, 0x00, 0x00, 0x00, 0x2E, 0x63,
+ 0x6F, 0x64, 0x65, 0x00, 0x00, 0x00 };
typedef struct
{
- u32 text_addr;
- u32 text_size;
- u32 ro_addr;
- u32 ro_size;
- u32 data_addr;
- u32 data_size;
- u32 total_size;
+ u32 text_addr;
+ u32 text_size;
+ u32 ro_addr;
+ u32 ro_size;
+ u32 data_addr;
+ u32 data_size;
+ u32 total_size;
} prog_addrs_t;
-static Handle g_handles[MAX_SESSIONS+2];
+static Handle g_handles[MAX_SESSIONS + 2];
static int g_active_handles;
static u64 g_cached_prog_handle;
static exheader_header g_exheader;
static char g_ret_buf[1024];
-static Result allocate_shared_mem(prog_addrs_t *shared, prog_addrs_t *vaddr, int flags)
+static Result
+allocate_shared_mem(prog_addrs_t* shared, prog_addrs_t* vaddr, int flags)
{
- // Somehow, we need to allow reallocating.
-
- u32 dummy;
-
- memcpy(shared, vaddr, sizeof(prog_addrs_t));
- shared->text_addr = 0x10000000; // Code is forcibly relocated to this address to kill ASLR (I believe.)
- shared->ro_addr = shared->text_addr + (shared->text_size << 12);
- shared->data_addr = shared->ro_addr + (shared->ro_size << 12);
- return svcControlMemory(&dummy, shared->text_addr, 0, shared->total_size << 12, (flags & 0xF00) | MEMOP_ALLOC, MEMPERM_READ | MEMPERM_WRITE);
+ // Somehow, we need to allow reallocating.
+
+ u32 dummy;
+
+ memcpy(shared, vaddr, sizeof(prog_addrs_t));
+ shared->text_addr = 0x10000000; // Code is forcibly relocated to this
+ // address to kill ASLR (I believe.)
+ shared->ro_addr = shared->text_addr + (shared->text_size << 12);
+ shared->data_addr = shared->ro_addr + (shared->ro_size << 12);
+ return svcControlMemory(
+ &dummy, shared->text_addr, 0, shared->total_size << 12,
+ (flags & 0xF00) | MEMOP_ALLOC, MEMPERM_READ | MEMPERM_WRITE);
}
-static Result load_code(u64 progid, prog_addrs_t *shared, prog_addrs_t *original, u64 prog_handle, int is_compressed)
+static Result
+load_code(u64 progid, prog_addrs_t* shared, prog_addrs_t* original,
+ u64 prog_handle, int is_compressed)
{
- IFile file;
- FS_Path archivePath;
- FS_Path path;
- Result res;
- u64 size;
- u64 total;
-
- archivePath.type = PATH_BINARY;
- archivePath.data = &prog_handle;
- archivePath.size = 8;
-
- path.type = PATH_BINARY;
- path.data = CODE_PATH;
- path.size = sizeof(CODE_PATH);
-
- if (R_FAILED(IFile_Open(&file, ARCHIVE_SAVEDATA_AND_CONTENT2, archivePath, path, FS_OPEN_READ)))
- {
- svcBreak(USERBREAK_ASSERT);
- }
-
- // get file size
- if (R_FAILED(IFile_GetSize(&file, &size)))
- {
- IFile_Close(&file);
- svcBreak(USERBREAK_ASSERT);
- }
-
- // check size
- if (size > (u64)shared->total_size << 12)
- {
- IFile_Close(&file);
- return 0xC900464F;
- }
-
- // read code
- res = IFile_Read(&file, &total, (void *)shared->text_addr, size);
- IFile_Close(&file); // done reading
- if (R_FAILED(res))
- {
- svcBreak(USERBREAK_ASSERT);
- }
-
- // decompress in place
- if (is_compressed)
- {
- lzss_decompress((u8 *)shared->text_addr + size);
- }
-
- // Patch segments
- patch_text(progid, (u8 *)shared->text_addr, shared->text_size << 12, original->text_size << 12);
- patch_data(progid, (u8 *)shared->data_addr, shared->data_size << 12, original->data_size << 12);
- patch_ro (progid, (u8 *)shared->ro_addr, shared->ro_size << 12, original->ro_size << 12);
-
- return 0;
+ IFile file;
+ FS_Path archivePath;
+ FS_Path path;
+ Result res;
+ u64 size;
+ u64 total;
+
+ archivePath.type = PATH_BINARY;
+ archivePath.data = &prog_handle;
+ archivePath.size = 8;
+
+ path.type = PATH_BINARY;
+ path.data = CODE_PATH;
+ path.size = sizeof(CODE_PATH);
+
+ if (R_FAILED(IFile_Open(&file, ARCHIVE_SAVEDATA_AND_CONTENT2, archivePath,
+ path, FS_OPEN_READ))) {
+ svcBreak(USERBREAK_ASSERT);
+ }
+
+ // get file size
+ if (R_FAILED(IFile_GetSize(&file, &size))) {
+ IFile_Close(&file);
+ svcBreak(USERBREAK_ASSERT);
+ }
+
+ // check size
+ if (size > (u64)shared->total_size << 12) {
+ IFile_Close(&file);
+ return 0xC900464F;
+ }
+
+ // read code
+ res = IFile_Read(&file, &total, (void*)shared->text_addr, size);
+ IFile_Close(&file); // done reading
+ if (R_FAILED(res)) {
+ svcBreak(USERBREAK_ASSERT);
+ }
+
+ // decompress in place
+ if (is_compressed) {
+ lzss_decompress((u8*)shared->text_addr + size);
+ }
+
+ // Patch segments
+ patch_text(progid, (u8*)shared->text_addr, shared->text_size << 12,
+ original->text_size << 12);
+ patch_data(progid, (u8*)shared->data_addr, shared->data_size << 12,
+ original->data_size << 12);
+ patch_ro(progid, (u8*)shared->ro_addr, shared->ro_size << 12,
+ original->ro_size << 12);
+
+ return 0;
}
-static Result loader_GetProgramInfo(exheader_header *exheader, u64 prog_handle)
+static Result
+loader_GetProgramInfo(exheader_header* exheader, u64 prog_handle)
{
- Result res;
-
- if (prog_handle >> 32 == 0xFFFF0000)
- {
- return FSREG_GetProgramInfo(exheader, 1, prog_handle);
- }
- else
- {
- res = FSREG_CheckHostLoadId(prog_handle);
- //if ((res >= 0 && (unsigned)res >> 27) || (res < 0 && ((unsigned)res >> 27)-32))
- //so use PXIPM if FSREG fails OR returns "info", is the second condition a bug?
- if (R_FAILED(res) || (R_SUCCEEDED(res) && R_LEVEL(res) != RL_SUCCESS))
- {
- return PXIPM_GetProgramInfo(exheader, prog_handle);
- }
- else
- {
- return FSREG_GetProgramInfo(exheader, 1, prog_handle);
+ Result res;
+
+ if (prog_handle >> 32 == 0xFFFF0000) {
+ return FSREG_GetProgramInfo(exheader, 1, prog_handle);
+ } else {
+ res = FSREG_CheckHostLoadId(prog_handle);
+ // if ((res >= 0 && (unsigned)res >> 27) || (res < 0 && ((unsigned)res
+ // >> 27)-32))
+ // so use PXIPM if FSREG fails OR returns "info", is the second
+ // condition a bug?
+ if (R_FAILED(res) || (R_SUCCEEDED(res) && R_LEVEL(res) != RL_SUCCESS)) {
+ return PXIPM_GetProgramInfo(exheader, prog_handle);
+ } else {
+ return FSREG_GetProgramInfo(exheader, 1, prog_handle);
+ }
}
- }
}
-extern void KernelSetState(unsigned int, unsigned int, unsigned int, unsigned int);
+extern void KernelSetState(unsigned int, unsigned int, unsigned int,
+ unsigned int);
-static void ConfigureNew3DSCPU(u8 mode) {
- // 10 -> r0 (Type)
- // mode -> r1 (Mode)
- // svc 0x7C
+static void
+ConfigureNew3DSCPU(u8 mode)
+{
+ // 10 -> r0 (Type)
+ // mode -> r1 (Mode)
+ // svc 0x7C
- KernelSetState(10, mode, 0, 0); // Yes, we syscall directly. Problem?
+ KernelSetState(10, mode, 0, 0); // Yes, we syscall directly. Problem?
}
-static Result loader_LoadProcess(Handle *process, u64 prog_handle)
+static Result
+loader_LoadProcess(Handle* process, u64 prog_handle)
{
- Result res;
- int count;
- u32 flags;
- u32 desc;
- u32 dummy;
- prog_addrs_t shared_addr;
- prog_addrs_t vaddr;
- prog_addrs_t original_vaddr;
- Handle codeset;
- CodeSetInfo codesetinfo;
- u32 data_mem_size;
- u64 progid;
- u32 text_grow, data_grow, ro_grow;
-
- // make sure the cached info corrosponds to the current prog_handle
- if (g_cached_prog_handle != prog_handle)
- {
- res = loader_GetProgramInfo(&g_exheader, prog_handle);
- g_cached_prog_handle = prog_handle;
- if (res < 0)
- {
- g_cached_prog_handle = 0;
- return res;
+ Result res;
+ int count;
+ u32 flags;
+ u32 desc;
+ u32 dummy;
+ prog_addrs_t shared_addr;
+ prog_addrs_t vaddr;
+ prog_addrs_t original_vaddr;
+ Handle codeset;
+ CodeSetInfo codesetinfo;
+ u32 data_mem_size;
+ u64 progid;
+ u32 text_grow, data_grow, ro_grow;
+
+ // make sure the cached info corrosponds to the current prog_handle
+ if (g_cached_prog_handle != prog_handle) {
+ res = loader_GetProgramInfo(&g_exheader, prog_handle);
+ g_cached_prog_handle = prog_handle;
+ if (res < 0) {
+ g_cached_prog_handle = 0;
+ return res;
+ }
}
- }
-
- // get kernel flags
- flags = 0;
- for (count = 0; count < 28; count++)
- {
- desc = g_exheader.arm11kernelcaps.descriptors[count];
- if (0x1FE == desc >> 23)
- {
- flags = desc & 0xF00;
+
+ // get kernel flags
+ flags = 0;
+ for (count = 0; count < 28; count++) {
+ desc = g_exheader.arm11kernelcaps.descriptors[count];
+ if (0x1FE == desc >> 23) {
+ flags = desc & 0xF00;
+ }
}
- }
- if (flags == 0)
- {
- return MAKERESULT(RL_PERMANENT, RS_INVALIDARG, 1, 2);
- }
-
- load_config(); // First order of business - we need the config file.
-
- // Check and set the CPU mode. Possible values: 0 - Keep o3ds speed, 1 - n3ds speed, -1 force o3ds
- // This is A-OK because the CPU speed parameter isn't passed through to any kernel function; meaning it has already been set.
- u8 n3ds_mode = g_exheader.arm11systemlocalcaps.flags[1] & 0x3;
- u8 cpu_mode = get_cpumode(progid);
- if (cpu_mode != 0xFF) { // Skip?
- u8 mode = n3ds_mode | cpu_mode; // Keep flags set by exheader.
- ConfigureNew3DSCPU(mode); // We do not use PXIPM because we are a sysmodule. It doesn't make sense.
- }
-
- // What the addressing info would be if not for expansion. This is passed to patchCode.
- original_vaddr.text_size = (g_exheader.codesetinfo.text.codesize + 4095) >> 12; // (Text size + one page) >> page size
- original_vaddr.ro_size = (g_exheader.codesetinfo.ro.codesize + 4095) >> 12;
- original_vaddr.data_size = (g_exheader.codesetinfo.data.codesize + 4095) >> 12;
- original_vaddr.total_size = original_vaddr.text_size + original_vaddr.ro_size + original_vaddr.data_size;
-
- // Allow changing code, ro, data sizes to allow adding code
- text_grow = get_text_extend(progid, g_exheader.codesetinfo.text.codesize);
- ro_grow = get_ro_extend(progid, g_exheader.codesetinfo.ro.codesize);
- data_grow = get_data_extend(progid, g_exheader.codesetinfo.data.codesize);
-
- // One page is 4096 bytes, thus all the 4095 constants.
-
- // Allocate process memory, growing as needed for extra patches
- vaddr.text_addr = g_exheader.codesetinfo.text.address;
- vaddr.text_size = (g_exheader.codesetinfo.text.codesize + text_grow + 4095) >> 12; // (Text size + one page) >> page size
- vaddr.ro_addr = g_exheader.codesetinfo.ro.address;
- vaddr.ro_size = (g_exheader.codesetinfo.ro.codesize + ro_grow + 4095) >> 12;
- vaddr.data_addr = g_exheader.codesetinfo.data.address;
- vaddr.data_size = (g_exheader.codesetinfo.data.codesize + data_grow + 4095) >> 12;
- data_mem_size = (g_exheader.codesetinfo.data.codesize + text_grow + g_exheader.codesetinfo.bsssize + 4095) >> 12;
- vaddr.total_size = vaddr.text_size + vaddr.ro_size + vaddr.data_size + text_grow + ro_grow + data_grow;
-
- if ((res = allocate_shared_mem(&shared_addr, &vaddr, flags)) < 0)
- {
- return res;
- }
-
- // load code
- progid = g_exheader.arm11systemlocalcaps.programid;
- if ((res = load_code(progid, &shared_addr, &original_vaddr, prog_handle, g_exheader.codesetinfo.flags.flag & 1)) >= 0)
- {
- memcpy(&codesetinfo.name, g_exheader.codesetinfo.name, 8);
- codesetinfo.program_id = progid;
- codesetinfo.text_addr = vaddr.text_addr;
- codesetinfo.text_size = vaddr.text_size;
- codesetinfo.text_size_total = vaddr.text_size;
- codesetinfo.ro_addr = vaddr.ro_addr;
- codesetinfo.ro_size = vaddr.ro_size;
- codesetinfo.ro_size_total = vaddr.ro_size;
- codesetinfo.rw_addr = vaddr.data_addr;
- codesetinfo.rw_size = vaddr.data_size;
- codesetinfo.rw_size_total = data_mem_size;
- res = svcCreateCodeSet(&codeset, &codesetinfo, (void *)shared_addr.text_addr, (void *)shared_addr.ro_addr, (void *)shared_addr.data_addr);
- if (res >= 0)
- {
- res = svcCreateProcess(process, codeset, g_exheader.arm11kernelcaps.descriptors, count);
- svcCloseHandle(codeset);
- if (res >= 0)
- {
- return 0;
- }
+ if (flags == 0) {
+ return MAKERESULT(RL_PERMANENT, RS_INVALIDARG, 1, 2);
+ }
+
+ load_config(); // First order of business - we need the config file.
+
+ // Check and set the CPU mode. Possible values: 0 - Keep o3ds speed, 1 -
+ // n3ds speed, -1 force o3ds
+ // This is A-OK because the CPU speed parameter isn't passed through to any
+ // kernel function; meaning it has already been set.
+ u8 n3ds_mode = g_exheader.arm11systemlocalcaps.flags[1] & 0x3;
+ u8 cpu_mode = get_cpumode(progid);
+ if (cpu_mode != 0xFF) { // Skip?
+ u8 mode = n3ds_mode | cpu_mode; // Keep flags set by exheader.
+ ConfigureNew3DSCPU(mode); // We do not use PXIPM because we are a
+ // sysmodule. It doesn't make sense.
+ }
+
+ // What the addressing info would be if not for expansion. This is passed to
+ // patchCode.
+ original_vaddr.text_size = (g_exheader.codesetinfo.text.codesize + 4095) >>
+ 12; // (Text size + one page) >> page size
+ original_vaddr.ro_size = (g_exheader.codesetinfo.ro.codesize + 4095) >> 12;
+ original_vaddr.data_size =
+ (g_exheader.codesetinfo.data.codesize + 4095) >> 12;
+ original_vaddr.total_size = original_vaddr.text_size +
+ original_vaddr.ro_size +
+ original_vaddr.data_size;
+
+ // Allow changing code, ro, data sizes to allow adding code
+ text_grow = get_text_extend(progid, g_exheader.codesetinfo.text.codesize);
+ ro_grow = get_ro_extend(progid, g_exheader.codesetinfo.ro.codesize);
+ data_grow = get_data_extend(progid, g_exheader.codesetinfo.data.codesize);
+
+ // One page is 4096 bytes, thus all the 4095 constants.
+
+ // Allocate process memory, growing as needed for extra patches
+ vaddr.text_addr = g_exheader.codesetinfo.text.address;
+ vaddr.text_size =
+ (g_exheader.codesetinfo.text.codesize + text_grow + 4095) >>
+ 12; // (Text size + one page) >> page size
+ vaddr.ro_addr = g_exheader.codesetinfo.ro.address;
+ vaddr.ro_size = (g_exheader.codesetinfo.ro.codesize + ro_grow + 4095) >> 12;
+ vaddr.data_addr = g_exheader.codesetinfo.data.address;
+ vaddr.data_size =
+ (g_exheader.codesetinfo.data.codesize + data_grow + 4095) >> 12;
+ data_mem_size = (g_exheader.codesetinfo.data.codesize + text_grow +
+ g_exheader.codesetinfo.bsssize + 4095) >>
+ 12;
+ vaddr.total_size = vaddr.text_size + vaddr.ro_size + vaddr.data_size +
+ text_grow + ro_grow + data_grow;
+
+ if ((res = allocate_shared_mem(&shared_addr, &vaddr, flags)) < 0) {
+ return res;
+ }
+
+ // load code
+ progid = g_exheader.arm11systemlocalcaps.programid;
+ if ((res = load_code(progid, &shared_addr, &original_vaddr, prog_handle,
+ g_exheader.codesetinfo.flags.flag & 1)) >= 0) {
+ memcpy(&codesetinfo.name, g_exheader.codesetinfo.name, 8);
+ codesetinfo.program_id = progid;
+ codesetinfo.text_addr = vaddr.text_addr;
+ codesetinfo.text_size = vaddr.text_size;
+ codesetinfo.text_size_total = vaddr.text_size;
+ codesetinfo.ro_addr = vaddr.ro_addr;
+ codesetinfo.ro_size = vaddr.ro_size;
+ codesetinfo.ro_size_total = vaddr.ro_size;
+ codesetinfo.rw_addr = vaddr.data_addr;
+ codesetinfo.rw_size = vaddr.data_size;
+ codesetinfo.rw_size_total = data_mem_size;
+ res = svcCreateCodeSet(
+ &codeset, &codesetinfo, (void*)shared_addr.text_addr,
+ (void*)shared_addr.ro_addr, (void*)shared_addr.data_addr);
+ if (res >= 0) {
+ res =
+ svcCreateProcess(process, codeset,
+ g_exheader.arm11kernelcaps.descriptors, count);
+ svcCloseHandle(codeset);
+ if (res >= 0) {
+ return 0;
+ }
+ }
}
- }
- svcControlMemory(&dummy, shared_addr.text_addr, 0, shared_addr.total_size << 12, MEMOP_FREE, 0);
- return res;
+ svcControlMemory(&dummy, shared_addr.text_addr, 0,
+ shared_addr.total_size << 12, MEMOP_FREE, 0);
+ return res;
}
-static Result loader_RegisterProgram(u64 *prog_handle, FS_ProgramInfo *title, FS_ProgramInfo *update)
+static Result
+loader_RegisterProgram(u64* prog_handle, FS_ProgramInfo* title,
+ FS_ProgramInfo* update)
{
- Result res;
- u64 prog_id;
-
- prog_id = title->programId;
- if (prog_id >> 32 != 0xFFFF0000)
- {
- res = FSREG_CheckHostLoadId(prog_id);
- //if ((res >= 0 && (unsigned)res >> 27) || (res < 0 && ((unsigned)res >> 27)-32))
- if (R_FAILED(res) || (R_SUCCEEDED(res) && R_LEVEL(res) != RL_SUCCESS))
- {
- res = PXIPM_RegisterProgram(prog_handle, title, update);
- if (res < 0)
- {
- return res;
- }
- if (*prog_handle >> 32 != 0xFFFF0000)
- {
- res = FSREG_CheckHostLoadId(*prog_handle);
- //if ((res >= 0 && (unsigned)res >> 27) || (res < 0 && ((unsigned)res >> 27)-32))
- if (R_FAILED(res) || (R_SUCCEEDED(res) && R_LEVEL(res) != RL_SUCCESS))
- {
- return 0;
+ Result res;
+ u64 prog_id;
+
+ prog_id = title->programId;
+ if (prog_id >> 32 != 0xFFFF0000) {
+ res = FSREG_CheckHostLoadId(prog_id);
+ // if ((res >= 0 && (unsigned)res >> 27) || (res < 0 && ((unsigned)res
+ // >> 27)-32))
+ if (R_FAILED(res) || (R_SUCCEEDED(res) && R_LEVEL(res) != RL_SUCCESS)) {
+ res = PXIPM_RegisterProgram(prog_handle, title, update);
+ if (res < 0) {
+ return res;
+ }
+ if (*prog_handle >> 32 != 0xFFFF0000) {
+ res = FSREG_CheckHostLoadId(*prog_handle);
+ // if ((res >= 0 && (unsigned)res >> 27) || (res < 0 &&
+ // ((unsigned)res >> 27)-32))
+ if (R_FAILED(res) ||
+ (R_SUCCEEDED(res) && R_LEVEL(res) != RL_SUCCESS)) {
+ return 0;
+ }
+ }
+ svcBreak(USERBREAK_ASSERT);
}
- }
- svcBreak(USERBREAK_ASSERT);
}
- }
-
- if ((title->mediaType != update->mediaType) || (prog_id != update->programId))
- {
- svcBreak(USERBREAK_ASSERT);
- }
- res = FSREG_LoadProgram(prog_handle, title);
- if (R_SUCCEEDED(res))
- {
- if (*prog_handle >> 32 == 0xFFFF0000)
- {
- return 0;
+
+ if ((title->mediaType != update->mediaType) ||
+ (prog_id != update->programId)) {
+ svcBreak(USERBREAK_ASSERT);
}
- res = FSREG_CheckHostLoadId(*prog_handle);
- //if ((res >= 0 && (unsigned)res >> 27) || (res < 0 && ((unsigned)res >> 27)-32))
- if (R_FAILED(res) || (R_SUCCEEDED(res) && R_LEVEL(res) != RL_SUCCESS))
- {
- svcBreak(USERBREAK_ASSERT);
+ res = FSREG_LoadProgram(prog_handle, title);
+ if (R_SUCCEEDED(res)) {
+ if (*prog_handle >> 32 == 0xFFFF0000) {
+ return 0;
+ }
+ res = FSREG_CheckHostLoadId(*prog_handle);
+ // if ((res >= 0 && (unsigned)res >> 27) || (res < 0 && ((unsigned)res
+ // >> 27)-32))
+ if (R_FAILED(res) || (R_SUCCEEDED(res) && R_LEVEL(res) != RL_SUCCESS)) {
+ svcBreak(USERBREAK_ASSERT);
+ }
}
- }
- return res;
+ return res;
}
-static Result loader_UnregisterProgram(u64 prog_handle)
+static Result
+loader_UnregisterProgram(u64 prog_handle)
{
- Result res;
-
- if (prog_handle >> 32 == 0xFFFF0000)
- {
- return FSREG_UnloadProgram(prog_handle);
- }
- else
- {
- res = FSREG_CheckHostLoadId(prog_handle);
- //if ((res >= 0 && (unsigned)res >> 27) || (res < 0 && ((unsigned)res >> 27)-32))
- if (R_FAILED(res) || (R_SUCCEEDED(res) && R_LEVEL(res) != RL_SUCCESS))
- {
- return PXIPM_UnregisterProgram(prog_handle);
- }
- else
- {
- return FSREG_UnloadProgram(prog_handle);
+ Result res;
+
+ if (prog_handle >> 32 == 0xFFFF0000) {
+ return FSREG_UnloadProgram(prog_handle);
+ } else {
+ res = FSREG_CheckHostLoadId(prog_handle);
+ // if ((res >= 0 && (unsigned)res >> 27) || (res < 0 && ((unsigned)res
+ // >> 27)-32))
+ if (R_FAILED(res) || (R_SUCCEEDED(res) && R_LEVEL(res) != RL_SUCCESS)) {
+ return PXIPM_UnregisterProgram(prog_handle);
+ } else {
+ return FSREG_UnloadProgram(prog_handle);
+ }
}
- }
}
-static void handle_commands(void)
+static void
+handle_commands(void)
{
- FS_ProgramInfo title;
- FS_ProgramInfo update;
- u32* cmdbuf;
- u16 cmdid;
- int res;
- Handle handle;
- u64 prog_handle;
-
- cmdbuf = getThreadCommandBuffer();
- cmdid = cmdbuf[0] >> 16;
- res = 0;
- switch (cmdid)
- {
- case 1: // LoadProcess
- {
- res = loader_LoadProcess(&handle, *(u64 *)&cmdbuf[1]);
- cmdbuf[0] = 0x10042;
- cmdbuf[1] = res;
- cmdbuf[2] = 16;
- cmdbuf[3] = handle;
- break;
- }
- case 2: // RegisterProgram
- {
- memcpy(&title, &cmdbuf[1], sizeof(FS_ProgramInfo));
- memcpy(&update, &cmdbuf[5], sizeof(FS_ProgramInfo));
- res = loader_RegisterProgram(&prog_handle, &title, &update);
- cmdbuf[0] = 0x200C0;
- cmdbuf[1] = res;
- *(u64 *)&cmdbuf[2] = prog_handle;
- break;
- }
- case 3: // UnregisterProgram
- {
- if (g_cached_prog_handle == prog_handle)
- {
- g_cached_prog_handle = 0;
- }
- cmdbuf[0] = 0x30040;
- cmdbuf[1] = loader_UnregisterProgram(*(u64 *)&cmdbuf[1]);
- break;
- }
- case 4: // GetProgramInfo
- {
- prog_handle = *(u64 *)&cmdbuf[1];
- if (prog_handle != g_cached_prog_handle)
- {
- res = loader_GetProgramInfo(&g_exheader, prog_handle);
- if (res >= 0)
+ FS_ProgramInfo title;
+ FS_ProgramInfo update;
+ u32* cmdbuf;
+ u16 cmdid;
+ int res;
+ Handle handle;
+ u64 prog_handle;
+
+ cmdbuf = getThreadCommandBuffer();
+ cmdid = cmdbuf[0] >> 16;
+ res = 0;
+ switch (cmdid) {
+ case 1: // LoadProcess
{
- g_cached_prog_handle = prog_handle;
+ res = loader_LoadProcess(&handle, *(u64*)&cmdbuf[1]);
+ cmdbuf[0] = 0x10042;
+ cmdbuf[1] = res;
+ cmdbuf[2] = 16;
+ cmdbuf[3] = handle;
+ break;
}
- else
+ case 2: // RegisterProgram
{
- g_cached_prog_handle = 0;
+ memcpy(&title, &cmdbuf[1], sizeof(FS_ProgramInfo));
+ memcpy(&update, &cmdbuf[5], sizeof(FS_ProgramInfo));
+ res = loader_RegisterProgram(&prog_handle, &title, &update);
+ cmdbuf[0] = 0x200C0;
+ cmdbuf[1] = res;
+ *(u64*)&cmdbuf[2] = prog_handle;
+ break;
+ }
+ case 3: // UnregisterProgram
+ {
+ if (g_cached_prog_handle == prog_handle) {
+ g_cached_prog_handle = 0;
+ }
+ cmdbuf[0] = 0x30040;
+ cmdbuf[1] = loader_UnregisterProgram(*(u64*)&cmdbuf[1]);
+ break;
+ }
+ case 4: // GetProgramInfo
+ {
+ prog_handle = *(u64*)&cmdbuf[1];
+ if (prog_handle != g_cached_prog_handle) {
+ res = loader_GetProgramInfo(&g_exheader, prog_handle);
+ if (res >= 0) {
+ g_cached_prog_handle = prog_handle;
+ } else {
+ g_cached_prog_handle = 0;
+ }
+ }
+ memcpy(&g_ret_buf, &g_exheader, 1024);
+ cmdbuf[0] = 0x40042;
+ cmdbuf[1] = res;
+ cmdbuf[2] = 0x1000002;
+ cmdbuf[3] = (u32)&g_ret_buf;
+ break;
+ }
+ default: // error
+ {
+ cmdbuf[0] = 0x40;
+ cmdbuf[1] = 0xD900182F;
+ break;
}
- }
- memcpy(&g_ret_buf, &g_exheader, 1024);
- cmdbuf[0] = 0x40042;
- cmdbuf[1] = res;
- cmdbuf[2] = 0x1000002;
- cmdbuf[3] = (u32) &g_ret_buf;
- break;
- }
- default: // error
- {
- cmdbuf[0] = 0x40;
- cmdbuf[1] = 0xD900182F;
- break;
}
- }
}
-static Result should_terminate(int *term_request)
+static Result
+should_terminate(int* term_request)
{
- u32 notid;
- Result ret;
-
- ret = srvSysReceiveNotification(¬id);
- if (R_FAILED(ret))
- {
- return ret;
- }
- if (notid == 0x100) // term request
- {
- *term_request = 1;
- }
- return 0;
+ u32 notid;
+ Result ret;
+
+ ret = srvSysReceiveNotification(¬id);
+ if (R_FAILED(ret)) {
+ return ret;
+ }
+ if (notid == 0x100) // term request
+ {
+ *term_request = 1;
+ }
+ return 0;
}
// this is called before main
-void __appInit()
+void
+__appInit()
{
- srvSysInit();
- fsregInit();
- fsldrInit();
- pxipmInit();
+ srvSysInit();
+ fsregInit();
+ fsldrInit();
+ pxipmInit();
}
// this is called after main exits
-void __appExit()
+void
+__appExit()
{
- pxipmExit();
- fsldrExit();
- fsregExit();
- srvSysExit();
+ pxipmExit();
+ fsldrExit();
+ fsregExit();
+ srvSysExit();
}
// stubs for non-needed pre-main functions
void __sync_fini();
void __system_initSyscalls();
-void __ctru_exit()
+void
+__ctru_exit()
{
- __appExit();
- __sync_fini();
- svcExitProcess();
+ __appExit();
+ __sync_fini();
+ svcExitProcess();
}
-void initSystem()
+void
+initSystem()
{
- __sync_init();
- __system_initSyscalls();
- __appInit();
+ __sync_init();
+ __system_initSyscalls();
+ __appInit();
}
-int main()
+int
+main()
{
- Result ret;
- Handle handle;
- Handle reply_target;
- Handle *srv_handle;
- Handle *notification_handle;
- s32 index;
- int i;
- int term_request;
- u32* cmdbuf;
-
- ret = 0;
-
- srv_handle = &g_handles[1];
- notification_handle = &g_handles[0];
-
- if (R_FAILED(srvSysRegisterService(srv_handle, "Loader", MAX_SESSIONS)))
- {
- svcBreak(USERBREAK_ASSERT);
- }
-
- if (R_FAILED(srvSysEnableNotification(notification_handle)))
- {
- svcBreak(USERBREAK_ASSERT);
- }
-
- g_active_handles = 2;
- g_cached_prog_handle = 0;
- index = 1;
-
- reply_target = 0;
- term_request = 0;
- do
- {
- if (reply_target == 0)
- {
- cmdbuf = getThreadCommandBuffer();
- cmdbuf[0] = 0xFFFF0000;
+ Result ret;
+ Handle handle;
+ Handle reply_target;
+ Handle* srv_handle;
+ Handle* notification_handle;
+ s32 index;
+ int i;
+ int term_request;
+ u32* cmdbuf;
+
+ ret = 0;
+
+ srv_handle = &g_handles[1];
+ notification_handle = &g_handles[0];
+
+ if (R_FAILED(srvSysRegisterService(srv_handle, "Loader", MAX_SESSIONS))) {
+ svcBreak(USERBREAK_ASSERT);
}
- ret = svcReplyAndReceive(&index, g_handles, g_active_handles, reply_target);
- if (R_FAILED(ret))
- {
- // check if any handle has been closed
- if (ret == (int)0xC920181A)
- {
- if (index == -1)
- {
- for (i = 2; i < MAX_SESSIONS+2; i++)
- {
- if (g_handles[i] == reply_target)
- {
- index = i;
- break;
- }
- }
- }
- svcCloseHandle(g_handles[index]);
- g_handles[index] = g_handles[g_active_handles-1];
- g_active_handles--;
- reply_target = 0;
- }
- else
- {
+ if (R_FAILED(srvSysEnableNotification(notification_handle))) {
svcBreak(USERBREAK_ASSERT);
- }
}
- else
- {
- // process responses
- reply_target = 0;
- switch (index)
- {
- case 0: // notification
- {
- if (R_FAILED(should_terminate(&term_request)))
- {
- svcBreak(USERBREAK_ASSERT);
- }
- break;
- }
- case 1: // new session
- {
- if (R_FAILED(svcAcceptSession(&handle, *srv_handle)))
- {
- svcBreak(USERBREAK_ASSERT);
- }
- if (g_active_handles < MAX_SESSIONS+2)
- {
- g_handles[g_active_handles] = handle;
- g_active_handles++;
- }
- else
- {
- svcCloseHandle(handle);
- }
- break;
+
+ g_active_handles = 2;
+ g_cached_prog_handle = 0;
+ index = 1;
+
+ reply_target = 0;
+ term_request = 0;
+ do {
+ if (reply_target == 0) {
+ cmdbuf = getThreadCommandBuffer();
+ cmdbuf[0] = 0xFFFF0000;
}
- default: // session
- {
- handle_commands();
- reply_target = g_handles[index];
- break;
+ ret = svcReplyAndReceive(&index, g_handles, g_active_handles,
+ reply_target);
+
+ if (R_FAILED(ret)) {
+ // check if any handle has been closed
+ if (ret == (int)0xC920181A) {
+ if (index == -1) {
+ for (i = 2; i < MAX_SESSIONS + 2; i++) {
+ if (g_handles[i] == reply_target) {
+ index = i;
+ break;
+ }
+ }
+ }
+ svcCloseHandle(g_handles[index]);
+ g_handles[index] = g_handles[g_active_handles - 1];
+ g_active_handles--;
+ reply_target = 0;
+ } else {
+ svcBreak(USERBREAK_ASSERT);
+ }
+ } else {
+ // process responses
+ reply_target = 0;
+ switch (index) {
+ case 0: // notification
+ {
+ if (R_FAILED(should_terminate(&term_request))) {
+ svcBreak(USERBREAK_ASSERT);
+ }
+ break;
+ }
+ case 1: // new session
+ {
+ if (R_FAILED(svcAcceptSession(&handle, *srv_handle))) {
+ svcBreak(USERBREAK_ASSERT);
+ }
+ if (g_active_handles < MAX_SESSIONS + 2) {
+ g_handles[g_active_handles] = handle;
+ g_active_handles++;
+ } else {
+ svcCloseHandle(handle);
+ }
+ break;
+ }
+ default: // session
+ {
+ handle_commands();
+ reply_target = g_handles[index];
+ break;
+ }
+ }
}
- }
- }
- } while (!term_request || g_active_handles != 2);
+ } while (!term_request || g_active_handles != 2);
- srvSysUnregisterService("Loader");
- svcCloseHandle(*srv_handle);
- svcCloseHandle(*notification_handle);
+ srvSysUnregisterService("Loader");
+ svcCloseHandle(*srv_handle);
+ svcCloseHandle(*notification_handle);
- return 0;
+ return 0;
}
#include <3ds.h>
-int lzss_decompress(u8 *buffer)
+int
+lzss_decompress(u8* buffer)
{
- // This WAS originally a decompilation in @yifan_lu's repo; it was rewritten for readability following ctrtool's namings.
- // You can thank me for making it more readable if you'd like; I don't really care. Did it for myself.
- unsigned int decompSize, v15;
- u8 *compressEndOff, *index, *stopIndex;
- char control;
- int v9, v13, v14, v16;
- int ret = 0;
+ // This WAS originally a decompilation in @yifan_lu's repo; it was rewritten
+ // for readability following ctrtool's namings.
+ // You can thank me for making it more readable if you'd like; I don't
+ // really care. Did it for myself.
+ unsigned int decompSize, v15;
+ u8 *compressEndOff, *index, *stopIndex;
+ char control;
+ int v9, v13, v14, v16;
+ int ret = 0;
- if ( !buffer ) // Return immediately when buffer is invalid.
- return 0;
+ if (!buffer) // Return immediately when buffer is invalid.
+ return 0;
- // v1=decompressedSize, v2=compressedSize, v3=index, v4=stopIndex
- decompSize = *((u32 *)buffer - 2);
- compressEndOff = &buffer[*((u32 *)buffer - 1)];
- index = &buffer[-(decompSize >> 24)]; // FIXME - The integer negation is due to a compiler optimization. It's probably okay, but...
- stopIndex = &buffer[-(decompSize & 0xFFFFFF)];
+ // v1=decompressedSize, v2=compressedSize, v3=index, v4=stopIndex
+ decompSize = *((u32*)buffer - 2);
+ compressEndOff = &buffer[*((u32*)buffer - 1)];
+ index = &buffer[-(decompSize >> 24)]; // FIXME - The integer negation is due
+ // to a compiler optimization. It's
+ // probably okay, but...
+ stopIndex = &buffer[-(decompSize & 0xFFFFFF)];
- while ( index > stopIndex ) // index > stopIndex
- {
- control = *(index-- - 1); // control (just scoping though)
- for (int i=0; i<8; i++)
+ while (index > stopIndex) // index > stopIndex
{
- if ( control & 0x80 ) // control & 0x80
- {
- v13 = *(index - 1);
- v14 = *(index - 2);
- index -= 2;
- v15 = ((v14 | (v13 << 8)) & 0xFFFF0FFF) + 2;
- v16 = v13 + 32;
- do
- {
- ret = compressEndOff[v15];
- *(compressEndOff-- - 1) = ret;
- v16 -= 16;
+ control = *(index-- - 1); // control (just scoping though)
+ for (int i = 0; i < 8; i++) {
+ if (control & 0x80) // control & 0x80
+ {
+ v13 = *(index - 1);
+ v14 = *(index - 2);
+ index -= 2;
+ v15 = ((v14 | (v13 << 8)) & 0xFFFF0FFF) + 2;
+ v16 = v13 + 32;
+ do {
+ ret = compressEndOff[v15];
+ *(compressEndOff-- - 1) = ret;
+ v16 -= 16;
+ } while (!(v16 < 0));
+ } else {
+ v9 = *(index-- - 1);
+ ret = v9;
+ *(compressEndOff-- - 1) = v9;
+ }
+ control *= 2;
+ if (index <= stopIndex)
+ return ret;
}
- while ( !(v16 < 0) );
- }
- else
- {
- v9 = *(index-- - 1);
- ret = v9;
- *(compressEndOff-- - 1) = v9;
- }
- control *= 2;
- if ( index <= stopIndex )
- return ret;
}
- }
- return ret;
+ return ret;
}
#pragma once
-int lzss_decompress(u8 *buffer);
+int lzss_decompress(u8* buffer);
#include "../config.h"
#include "../../../../source/patch_format.h"
-void disable_cart_updates(u64 progId, u8 *code, u32 size) {
- static const u8 stopCartUpdatesPattern[] = {0x0C, 0x18, 0xE1, 0xD8};
- static const u8 stopCartUpdatesPatch[] = {0x0B, 0x18, 0x21, 0xC8};
+void
+disable_cart_updates(u64 progId, u8* code, u32 size)
+{
+ static const u8 stopCartUpdatesPattern[] = { 0x0C, 0x18, 0xE1, 0xD8 };
+ static const u8 stopCartUpdatesPatch[] = { 0x0B, 0x18, 0x21, 0xC8 };
- //Disable updates from foreign carts (makes carts region-free)
- patchMemory(code, size,
- stopCartUpdatesPattern,
- sizeof(stopCartUpdatesPattern), 0,
- stopCartUpdatesPatch,
- sizeof(stopCartUpdatesPatch), 2
- );
+ // Disable updates from foreign carts (makes carts region-free)
+ patchMemory(code, size, stopCartUpdatesPattern,
+ sizeof(stopCartUpdatesPattern), 0, stopCartUpdatesPatch,
+ sizeof(stopCartUpdatesPatch), 2);
}
-
#include "../config.h"
#include "../../../../source/patch_format.h"
-void disable_eshop_updates(u64 progId, u8 *code, u32 size) {
- static const u8 skipEshopUpdateCheckPattern[] = {0x30, 0xB5, 0xF1, 0xB0};
- static const u8 skipEshopUpdateCheckPatch[] = {0x00, 0x20, 0x08, 0x60, 0x70, 0x47};
+void
+disable_eshop_updates(u64 progId, u8* code, u32 size)
+{
+ static const u8 skipEshopUpdateCheckPattern[] = { 0x30, 0xB5, 0xF1, 0xB0 };
+ static const u8 skipEshopUpdateCheckPatch[] = { 0x00, 0x20, 0x08,
+ 0x60, 0x70, 0x47 };
- //Skip update checks to access the EShop
- patchMemory(code, size,
- skipEshopUpdateCheckPattern,
- sizeof(skipEshopUpdateCheckPattern), 0,
- skipEshopUpdateCheckPatch,
- sizeof(skipEshopUpdateCheckPatch), 1
- );
+ // Skip update checks to access the EShop
+ patchMemory(code, size, skipEshopUpdateCheckPattern,
+ sizeof(skipEshopUpdateCheckPattern), 0,
+ skipEshopUpdateCheckPatch, sizeof(skipEshopUpdateCheckPatch),
+ 1);
}
-
#include "../config.h"
#include "../../../../source/patch_format.h"
-void disable_nim_updates(u64 progId, u8 *code, u32 size) {
- static const u8 blockAutoUpdatesPattern[] = {0x25, 0x79, 0x0B, 0x99};
- static const u8 blockAutoUpdatesPatch[] = {0xE3, 0xA0};
+void
+disable_nim_updates(u64 progId, u8* code, u32 size)
+{
+ static const u8 blockAutoUpdatesPattern[] = { 0x25, 0x79, 0x0B, 0x99 };
+ static const u8 blockAutoUpdatesPatch[] = { 0xE3, 0xA0 };
- //Block silent auto-updates
- patchMemory(code, size,
- blockAutoUpdatesPattern,
- sizeof(blockAutoUpdatesPattern), 0,
- blockAutoUpdatesPatch,
- sizeof(blockAutoUpdatesPatch), 1
- );
+ // Block silent auto-updates
+ patchMemory(code, size, blockAutoUpdatesPattern,
+ sizeof(blockAutoUpdatesPattern), 0, blockAutoUpdatesPatch,
+ sizeof(blockAutoUpdatesPatch), 1);
}
-
#include "../config.h"
#include "../../../../source/patch_format.h"
-void fake_friends_version(u64 progId, u8 *code, u32 size) {
- static const u8 fpdVerPattern[] = {0xE0, 0x1E, 0xFF, 0x2F, 0xE1, 0x01, 0x01, 0x01};
- static const u8 fpdVerPatch = 0x06; // Latest version.
+void
+fake_friends_version(u64 progId, u8* code, u32 size)
+{
+ static const u8 fpdVerPattern[] = { 0xE0, 0x1E, 0xFF, 0x2F,
+ 0xE1, 0x01, 0x01, 0x01 };
+ static const u8 fpdVerPatch = 0x06; // Latest version.
- //Allow online access to work with old friends modules
- patchMemory(code, size,
- fpdVerPattern,
- sizeof(fpdVerPattern), 9,
- &fpdVerPatch,
- sizeof(fpdVerPatch), 1
- );
+ // Allow online access to work with old friends modules
+ patchMemory(code, size, fpdVerPattern, sizeof(fpdVerPattern), 9,
+ &fpdVerPatch, sizeof(fpdVerPatch), 1);
}
-
#include "../config.h"
#include "../../../../source/patch_format.h"
-void settings_string(u64 progId, u8 *code, u32 size) {
- static const u16 verPattern[] = u"Ver.";
- static const u16 verPatch[] = u".hax";
+void
+settings_string(u64 progId, u8* code, u32 size)
+{
+ static const u16 verPattern[] = u"Ver.";
+ static const u16 verPatch[] = u".hax";
- //Patch Ver. string
- patchMemory(code, size,
- verPattern,
- sizeof(verPattern) - sizeof(u16), 0,
- verPatch,
- sizeof(verPatch) - sizeof(u16), 1
- );
+ // Patch Ver. string
+ patchMemory(code, size, verPattern, sizeof(verPattern) - sizeof(u16), 0,
+ verPatch, sizeof(verPatch) - sizeof(u16), 1);
}
-
#pragma once
-void disable_cart_updates(u64 progId, u8 *code, u32 size);
-void disable_eshop_updates(u64 progId, u8 *code, u32 size);
-void disable_nim_updates(u64 progId, u8 *code, u32 size);
-void fake_friends_version(u64 progId, u8 *code, u32 size);
-void settings_string(u64 progId, u8 *code, u32 size);
-void region_patch(u64 progId, u8 *code, u32 size);
-void ro_sigpatch(u64 progId, u8 *code, u32 size);
-void secureinfo_sigpatch(u64 progId, u8 *code, u32 size);
+void disable_cart_updates(u64 progId, u8* code, u32 size);
+void disable_eshop_updates(u64 progId, u8* code, u32 size);
+void disable_nim_updates(u64 progId, u8* code, u32 size);
+void fake_friends_version(u64 progId, u8* code, u32 size);
+void settings_string(u64 progId, u8* code, u32 size);
+void region_patch(u64 progId, u8* code, u32 size);
+void ro_sigpatch(u64 progId, u8* code, u32 size);
+void secureinfo_sigpatch(u64 progId, u8* code, u32 size);
#include "../config.h"
#include "../../../../source/patch_format.h"
-void region_patch(u64 progId, u8 *code, u32 size) {
- static const u8 regionFreePattern[] = {0x00, 0x00, 0x55, 0xE3, 0x01, 0x10, 0xA0, 0xE3};
- static const u8 regionFreePatch[] = {0x01, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1};
+void
+region_patch(u64 progId, u8* code, u32 size)
+{
+ static const u8 regionFreePattern[] = { 0x00, 0x00, 0x55, 0xE3,
+ 0x01, 0x10, 0xA0, 0xE3 };
+ static const u8 regionFreePatch[] = { 0x01, 0x00, 0xA0, 0xE3,
+ 0x1E, 0xFF, 0x2F, 0xE1 };
- //Patch SMDH region checks
- patchMemory(code, size,
- regionFreePattern,
- sizeof(regionFreePattern), -16,
- regionFreePatch,
- sizeof(regionFreePatch), 1
- );
+ // Patch SMDH region checks
+ patchMemory(code, size, regionFreePattern, sizeof(regionFreePattern), -16,
+ regionFreePatch, sizeof(regionFreePatch), 1);
}
#include "../config.h"
#include "../../../../source/patch_format.h"
-void ro_sigpatch(u64 progId, u8 *code, u32 size) {
- static const u8 sigCheckPattern[] = {0x30, 0x40, 0x2D, 0xE9, 0x02, 0x50, 0xA0, 0xE1};
- static const u8 sha256ChecksPattern1[] = {0x30, 0x40, 0x2D, 0xE9, 0x24, 0xD0, 0x4D, 0xE2};
- static const u8 sha256ChecksPattern2[] = {0xF8, 0x4F, 0x2D, 0xE9, 0x01, 0x70, 0xA0, 0xE1};
+void
+ro_sigpatch(u64 progId, u8* code, u32 size)
+{
+ static const u8 sigCheckPattern[] = { 0x30, 0x40, 0x2D, 0xE9,
+ 0x02, 0x50, 0xA0, 0xE1 };
+ static const u8 sha256ChecksPattern1[] = { 0x30, 0x40, 0x2D, 0xE9,
+ 0x24, 0xD0, 0x4D, 0xE2 };
+ static const u8 sha256ChecksPattern2[] = { 0xF8, 0x4F, 0x2D, 0xE9,
+ 0x01, 0x70, 0xA0, 0xE1 };
- // mov r0, #0; bx lr - equivalent to 'return 0;'
- static const u8 stub[] = {0x00, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1};
+ // mov r0, #0; bx lr - equivalent to 'return 0;'
+ static const u8 stub[] = { 0x00, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1 };
- //Disable CRR0 signature (RSA2048 with SHA256) check
- patchMemory(code, size,
- sigCheckPattern,
- sizeof(sigCheckPattern), 0,
- stub,
- sizeof(stub), 1
- );
+ // Disable CRR0 signature (RSA2048 with SHA256) check
+ patchMemory(code, size, sigCheckPattern, sizeof(sigCheckPattern), 0, stub,
+ sizeof(stub), 1);
- //Disable CRO0/CRR0 SHA256 hash checks (section hashes, and hash table)
- patchMemory(code, size,
- sha256ChecksPattern1,
- sizeof(sha256ChecksPattern1), 0,
- stub,
- sizeof(stub), 1
- );
+ // Disable CRO0/CRR0 SHA256 hash checks (section hashes, and hash table)
+ patchMemory(code, size, sha256ChecksPattern1, sizeof(sha256ChecksPattern1),
+ 0, stub, sizeof(stub), 1);
- patchMemory(code, size,
- sha256ChecksPattern2,
- sizeof(sha256ChecksPattern2), 0,
- stub,
- sizeof(stub), 1
- );
+ patchMemory(code, size, sha256ChecksPattern2, sizeof(sha256ChecksPattern2),
+ 0, stub, sizeof(stub), 1);
}
#include "../config.h"
#include "../../../../source/patch_format.h"
-void secureinfo_sigpatch(u64 progId, u8 *code, u32 size) {
- static const u8 secureinfoSigCheckPattern[] = {0x06, 0x46, 0x10, 0x48, 0xFC};
- static const u8 secureinfoSigCheckPatch[] = {0x00, 0x26};
+void
+secureinfo_sigpatch(u64 progId, u8* code, u32 size)
+{
+ static const u8 secureinfoSigCheckPattern[] = { 0x06, 0x46, 0x10, 0x48,
+ 0xFC };
+ static const u8 secureinfoSigCheckPatch[] = { 0x00, 0x26 };
- //Disable SecureInfo signature check
- patchMemory(code, size,
- secureinfoSigCheckPattern,
- sizeof(secureinfoSigCheckPattern), 0,
- secureinfoSigCheckPatch,
- sizeof(secureinfoSigCheckPatch), 1
- );
+ // Disable SecureInfo signature check
+ patchMemory(code, size, secureinfoSigCheckPattern,
+ sizeof(secureinfoSigCheckPattern), 0, secureinfoSigCheckPatch,
+ sizeof(secureinfoSigCheckPatch), 1);
}
-
#include "patch/patch.h"
-static int memcmp(const void *buf1, const void *buf2, u32 size)
+static int
+memcmp(const void* buf1, const void* buf2, u32 size)
{
- const u8 *buf1c = (const u8 *)buf1;
- const u8 *buf2c = (const u8 *)buf2;
+ const u8* buf1c = (const u8*)buf1;
+ const u8* buf2c = (const u8*)buf2;
- for(u32 i = 0; i < size; i++)
- {
+ for (u32 i = 0; i < size; i++) {
int cmp = buf1c[i] - buf2c[i];
- if(cmp) return cmp;
+ if (cmp)
+ return cmp;
}
return 0;
}
-//Quick Search algorithm, adapted from http://igm.univ-mlv.fr/~lecroq/string/node19.html#SECTION00190
-static u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize)
+// Quick Search algorithm, adapted from
+// http://igm.univ-mlv.fr/~lecroq/string/node19.html#SECTION00190
+static u8*
+memsearch(u8* startPos, const void* pattern, u32 size, u32 patternSize)
{
- const u8 *patternc = (const u8 *)pattern;
+ const u8* patternc = (const u8*)pattern;
- //Preprocessing
+ // Preprocessing
u32 table[256];
- for(u32 i = 0; i < 256; ++i)
+ for (u32 i = 0; i < 256; ++i)
table[i] = patternSize + 1;
- for(u32 i = 0; i < patternSize; ++i)
+ for (u32 i = 0; i < patternSize; ++i)
table[patternc[i]] = patternSize - i;
- //Searching
+ // Searching
u32 j = 0;
- while(j <= size - patternSize)
- {
- if(memcmp(patternc, startPos + j, patternSize) == 0)
+ while (j <= size - patternSize) {
+ if (memcmp(patternc, startPos + j, patternSize) == 0)
return startPos + j;
j += table[startPos[j + patternSize]];
}
return NULL;
}
-u32 patchMemory(u8 *start, u32 size, const void *pattern, u32 patSize, int offset, const void *replace, u32 repSize, u32 count)
+u32
+patchMemory(u8* start, u32 size, const void* pattern, u32 patSize, int offset,
+ const void* replace, u32 repSize, u32 count)
{
u32 i;
- for(i = 0; i < count; i++)
- {
- u8 *found = memsearch(start, pattern, size, patSize);
+ for (i = 0; i < count; i++) {
+ u8* found = memsearch(start, pattern, size, patSize);
- if(found == NULL) break;
+ if (found == NULL)
+ break;
- // FIXME - This is throwing on Werror.
+ // FIXME - This is throwing on Werror.
memcpy(found + offset, replace, repSize);
u32 at = (u32)(found - start);
- if(at + patSize > size) break;
+ if (at + patSize > size)
+ break;
size -= at + patSize;
start = found + patSize;
return i;
}
-static inline size_t strnlen(const char *string, size_t maxlen)
+static inline size_t
+strnlen(const char* string, size_t maxlen)
{
size_t size;
- for(size = 0; *string && size < maxlen; string++, size++);
+ for (size = 0; *string && size < maxlen; string++, size++)
+ ;
return size;
}
-static int fileOpen(IFile *file, FS_ArchiveID id, const char *path, int flags)
+static int
+fileOpen(IFile* file, FS_ArchiveID id, const char* path, int flags)
{
FS_Path apath;
FS_Path ppath;
apath.type = PATH_EMPTY;
apath.size = 1;
- apath.data = (u8 *)"";
+ apath.data = (u8*)"";
ppath.type = PATH_ASCII;
ppath.data = path;
ppath.size = strnlen(path, PATH_MAX) + 1;
- return IFile_Open(file, id, apath, ppath, flags);
+ return IFile_Open(file, id, apath, ppath, flags);
}
static struct config_file config;
static int failed_load_config = 1;
-void load_config() {
- static IFile file;
+void
+load_config()
+{
+ static IFile file;
static u64 total;
- // Open file.
- if (!R_SUCCEEDED(fileOpen(&file, ARCHIVE_SDMC, PATH_CONFIG, FS_OPEN_READ))) {
- // Failed to open.
+ // Open file.
+ if (!R_SUCCEEDED(
+ fileOpen(&file, ARCHIVE_SDMC, PATH_CONFIG, FS_OPEN_READ))) {
+ // Failed to open.
return;
}
- // Read file.
- if (!R_SUCCEEDED(IFile_Read(&file, &total, &config, sizeof(struct config_file)))) {
- IFile_Close(&file); // Read to memory.
+ // Read file.
+ if (!R_SUCCEEDED(
+ IFile_Read(&file, &total, &config, sizeof(struct config_file)))) {
+ IFile_Close(&file); // Read to memory.
- // Failed to read.
- return;
- }
+ // Failed to read.
+ return;
+ }
- IFile_Close(&file); // Read to memory.
+ IFile_Close(&file); // Read to memory.
- if (config.magic[0] != 'O' || config.magic[1] != 'V' || config.magic[2] != 'A' || config.magic[3] != 'N') {
- // Incorrect magic.
- // Failed to read.
- return;
- }
+ if (config.magic[0] != 'O' || config.magic[1] != 'V' ||
+ config.magic[2] != 'A' || config.magic[3] != 'N') {
+ // Incorrect magic.
+ // Failed to read.
+ return;
+ }
- if (config.config_ver != config_version) {
- // Invalid version.
- return;
+ if (config.config_ver != config_version) {
+ // Invalid version.
+ return;
}
- failed_load_config = 0;
+ failed_load_config = 0;
- return;
+ return;
}
-static int loadTitleLocaleConfig(u64 progId, u8 *regionId, u8 *languageId)
+static int
+loadTitleLocaleConfig(u64 progId, u8* regionId, u8* languageId)
{
- // FIXME - Rewrite this function to use a single line-based config
+ // FIXME - Rewrite this function to use a single line-based config
- // Directory seeks have severe issues on FAT and
- // dumping configs based on 3dsdb (more than 1000) causes things
- // to kinda choke. FAT is not meant for large numbers of files per
- // directory due to linear seeks rather than tree or hash-based indexes
+ // Directory seeks have severe issues on FAT and
+ // dumping configs based on 3dsdb (more than 1000) causes things
+ // to kinda choke. FAT is not meant for large numbers of files per
+ // directory due to linear seeks rather than tree or hash-based indexes
char path[] = "/corbenik/etc/locale.conf"; // The locale config file.
char progid_str[16];
// Hexdump.
- for(int i=0; i < 16; i += 2) {
- progid_str[i] = ("0123456789ABCDEF")[ (((u8*)&progId)[0] >> 4) & 0xf ];
- progid_str[i+1] = ("0123456789ABCDEF")[ ((u8*)&progId)[0] & 0xf ];
+ for (int i = 0; i < 16; i += 2) {
+ progid_str[i] = ("0123456789ABCDEF")[(((u8*)&progId)[0] >> 4) & 0xf];
+ progid_str[i + 1] = ("0123456789ABCDEF")[((u8*)&progId)[0] & 0xf];
}
- static const char *regions[] = {"JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"};
- static const char *languages[] = {"JA", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"};
+ static const char* regions[] = { "JPN", "USA", "EUR", "AUS",
+ "CHN", "KOR", "TWN" };
+ static const char* languages[] = { "JA", "EN", "FR", "DE", "IT", "ES",
+ "ZH", "KO", "NL", "PT", "RU", "TW" };
IFile file;
Result eof = fileOpen(&file, ARCHIVE_SDMC, path, FS_OPEN_READ);
- if(R_SUCCEEDED(eof))
- {
+ if (R_SUCCEEDED(eof)) {
char c;
char buf_prog[16];
char country_tmp[16];
char lang_tmp[16];
u64 total;
- // TODO - Open and seek file properly
+ // TODO - Open and seek file properly
int i = 0;
- int state = 0; // State. 0 = get_titleid, 1 = get_region, 2 = get_language, 3 = process entry
- while(1) {
- eof = IFile_Read(&file, &total, &c, 1); // Read character.
-
- if (c == ' ' || c == '\n' || c == '\r' || c == '\t') // Skip space characters.
- continue;
+ int state = 0; // State. 0 = get_titleid, 1 = get_region, 2 =
+ // get_language, 3 = process entry
+ while (1) {
+ eof = IFile_Read(&file, &total, &c, 1); // Read character.
+
+ if (c == ' ' || c == '\n' || c == '\r' ||
+ c == '\t') // Skip space characters.
+ continue;
+
+ if (c == '#') { // Comment! Skip until a \n or \r.
+ while (c != '\n' && c != '\r') {
+ eof = IFile_Read(&file, &total, &c, 1); // Read character.
+ }
+ continue; // Resume loop.
+ }
- if (c == '#') { // Comment! Skip until a \n or \r.
- while(c != '\n' && c != '\r') {
- eof = IFile_Read(&file, &total, &c, 1); // Read character.
+ switch (state) {
+ case 0:
+ // Read titleID.
+ for (i = 0; i < 16; i++) {
+ buf_prog[i] = c;
+ if (i != 15)
+ eof = IFile_Read(&file, &total, &c,
+ 1); // Read character.
+ }
+ state = 1;
+ break;
+ case 1:
+ // Read country name. Must be <16 chars, past that is
+ // ignored.
+ i = 0;
+ while (c != ' ' && c != '\n' && c != '\r' &&
+ c != '\t') { // While we're not reading a space...
+ if (i < 15) {
+ country_tmp[i] = c;
+ i++;
+ }
+ eof = IFile_Read(&file, &total, &c,
+ 1); // Read character unless last one.
+ }
+ state = 2;
+ break;
+ case 2:
+ // Read language name. See country name, code is basically
+ // identical.
+ i = 0;
+ while (c != ' ' && c != '\n' && c != '\r' &&
+ c != '\t') { // While we're not reading a space...
+ if (i < 15) { // Only read in if <16.
+ lang_tmp[i] = c;
+ i++;
+ }
+ eof = IFile_Read(&file, &total, &c,
+ 1); // Read character unless last one.
+ }
+ state = 3;
+ break;
+ case 3:
+ // Process entry, return and apply if matched.
+ if (!memcmp(progid_str, buf_prog, 16)) {
+ // TitleID matched. Apply language emulation; but first,
+ // process language and country.
+ for (i = 0; i < 7; i++) {
+ if (!memcmp(country_tmp, regions[i], 3)) {
+ *regionId = (u8)i;
+ }
+ }
+
+ for (u32 i = 0; i < 12; i++) {
+ if (!memcmp(lang_tmp, languages[i], 2)) {
+ *languageId = (u8)i;
+ }
+ }
+ state = 4; // Processed. Go on.
+ break;
+ }
+ state = 0; // Nope. Move onto the next one.
+ break;
}
- continue; // Resume loop.
- }
-
- switch(state) {
- case 0:
- // Read titleID.
- for(i = 0; i < 16; i++) {
- buf_prog[i] = c;
- if (i != 15)
- eof = IFile_Read(&file, &total, &c, 1); // Read character.
- }
- state = 1;
- break;
- case 1:
- // Read country name. Must be <16 chars, past that is ignored.
- i = 0;
- while (c != ' ' && c != '\n' && c != '\r' && c != '\t') { // While we're not reading a space...
- if (i < 15) {
- country_tmp[i] = c;
- i++;
- }
- eof = IFile_Read(&file, &total, &c, 1); // Read character unless last one.
- }
- state = 2;
- break;
- case 2:
- // Read language name. See country name, code is basically identical.
- i = 0;
- while (c != ' ' && c != '\n' && c != '\r' && c != '\t') { // While we're not reading a space...
- if (i < 15) { // Only read in if <16.
- lang_tmp[i] = c;
- i++;
- }
- eof = IFile_Read(&file, &total, &c, 1); // Read character unless last one.
- }
- state = 3;
- break;
- case 3:
- // Process entry, return and apply if matched.
- if(!memcmp(progid_str, buf_prog, 16)) {
- // TitleID matched. Apply language emulation; but first, process language and country.
- for(i = 0; i < 7; i++) {
- if(!memcmp(country_tmp, regions[i], 3)) {
- *regionId = (u8)i;
- }
- }
- for(u32 i = 0; i < 12; i++) {
- if(!memcmp(lang_tmp, languages[i], 2)) {
- *languageId = (u8)i;
- }
- }
- state = 4; // Processed. Go on.
+ if (!R_SUCCEEDED(eof) || total == 0 || state == 4)
break;
- }
- state = 0; // Nope. Move onto the next one.
- break;
- }
-
- if(!R_SUCCEEDED(eof) || total == 0 || state == 4)
- break;
}
}
return eof;
}
-static u8 *getCfgOffsets(u8 *code, u32 size, u32 *CFGUHandleOffset)
+static u8*
+getCfgOffsets(u8* code, u32 size, u32* CFGUHandleOffset)
{
/* HANS:
Look for error code which is known to be stored near cfg:u handle
this way we can find the right candidate
(handle should also be stored right after end of candidate function) */
- u32 n = 0,
- possible[24];
+ u32 n = 0, possible[24];
- for(u8 *pos = code + 4; n < 24 && pos < code + size - 4; pos += 4)
- {
- if(*(u32 *)pos == 0xD8A103F9)
- {
- for(u32 *l = (u32 *)pos - 4; n < 24 && l < (u32 *)pos + 4; l++)
- if(*l <= 0x10000000) possible[n++] = *l;
+ for (u8* pos = code + 4; n < 24 && pos < code + size - 4; pos += 4) {
+ if (*(u32*)pos == 0xD8A103F9) {
+ for (u32* l = (u32*)pos - 4; n < 24 && l < (u32*)pos + 4; l++)
+ if (*l <= 0x10000000)
+ possible[n++] = *l;
}
}
- for(u8 *CFGU_GetConfigInfoBlk2_endPos = code; CFGU_GetConfigInfoBlk2_endPos < code + size - 8; CFGU_GetConfigInfoBlk2_endPos += 4)
- {
- static const u32 CFGU_GetConfigInfoBlk2_endPattern[] = {0xE8BD8010, 0x00010082};
+ for (u8* CFGU_GetConfigInfoBlk2_endPos = code;
+ CFGU_GetConfigInfoBlk2_endPos < code + size - 8;
+ CFGU_GetConfigInfoBlk2_endPos += 4) {
+ static const u32 CFGU_GetConfigInfoBlk2_endPattern[] = { 0xE8BD8010,
+ 0x00010082 };
- //There might be multiple implementations of GetConfigInfoBlk2 but let's search for the one we want
- u32 *cmp = (u32 *)CFGU_GetConfigInfoBlk2_endPos;
+ // There might be multiple implementations of GetConfigInfoBlk2 but
+ // let's search for the one we want
+ u32* cmp = (u32*)CFGU_GetConfigInfoBlk2_endPos;
- if(cmp[0] == CFGU_GetConfigInfoBlk2_endPattern[0] && cmp[1] == CFGU_GetConfigInfoBlk2_endPattern[1])
- {
- *CFGUHandleOffset = *((u32 *)CFGU_GetConfigInfoBlk2_endPos + 2);
+ if (cmp[0] == CFGU_GetConfigInfoBlk2_endPattern[0] &&
+ cmp[1] == CFGU_GetConfigInfoBlk2_endPattern[1]) {
+ *CFGUHandleOffset = *((u32*)CFGU_GetConfigInfoBlk2_endPos + 2);
- for(u32 i = 0; i < n; i++)
- if(possible[i] == *CFGUHandleOffset) return CFGU_GetConfigInfoBlk2_endPos;
+ for (u32 i = 0; i < n; i++)
+ if (possible[i] == *CFGUHandleOffset)
+ return CFGU_GetConfigInfoBlk2_endPos;
CFGU_GetConfigInfoBlk2_endPos += 4;
}
return NULL;
}
-static void patchCfgGetLanguage(u8 *code, u32 size, u8 languageId, u8 *CFGU_GetConfigInfoBlk2_endPos)
+static void
+patchCfgGetLanguage(u8* code, u32 size, u8 languageId,
+ u8* CFGU_GetConfigInfoBlk2_endPos)
{
- u8 *CFGU_GetConfigInfoBlk2_startPos; //Let's find STMFD SP (there might be a NOP before, but nevermind)
-
- for(CFGU_GetConfigInfoBlk2_startPos = CFGU_GetConfigInfoBlk2_endPos - 4;
- CFGU_GetConfigInfoBlk2_startPos >= code && *((u16 *)CFGU_GetConfigInfoBlk2_startPos + 1) != 0xE92D;
- CFGU_GetConfigInfoBlk2_startPos -= 2);
-
- for(u8 *languageBlkIdPos = code; languageBlkIdPos < code + size; languageBlkIdPos += 4)
- {
- if(*(u32 *)languageBlkIdPos == 0xA0002)
- {
- for(u8 *instr = languageBlkIdPos - 8; instr >= languageBlkIdPos - 0x1008 && instr >= code + 4; instr -= 4) //Should be enough
+ u8* CFGU_GetConfigInfoBlk2_startPos; // Let's find STMFD SP (there might be
+ // a NOP before, but nevermind)
+
+ for (CFGU_GetConfigInfoBlk2_startPos = CFGU_GetConfigInfoBlk2_endPos - 4;
+ CFGU_GetConfigInfoBlk2_startPos >= code &&
+ *((u16*)CFGU_GetConfigInfoBlk2_startPos + 1) != 0xE92D;
+ CFGU_GetConfigInfoBlk2_startPos -= 2)
+ ;
+
+ for (u8* languageBlkIdPos = code; languageBlkIdPos < code + size;
+ languageBlkIdPos += 4) {
+ if (*(u32*)languageBlkIdPos == 0xA0002) {
+ for (u8* instr = languageBlkIdPos - 8;
+ instr >= languageBlkIdPos - 0x1008 && instr >= code + 4;
+ instr -= 4) // Should be enough
{
- if(instr[3] == 0xEB) //We're looking for BL
+ if (instr[3] == 0xEB) // We're looking for BL
{
- u8 *calledFunction = instr;
- u32 i = 0,
- found;
+ u8* calledFunction = instr;
+ u32 i = 0, found;
- do
- {
- u32 low24 = (*(u32 *)calledFunction & 0x00FFFFFF) << 2;
- u32 signMask = (u32)(-(low24 >> 25)) & 0xFC000000; //Sign extension
- s32 offset = (s32)(low24 | signMask) + 8; //Branch offset + 8 for prefetch
+ do {
+ u32 low24 = (*(u32*)calledFunction & 0x00FFFFFF) << 2;
+ u32 signMask = (u32)(-(low24 >> 25)) &
+ 0xFC000000; // Sign extension
+ s32 offset = (s32)(low24 | signMask) +
+ 8; // Branch offset + 8 for prefetch
calledFunction += offset;
- found = calledFunction >= CFGU_GetConfigInfoBlk2_startPos - 4 && calledFunction <= CFGU_GetConfigInfoBlk2_endPos;
+ found = calledFunction >=
+ CFGU_GetConfigInfoBlk2_startPos - 4 &&
+ calledFunction <= CFGU_GetConfigInfoBlk2_endPos;
i++;
- }
- while(i < 2 && !found && calledFunction[3] == 0xEA);
-
- if(found)
- {
- *((u32 *)instr - 1) = 0xE3A00000 | languageId; // mov r0, sp => mov r0, =languageId
- *(u32 *)instr = 0xE5CD0000; // bl CFGU_GetConfigInfoBlk2 => strb r0, [sp]
- *((u32 *)instr + 1) = 0xE3B00000; // (1 or 2 instructions) => movs r0, 0 (result code)
-
- //We're done
+ } while (i < 2 && !found && calledFunction[3] == 0xEA);
+
+ if (found) {
+ *((u32*)instr - 1) =
+ 0xE3A00000 | languageId; // mov r0, sp
+ // => mov r0, =languageId
+ *(u32*)instr = 0xE5CD0000; // bl
+ // CFGU_GetConfigInfoBlk2 =>
+ // strb r0, [sp]
+ *((u32*)instr + 1) =
+ 0xE3B00000; // (1 or 2 instructions) => movs
+ // r0, 0 (result code)
+
+ // We're done
return;
}
}
}
}
-static void patchCfgGetRegion(u8 *code, u32 size, u8 regionId, u32 CFGUHandleOffset)
+static void
+patchCfgGetRegion(u8* code, u32 size, u8 regionId, u32 CFGUHandleOffset)
{
- for(u8 *cmdPos = code; cmdPos < code + size - 28; cmdPos += 4)
- {
- static const u32 cfgSecureInfoGetRegionCmdPattern[] = {0xEE1D4F70, 0xE3A00802, 0xE5A40080};
-
- u32 *cmp = (u32 *)cmdPos;
-
- if(cmp[0] == cfgSecureInfoGetRegionCmdPattern[0] && cmp[1] == cfgSecureInfoGetRegionCmdPattern[1] &&
- cmp[2] == cfgSecureInfoGetRegionCmdPattern[2] && *((u16 *)cmdPos + 7) == 0xE59F &&
- *(u32 *)(cmdPos + 20 + *((u16 *)cmdPos + 6)) == CFGUHandleOffset)
- {
- *((u32 *)cmdPos + 4) = 0xE3A00000 | regionId; // mov r0, =regionId
- *((u32 *)cmdPos + 5) = 0xE5C40008; // strb r0, [r4, 8]
- *((u32 *)cmdPos + 6) = 0xE3B00000; // movs r0, 0 (result code) ('s' not needed but nvm)
- *((u32 *)cmdPos + 7) = 0xE5840004; // str r0, [r4, 4]
-
- //The remaining, not patched, function code will do the rest for us
+ for (u8* cmdPos = code; cmdPos < code + size - 28; cmdPos += 4) {
+ static const u32 cfgSecureInfoGetRegionCmdPattern[] = { 0xEE1D4F70,
+ 0xE3A00802,
+ 0xE5A40080 };
+
+ u32* cmp = (u32*)cmdPos;
+
+ if (cmp[0] == cfgSecureInfoGetRegionCmdPattern[0] &&
+ cmp[1] == cfgSecureInfoGetRegionCmdPattern[1] &&
+ cmp[2] == cfgSecureInfoGetRegionCmdPattern[2] &&
+ *((u16*)cmdPos + 7) == 0xE59F &&
+ *(u32*)(cmdPos + 20 + *((u16*)cmdPos + 6)) == CFGUHandleOffset) {
+ *((u32*)cmdPos + 4) = 0xE3A00000 | regionId; // mov r0, =regionId
+ *((u32*)cmdPos + 5) = 0xE5C40008; // strb r0, [r4, 8]
+ *((u32*)cmdPos + 6) = 0xE3B00000; // movs r0, 0 (result
+ // code) ('s' not needed but nvm)
+ *((u32*)cmdPos + 7) = 0xE5840004; // str r0, [r4, 4]
+
+ // The remaining, not patched, function code will do the rest for us
break;
}
}
}
-static void adjust_cpu_settings(u64 progId, u8 *code, u32 size) {
- if (!failed_load_config) {
- u32 cpuSetting = 0;
- // L2
- cpuSetting |= config.options[OPTION_LOADER_CPU_L2];
- // Speed
- cpuSetting |= config.options[OPTION_LOADER_CPU_800MHZ] << 1;
-
- if(cpuSetting) {
- static const u8 cfgN3dsCpuPattern[] = {0x00, 0x40, 0xA0, 0xE1, 0x07, 0x00};
-
- u32 *cfgN3dsCpuLoc = (u32 *)memsearch(code, cfgN3dsCpuPattern, size, sizeof(cfgN3dsCpuPattern));
-
- //Patch N3DS CPU Clock and L2 cache setting
- if(cfgN3dsCpuLoc != NULL) {
- *(cfgN3dsCpuLoc + 1) = 0xE1A00000;
- *(cfgN3dsCpuLoc + 8) = 0xE3A00000 | cpuSetting;
- }
- }
- }
+static void
+adjust_cpu_settings(u64 progId, u8* code, u32 size)
+{
+ if (!failed_load_config) {
+ u32 cpuSetting = 0;
+ // L2
+ cpuSetting |= config.options[OPTION_LOADER_CPU_L2];
+ // Speed
+ cpuSetting |= config.options[OPTION_LOADER_CPU_800MHZ] << 1;
+
+ if (cpuSetting) {
+ static const u8 cfgN3dsCpuPattern[] = { 0x00, 0x40, 0xA0,
+ 0xE1, 0x07, 0x00 };
+
+ u32* cfgN3dsCpuLoc = (u32*)memsearch(code, cfgN3dsCpuPattern, size,
+ sizeof(cfgN3dsCpuPattern));
+
+ // Patch N3DS CPU Clock and L2 cache setting
+ if (cfgN3dsCpuLoc != NULL) {
+ *(cfgN3dsCpuLoc + 1) = 0xE1A00000;
+ *(cfgN3dsCpuLoc + 8) = 0xE3A00000 | cpuSetting;
+ }
+ }
+ }
}
-void language_emu(u64 progId, u8 *code, u32 size) {
- if(!failed_load_config && config.options[OPTION_LOADER_LANGEMU]) {
- u32 tidHigh = (progId & 0xFFFFFFF000000000LL) >> 0x24;
-
- if(tidHigh == 0x0004000) { // Normal Game
- //Language emulation
- u8 regionId = 0xFF,
- languageId = 0xFF;
-
- if(R_SUCCEEDED(loadTitleLocaleConfig(progId, ®ionId, &languageId))) {
- u32 CFGUHandleOffset;
-
- u8 *CFGU_GetConfigInfoBlk2_endPos = getCfgOffsets(code, size, &CFGUHandleOffset);
-
- if(CFGU_GetConfigInfoBlk2_endPos != NULL) {
- if(languageId != 0xFF)
- patchCfgGetLanguage(code, size, languageId, CFGU_GetConfigInfoBlk2_endPos);
- if(regionId != 0xFF)
- patchCfgGetRegion(code, size, regionId, CFGUHandleOffset);
- }
- }
- }
- }
+void
+language_emu(u64 progId, u8* code, u32 size)
+{
+ if (!failed_load_config && config.options[OPTION_LOADER_LANGEMU]) {
+ u32 tidHigh = (progId & 0xFFFFFFF000000000LL) >> 0x24;
+
+ if (tidHigh == 0x0004000) { // Normal Game
+ // Language emulation
+ u8 regionId = 0xFF, languageId = 0xFF;
+
+ if (R_SUCCEEDED(
+ loadTitleLocaleConfig(progId, ®ionId, &languageId))) {
+ u32 CFGUHandleOffset;
+
+ u8* CFGU_GetConfigInfoBlk2_endPos =
+ getCfgOffsets(code, size, &CFGUHandleOffset);
+
+ if (CFGU_GetConfigInfoBlk2_endPos != NULL) {
+ if (languageId != 0xFF)
+ patchCfgGetLanguage(code, size, languageId,
+ CFGU_GetConfigInfoBlk2_endPos);
+ if (regionId != 0xFF)
+ patchCfgGetRegion(code, size, regionId,
+ CFGUHandleOffset);
+ }
+ }
+ }
+ }
}
-void overlay_patch(u64 progId, u8 *code, u32 size) {
- // TODO - Implement.
+void
+overlay_patch(u64 progId, u8* code, u32 size)
+{
+ // TODO - Implement.
}
// This is only for the .data segment.
-void patch_data(u64 progId, u8 *data, u32 size, u32 orig_size) {
+void
+patch_data(u64 progId, u8* data, u32 size, u32 orig_size)
+{
}
// This is only for the .ro segment.
-void patch_ro(u64 progId, u8 *ro, u32 size, u32 orig_size) {
+void
+patch_ro(u64 progId, u8* ro, u32 size, u32 orig_size)
+{
}
// This is only for the .code segment.
-void patch_text(u64 progId, u8 *text, u32 size, u32 orig_size) {
- switch(progId)
- {
+void
+patch_text(u64 progId, u8* text, u32 size, u32 orig_size)
+{
+ switch (progId) {
case 0x0004003000008F02LL: // USA Menu
case 0x0004003000008202LL: // EUR Menu
case 0x0004003000009802LL: // JPN Menu
case 0x000400300000A902LL: // KOR Menu
case 0x000400300000B102LL: // TWN Menu
{
- region_patch(progId, text, orig_size);
+ region_patch(progId, text, orig_size);
break;
}
case 0x0004013000002C02LL: // NIM
{
- disable_nim_updates(progId, text, orig_size);
- disable_eshop_updates(progId, text, orig_size);
+ disable_nim_updates(progId, text, orig_size);
+ disable_eshop_updates(progId, text, orig_size);
break;
}
case 0x0004013000003202LL: // FRIENDS
{
- fake_friends_version(progId, text, orig_size);
+ fake_friends_version(progId, text, orig_size);
break;
}
case 0x0004001000027000LL: // KOR MSET
case 0x0004001000028000LL: // TWN MSET
{
- settings_string(progId, text, size);
+ settings_string(progId, text, size);
break;
}
case 0x0004013000008002LL: // NS
{
- disable_cart_updates(progId, text, orig_size);
- adjust_cpu_settings(progId, text, orig_size);
+ disable_cart_updates(progId, text, orig_size);
+ adjust_cpu_settings(progId, text, orig_size);
break;
}
case 0x0004013000001702LL: // CFG
{
- secureinfo_sigpatch(progId, text, orig_size);
+ secureinfo_sigpatch(progId, text, orig_size);
+ break;
+ }
+ case 0x0004013000003702LL: // RO
+ {
+ ro_sigpatch(progId, text, orig_size);
break;
}
- case 0x0004013000003702LL: // RO
- {
- ro_sigpatch(progId, text, orig_size);
- break;
- }
default: // Anything else.
- {
- language_emu(progId, text, orig_size);
+ {
+ language_emu(progId, text, orig_size);
break;
}
}
}
// Gets how many bytes .text must be extended by for patches to fit.
-u32 get_text_extend(u64 progId, u32 size_orig) {
- return 0; // Stub - nothing needs this yet
+u32
+get_text_extend(u64 progId, u32 size_orig)
+{
+ return 0; // Stub - nothing needs this yet
}
// Gets how many bytes .ro must be extended.
-u32 get_ro_extend(u64 progId, u32 size_orig) {
- return 0; // Stub - nothing needs this yet
+u32
+get_ro_extend(u64 progId, u32 size_orig)
+{
+ return 0; // Stub - nothing needs this yet
}
// Again, same, but for .data.
-u32 get_data_extend(u64 progId, u32 size_orig) {
- return 0; // Stub - nothing needs this yet
+u32
+get_data_extend(u64 progId, u32 size_orig)
+{
+ return 0; // Stub - nothing needs this yet
}
// Get CPU speed for progId.
-u8 get_cpumode(u64 progId) {
- return 0xff; // Skip.
+u8
+get_cpumode(u64 progId)
+{
+ return 0xff; // Skip.
}
#include <3ds/types.h>
-void patch_text(u64 progId, u8 *text, u32 size, u32 orig_size);
-void patch_data(u64 progId, u8 *data, u32 size, u32 orig_size);
-void patch_ro(u64 progId, u8 *ro, u32 size, u32 orig_size);
+void patch_text(u64 progId, u8* text, u32 size, u32 orig_size);
+void patch_data(u64 progId, u8* data, u32 size, u32 orig_size);
+void patch_ro(u64 progId, u8* ro, u32 size, u32 orig_size);
u32 get_text_extend(u64 progId, u32 size_orig);
u32 get_ro_extend(u64 progId, u32 size_orig);
void load_config();
-u32 patchMemory(u8 *start, u32 size, const void *pattern, u32 patSize, int offset, const void *replace, u32 repSize, u32 count);
+u32 patchMemory(u8* start, u32 size, const void* pattern, u32 patSize,
+ int offset, const void* replace, u32 repSize, u32 count);
u8 get_cpumode(u64 progId);
static Handle pxipmHandle;
static int pxipmRefCount;
-Result pxipmInit(void)
+Result
+pxipmInit(void)
{
- Result ret = 0;
+ Result ret = 0;
- if (AtomicPostIncrement(&pxipmRefCount)) return 0;
+ if (AtomicPostIncrement(&pxipmRefCount))
+ return 0;
- ret = srvSysGetServiceHandle(&pxipmHandle, "PxiPM");
+ ret = srvSysGetServiceHandle(&pxipmHandle, "PxiPM");
- if (R_FAILED(ret)) AtomicDecrement(&pxipmRefCount);
- return ret;
+ if (R_FAILED(ret))
+ AtomicDecrement(&pxipmRefCount);
+ return ret;
}
-void pxipmExit(void)
+void
+pxipmExit(void)
{
- if (AtomicDecrement(&pxipmRefCount)) return;
- svcCloseHandle(pxipmHandle);
+ if (AtomicDecrement(&pxipmRefCount))
+ return;
+ svcCloseHandle(pxipmHandle);
}
-Result PXIPM_RegisterProgram(u64 *prog_handle, FS_ProgramInfo *title, FS_ProgramInfo *update)
+Result
+PXIPM_RegisterProgram(u64* prog_handle, FS_ProgramInfo* title,
+ FS_ProgramInfo* update)
{
- u32 *cmdbuf = getThreadCommandBuffer();
-
- cmdbuf[0] = IPC_MakeHeader(0x2,8,0); // 0x20200
- memcpy(&cmdbuf[1], &title->programId, sizeof(u64));
- *(u8 *)&cmdbuf[3] = title->mediaType;
- memcpy(((u8 *)&cmdbuf[3])+1, &title->padding, 7);
- memcpy(&cmdbuf[5], &update->programId, sizeof(u64));
- *(u8 *)&cmdbuf[7] = update->mediaType;
- memcpy(((u8 *)&cmdbuf[7])+1, &update->padding, 7);
-
- Result ret = 0;
- if(R_FAILED(ret = svcSendSyncRequest(pxipmHandle))) return ret;
- *prog_handle = *(u64*)&cmdbuf[2];
-
- return cmdbuf[1];
+ u32* cmdbuf = getThreadCommandBuffer();
+
+ cmdbuf[0] = IPC_MakeHeader(0x2, 8, 0); // 0x20200
+ memcpy(&cmdbuf[1], &title->programId, sizeof(u64));
+ *(u8*)&cmdbuf[3] = title->mediaType;
+ memcpy(((u8*)&cmdbuf[3]) + 1, &title->padding, 7);
+ memcpy(&cmdbuf[5], &update->programId, sizeof(u64));
+ *(u8*)&cmdbuf[7] = update->mediaType;
+ memcpy(((u8*)&cmdbuf[7]) + 1, &update->padding, 7);
+
+ Result ret = 0;
+ if (R_FAILED(ret = svcSendSyncRequest(pxipmHandle)))
+ return ret;
+ *prog_handle = *(u64*)&cmdbuf[2];
+
+ return cmdbuf[1];
}
-Result PXIPM_GetProgramInfo(exheader_header *exheader, u64 prog_handle)
+Result
+PXIPM_GetProgramInfo(exheader_header* exheader, u64 prog_handle)
{
- u32 *cmdbuf = getThreadCommandBuffer();
+ u32* cmdbuf = getThreadCommandBuffer();
- cmdbuf[0] = IPC_MakeHeader(0x1,2,2); // 0x10082
- cmdbuf[1] = (u32) (prog_handle);
- cmdbuf[2] = (u32) (prog_handle >> 32);
- cmdbuf[3] = (0x400 << 8) | 0x4;
- cmdbuf[4] = (u32) exheader;
+ cmdbuf[0] = IPC_MakeHeader(0x1, 2, 2); // 0x10082
+ cmdbuf[1] = (u32)(prog_handle);
+ cmdbuf[2] = (u32)(prog_handle >> 32);
+ cmdbuf[3] = (0x400 << 8) | 0x4;
+ cmdbuf[4] = (u32)exheader;
- Result ret = 0;
- if(R_FAILED(ret = svcSendSyncRequest(pxipmHandle))) return ret;
+ Result ret = 0;
+ if (R_FAILED(ret = svcSendSyncRequest(pxipmHandle)))
+ return ret;
- return cmdbuf[1];
+ return cmdbuf[1];
}
-Result PXIPM_UnregisterProgram(u64 prog_handle)
+Result
+PXIPM_UnregisterProgram(u64 prog_handle)
{
- u32 *cmdbuf = getThreadCommandBuffer();
+ u32* cmdbuf = getThreadCommandBuffer();
- cmdbuf[0] = IPC_MakeHeader(0x3,2,0); // 0x30080
- cmdbuf[1] = (u32) (prog_handle);
- cmdbuf[2] = (u32) (prog_handle >> 32);
+ cmdbuf[0] = IPC_MakeHeader(0x3, 2, 0); // 0x30080
+ cmdbuf[1] = (u32)(prog_handle);
+ cmdbuf[2] = (u32)(prog_handle >> 32);
- Result ret = 0;
- if(R_FAILED(ret = svcSendSyncRequest(pxipmHandle))) return ret;
+ Result ret = 0;
+ if (R_FAILED(ret = svcSendSyncRequest(pxipmHandle)))
+ return ret;
- return cmdbuf[1];
+ return cmdbuf[1];
}
Result pxipmInit(void);
void pxipmExit(void);
-Result PXIPM_RegisterProgram(u64 *prog_handle, FS_ProgramInfo *title, FS_ProgramInfo *update);
-Result PXIPM_GetProgramInfo(exheader_header *exheader, u64 prog_handle);
+Result PXIPM_RegisterProgram(u64* prog_handle, FS_ProgramInfo* title,
+ FS_ProgramInfo* update);
+Result PXIPM_GetProgramInfo(exheader_header* exheader, u64 prog_handle);
Result PXIPM_UnregisterProgram(u64 prog_handle);
static RecursiveLock initLock;
static int initLockinit = 0;
-Result srvSysInit()
+Result
+srvSysInit()
{
- Result rc = 0;
+ Result rc = 0;
+
+ if (!initLockinit) {
+ RecursiveLock_Init(&initLock);
+ }
+
+ RecursiveLock_Lock(&initLock);
+
+ if (srvRefCount > 0) {
+ RecursiveLock_Unlock(&initLock);
+ return MAKERESULT(RL_INFO, RS_NOP, 25, RD_ALREADY_INITIALIZED);
+ }
+
+ while (1) {
+ rc = svcConnectToPort(&srvHandle, "srv:");
+ if (R_LEVEL(rc) != RL_PERMANENT || R_SUMMARY(rc) != RS_NOTFOUND ||
+ R_DESCRIPTION(rc) != RD_NOT_FOUND)
+ break;
+ svcSleepThread(500000);
+ }
+ if (R_SUCCEEDED(rc)) {
+ rc = srvSysRegisterClient();
+ srvRefCount++;
+ }
- if (!initLockinit)
- {
- RecursiveLock_Init(&initLock);
- }
-
- RecursiveLock_Lock(&initLock);
-
- if (srvRefCount > 0)
- {
RecursiveLock_Unlock(&initLock);
- return MAKERESULT(RL_INFO, RS_NOP, 25, RD_ALREADY_INITIALIZED);
- }
-
- while (1)
- {
- rc = svcConnectToPort(&srvHandle, "srv:");
- if (R_LEVEL(rc) != RL_PERMANENT ||
- R_SUMMARY(rc) != RS_NOTFOUND ||
- R_DESCRIPTION(rc) != RD_NOT_FOUND
- ) break;
- svcSleepThread(500000);
- }
- if (R_SUCCEEDED(rc))
- {
- rc = srvSysRegisterClient();
- srvRefCount++;
- }
-
- RecursiveLock_Unlock(&initLock);
- return rc;
+ return rc;
}
-Result srvSysRegisterClient(void)
+Result
+srvSysRegisterClient(void)
{
- Result rc = 0;
- u32* cmdbuf = getThreadCommandBuffer();
+ Result rc = 0;
+ u32* cmdbuf = getThreadCommandBuffer();
- cmdbuf[0] = IPC_MakeHeader(0x1,0,2); // 0x10002
- cmdbuf[1] = IPC_Desc_CurProcessHandle();
+ cmdbuf[0] = IPC_MakeHeader(0x1, 0, 2); // 0x10002
+ cmdbuf[1] = IPC_Desc_CurProcessHandle();
- if(R_FAILED(rc = svcSendSyncRequest(srvHandle)))return rc;
+ if (R_FAILED(rc = svcSendSyncRequest(srvHandle)))
+ return rc;
- return cmdbuf[1];
+ return cmdbuf[1];
}
-Result srvSysExit()
+Result
+srvSysExit()
{
- Result rc;
- RecursiveLock_Lock(&initLock);
-
- if (srvRefCount > 1)
- {
+ Result rc;
+ RecursiveLock_Lock(&initLock);
+
+ if (srvRefCount > 1) {
+ srvRefCount--;
+ RecursiveLock_Unlock(&initLock);
+ return MAKERESULT(RL_INFO, RS_NOP, 25, RD_BUSY);
+ }
+
+ if (srvHandle != 0)
+ svcCloseHandle(srvHandle);
+ else
+ svcBreak(USERBREAK_ASSERT);
+ rc = (Result)srvHandle; // yeah, I think this is a benign bug
+ srvHandle = 0;
srvRefCount--;
RecursiveLock_Unlock(&initLock);
- return MAKERESULT(RL_INFO, RS_NOP, 25, RD_BUSY);
- }
-
- if (srvHandle != 0) svcCloseHandle(srvHandle);
- else svcBreak(USERBREAK_ASSERT);
- rc = (Result)srvHandle; // yeah, I think this is a benign bug
- srvHandle = 0;
- srvRefCount--;
- RecursiveLock_Unlock(&initLock);
- return rc;
+ return rc;
}
-Result srvSysGetServiceHandle(Handle* out, const char* name)
+Result
+srvSysGetServiceHandle(Handle* out, const char* name)
{
- Result rc = 0;
- u32* cmdbuf = getThreadCommandBuffer();
+ Result rc = 0;
+ u32* cmdbuf = getThreadCommandBuffer();
- cmdbuf[0] = IPC_MakeHeader(0x5,4,0); // 0x50100
- strncpy((char*) &cmdbuf[1], name,8);
- cmdbuf[3] = strlen(name);
- cmdbuf[4] = 0x0;
+ cmdbuf[0] = IPC_MakeHeader(0x5, 4, 0); // 0x50100
+ strncpy((char*)&cmdbuf[1], name, 8);
+ cmdbuf[3] = strlen(name);
+ cmdbuf[4] = 0x0;
- if(R_FAILED(rc = svcSendSyncRequest(srvHandle)))return rc;
+ if (R_FAILED(rc = svcSendSyncRequest(srvHandle)))
+ return rc;
- if(out) *out = cmdbuf[3];
+ if (out)
+ *out = cmdbuf[3];
- return cmdbuf[1];
+ return cmdbuf[1];
}
-Result srvSysEnableNotification(Handle* semaphoreOut)
+Result
+srvSysEnableNotification(Handle* semaphoreOut)
{
- Result rc = 0;
- u32* cmdbuf = getThreadCommandBuffer();
+ Result rc = 0;
+ u32* cmdbuf = getThreadCommandBuffer();
- cmdbuf[0] = IPC_MakeHeader(0x2,0,0);
+ cmdbuf[0] = IPC_MakeHeader(0x2, 0, 0);
- if(R_FAILED(rc = svcSendSyncRequest(srvHandle)))return rc;
+ if (R_FAILED(rc = svcSendSyncRequest(srvHandle)))
+ return rc;
- if(semaphoreOut) *semaphoreOut = cmdbuf[3];
+ if (semaphoreOut)
+ *semaphoreOut = cmdbuf[3];
- return cmdbuf[1];
+ return cmdbuf[1];
}
-Result srvSysReceiveNotification(u32* notificationIdOut)
+Result
+srvSysReceiveNotification(u32* notificationIdOut)
{
- Result rc = 0;
- u32* cmdbuf = getThreadCommandBuffer();
+ Result rc = 0;
+ u32* cmdbuf = getThreadCommandBuffer();
- cmdbuf[0] = IPC_MakeHeader(0xB,0,0); // 0xB0000
+ cmdbuf[0] = IPC_MakeHeader(0xB, 0, 0); // 0xB0000
- if(R_FAILED(rc = svcSendSyncRequest(srvHandle)))return rc;
+ if (R_FAILED(rc = svcSendSyncRequest(srvHandle)))
+ return rc;
- if(notificationIdOut) *notificationIdOut = cmdbuf[2];
+ if (notificationIdOut)
+ *notificationIdOut = cmdbuf[2];
- return cmdbuf[1];
+ return cmdbuf[1];
}
-Result srvSysRegisterService(Handle* out, const char* name, int maxSessions)
+Result
+srvSysRegisterService(Handle* out, const char* name, int maxSessions)
{
- Result rc = 0;
- u32* cmdbuf = getThreadCommandBuffer();
+ Result rc = 0;
+ u32* cmdbuf = getThreadCommandBuffer();
- cmdbuf[0] = IPC_MakeHeader(0x3,4,0); // 0x30100
- strncpy((char*) &cmdbuf[1], name,8);
- cmdbuf[3] = strlen(name);
- cmdbuf[4] = maxSessions;
+ cmdbuf[0] = IPC_MakeHeader(0x3, 4, 0); // 0x30100
+ strncpy((char*)&cmdbuf[1], name, 8);
+ cmdbuf[3] = strlen(name);
+ cmdbuf[4] = maxSessions;
- if(R_FAILED(rc = svcSendSyncRequest(srvHandle)))return rc;
+ if (R_FAILED(rc = svcSendSyncRequest(srvHandle)))
+ return rc;
- if(out) *out = cmdbuf[3];
+ if (out)
+ *out = cmdbuf[3];
- return cmdbuf[1];
+ return cmdbuf[1];
}
-Result srvSysUnregisterService(const char* name)
+Result
+srvSysUnregisterService(const char* name)
{
- Result rc = 0;
- u32* cmdbuf = getThreadCommandBuffer();
+ Result rc = 0;
+ u32* cmdbuf = getThreadCommandBuffer();
- cmdbuf[0] = IPC_MakeHeader(0x4,3,0); // 0x400C0
- strncpy((char*) &cmdbuf[1], name,8);
- cmdbuf[3] = strlen(name);
+ cmdbuf[0] = IPC_MakeHeader(0x4, 3, 0); // 0x400C0
+ strncpy((char*)&cmdbuf[1], name, 8);
+ cmdbuf[3] = strlen(name);
- if(R_FAILED(rc = svcSendSyncRequest(srvHandle)))return rc;
+ if (R_FAILED(rc = svcSendSyncRequest(srvHandle)))
+ return rc;
- return cmdbuf[1];
+ return cmdbuf[1];
}
Result srvSysExit(void);
/**
- * @brief Retrieves a service handle, retrieving from the environment handle list if possible.
+ * @brief Retrieves a service handle, retrieving from the environment handle
+ * list if possible.
* @param out Pointer to write the handle to.
* @param name Name of the service.
*/
/**
* @brief Receives a notification.
- * @param notificationIdOut Pointer to output the ID of the received notification to.
+ * @param notificationIdOut Pointer to output the ID of the received
+ * notification to.
*/
Result srvSysReceiveNotification(u32* notificationIdOut);
struct config_file config;
-void regenerate_config() {
- f_mkdir(PATH_CFW);
- f_mkdir(PATH_CONFIG);
+void
+regenerate_config()
+{
+ f_mkdir(PATH_CFW);
+ f_mkdir(PATH_CONFIG);
fprintf(BOTTOM_SCREEN, "Created directory structure.\n");
memcpy(&(config.magic), CONFIG_MAGIC, 4);
config.config_ver = config_version;
-
- if(!(conf_handle = fopen(PATH_CONFIG, "w")))
+ if (!(conf_handle = fopen(PATH_CONFIG, "w")))
abort("Failed to open config for write?\n");
fwrite(&config, 1, sizeof(config), conf_handle);
fprintf(BOTTOM_SCREEN, "Config file written.\n");
}
-void load_config() {
+void
+load_config()
+{
// Zero on success.
if (!(conf_handle = fopen(PATH_CONFIG, "r"))) {
fprintf(BOTTOM_SCREEN, "Config file is missing:\n"
" %s\n"
"Will create it with defaults.\n",
- PATH_CONFIG);
+ PATH_CONFIG);
regenerate_config();
} else {
fread(&config, 1, sizeof(config), conf_handle);
"has incorrect magic:\n"
" '%c%c%c%c'\n"
"Regenerating with defaults.\n",
- PATH_CONFIG,
- config.magic[0], config.magic[1], config.magic[2], config.magic[3]);
+ PATH_CONFIG, config.magic[0], config.magic[1],
+ config.magic[2], config.magic[3]);
f_unlink(PATH_CONFIG);
regenerate_config();
}
fprintf(BOTTOM_SCREEN, "Config file has outdated version:\n"
" %s\n"
"Regenerating with defaults.\n",
- PATH_CONFIG);
+ PATH_CONFIG);
f_unlink(PATH_CONFIG);
regenerate_config();
}
}
- if (!config.options[OPTION_SILENCE])
- fprintf(BOTTOM_SCREEN, "Config file loaded.\n");
+ if (!config.options[OPTION_SILENCE])
+ fprintf(BOTTOM_SCREEN, "Config file loaded.\n");
}
-void save_config() {
- fprintf(stderr, "Saving config.\n");
+void
+save_config()
+{
+ fprintf(stderr, "Saving config.\n");
f_unlink(PATH_CONFIG);
- if(!(conf_handle = fopen(PATH_CONFIG, "w")))
+ if (!(conf_handle = fopen(PATH_CONFIG, "w")))
abort("Failed to open config for write?\n");
fwrite(&config, 1, sizeof(config), conf_handle);
#define CONFIG_MAGIC "OVAN"
// Structure of config file
-struct config_file {
- char magic[4]; // "OVAN" for shits and giggles again.
+struct config_file
+{
+ char magic[4]; // "OVAN" for shits and giggles again.
- uint32_t config_ver; // Config file version.
+ uint32_t config_ver; // Config file version.
- uint8_t options[256]; // Options in the menu - deliberately large to avoid config version bumps.
+ uint8_t options[256]; // Options in the menu - deliberately large to avoid
+ // config version bumps.
- uint64_t patch_ids[256]; // What patches are enabled by UUID. 256 is an arbitrary limit - contact me if you hit it.
-}__attribute__((packed));
+ uint64_t patch_ids[256]; // What patches are enabled by UUID. 256 is an
+ // arbitrary limit - contact me if you hit it.
+} __attribute__((packed));
extern struct config_file config;
-enum type {
- boolean_val, // Toggle
- ranged_val, // N1 - N2, left and right to pick.
- mask_val // Bitmask allowed values.
+enum type
+{
+ boolean_val, // Toggle
+ ranged_val, // N1 - N2, left and right to pick.
+ mask_val // Bitmask allowed values.
};
-struct range_str {
- int a, b;
+struct range_str
+{
+ int a, b;
};
-struct options_s {
- int index;
- char name[64];
- enum type allowed;
- uint32_t a, b;
-}__attribute__((packed));
-
-#define OPTION_SIGPATCH 0 // Use builtin signature patch.
-#define OPTION_FIRMPROT 1 // Protect firmware from writes.
-#define OPTION_LOADER 2 // Use builtin loader module replacer.
-#define OPTION_SERVICES 3 // Inject services (including backdoor for 11)
-#define OPTION_ARM9THREAD 4 // Use builtin ARM9 thread injector.
-
-#define OPTION_AUTOBOOT 5 // Skip menu unless L is held.
-#define OPTION_SILENCE 6 // Don't print debug information.
-#define OPTION_TRACE 7 // Pause for A key on each step.
-
-#define OPTION_TRANSP_BG 8 // Background color is not drawn under text.
-#define OPTION_NO_CLEAR_BG 9 // Framebuffer is preserved from whatever ran before us.
-#define OPTION_READ_ME 10 // Remove Help/Readme from menu.
-
-#define OPTION_LOADER_CPU_L2 11 // Enable L2 cache.
+struct options_s
+{
+ int index;
+ char name[64];
+ enum type allowed;
+ uint32_t a, b;
+} __attribute__((packed));
+
+#define OPTION_SIGPATCH 0 // Use builtin signature patch.
+#define OPTION_FIRMPROT 1 // Protect firmware from writes.
+#define OPTION_LOADER 2 // Use builtin loader module replacer.
+#define OPTION_SERVICES 3 // Inject services (including backdoor for 11)
+#define OPTION_ARM9THREAD 4 // Use builtin ARM9 thread injector.
+
+#define OPTION_AUTOBOOT 5 // Skip menu unless L is held.
+#define OPTION_SILENCE 6 // Don't print debug information.
+#define OPTION_TRACE 7 // Pause for A key on each step.
+
+#define OPTION_TRANSP_BG 8 // Background color is not drawn under text.
+#define OPTION_NO_CLEAR_BG \
+ 9 // Framebuffer is preserved from whatever ran before us.
+#define OPTION_READ_ME 10 // Remove Help/Readme from menu.
+
+#define OPTION_LOADER_CPU_L2 11 // Enable L2 cache.
#define OPTION_LOADER_CPU_800MHZ 12 // Enable 800Mhz mode.
-#define OPTION_LOADER_LANGEMU 13 // Enable 800Mhz mode.
+#define OPTION_LOADER_LANGEMU 13 // Enable 800Mhz mode.
-#define OPTION_REPLACE_ALLOCATED_SVC 14 // Replace allocated services. Normally you don't want this.
+#define OPTION_REPLACE_ALLOCATED_SVC \
+ 14 // Replace allocated services. Normally you don't want this.
-#define IGNORE_PATCH_DEPS 14 // Ignore patch UUID dependencies. Not recommended.
-#define IGNORE_BROKEN_SHIT 15 // Allow enabling patches which are marked as 'incompatible'. Chances are there's a reason.
+#define IGNORE_PATCH_DEPS 14 // Ignore patch UUID dependencies. Not recommended.
+#define IGNORE_BROKEN_SHIT \
+ 15 // Allow enabling patches which are marked as 'incompatible'. Chances are
+ // there's a reason.
//#define HEADER_COLOR 12 // Color of header text.
//#define BG_COLOR 13 // Color of background.
...
*/
-
#endif
/* storage control modules to the FatFs module with a defined API. */
/*-----------------------------------------------------------------------*/
-#include "diskio.h" /* FatFs lower layer API */
+#include "diskio.h" /* FatFs lower layer API */
#include "sdmmc.h"
-
/*-----------------------------------------------------------------------*/
/* Get Drive Status */
/*-----------------------------------------------------------------------*/
-DSTATUS disk_status (
- __attribute__((unused))
- BYTE pdrv /* Physical drive nmuber to identify the drive */
-)
+DSTATUS
+disk_status(__attribute__((unused))
+ BYTE pdrv /* Physical drive nmuber to identify the drive */
+ )
{
- return RES_OK;
+ return RES_OK;
}
-
-
/*-----------------------------------------------------------------------*/
/* Inidialize a Drive */
/*-----------------------------------------------------------------------*/
-DSTATUS disk_initialize (
- __attribute__((unused))
- BYTE pdrv /* Physical drive nmuber to identify the drive */
-)
+DSTATUS
+disk_initialize(__attribute__((unused))
+ BYTE pdrv /* Physical drive nmuber to identify the drive */
+ )
{
- if (!sdmmc_sdcard_init())
+ if (!sdmmc_sdcard_init())
return RES_PARERR;
- return RES_OK;
+ return RES_OK;
}
-
-
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
/*-----------------------------------------------------------------------*/
-DRESULT disk_read (
- __attribute__((unused))
- BYTE pdrv, /* Physical drive nmuber to identify the drive */
- BYTE *buff, /* Data buffer to store read data */
- DWORD sector, /* Sector address in LBA */
- UINT count /* Number of sectors to read */
-)
+DRESULT
+disk_read(__attribute__((unused))
+ BYTE pdrv, /* Physical drive nmuber to identify the drive */
+ BYTE* buff, /* Data buffer to store read data */
+ DWORD sector, /* Sector address in LBA */
+ UINT count /* Number of sectors to read */
+ )
{
- if (sdmmc_sdcard_readsectors(sector, count, buff)) {
- return RES_PARERR;
- }
+ if (sdmmc_sdcard_readsectors(sector, count, buff)) {
+ return RES_PARERR;
+ }
- return RES_OK;
+ return RES_OK;
}
-
-
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
/*-----------------------------------------------------------------------*/
#if _USE_WRITE
-DRESULT disk_write (
- __attribute__((unused))
- BYTE pdrv, /* Physical drive nmuber to identify the drive */
- const BYTE *buff, /* Data to be written */
- DWORD sector, /* Sector address in LBA */
- UINT count /* Number of sectors to write */
-)
+DRESULT
+disk_write(__attribute__((unused))
+ BYTE pdrv, /* Physical drive nmuber to identify the drive */
+ const BYTE* buff, /* Data to be written */
+ DWORD sector, /* Sector address in LBA */
+ UINT count /* Number of sectors to write */
+ )
{
- if (sdmmc_sdcard_writesectors(sector, count, (BYTE *)buff)) {
- return RES_PARERR;
- }
+ if (sdmmc_sdcard_writesectors(sector, count, (BYTE*)buff)) {
+ return RES_PARERR;
+ }
- return RES_OK;
+ return RES_OK;
}
#endif
-
-
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
/*-----------------------------------------------------------------------*/
#if _USE_IOCTL
-DRESULT disk_ioctl (
- __attribute__((unused))
- BYTE pdrv, /* Physical drive nmuber (0..) */
- __attribute__((unused))
- BYTE cmd, /* Control code */
- __attribute__((unused))
- void *buff /* Buffer to send/receive control data */
-)
+DRESULT
+disk_ioctl(
+ __attribute__((unused)) BYTE pdrv, /* Physical drive nmuber (0..) */
+ __attribute__((unused)) BYTE cmd, /* Control code */
+ __attribute__((unused)) void* buff /* Buffer to send/receive control data */
+ )
{
switch (cmd) {
case GET_SECTOR_SIZE:
- *((DWORD*) buff) = 0x200;
+ *((DWORD*)buff) = 0x200;
return RES_OK;
case GET_SECTOR_COUNT:
- *((DWORD*) buff) = getMMCDevice(1)->total_size;
+ *((DWORD*)buff) = getMMCDevice(1)->total_size;
return RES_OK;
case GET_BLOCK_SIZE:
- *((DWORD*) buff) = 0x2000;
+ *((DWORD*)buff) = 0x2000;
return RES_OK;
case CTRL_SYNC:
// nothing to do here - the disk_write function handles that
return RES_OK;
}
- return RES_PARERR;
+ return RES_PARERR;
}
#endif
extern "C" {
#endif
-#define _USE_WRITE 1 /* 1: Enable disk_write function */
-#define _USE_IOCTL 1 /* 1: Enable disk_ioctl fucntion */
+#define _USE_WRITE 1 /* 1: Enable disk_write function */
+#define _USE_IOCTL 1 /* 1: Enable disk_ioctl fucntion */
#include "integer.h"
-
/* Status of Disk Functions */
-typedef BYTE DSTATUS;
+typedef BYTE DSTATUS;
/* Results of Disk Functions */
typedef enum {
- RES_OK = 0, /* 0: Successful */
- RES_ERROR, /* 1: R/W Error */
- RES_WRPRT, /* 2: Write Protected */
- RES_NOTRDY, /* 3: Not Ready */
- RES_PARERR /* 4: Invalid Parameter */
+ RES_OK = 0, /* 0: Successful */
+ RES_ERROR, /* 1: R/W Error */
+ RES_WRPRT, /* 2: Write Protected */
+ RES_NOTRDY, /* 3: Not Ready */
+ RES_PARERR /* 4: Invalid Parameter */
} DRESULT;
-
/*---------------------------------------*/
/* Prototypes for disk control functions */
-
-DSTATUS disk_initialize (BYTE pdrv);
-DSTATUS disk_status (BYTE pdrv);
-DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
-DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
-DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
-
+DSTATUS disk_initialize(BYTE pdrv);
+DSTATUS disk_status(BYTE pdrv);
+DRESULT disk_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
+DRESULT disk_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
+DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void* buff);
/* Disk Status Bits (DSTATUS) */
-#define STA_NOINIT 0x01 /* Drive not initialized */
-#define STA_NODISK 0x02 /* No medium in the drive */
-#define STA_PROTECT 0x04 /* Write protected */
-
+#define STA_NOINIT 0x01 /* Drive not initialized */
+#define STA_NODISK 0x02 /* No medium in the drive */
+#define STA_PROTECT 0x04 /* Write protected */
/* Command code for disk_ioctrl fucntion */
/* Generic command (Used by FatFs) */
-#define CTRL_SYNC 0 /* Complete pending write process (needed at _FS_READONLY == 0) */
-#define GET_SECTOR_COUNT 1 /* Get media size (needed at _USE_MKFS == 1) */
-#define GET_SECTOR_SIZE 2 /* Get sector size (needed at _MAX_SS != _MIN_SS) */
-#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at _USE_MKFS == 1) */
-#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */
+#define CTRL_SYNC \
+ 0 /* Complete pending write process (needed at _FS_READONLY == 0) */
+#define GET_SECTOR_COUNT 1 /* Get media size (needed at _USE_MKFS == 1) */
+#define GET_SECTOR_SIZE 2 /* Get sector size (needed at _MAX_SS != _MIN_SS) */
+#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at _USE_MKFS == 1) */
+#define CTRL_TRIM \
+ 4 /* Inform device that the data on the block of sectors is no longer used \
+ (needed at _USE_TRIM == 1) */
/* Generic command (Not used by FatFs) */
-#define CTRL_POWER 5 /* Get/Set power status */
-#define CTRL_LOCK 6 /* Lock/Unlock media removal */
-#define CTRL_EJECT 7 /* Eject media */
-#define CTRL_FORMAT 8 /* Create physical format on the media */
+#define CTRL_POWER 5 /* Get/Set power status */
+#define CTRL_LOCK 6 /* Lock/Unlock media removal */
+#define CTRL_EJECT 7 /* Eject media */
+#define CTRL_FORMAT 8 /* Create physical format on the media */
/* MMC/SDC specific ioctl command */
-#define MMC_GET_TYPE 10 /* Get card type */
-#define MMC_GET_CSD 11 /* Get CSD */
-#define MMC_GET_CID 12 /* Get CID */
-#define MMC_GET_OCR 13 /* Get OCR */
-#define MMC_GET_SDSTAT 14 /* Get SD status */
+#define MMC_GET_TYPE 10 /* Get card type */
+#define MMC_GET_CSD 11 /* Get CSD */
+#define MMC_GET_CID 12 /* Get CID */
+#define MMC_GET_OCR 13 /* Get OCR */
+#define MMC_GET_SDSTAT 14 /* Get SD status */
/* ATA/CF specific ioctl command */
-#define ATA_GET_REV 20 /* Get F/W revision */
-#define ATA_GET_MODEL 21 /* Get model name */
-#define ATA_GET_SN 22 /* Get serial number */
+#define ATA_GET_REV 20 /* Get F/W revision */
+#define ATA_GET_MODEL 21 /* Get model name */
+#define ATA_GET_SN 22 /* Get serial number */
#ifdef __cplusplus
}
/ by use of this software.
/----------------------------------------------------------------------------*/
-
-#include "ff.h" /* Declarations of FatFs API */
-#include "diskio.h" /* Declarations of disk I/O functions */
-
+#include "ff.h" /* Declarations of FatFs API */
+#include "diskio.h" /* Declarations of disk I/O functions */
/*--------------------------------------------------------------------------
---------------------------------------------------------------------------*/
-#if _FATFS != 32020 /* Revision ID */
+#if _FATFS != 32020 /* Revision ID */
#error Wrong include file (ff.h).
#endif
-
/* Reentrancy related */
#if _FS_REENTRANT
#if _USE_LFN == 1
#error Static LFN work area cannot be used at thread-safe configuration
#endif
-#define ENTER_FF(fs) { if (!lock_fs(fs)) return FR_TIMEOUT; }
-#define LEAVE_FF(fs, res) { unlock_fs(fs, res); return res; }
+#define ENTER_FF(fs) \
+ { \
+ if (!lock_fs(fs)) \
+ return FR_TIMEOUT; \
+ }
+#define LEAVE_FF(fs, res) \
+ { \
+ unlock_fs(fs, res); \
+ return res; \
+ }
#else
-#define ENTER_FF(fs)
-#define LEAVE_FF(fs, res) return res
+#define ENTER_FF(fs)
+#define LEAVE_FF(fs, res) return res
#endif
-#define ABORT(fs, res) { fp->err = (BYTE)(res); LEAVE_FF(fs, res); }
-
+#define ABORT(fs, res) \
+ { \
+ fp->err = (BYTE)(res); \
+ LEAVE_FF(fs, res); \
+ }
/* Definitions of sector size */
-#if (_MAX_SS < _MIN_SS) || (_MAX_SS != 512 && _MAX_SS != 1024 && _MAX_SS != 2048 && _MAX_SS != 4096) || (_MIN_SS != 512 && _MIN_SS != 1024 && _MIN_SS != 2048 && _MIN_SS != 4096)
+#if (_MAX_SS < _MIN_SS) || (_MAX_SS != 512 && _MAX_SS != 1024 && \
+ _MAX_SS != 2048 && _MAX_SS != 4096) || \
+ (_MIN_SS != 512 && _MIN_SS != 1024 && _MIN_SS != 2048 && _MIN_SS != 4096)
#error Wrong sector size configuration
#endif
#if _MAX_SS == _MIN_SS
-#define SS(fs) ((UINT)_MAX_SS) /* Fixed sector size */
+#define SS(fs) ((UINT)_MAX_SS) /* Fixed sector size */
#else
-#define SS(fs) ((fs)->ssize) /* Variable sector size */
+#define SS(fs) ((fs)->ssize) /* Variable sector size */
#endif
-
/* Timestamp feature */
#if _FS_NORTC == 1
-#if _NORTC_YEAR < 1980 || _NORTC_YEAR > 2107 || _NORTC_MON < 1 || _NORTC_MON > 12 || _NORTC_MDAY < 1 || _NORTC_MDAY > 31
+#if _NORTC_YEAR < 1980 || _NORTC_YEAR > 2107 || _NORTC_MON < 1 || \
+ _NORTC_MON > 12 || _NORTC_MDAY < 1 || _NORTC_MDAY > 31
#error Invalid _FS_NORTC settings
#endif
-#define GET_FATTIME() ((DWORD)(_NORTC_YEAR - 1980) << 25 | (DWORD)_NORTC_MON << 21 | (DWORD)_NORTC_MDAY << 16)
+#define GET_FATTIME() \
+ ((DWORD)(_NORTC_YEAR - 1980) << 25 | (DWORD)_NORTC_MON << 21 | \
+ (DWORD)_NORTC_MDAY << 16)
#else
-#define GET_FATTIME() get_fattime()
+#define GET_FATTIME() get_fattime()
#endif
-
/* File access control feature */
#if _FS_LOCK
#if _FS_READONLY
#error _FS_LOCK must be 0 at read-only configuration
#endif
-typedef struct {
- FATFS *fs; /* Object ID 1, volume (NULL:blank entry) */
- DWORD clu; /* Object ID 2, directory (0:root) */
- WORD idx; /* Object ID 3, directory index */
- WORD ctr; /* Object open counter, 0:none, 0x01..0xFF:read mode open count, 0x100:write mode */
+typedef struct
+{
+ FATFS* fs; /* Object ID 1, volume (NULL:blank entry) */
+ DWORD clu; /* Object ID 2, directory (0:root) */
+ WORD idx; /* Object ID 3, directory index */
+ WORD ctr; /* Object open counter, 0:none, 0x01..0xFF:read mode open count,
+ 0x100:write mode */
} FILESEM;
#endif
-
-
/* DBCS code ranges and SBCS extend character conversion table */
-#if _CODE_PAGE == 932 /* Japanese Shift-JIS */
-#define _DF1S 0x81 /* DBC 1st byte range 1 start */
-#define _DF1E 0x9F /* DBC 1st byte range 1 end */
-#define _DF2S 0xE0 /* DBC 1st byte range 2 start */
-#define _DF2E 0xFC /* DBC 1st byte range 2 end */
-#define _DS1S 0x40 /* DBC 2nd byte range 1 start */
-#define _DS1E 0x7E /* DBC 2nd byte range 1 end */
-#define _DS2S 0x80 /* DBC 2nd byte range 2 start */
-#define _DS2E 0xFC /* DBC 2nd byte range 2 end */
-
-#elif _CODE_PAGE == 936 /* Simplified Chinese GBK */
-#define _DF1S 0x81
-#define _DF1E 0xFE
-#define _DS1S 0x40
-#define _DS1E 0x7E
-#define _DS2S 0x80
-#define _DS2E 0xFE
-
-#elif _CODE_PAGE == 949 /* Korean */
-#define _DF1S 0x81
-#define _DF1E 0xFE
-#define _DS1S 0x41
-#define _DS1E 0x5A
-#define _DS2S 0x61
-#define _DS2E 0x7A
-#define _DS3S 0x81
-#define _DS3E 0xFE
-
-#elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */
-#define _DF1S 0x81
-#define _DF1E 0xFE
-#define _DS1S 0x40
-#define _DS1E 0x7E
-#define _DS2S 0xA1
-#define _DS2E 0xFE
-
-#elif _CODE_PAGE == 437 /* U.S. (OEM) */
-#define _DF1S 0
-/*#define _EXCVT {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F,0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
- 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
- 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
- 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}*/
-
-static
-const unsigned short Tbl[] = { /* CP437(0x80-0xFF) to Unicode conversion table */
- 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
- 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
- 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
- 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
- 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA,
- 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
- 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
- 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
- 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
- 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
- 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
- 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
- 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4,
- 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
- 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248,
- 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
-};
-
-WCHAR ff_convert( /* Converted character, Returns zero on error */
-WCHAR src, /* Character code to be converted */
-UINT dir /* 0: Unicode to OEMCP, 1: OEMCP to Unicode */
-)
+#if _CODE_PAGE == 932 /* Japanese Shift-JIS */
+#define _DF1S 0x81 /* DBC 1st byte range 1 start */
+#define _DF1E 0x9F /* DBC 1st byte range 1 end */
+#define _DF2S 0xE0 /* DBC 1st byte range 2 start */
+#define _DF2E 0xFC /* DBC 1st byte range 2 end */
+#define _DS1S 0x40 /* DBC 2nd byte range 1 start */
+#define _DS1E 0x7E /* DBC 2nd byte range 1 end */
+#define _DS2S 0x80 /* DBC 2nd byte range 2 start */
+#define _DS2E 0xFC /* DBC 2nd byte range 2 end */
+
+#elif _CODE_PAGE == 936 /* Simplified Chinese GBK */
+#define _DF1S 0x81
+#define _DF1E 0xFE
+#define _DS1S 0x40
+#define _DS1E 0x7E
+#define _DS2S 0x80
+#define _DS2E 0xFE
+
+#elif _CODE_PAGE == 949 /* Korean */
+#define _DF1S 0x81
+#define _DF1E 0xFE
+#define _DS1S 0x41
+#define _DS1E 0x5A
+#define _DS2S 0x61
+#define _DS2E 0x7A
+#define _DS3S 0x81
+#define _DS3E 0xFE
+
+#elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */
+#define _DF1S 0x81
+#define _DF1E 0xFE
+#define _DS1S 0x40
+#define _DS1E 0x7E
+#define _DS2S 0xA1
+#define _DS2E 0xFE
+
+#elif _CODE_PAGE == 437 /* U.S. (OEM) */
+#define _DF1S 0
+/*#define _EXCVT
+ {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F,0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
+ \
+ 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
+ \
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
+ \
+ 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}*/
+
+static const unsigned short Tbl[] =
+ { /* CP437(0x80-0xFF) to Unicode conversion table */
+ 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA,
+ 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, 0x00C9, 0x00E6,
+ 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC,
+ 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, 0x00E1, 0x00ED, 0x00F3, 0x00FA,
+ 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC,
+ 0x00A1, 0x00AB, 0x00BB, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561,
+ 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B,
+ 0x2510, 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
+ 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, 0x2568,
+ 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518,
+ 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, 0x03B1, 0x00DF, 0x0393,
+ 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4,
+ 0x221E, 0x03C6, 0x03B5, 0x2229, 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320,
+ 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2,
+ 0x25A0, 0x00A0
+ };
+
+WCHAR
+ff_convert( /* Converted character, Returns zero on error */
+ WCHAR src, /* Character code to be converted */
+ UINT dir /* 0: Unicode to OEMCP, 1: OEMCP to Unicode */
+ )
{
- WCHAR c;
-
- if(src < 0x80)
- { /* ASCII */
- c = src;
- }
- else
- {
- if(dir)
- { /* OEMCP to Unicode */
- c = (src >= 0x100) ? 0 : Tbl[src - 0x80];
- }
- else
- { /* Unicode to OEMCP */
- for(c = 0; c < 0x80; c++)
- {
- if(src == Tbl[c])
- break;
- }
- c = (c + 0x80) & 0xFF;
- }
- }
-
- return c;
+ WCHAR c;
+
+ if (src < 0x80) { /* ASCII */
+ c = src;
+ } else {
+ if (dir) { /* OEMCP to Unicode */
+ c = (src >= 0x100) ? 0 : Tbl[src - 0x80];
+ } else { /* Unicode to OEMCP */
+ for (c = 0; c < 0x80; c++) {
+ if (src == Tbl[c])
+ break;
+ }
+ c = (c + 0x80) & 0xFF;
+ }
+ }
+
+ return c;
}
-WCHAR ff_wtoupper(WCHAR chr)
+WCHAR
+ff_wtoupper(WCHAR chr)
{
- if(chr >= 'a' && chr <= 'z')
- return (chr - 32);
- else
- return chr;
+ if (chr >= 'a' && chr <= 'z')
+ return (chr - 32);
+ else
+ return chr;
}
-#elif _CODE_PAGE == 720 /* Arabic (OEM) */
-#define _DF1S 0
-#define _EXCVT {0x80,0x81,0x45,0x41,0x84,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x49,0x49,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
- 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
- 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
- 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
-
-#elif _CODE_PAGE == 737 /* Greek (OEM) */
-#define _DF1S 0
-#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \
- 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
- 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
- 0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xE7,0xE8,0xF1,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
-
-#elif _CODE_PAGE == 775 /* Baltic (OEM) */
-#define _DF1S 0
-#define _EXCVT {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
- 0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
- 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
- 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
-
-#elif _CODE_PAGE == 850 /* Multilingual Latin 1 (OEM) */
-#define _DF1S 0
-#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
- 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
- 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
- 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
-
-#elif _CODE_PAGE == 852 /* Latin 2 (OEM) */
-#define _DF1S 0
-#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F,0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0x9F, \
- 0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \
- 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
- 0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF}
-
-#elif _CODE_PAGE == 855 /* Cyrillic (OEM) */
-#define _DF1S 0
-#define _EXCVT {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F,0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \
- 0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \
- 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \
- 0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF}
-
-#elif _CODE_PAGE == 857 /* Turkish (OEM) */
-#define _DF1S 0
-#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x98,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \
- 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
- 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
- 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0x59,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
-
-#elif _CODE_PAGE == 858 /* Multilingual Latin 1 + Euro (OEM) */
-#define _DF1S 0
-#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
- 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
- 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
- 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
-
-#elif _CODE_PAGE == 862 /* Hebrew (OEM) */
-#define _DF1S 0
-#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
- 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
- 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
- 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
-
-#elif _CODE_PAGE == 866 /* Russian (OEM) */
-#define _DF1S 0
-#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
- 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
- 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
- 0x90,0x91,0x92,0x93,0x9d,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
-
-#elif _CODE_PAGE == 874 /* Thai (OEM, Windows) */
-#define _DF1S 0
-#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
- 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
- 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
- 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
+#elif _CODE_PAGE == 720 /* Arabic (OEM) */
+#define _DF1S 0
+#define _EXCVT \
+ { \
+ 0x80, 0x81, 0x45, 0x41, 0x84, 0x41, 0x86, 0x43, 0x45, 0x45, 0x45, \
+ 0x49, 0x49, 0x8D, 0x8E, 0x8F, 0x90, 0x92, 0x92, 0x93, 0x94, 0x95, \
+ 0x49, 0x49, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, \
+ 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, \
+ 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, \
+ 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, \
+ 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, \
+ 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, \
+ 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, \
+ 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, \
+ 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, \
+ 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF \
+ }
+
+#elif _CODE_PAGE == 737 /* Greek (OEM) */
+#define _DF1S 0
+#define _EXCVT \
+ { \
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, \
+ 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x92, 0x92, 0x93, 0x94, 0x95, \
+ 0x96, 0x97, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, \
+ 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0xAA, 0x92, \
+ 0x93, 0x94, 0x95, 0x96, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, \
+ 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, \
+ 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, \
+ 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, \
+ 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0x97, 0xEA, 0xEB, \
+ 0xEC, 0xE4, 0xED, 0xEE, 0xE7, 0xE8, 0xF1, 0xEA, 0xEB, 0xEC, 0xED, \
+ 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, \
+ 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF \
+ }
+
+#elif _CODE_PAGE == 775 /* Baltic (OEM) */
+#define _DF1S 0
+#define _EXCVT \
+ { \
+ 0x80, 0x9A, 0x91, 0xA0, 0x8E, 0x95, 0x8F, 0x80, 0xAD, 0xED, 0x8A, \
+ 0x8A, 0xA1, 0x8D, 0x8E, 0x8F, 0x90, 0x92, 0x92, 0xE2, 0x99, 0x95, \
+ 0x96, 0x97, 0x97, 0x99, 0x9A, 0x9D, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, \
+ 0xA1, 0xE0, 0xA3, 0xA3, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, \
+ 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, \
+ 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, \
+ 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, \
+ 0xCD, 0xCE, 0xCF, 0xB5, 0xB6, 0xB7, 0xB8, 0xBD, 0xBE, 0xC6, 0xC7, \
+ 0xA5, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, \
+ 0xE3, 0xE5, 0xE5, 0xE6, 0xE3, 0xE8, 0xE8, 0xEA, 0xEA, 0xEE, 0xED, \
+ 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, \
+ 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF \
+ }
+
+#elif _CODE_PAGE == 850 /* Multilingual Latin 1 (OEM) */
+#define _DF1S 0
+#define _EXCVT \
+ { \
+ 0x80, 0x9A, 0x90, 0xB6, 0x8E, 0xB7, 0x8F, 0x80, 0xD2, 0xD3, 0xD4, \
+ 0xD8, 0xD7, 0xDE, 0x8E, 0x8F, 0x90, 0x92, 0x92, 0xE2, 0x99, 0xE3, \
+ 0xEA, 0xEB, 0x59, 0x99, 0x9A, 0x9D, 0x9C, 0x9D, 0x9E, 0x9F, 0xB5, \
+ 0xD6, 0xE0, 0xE9, 0xA5, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, \
+ 0xAC, 0x21, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, \
+ 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, \
+ 0xC2, 0xC3, 0xC4, 0xC5, 0xC7, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, \
+ 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, \
+ 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, \
+ 0xE3, 0xE5, 0xE5, 0xE6, 0xE7, 0xE7, 0xE9, 0xEA, 0xEB, 0xED, 0xED, \
+ 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, \
+ 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF \
+ }
+
+#elif _CODE_PAGE == 852 /* Latin 2 (OEM) */
+#define _DF1S 0
+#define _EXCVT \
+ { \
+ 0x80, 0x9A, 0x90, 0xB6, 0x8E, 0xDE, 0x8F, 0x80, 0x9D, 0xD3, 0x8A, \
+ 0x8A, 0xD7, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x91, 0xE2, 0x99, 0x95, \
+ 0x95, 0x97, 0x97, 0x99, 0x9A, 0x9B, 0x9B, 0x9D, 0x9E, 0x9F, 0xB5, \
+ 0xD6, 0xE0, 0xE9, 0xA4, 0xA4, 0xA6, 0xA6, 0xA8, 0xA8, 0xAA, 0x8D, \
+ 0xAC, 0xB8, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, \
+ 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBD, 0xBF, 0xC0, 0xC1, \
+ 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC6, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, \
+ 0xCD, 0xCE, 0xCF, 0xD1, 0xD1, 0xD2, 0xD3, 0xD2, 0xD5, 0xD6, 0xD7, \
+ 0xB7, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, \
+ 0xE3, 0xE3, 0xD5, 0xE6, 0xE6, 0xE8, 0xE9, 0xE8, 0xEB, 0xED, 0xED, \
+ 0xDD, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, \
+ 0xF9, 0xFA, 0xEB, 0xFC, 0xFC, 0xFE, 0xFF \
+ }
+
+#elif _CODE_PAGE == 855 /* Cyrillic (OEM) */
+#define _DF1S 0
+#define _EXCVT \
+ { \
+ 0x81, 0x81, 0x83, 0x83, 0x85, 0x85, 0x87, 0x87, 0x89, 0x89, 0x8B, \
+ 0x8B, 0x8D, 0x8D, 0x8F, 0x8F, 0x91, 0x91, 0x93, 0x93, 0x95, 0x95, \
+ 0x97, 0x97, 0x99, 0x99, 0x9B, 0x9B, 0x9D, 0x9D, 0x9F, 0x9F, 0xA1, \
+ 0xA1, 0xA3, 0xA3, 0xA5, 0xA5, 0xA7, 0xA7, 0xA9, 0xA9, 0xAB, 0xAB, \
+ 0xAD, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB6, 0xB6, \
+ 0xB8, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBE, 0xBE, 0xBF, 0xC0, 0xC1, \
+ 0xC2, 0xC3, 0xC4, 0xC5, 0xC7, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, \
+ 0xCD, 0xCE, 0xCF, 0xD1, 0xD1, 0xD3, 0xD3, 0xD5, 0xD5, 0xD7, 0xD7, \
+ 0xDD, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xE0, 0xDF, 0xE0, 0xE2, 0xE2, \
+ 0xE4, 0xE4, 0xE6, 0xE6, 0xE8, 0xE8, 0xEA, 0xEA, 0xEC, 0xEC, 0xEE, \
+ 0xEE, 0xEF, 0xF0, 0xF2, 0xF2, 0xF4, 0xF4, 0xF6, 0xF6, 0xF8, 0xF8, \
+ 0xFA, 0xFA, 0xFC, 0xFC, 0xFD, 0xFE, 0xFF \
+ }
+
+#elif _CODE_PAGE == 857 /* Turkish (OEM) */
+#define _DF1S 0
+#define _EXCVT \
+ { \
+ 0x80, 0x9A, 0x90, 0xB6, 0x8E, 0xB7, 0x8F, 0x80, 0xD2, 0xD3, 0xD4, \
+ 0xD8, 0xD7, 0x98, 0x8E, 0x8F, 0x90, 0x92, 0x92, 0xE2, 0x99, 0xE3, \
+ 0xEA, 0xEB, 0x98, 0x99, 0x9A, 0x9D, 0x9C, 0x9D, 0x9E, 0x9E, 0xB5, \
+ 0xD6, 0xE0, 0xE9, 0xA5, 0xA5, 0xA6, 0xA6, 0xA8, 0xA9, 0xAA, 0xAB, \
+ 0xAC, 0x21, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, \
+ 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, \
+ 0xC2, 0xC3, 0xC4, 0xC5, 0xC7, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, \
+ 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, \
+ 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, \
+ 0xE3, 0xE5, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xDE, 0x59, \
+ 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, \
+ 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF \
+ }
+
+#elif _CODE_PAGE == 858 /* Multilingual Latin 1 + Euro (OEM) */
+#define _DF1S 0
+#define _EXCVT \
+ { \
+ 0x80, 0x9A, 0x90, 0xB6, 0x8E, 0xB7, 0x8F, 0x80, 0xD2, 0xD3, 0xD4, \
+ 0xD8, 0xD7, 0xDE, 0x8E, 0x8F, 0x90, 0x92, 0x92, 0xE2, 0x99, 0xE3, \
+ 0xEA, 0xEB, 0x59, 0x99, 0x9A, 0x9D, 0x9C, 0x9D, 0x9E, 0x9F, 0xB5, \
+ 0xD6, 0xE0, 0xE9, 0xA5, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, \
+ 0xAC, 0x21, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, \
+ 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, \
+ 0xC2, 0xC3, 0xC4, 0xC5, 0xC7, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, \
+ 0xCD, 0xCE, 0xCF, 0xD1, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, \
+ 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, \
+ 0xE3, 0xE5, 0xE5, 0xE6, 0xE7, 0xE7, 0xE9, 0xEA, 0xEB, 0xED, 0xED, \
+ 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, \
+ 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF \
+ }
+
+#elif _CODE_PAGE == 862 /* Hebrew (OEM) */
+#define _DF1S 0
+#define _EXCVT \
+ { \
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, \
+ 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, \
+ 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0x41, \
+ 0x49, 0x4F, 0x55, 0xA5, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, \
+ 0xAC, 0x21, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, \
+ 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, \
+ 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, \
+ 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, \
+ 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, \
+ 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, \
+ 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, \
+ 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF \
+ }
+
+#elif _CODE_PAGE == 866 /* Russian (OEM) */
+#define _DF1S 0
+#define _EXCVT \
+ { \
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, \
+ 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, \
+ 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0x80, \
+ 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, \
+ 0x8C, 0x8D, 0x8E, 0x8F, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, \
+ 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, \
+ 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, \
+ 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, \
+ 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0x90, 0x91, 0x92, \
+ 0x93, 0x9d, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, \
+ 0x9E, 0x9F, 0xF0, 0xF0, 0xF2, 0xF2, 0xF4, 0xF4, 0xF6, 0xF6, 0xF8, \
+ 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF \
+ }
+
+#elif _CODE_PAGE == 874 /* Thai (OEM, Windows) */
+#define _DF1S 0
+#define _EXCVT \
+ { \
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, \
+ 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, \
+ 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, \
+ 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, \
+ 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, \
+ 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, \
+ 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, \
+ 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, \
+ 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, \
+ 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, \
+ 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, \
+ 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF \
+ }
#elif _CODE_PAGE == 1250 /* Central Europe (Windows) */
-#define _DF1S 0
-#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \
- 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xA3,0xB4,0xB5,0xB6,0xB7,0xB8,0xA5,0xAA,0xBB,0xBC,0xBD,0xBC,0xAF, \
- 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
- 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF}
+#define _DF1S 0
+#define _EXCVT \
+ { \
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, \
+ 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, \
+ 0x96, 0x97, 0x98, 0x99, 0x8A, 0x9B, 0x8C, 0x8D, 0x8E, 0x8F, 0xA0, \
+ 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, \
+ 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xA3, 0xB4, 0xB5, 0xB6, \
+ 0xB7, 0xB8, 0xA5, 0xAA, 0xBB, 0xBC, 0xBD, 0xBC, 0xAF, 0xC0, 0xC1, \
+ 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, \
+ 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, \
+ 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xC0, 0xC1, 0xC2, \
+ 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, \
+ 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xF7, 0xD8, \
+ 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xFF \
+ }
#elif _CODE_PAGE == 1251 /* Cyrillic (Windows) */
-#define _DF1S 0
-#define _EXCVT {0x80,0x81,0x82,0x82,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x80,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \
- 0xA0,0xA2,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB2,0xA5,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xA3,0xBD,0xBD,0xAF, \
- 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
- 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF}
+#define _DF1S 0
+#define _EXCVT \
+ { \
+ 0x80, 0x81, 0x82, 0x82, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, \
+ 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x80, 0x91, 0x92, 0x93, 0x94, 0x95, \
+ 0x96, 0x97, 0x98, 0x99, 0x8A, 0x9B, 0x8C, 0x8D, 0x8E, 0x8F, 0xA0, \
+ 0xA2, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, \
+ 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB2, 0xA5, 0xB5, 0xB6, \
+ 0xB7, 0xA8, 0xB9, 0xAA, 0xBB, 0xA3, 0xBD, 0xBD, 0xAF, 0xC0, 0xC1, \
+ 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, \
+ 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, \
+ 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xC0, 0xC1, 0xC2, \
+ 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, \
+ 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, \
+ 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF \
+ }
#elif _CODE_PAGE == 1252 /* Latin 1 (Windows) */
-#define _DF1S 0
-#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0xAd,0x9B,0x8C,0x9D,0xAE,0x9F, \
- 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
- 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
- 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F}
+#define _DF1S 0
+#define _EXCVT \
+ { \
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, \
+ 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, \
+ 0x96, 0x97, 0x98, 0x99, 0xAd, 0x9B, 0x8C, 0x9D, 0xAE, 0x9F, 0xA0, \
+ 0x21, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, \
+ 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, \
+ 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, \
+ 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, \
+ 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, \
+ 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xC0, 0xC1, 0xC2, \
+ 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, \
+ 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xF7, 0xD8, \
+ 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0x9F \
+ }
#elif _CODE_PAGE == 1253 /* Greek (Windows) */
-#define _DF1S 0
-#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
- 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
- 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xA2,0xB8,0xB9,0xBA, \
- 0xE0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xFB,0xBC,0xFD,0xBF,0xFF}
+#define _DF1S 0
+#define _EXCVT \
+ { \
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, \
+ 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, \
+ 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, \
+ 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, \
+ 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, \
+ 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, \
+ 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, \
+ 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, \
+ 0xD8, 0xD9, 0xDA, 0xDB, 0xA2, 0xB8, 0xB9, 0xBA, 0xE0, 0xC1, 0xC2, \
+ 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, \
+ 0xCE, 0xCF, 0xD0, 0xD1, 0xF2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, \
+ 0xD9, 0xDA, 0xFB, 0xBC, 0xFD, 0xBF, 0xFF \
+ }
#elif _CODE_PAGE == 1254 /* Turkish (Windows) */
-#define _DF1S 0
-#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x9D,0x9E,0x9F, \
- 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
- 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
- 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F}
+#define _DF1S 0
+#define _EXCVT \
+ { \
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, \
+ 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, \
+ 0x96, 0x97, 0x98, 0x99, 0x8A, 0x9B, 0x8C, 0x9D, 0x9E, 0x9F, 0xA0, \
+ 0x21, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, \
+ 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, \
+ 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, \
+ 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, \
+ 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, \
+ 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xC0, 0xC1, 0xC2, \
+ 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, \
+ 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xF7, 0xD8, \
+ 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0x9F \
+ }
#elif _CODE_PAGE == 1255 /* Hebrew (Windows) */
-#define _DF1S 0
-#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
- 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
- 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
- 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
+#define _DF1S 0
+#define _EXCVT \
+ { \
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, \
+ 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, \
+ 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, \
+ 0x21, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, \
+ 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, \
+ 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, \
+ 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, \
+ 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, \
+ 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, \
+ 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, \
+ 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, \
+ 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF \
+ }
#elif _CODE_PAGE == 1256 /* Arabic (Windows) */
-#define _DF1S 0
-#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x8C,0x9D,0x9E,0x9F, \
- 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
- 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
- 0x41,0xE1,0x41,0xE3,0xE4,0xE5,0xE6,0x43,0x45,0x45,0x45,0x45,0xEC,0xED,0x49,0x49,0xF0,0xF1,0xF2,0xF3,0x4F,0xF5,0xF6,0xF7,0xF8,0x55,0xFA,0x55,0x55,0xFD,0xFE,0xFF}
+#define _DF1S 0
+#define _EXCVT \
+ { \
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, \
+ 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, \
+ 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x8C, 0x9D, 0x9E, 0x9F, 0xA0, \
+ 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, \
+ 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, \
+ 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, \
+ 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, \
+ 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, \
+ 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0x41, 0xE1, 0x41, \
+ 0xE3, 0xE4, 0xE5, 0xE6, 0x43, 0x45, 0x45, 0x45, 0x45, 0xEC, 0xED, \
+ 0x49, 0x49, 0xF0, 0xF1, 0xF2, 0xF3, 0x4F, 0xF5, 0xF6, 0xF7, 0xF8, \
+ 0x55, 0xFA, 0x55, 0x55, 0xFD, 0xFE, 0xFF \
+ }
#elif _CODE_PAGE == 1257 /* Baltic (Windows) */
-#define _DF1S 0
-#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
- 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xBC,0xBD,0xBE,0xAF, \
- 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
- 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF}
+#define _DF1S 0
+#define _EXCVT \
+ { \
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, \
+ 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, \
+ 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, \
+ 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, \
+ 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, \
+ 0xB7, 0xA8, 0xB9, 0xAA, 0xBB, 0xBC, 0xBD, 0xBE, 0xAF, 0xC0, 0xC1, \
+ 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, \
+ 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, \
+ 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xC0, 0xC1, 0xC2, \
+ 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, \
+ 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xF7, 0xD8, \
+ 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xFF \
+ }
#elif _CODE_PAGE == 1258 /* Vietnam (OEM, Windows) */
-#define _DF1S 0
-#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0xAC,0x9D,0x9E,0x9F, \
- 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
- 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
- 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xEC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xFE,0x9F}
-
-#elif _CODE_PAGE == 1 /* ASCII (for only non-LFN cfg) */
+#define _DF1S 0
+#define _EXCVT \
+ { \
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, \
+ 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, \
+ 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0xAC, 0x9D, 0x9E, 0x9F, 0xA0, \
+ 0x21, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, \
+ 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, \
+ 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, \
+ 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, \
+ 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, \
+ 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xC0, 0xC1, 0xC2, \
+ 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xEC, 0xCD, \
+ 0xCE, 0xCF, 0xD0, 0xD1, 0xF2, 0xD3, 0xD4, 0xD5, 0xD6, 0xF7, 0xD8, \
+ 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xFE, 0x9F \
+ }
+
+#elif _CODE_PAGE == 1 /* ASCII (for only non-LFN cfg) */
#if _USE_LFN
#error Cannot use LFN feature without valid code page.
#endif
-#define _DF1S 0
+#define _DF1S 0
#else
#error Unknown code page
#endif
-
/* Character code support macros */
-#define IsUpper(c) (((c)>='A')&&((c)<='Z'))
-#define IsLower(c) (((c)>='a')&&((c)<='z'))
-#define IsDigit(c) (((c)>='0')&&((c)<='9'))
+#define IsUpper(c) (((c) >= 'A') && ((c) <= 'Z'))
+#define IsLower(c) (((c) >= 'a') && ((c) <= 'z'))
+#define IsDigit(c) (((c) >= '0') && ((c) <= '9'))
-#if _DF1S /* Code page is DBCS */
+#if _DF1S /* Code page is DBCS */
-#ifdef _DF2S /* Two 1st byte areas */
-#define IsDBCS1(c) (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E))
-#else /* One 1st byte area */
-#define IsDBCS1(c) ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E)
+#ifdef _DF2S /* Two 1st byte areas */
+#define IsDBCS1(c) \
+ (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || \
+ ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E))
+#else /* One 1st byte area */
+#define IsDBCS1(c) ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E)
#endif
-#ifdef _DS3S /* Three 2nd byte areas */
-#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E))
-#else /* Two 2nd byte areas */
-#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E))
+#ifdef _DS3S /* Three 2nd byte areas */
+#define IsDBCS2(c) \
+ (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || \
+ ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || \
+ ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E))
+#else /* Two 2nd byte areas */
+#define IsDBCS2(c) \
+ (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || \
+ ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E))
#endif
-#else /* Code page is SBCS */
+#else /* Code page is SBCS */
-#define IsDBCS1(c) 0
-#define IsDBCS2(c) 0
+#define IsDBCS1(c) 0
+#define IsDBCS2(c) 0
#endif /* _DF1S */
-
/* Name status flags */
-#define NSFLAG 11 /* Index of name status byte in fn[] */
-#define NS_LOSS 0x01 /* Out of 8.3 format */
-#define NS_LFN 0x02 /* Force to create LFN entry */
-#define NS_LAST 0x04 /* Last segment */
-#define NS_BODY 0x08 /* Lower case flag (body) */
-#define NS_EXT 0x10 /* Lower case flag (ext) */
-#define NS_DOT 0x20 /* Dot entry */
-
-
-/* FAT sub-type boundaries (Differ from specs but correct for real DOS/Windows) */
-#define MIN_FAT16 4086U /* Minimum number of clusters as FAT16 */
-#define MIN_FAT32 65526U /* Minimum number of clusters as FAT32 */
-
+#define NSFLAG 11 /* Index of name status byte in fn[] */
+#define NS_LOSS 0x01 /* Out of 8.3 format */
+#define NS_LFN 0x02 /* Force to create LFN entry */
+#define NS_LAST 0x04 /* Last segment */
+#define NS_BODY 0x08 /* Lower case flag (body) */
+#define NS_EXT 0x10 /* Lower case flag (ext) */
+#define NS_DOT 0x20 /* Dot entry */
+
+/* FAT sub-type boundaries (Differ from specs but correct for real DOS/Windows)
+ */
+#define MIN_FAT16 4086U /* Minimum number of clusters as FAT16 */
+#define MIN_FAT32 65526U /* Minimum number of clusters as FAT32 */
/* FatFs refers the members in the FAT structures as byte array instead of
/ structure member because the structure is not binary compatible between
/ different platforms */
-#define BS_jmpBoot 0 /* x86 jump instruction (3) */
-#define BS_OEMName 3 /* OEM name (8) */
-#define BPB_BytsPerSec 11 /* Sector size [byte] (2) */
-#define BPB_SecPerClus 13 /* Cluster size [sector] (1) */
-#define BPB_RsvdSecCnt 14 /* Size of reserved area [sector] (2) */
-#define BPB_NumFATs 16 /* Number of FAT copies (1) */
-#define BPB_RootEntCnt 17 /* Number of root directory entries for FAT12/16 (2) */
-#define BPB_TotSec16 19 /* Volume size [sector] (2) */
-#define BPB_Media 21 /* Media descriptor (1) */
-#define BPB_FATSz16 22 /* FAT size [sector] (2) */
-#define BPB_SecPerTrk 24 /* Track size [sector] (2) */
-#define BPB_NumHeads 26 /* Number of heads (2) */
-#define BPB_HiddSec 28 /* Number of special hidden sectors (4) */
-#define BPB_TotSec32 32 /* Volume size [sector] (4) */
-#define BS_DrvNum 36 /* Physical drive number (2) */
-#define BS_BootSig 38 /* Extended boot signature (1) */
-#define BS_VolID 39 /* Volume serial number (4) */
-#define BS_VolLab 43 /* Volume label (8) */
-#define BS_FilSysType 54 /* File system type (1) */
-#define BPB_FATSz32 36 /* FAT size [sector] (4) */
-#define BPB_ExtFlags 40 /* Extended flags (2) */
-#define BPB_FSVer 42 /* File system version (2) */
-#define BPB_RootClus 44 /* Root directory first cluster (4) */
-#define BPB_FSInfo 48 /* Offset of FSINFO sector (2) */
-#define BPB_BkBootSec 50 /* Offset of backup boot sector (2) */
-#define BS_DrvNum32 64 /* Physical drive number (2) */
-#define BS_BootSig32 66 /* Extended boot signature (1) */
-#define BS_VolID32 67 /* Volume serial number (4) */
-#define BS_VolLab32 71 /* Volume label (8) */
-#define BS_FilSysType32 82 /* File system type (1) */
-#define FSI_LeadSig 0 /* FSI: Leading signature (4) */
-#define FSI_StrucSig 484 /* FSI: Structure signature (4) */
-#define FSI_Free_Count 488 /* FSI: Number of free clusters (4) */
-#define FSI_Nxt_Free 492 /* FSI: Last allocated cluster (4) */
-#define MBR_Table 446 /* MBR: Partition table offset (2) */
-#define SZ_PTE 16 /* MBR: Size of a partition table entry */
-#define BS_55AA 510 /* Signature word (2) */
-
-#define DIR_Name 0 /* Short file name (11) */
-#define DIR_Attr 11 /* Attribute (1) */
-#define DIR_NTres 12 /* Lower case flag (1) */
-#define DIR_CrtTimeTenth 13 /* Created time sub-second (1) */
-#define DIR_CrtTime 14 /* Created time (2) */
-#define DIR_CrtDate 16 /* Created date (2) */
-#define DIR_LstAccDate 18 /* Last accessed date (2) */
-#define DIR_FstClusHI 20 /* Higher 16-bit of first cluster (2) */
-#define DIR_WrtTime 22 /* Modified time (2) */
-#define DIR_WrtDate 24 /* Modified date (2) */
-#define DIR_FstClusLO 26 /* Lower 16-bit of first cluster (2) */
-#define DIR_FileSize 28 /* File size (4) */
-#define LDIR_Ord 0 /* LFN entry order and LLE flag (1) */
-#define LDIR_Attr 11 /* LFN attribute (1) */
-#define LDIR_Type 12 /* LFN type (1) */
-#define LDIR_Chksum 13 /* Sum of corresponding SFN entry */
-#define LDIR_FstClusLO 26 /* Must be zero (0) */
-#define SZ_DIRE 32 /* Size of a directory entry */
-#define LLEF 0x40 /* Last long entry flag in LDIR_Ord */
-#define DDEM 0xE5 /* Deleted directory entry mark at DIR_Name[0] */
-#define RDDEM 0x05 /* Replacement of the character collides with DDEM */
-
-
-
+#define BS_jmpBoot 0 /* x86 jump instruction (3) */
+#define BS_OEMName 3 /* OEM name (8) */
+#define BPB_BytsPerSec 11 /* Sector size [byte] (2) */
+#define BPB_SecPerClus 13 /* Cluster size [sector] (1) */
+#define BPB_RsvdSecCnt 14 /* Size of reserved area [sector] (2) */
+#define BPB_NumFATs 16 /* Number of FAT copies (1) */
+#define BPB_RootEntCnt \
+ 17 /* Number of root directory entries for FAT12/16 (2) */
+#define BPB_TotSec16 19 /* Volume size [sector] (2) */
+#define BPB_Media 21 /* Media descriptor (1) */
+#define BPB_FATSz16 22 /* FAT size [sector] (2) */
+#define BPB_SecPerTrk 24 /* Track size [sector] (2) */
+#define BPB_NumHeads 26 /* Number of heads (2) */
+#define BPB_HiddSec 28 /* Number of special hidden sectors (4) */
+#define BPB_TotSec32 32 /* Volume size [sector] (4) */
+#define BS_DrvNum 36 /* Physical drive number (2) */
+#define BS_BootSig 38 /* Extended boot signature (1) */
+#define BS_VolID 39 /* Volume serial number (4) */
+#define BS_VolLab 43 /* Volume label (8) */
+#define BS_FilSysType 54 /* File system type (1) */
+#define BPB_FATSz32 36 /* FAT size [sector] (4) */
+#define BPB_ExtFlags 40 /* Extended flags (2) */
+#define BPB_FSVer 42 /* File system version (2) */
+#define BPB_RootClus 44 /* Root directory first cluster (4) */
+#define BPB_FSInfo 48 /* Offset of FSINFO sector (2) */
+#define BPB_BkBootSec 50 /* Offset of backup boot sector (2) */
+#define BS_DrvNum32 64 /* Physical drive number (2) */
+#define BS_BootSig32 66 /* Extended boot signature (1) */
+#define BS_VolID32 67 /* Volume serial number (4) */
+#define BS_VolLab32 71 /* Volume label (8) */
+#define BS_FilSysType32 82 /* File system type (1) */
+#define FSI_LeadSig 0 /* FSI: Leading signature (4) */
+#define FSI_StrucSig 484 /* FSI: Structure signature (4) */
+#define FSI_Free_Count 488 /* FSI: Number of free clusters (4) */
+#define FSI_Nxt_Free 492 /* FSI: Last allocated cluster (4) */
+#define MBR_Table 446 /* MBR: Partition table offset (2) */
+#define SZ_PTE 16 /* MBR: Size of a partition table entry */
+#define BS_55AA 510 /* Signature word (2) */
+
+#define DIR_Name 0 /* Short file name (11) */
+#define DIR_Attr 11 /* Attribute (1) */
+#define DIR_NTres 12 /* Lower case flag (1) */
+#define DIR_CrtTimeTenth 13 /* Created time sub-second (1) */
+#define DIR_CrtTime 14 /* Created time (2) */
+#define DIR_CrtDate 16 /* Created date (2) */
+#define DIR_LstAccDate 18 /* Last accessed date (2) */
+#define DIR_FstClusHI 20 /* Higher 16-bit of first cluster (2) */
+#define DIR_WrtTime 22 /* Modified time (2) */
+#define DIR_WrtDate 24 /* Modified date (2) */
+#define DIR_FstClusLO 26 /* Lower 16-bit of first cluster (2) */
+#define DIR_FileSize 28 /* File size (4) */
+#define LDIR_Ord 0 /* LFN entry order and LLE flag (1) */
+#define LDIR_Attr 11 /* LFN attribute (1) */
+#define LDIR_Type 12 /* LFN type (1) */
+#define LDIR_Chksum 13 /* Sum of corresponding SFN entry */
+#define LDIR_FstClusLO 26 /* Must be zero (0) */
+#define SZ_DIRE 32 /* Size of a directory entry */
+#define LLEF 0x40 /* Last long entry flag in LDIR_Ord */
+#define DDEM 0xE5 /* Deleted directory entry mark at DIR_Name[0] */
+#define RDDEM 0x05 /* Replacement of the character collides with DDEM */
/*------------------------------------------------------------*/
/* Module private work area */
#if _VOLUMES < 1 || _VOLUMES > 9
#error Wrong _VOLUMES setting
#endif
-static FATFS *FatFs[_VOLUMES]; /* Pointer to the file system objects (logical drives) */
-static WORD Fsid; /* File system mount ID */
+static FATFS*
+ FatFs[_VOLUMES]; /* Pointer to the file system objects (logical drives) */
+static WORD Fsid; /* File system mount ID */
#if _FS_RPATH && _VOLUMES >= 2
-static BYTE CurrVol; /* Current drive */
+static BYTE CurrVol; /* Current drive */
#endif
#if _FS_LOCK
-static FILESEM Files[_FS_LOCK]; /* Open object lock semaphores */
+static FILESEM Files[_FS_LOCK]; /* Open object lock semaphores */
#endif
-#if _USE_LFN == 0 /* Non LFN feature */
-#define DEFINE_NAMEBUF BYTE sfn[12]
-#define INIT_BUF(dobj) (dobj).fn = sfn
-#define FREE_BUF()
+#if _USE_LFN == 0 /* Non LFN feature */
+#define DEFINE_NAMEBUF BYTE sfn[12]
+#define INIT_BUF(dobj) (dobj).fn = sfn
+#define FREE_BUF()
#else
#if _MAX_LFN < 12 || _MAX_LFN > 255
#error Wrong _MAX_LFN setting
#endif
-#if _USE_LFN == 1 /* LFN feature with static working buffer */
+#if _USE_LFN == 1 /* LFN feature with static working buffer */
static WCHAR LfnBuf[_MAX_LFN + 1];
-#define DEFINE_NAMEBUF BYTE sfn[12]
-#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = LfnBuf; }
-#define FREE_BUF()
-#elif _USE_LFN == 2 /* LFN feature with dynamic working buffer on the stack */
-#define DEFINE_NAMEBUF BYTE sfn[12]; WCHAR lbuf[_MAX_LFN + 1]
-#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = lbuf; }
-#define FREE_BUF()
-#elif _USE_LFN == 3 /* LFN feature with dynamic working buffer on the heap */
-#define DEFINE_NAMEBUF BYTE sfn[12]; WCHAR *lfn
-#define INIT_BUF(dobj) { lfn = ff_memalloc((_MAX_LFN + 1) * 2); if (!lfn) LEAVE_FF((dobj).fs, FR_NOT_ENOUGH_CORE); (dobj).lfn = lfn; (dobj).fn = sfn; }
-#define FREE_BUF() ff_memfree(lfn)
+#define DEFINE_NAMEBUF BYTE sfn[12]
+#define INIT_BUF(dobj) \
+ { \
+ (dobj).fn = sfn; \
+ (dobj).lfn = LfnBuf; \
+ }
+#define FREE_BUF()
+#elif _USE_LFN == 2 /* LFN feature with dynamic working buffer on the stack */
+#define DEFINE_NAMEBUF \
+ BYTE sfn[12]; \
+ WCHAR lbuf[_MAX_LFN + 1]
+#define INIT_BUF(dobj) \
+ { \
+ (dobj).fn = sfn; \
+ (dobj).lfn = lbuf; \
+ }
+#define FREE_BUF()
+#elif _USE_LFN == 3 /* LFN feature with dynamic working buffer on the heap */
+#define DEFINE_NAMEBUF \
+ BYTE sfn[12]; \
+ WCHAR* lfn
+#define INIT_BUF(dobj) \
+ { \
+ lfn = ff_memalloc((_MAX_LFN + 1) * 2); \
+ if (!lfn) \
+ LEAVE_FF((dobj).fs, FR_NOT_ENOUGH_CORE); \
+ (dobj).lfn = lfn; \
+ (dobj).fn = sfn; \
+ }
+#define FREE_BUF() ff_memfree(lfn)
#else
#error Wrong _USE_LFN setting
#endif
#endif
#ifdef _EXCVT
-static const BYTE ExCvt[] = _EXCVT; /* Upper conversion table for extended characters */
+static const BYTE ExCvt[] =
+ _EXCVT; /* Upper conversion table for extended characters */
#endif
-
-
-
-
-
/*--------------------------------------------------------------------------
Module Private Functions
---------------------------------------------------------------------------*/
-
/*-----------------------------------------------------------------------*/
/* String functions */
/*-----------------------------------------------------------------------*/
/* Copy memory to memory */
-static
-void mem_cpy (void* dst, const void* src, UINT cnt) {
- BYTE *d = (BYTE*)dst;
- const BYTE *s = (const BYTE*)src;
+static void
+mem_cpy(void* dst, const void* src, UINT cnt)
+{
+ BYTE* d = (BYTE*)dst;
+ const BYTE* s = (const BYTE*)src;
#if _WORD_ACCESS == 1
- while (cnt >= sizeof (int)) {
- *(int*)d = *(int*)s;
- d += sizeof (int); s += sizeof (int);
- cnt -= sizeof (int);
- }
-#endif
- while (cnt--)
- *d++ = *s++;
+ while (cnt >= sizeof(int)) {
+ *(int*)d = *(int*)s;
+ d += sizeof(int);
+ s += sizeof(int);
+ cnt -= sizeof(int);
+ }
+#endif
+ while (cnt--)
+ *d++ = *s++;
}
/* Fill memory */
-static
-void mem_set (void* dst, int val, UINT cnt) {
- BYTE *d = (BYTE*)dst;
+static void
+mem_set(void* dst, int val, UINT cnt)
+{
+ BYTE* d = (BYTE*)dst;
- while (cnt--)
- *d++ = (BYTE)val;
+ while (cnt--)
+ *d++ = (BYTE)val;
}
/* Compare memory to memory */
-static
-int mem_cmp (const void* dst, const void* src, UINT cnt) {
- const BYTE *d = (const BYTE *)dst, *s = (const BYTE *)src;
- int r = 0;
+static int
+mem_cmp(const void* dst, const void* src, UINT cnt)
+{
+ const BYTE *d = (const BYTE *)dst, *s = (const BYTE *)src;
+ int r = 0;
- while (cnt-- && (r = *d++ - *s++) == 0) ;
- return r;
+ while (cnt-- && (r = *d++ - *s++) == 0)
+ ;
+ return r;
}
/* Check if chr is contained in the string */
-static
-int chk_chr (const char* str, int chr) {
- while (*str && *str != chr) str++;
- return *str;
+static int
+chk_chr(const char* str, int chr)
+{
+ while (*str && *str != chr)
+ str++;
+ return *str;
}
-
-
-
/*-----------------------------------------------------------------------*/
/* Request/Release grant to access the volume */
/*-----------------------------------------------------------------------*/
#if _FS_REENTRANT
-static
-int lock_fs (
- FATFS* fs /* File system object */
-)
+static int
+lock_fs(FATFS* fs /* File system object */
+ )
{
- return ff_req_grant(fs->sobj);
+ return ff_req_grant(fs->sobj);
}
-
-static
-void unlock_fs (
- FATFS* fs, /* File system object */
- FRESULT res /* Result code to be returned */
-)
+static void
+unlock_fs(FATFS* fs, /* File system object */
+ FRESULT res /* Result code to be returned */
+ )
{
- if (fs &&
- res != FR_NOT_ENABLED &&
- res != FR_INVALID_DRIVE &&
- res != FR_INVALID_OBJECT &&
- res != FR_TIMEOUT) {
- ff_rel_grant(fs->sobj);
- }
+ if (fs && res != FR_NOT_ENABLED && res != FR_INVALID_DRIVE &&
+ res != FR_INVALID_OBJECT && res != FR_TIMEOUT) {
+ ff_rel_grant(fs->sobj);
+ }
}
#endif
-
-
-
/*-----------------------------------------------------------------------*/
/* File lock control functions */
/*-----------------------------------------------------------------------*/
#if _FS_LOCK
-static
-FRESULT chk_lock ( /* Check if the file can be accessed */
- DIR* dp, /* Directory object pointing the file to be checked */
- int acc /* Desired access type (0:Read, 1:Write, 2:Delete/Rename) */
-)
+static FRESULT
+chk_lock( /* Check if the file can be accessed */
+ DIR* dp, /* Directory object pointing the file to be checked */
+ int acc /* Desired access type (0:Read, 1:Write, 2:Delete/Rename) */
+ )
{
- UINT i, be;
-
- /* Search file semaphore table */
- for (i = be = 0; i < _FS_LOCK; i++) {
- if (Files[i].fs) { /* Existing entry */
- if (Files[i].fs == dp->fs && /* Check if the object matched with an open object */
- Files[i].clu == dp->sclust &&
- Files[i].idx == dp->index) break;
- } else { /* Blank entry */
- be = 1;
- }
- }
- if (i == _FS_LOCK) /* The object is not opened */
- return (be || acc == 2) ? FR_OK : FR_TOO_MANY_OPEN_FILES; /* Is there a blank entry for new object? */
-
- /* The object has been opened. Reject any open against writing file and all write mode open */
- return (acc || Files[i].ctr == 0x100) ? FR_LOCKED : FR_OK;
+ UINT i, be;
+
+ /* Search file semaphore table */
+ for (i = be = 0; i < _FS_LOCK; i++) {
+ if (Files[i].fs) { /* Existing entry */
+ if (Files[i].fs ==
+ dp
+ ->fs && /* Check if the object matched with an open
+ object */
+ Files[i].clu == dp->sclust &&
+ Files[i].idx == dp->index)
+ break;
+ } else { /* Blank entry */
+ be = 1;
+ }
+ }
+ if (i == _FS_LOCK) /* The object is not opened */
+ return (be || acc == 2) ? FR_OK
+ : FR_TOO_MANY_OPEN_FILES; /* Is there a blank
+ entry for new
+ object? */
+
+ /* The object has been opened. Reject any open against writing file and all
+ * write mode open */
+ return (acc || Files[i].ctr == 0x100) ? FR_LOCKED : FR_OK;
}
-
-static
-int enq_lock (void) /* Check if an entry is available for a new object */
+static int enq_lock(void) /* Check if an entry is available for a new object */
{
- UINT i;
+ UINT i;
- for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ;
- return (i == _FS_LOCK) ? 0 : 1;
+ for (i = 0; i < _FS_LOCK && Files[i].fs; i++)
+ ;
+ return (i == _FS_LOCK) ? 0 : 1;
}
-
-static
-UINT inc_lock ( /* Increment object open counter and returns its index (0:Internal error) */
- DIR* dp, /* Directory object pointing the file to register or increment */
- int acc /* Desired access (0:Read, 1:Write, 2:Delete/Rename) */
-)
+static UINT
+inc_lock(/* Increment object open counter and returns its index (0:Internal
+ error) */
+ DIR*
+ dp, /* Directory object pointing the file to register or increment
+ */
+ int acc /* Desired access (0:Read, 1:Write, 2:Delete/Rename) */
+ )
{
- UINT i;
-
-
- for (i = 0; i < _FS_LOCK; i++) { /* Find the object */
- if (Files[i].fs == dp->fs &&
- Files[i].clu == dp->sclust &&
- Files[i].idx == dp->index) break;
- }
-
- if (i == _FS_LOCK) { /* Not opened. Register it as new. */
- for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ;
- if (i == _FS_LOCK) return 0; /* No free entry to register (int err) */
- Files[i].fs = dp->fs;
- Files[i].clu = dp->sclust;
- Files[i].idx = dp->index;
- Files[i].ctr = 0;
- }
-
- if (acc && Files[i].ctr) return 0; /* Access violation (int err) */
-
- Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1; /* Set semaphore value */
-
- return i + 1;
+ UINT i;
+
+ for (i = 0; i < _FS_LOCK; i++) { /* Find the object */
+ if (Files[i].fs == dp->fs && Files[i].clu == dp->sclust &&
+ Files[i].idx == dp->index)
+ break;
+ }
+
+ if (i == _FS_LOCK) { /* Not opened. Register it as new. */
+ for (i = 0; i < _FS_LOCK && Files[i].fs; i++)
+ ;
+ if (i == _FS_LOCK)
+ return 0; /* No free entry to register (int err) */
+ Files[i].fs = dp->fs;
+ Files[i].clu = dp->sclust;
+ Files[i].idx = dp->index;
+ Files[i].ctr = 0;
+ }
+
+ if (acc && Files[i].ctr)
+ return 0; /* Access violation (int err) */
+
+ Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1; /* Set semaphore value */
+
+ return i + 1;
}
-
-static
-FRESULT dec_lock ( /* Decrement object open counter */
- UINT i /* Semaphore index (1..) */
-)
+static FRESULT
+dec_lock( /* Decrement object open counter */
+ UINT i /* Semaphore index (1..) */
+ )
{
- WORD n;
- FRESULT res;
-
-
- if (--i < _FS_LOCK) { /* Shift index number origin from 0 */
- n = Files[i].ctr;
- if (n == 0x100) n = 0; /* If write mode open, delete the entry */
- if (n) n--; /* Decrement read mode open count */
- Files[i].ctr = n;
- if (!n) Files[i].fs = 0; /* Delete the entry if open count gets zero */
- res = FR_OK;
- } else {
- res = FR_INT_ERR; /* Invalid index nunber */
- }
- return res;
+ WORD n;
+ FRESULT res;
+
+ if (--i < _FS_LOCK) { /* Shift index number origin from 0 */
+ n = Files[i].ctr;
+ if (n == 0x100)
+ n = 0; /* If write mode open, delete the entry */
+ if (n)
+ n--; /* Decrement read mode open count */
+ Files[i].ctr = n;
+ if (!n)
+ Files[i].fs = 0; /* Delete the entry if open count gets zero */
+ res = FR_OK;
+ } else {
+ res = FR_INT_ERR; /* Invalid index nunber */
+ }
+ return res;
}
-
-static
-void clear_lock ( /* Clear lock entries of the volume */
- FATFS *fs
-)
+static void
+clear_lock(/* Clear lock entries of the volume */
+ FATFS* fs)
{
- UINT i;
+ UINT i;
- for (i = 0; i < _FS_LOCK; i++) {
- if (Files[i].fs == fs) Files[i].fs = 0;
- }
+ for (i = 0; i < _FS_LOCK; i++) {
+ if (Files[i].fs == fs)
+ Files[i].fs = 0;
+ }
}
#endif
-
-
-
/*-----------------------------------------------------------------------*/
/* Move/Flush disk access window in the file system object */
/*-----------------------------------------------------------------------*/
#if !_FS_READONLY
-static
-FRESULT sync_window (
- FATFS* fs /* File system object */
-)
+static FRESULT
+sync_window(FATFS* fs /* File system object */
+ )
{
- DWORD wsect;
- UINT nf;
- FRESULT res = FR_OK;
-
-
- if (fs->wflag) { /* Write back the sector if it is dirty */
- wsect = fs->winsect; /* Current sector number */
- if (disk_write(fs->drv, fs->win, wsect, 1) != RES_OK) {
- res = FR_DISK_ERR;
- } else {
- fs->wflag = 0;
- if (wsect - fs->fatbase < fs->fsize) { /* Is it in the FAT area? */
- for (nf = fs->n_fats; nf >= 2; nf--) { /* Reflect the change to all FAT copies */
- wsect += fs->fsize;
- disk_write(fs->drv, fs->win, wsect, 1);
- }
- }
- }
- }
- return res;
+ DWORD wsect;
+ UINT nf;
+ FRESULT res = FR_OK;
+
+ if (fs->wflag) { /* Write back the sector if it is dirty */
+ wsect = fs->winsect; /* Current sector number */
+ if (disk_write(fs->drv, fs->win, wsect, 1) != RES_OK) {
+ res = FR_DISK_ERR;
+ } else {
+ fs->wflag = 0;
+ if (wsect - fs->fatbase < fs->fsize) { /* Is it in the FAT area? */
+ for (nf = fs->n_fats; nf >= 2;
+ nf--) { /* Reflect the change to all FAT copies */
+ wsect += fs->fsize;
+ disk_write(fs->drv, fs->win, wsect, 1);
+ }
+ }
+ }
+ }
+ return res;
}
#endif
-
-static
-FRESULT move_window (
- FATFS* fs, /* File system object */
- DWORD sector /* Sector number to make appearance in the fs->win[] */
-)
+static FRESULT
+move_window(FATFS* fs, /* File system object */
+ DWORD sector /* Sector number to make appearance in the fs->win[] */
+ )
{
- FRESULT res = FR_OK;
+ FRESULT res = FR_OK;
-
- if (sector != fs->winsect) { /* Window offset changed? */
+ if (sector != fs->winsect) { /* Window offset changed? */
#if !_FS_READONLY
- res = sync_window(fs); /* Write-back changes */
-#endif
- if (res == FR_OK) { /* Fill sector window with new data */
- if (disk_read(fs->drv, fs->win, sector, 1) != RES_OK) {
- sector = 0xFFFFFFFF; /* Invalidate window if data is not reliable */
- res = FR_DISK_ERR;
- }
- fs->winsect = sector;
- }
- }
- return res;
+ res = sync_window(fs); /* Write-back changes */
+#endif
+ if (res == FR_OK) { /* Fill sector window with new data */
+ if (disk_read(fs->drv, fs->win, sector, 1) != RES_OK) {
+ sector =
+ 0xFFFFFFFF; /* Invalidate window if data is not reliable */
+ res = FR_DISK_ERR;
+ }
+ fs->winsect = sector;
+ }
+ }
+ return res;
}
-
-
-
/*-----------------------------------------------------------------------*/
/* Synchronize file system and strage device */
/*-----------------------------------------------------------------------*/
#if !_FS_READONLY
-static
-FRESULT sync_fs ( /* FR_OK: successful, FR_DISK_ERR: failed */
- FATFS* fs /* File system object */
-)
+static FRESULT
+sync_fs( /* FR_OK: successful, FR_DISK_ERR: failed */
+ FATFS* fs /* File system object */
+ )
{
- FRESULT res;
-
-
- res = sync_window(fs);
- if (res == FR_OK) {
- /* Update FSINFO sector if needed */
- if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) {
- /* Create FSINFO structure */
- mem_set(fs->win, 0, SS(fs));
- ST_WORD(fs->win + BS_55AA, 0xAA55);
- ST_DWORD(fs->win + FSI_LeadSig, 0x41615252);
- ST_DWORD(fs->win + FSI_StrucSig, 0x61417272);
- ST_DWORD(fs->win + FSI_Free_Count, fs->free_clust);
- ST_DWORD(fs->win + FSI_Nxt_Free, fs->last_clust);
- /* Write it into the FSINFO sector */
- fs->winsect = fs->volbase + 1;
- disk_write(fs->drv, fs->win, fs->winsect, 1);
- fs->fsi_flag = 0;
- }
- /* Make sure that no pending write process in the physical drive */
- if (disk_ioctl(fs->drv, CTRL_SYNC, 0) != RES_OK)
- res = FR_DISK_ERR;
- }
-
- return res;
+ FRESULT res;
+
+ res = sync_window(fs);
+ if (res == FR_OK) {
+ /* Update FSINFO sector if needed */
+ if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) {
+ /* Create FSINFO structure */
+ mem_set(fs->win, 0, SS(fs));
+ ST_WORD(fs->win + BS_55AA, 0xAA55);
+ ST_DWORD(fs->win + FSI_LeadSig, 0x41615252);
+ ST_DWORD(fs->win + FSI_StrucSig, 0x61417272);
+ ST_DWORD(fs->win + FSI_Free_Count, fs->free_clust);
+ ST_DWORD(fs->win + FSI_Nxt_Free, fs->last_clust);
+ /* Write it into the FSINFO sector */
+ fs->winsect = fs->volbase + 1;
+ disk_write(fs->drv, fs->win, fs->winsect, 1);
+ fs->fsi_flag = 0;
+ }
+ /* Make sure that no pending write process in the physical drive */
+ if (disk_ioctl(fs->drv, CTRL_SYNC, 0) != RES_OK)
+ res = FR_DISK_ERR;
+ }
+
+ return res;
}
#endif
-
-
-
/*-----------------------------------------------------------------------*/
/* Get sector# from cluster# */
/*-----------------------------------------------------------------------*/
/* Hidden API for hacks and disk tools */
-DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */
- FATFS* fs, /* File system object */
- DWORD clst /* Cluster# to be converted */
-)
+DWORD
+clust2sect( /* !=0: Sector number, 0: Failed - invalid cluster# */
+ FATFS* fs, /* File system object */
+ DWORD clst /* Cluster# to be converted */
+ )
{
- clst -= 2;
- if (clst >= fs->n_fatent - 2) return 0; /* Invalid cluster# */
- return clst * fs->csize + fs->database;
+ clst -= 2;
+ if (clst >= fs->n_fatent - 2)
+ return 0; /* Invalid cluster# */
+ return clst * fs->csize + fs->database;
}
-
-
-
/*-----------------------------------------------------------------------*/
/* FAT access - Read value of a FAT entry */
/*-----------------------------------------------------------------------*/
/* Hidden API for hacks and disk tools */
-DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x0FFFFFFF:Cluster status */
- FATFS* fs, /* File system object */
- DWORD clst /* FAT index number (cluster number) to get the value */
-)
+DWORD
+get_fat(/* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x0FFFFFFF:Cluster status
+ */
+ FATFS* fs, /* File system object */
+ DWORD clst /* FAT index number (cluster number) to get the value */
+ )
{
- UINT wc, bc;
- BYTE *p;
- DWORD val;
-
-
- if (clst < 2 || clst >= fs->n_fatent) { /* Check range */
- val = 1; /* Internal error */
-
- } else {
- val = 0xFFFFFFFF; /* Default value falls on disk error */
-
- switch (fs->fs_type) {
- case FS_FAT12 :
- bc = (UINT)clst; bc += bc / 2;
- if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break;
- wc = fs->win[bc++ % SS(fs)];
- if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break;
- wc |= fs->win[bc % SS(fs)] << 8;
- val = clst & 1 ? wc >> 4 : (wc & 0xFFF);
- break;
-
- case FS_FAT16 :
- if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))) != FR_OK) break;
- p = &fs->win[clst * 2 % SS(fs)];
- val = LD_WORD(p);
- break;
-
- case FS_FAT32 :
- if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break;
- p = &fs->win[clst * 4 % SS(fs)];
- val = LD_DWORD(p) & 0x0FFFFFFF;
- break;
-
- default:
- val = 1; /* Internal error */
- }
- }
-
- return val;
+ UINT wc, bc;
+ BYTE* p;
+ DWORD val;
+
+ if (clst < 2 || clst >= fs->n_fatent) { /* Check range */
+ val = 1; /* Internal error */
+
+ } else {
+ val = 0xFFFFFFFF; /* Default value falls on disk error */
+
+ switch (fs->fs_type) {
+ case FS_FAT12:
+ bc = (UINT)clst;
+ bc += bc / 2;
+ if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK)
+ break;
+ wc = fs->win[bc++ % SS(fs)];
+ if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK)
+ break;
+ wc |= fs->win[bc % SS(fs)] << 8;
+ val = clst & 1 ? wc >> 4 : (wc & 0xFFF);
+ break;
+
+ case FS_FAT16:
+ if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))) !=
+ FR_OK)
+ break;
+ p = &fs->win[clst * 2 % SS(fs)];
+ val = LD_WORD(p);
+ break;
+
+ case FS_FAT32:
+ if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) !=
+ FR_OK)
+ break;
+ p = &fs->win[clst * 4 % SS(fs)];
+ val = LD_DWORD(p) & 0x0FFFFFFF;
+ break;
+
+ default:
+ val = 1; /* Internal error */
+ }
+ }
+
+ return val;
}
-
-
-
/*-----------------------------------------------------------------------*/
/* FAT access - Change value of a FAT entry */
/*-----------------------------------------------------------------------*/
/* Hidden API for hacks and disk tools */
#if !_FS_READONLY
-FRESULT put_fat (
- FATFS* fs, /* File system object */
- DWORD clst, /* FAT index number (cluster number) to be changed */
- DWORD val /* New value to be set to the entry */
-)
+FRESULT
+put_fat(FATFS* fs, /* File system object */
+ DWORD clst, /* FAT index number (cluster number) to be changed */
+ DWORD val /* New value to be set to the entry */
+ )
{
- UINT bc;
- BYTE *p;
- FRESULT res;
-
-
- if (clst < 2 || clst >= fs->n_fatent) { /* Check range */
- res = FR_INT_ERR;
-
- } else {
- switch (fs->fs_type) {
- case FS_FAT12 :
- bc = (UINT)clst; bc += bc / 2;
- res = move_window(fs, fs->fatbase + (bc / SS(fs)));
- if (res != FR_OK) break;
- p = &fs->win[bc++ % SS(fs)];
- *p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val;
- fs->wflag = 1;
- res = move_window(fs, fs->fatbase + (bc / SS(fs)));
- if (res != FR_OK) break;
- p = &fs->win[bc % SS(fs)];
- *p = (clst & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F));
- fs->wflag = 1;
- break;
-
- case FS_FAT16 :
- res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2)));
- if (res != FR_OK) break;
- p = &fs->win[clst * 2 % SS(fs)];
- ST_WORD(p, (WORD)val);
- fs->wflag = 1;
- break;
-
- case FS_FAT32 :
- res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4)));
- if (res != FR_OK) break;
- p = &fs->win[clst * 4 % SS(fs)];
- val |= LD_DWORD(p) & 0xF0000000;
- ST_DWORD(p, val);
- fs->wflag = 1;
- break;
-
- default :
- res = FR_INT_ERR;
- }
- }
-
- return res;
+ UINT bc;
+ BYTE* p;
+ FRESULT res;
+
+ if (clst < 2 || clst >= fs->n_fatent) { /* Check range */
+ res = FR_INT_ERR;
+
+ } else {
+ switch (fs->fs_type) {
+ case FS_FAT12:
+ bc = (UINT)clst;
+ bc += bc / 2;
+ res = move_window(fs, fs->fatbase + (bc / SS(fs)));
+ if (res != FR_OK)
+ break;
+ p = &fs->win[bc++ % SS(fs)];
+ *p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val;
+ fs->wflag = 1;
+ res = move_window(fs, fs->fatbase + (bc / SS(fs)));
+ if (res != FR_OK)
+ break;
+ p = &fs->win[bc % SS(fs)];
+ *p = (clst & 1) ? (BYTE)(val >> 4)
+ : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F));
+ fs->wflag = 1;
+ break;
+
+ case FS_FAT16:
+ res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2)));
+ if (res != FR_OK)
+ break;
+ p = &fs->win[clst * 2 % SS(fs)];
+ ST_WORD(p, (WORD)val);
+ fs->wflag = 1;
+ break;
+
+ case FS_FAT32:
+ res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4)));
+ if (res != FR_OK)
+ break;
+ p = &fs->win[clst * 4 % SS(fs)];
+ val |= LD_DWORD(p) & 0xF0000000;
+ ST_DWORD(p, val);
+ fs->wflag = 1;
+ break;
+
+ default:
+ res = FR_INT_ERR;
+ }
+ }
+
+ return res;
}
#endif /* !_FS_READONLY */
-
-
-
/*-----------------------------------------------------------------------*/
/* FAT handling - Remove a cluster chain */
/*-----------------------------------------------------------------------*/
#if !_FS_READONLY
-static
-FRESULT remove_chain (
- FATFS* fs, /* File system object */
- DWORD clst /* Cluster# to remove a chain from */
-)
+static FRESULT
+remove_chain(FATFS* fs, /* File system object */
+ DWORD clst /* Cluster# to remove a chain from */
+ )
{
- FRESULT res;
- DWORD nxt;
+ FRESULT res;
+ DWORD nxt;
#if _USE_TRIM
- DWORD scl = clst, ecl = clst, rt[2];
-#endif
-
- if (clst < 2 || clst >= fs->n_fatent) { /* Check range */
- res = FR_INT_ERR;
-
- } else {
- res = FR_OK;
- while (clst < fs->n_fatent) { /* Not a last link? */
- nxt = get_fat(fs, clst); /* Get cluster status */
- if (nxt == 0) break; /* Empty cluster? */
- if (nxt == 1) { res = FR_INT_ERR; break; } /* Internal error? */
- if (nxt == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } /* Disk error? */
- res = put_fat(fs, clst, 0); /* Mark the cluster "empty" */
- if (res != FR_OK) break;
- if (fs->free_clust != 0xFFFFFFFF) { /* Update FSINFO */
- fs->free_clust++;
- fs->fsi_flag |= 1;
- }
+ DWORD scl = clst, ecl = clst, rt[2];
+#endif
+
+ if (clst < 2 || clst >= fs->n_fatent) { /* Check range */
+ res = FR_INT_ERR;
+
+ } else {
+ res = FR_OK;
+ while (clst < fs->n_fatent) { /* Not a last link? */
+ nxt = get_fat(fs, clst); /* Get cluster status */
+ if (nxt == 0)
+ break; /* Empty cluster? */
+ if (nxt == 1) {
+ res = FR_INT_ERR;
+ break;
+ } /* Internal error? */
+ if (nxt == 0xFFFFFFFF) {
+ res = FR_DISK_ERR;
+ break;
+ } /* Disk error? */
+ res = put_fat(fs, clst, 0); /* Mark the cluster "empty" */
+ if (res != FR_OK)
+ break;
+ if (fs->free_clust != 0xFFFFFFFF) { /* Update FSINFO */
+ fs->free_clust++;
+ fs->fsi_flag |= 1;
+ }
#if _USE_TRIM
- if (ecl + 1 == nxt) { /* Is next cluster contiguous? */
- ecl = nxt;
- } else { /* End of contiguous clusters */
- rt[0] = clust2sect(fs, scl); /* Start sector */
- rt[1] = clust2sect(fs, ecl) + fs->csize - 1; /* End sector */
- disk_ioctl(fs->drv, CTRL_TRIM, rt); /* Erase the block */
- scl = ecl = nxt;
- }
-#endif
- clst = nxt; /* Next cluster */
- }
- }
-
- return res;
+ if (ecl + 1 == nxt) { /* Is next cluster contiguous? */
+ ecl = nxt;
+ } else { /* End of contiguous clusters */
+ rt[0] = clust2sect(fs, scl); /* Start sector */
+ rt[1] = clust2sect(fs, ecl) + fs->csize - 1; /* End sector */
+ disk_ioctl(fs->drv, CTRL_TRIM, rt); /* Erase the block */
+ scl = ecl = nxt;
+ }
+#endif
+ clst = nxt; /* Next cluster */
+ }
+ }
+
+ return res;
}
#endif
-
-
-
/*-----------------------------------------------------------------------*/
/* FAT handling - Stretch or Create a cluster chain */
/*-----------------------------------------------------------------------*/
#if !_FS_READONLY
-static
-DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */
- FATFS* fs, /* File system object */
- DWORD clst /* Cluster# to stretch. 0 means create a new chain. */
-)
+static DWORD
+create_chain(/* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error,
+ >=2:New cluster# */
+ FATFS* fs, /* File system object */
+ DWORD clst /* Cluster# to stretch. 0 means create a new chain. */
+ )
{
- DWORD cs, ncl, scl;
- FRESULT res;
-
-
- if (clst == 0) { /* Create a new chain */
- scl = fs->last_clust; /* Get suggested start point */
- if (!scl || scl >= fs->n_fatent) scl = 1;
- }
- else { /* Stretch the current chain */
- cs = get_fat(fs, clst); /* Check the cluster status */
- if (cs < 2) return 1; /* Invalid value */
- if (cs == 0xFFFFFFFF) return cs; /* A disk error occurred */
- if (cs < fs->n_fatent) return cs; /* It is already followed by next cluster */
- scl = clst;
- }
-
- ncl = scl; /* Start cluster */
- for (;;) {
- ncl++; /* Next cluster */
- if (ncl >= fs->n_fatent) { /* Check wrap around */
- ncl = 2;
- if (ncl > scl) return 0; /* No free cluster */
- }
- cs = get_fat(fs, ncl); /* Get the cluster status */
- if (cs == 0) break; /* Found a free cluster */
- if (cs == 0xFFFFFFFF || cs == 1)/* An error occurred */
- return cs;
- if (ncl == scl) return 0; /* No free cluster */
- }
-
- res = put_fat(fs, ncl, 0x0FFFFFFF); /* Mark the new cluster "last link" */
- if (res == FR_OK && clst != 0) {
- res = put_fat(fs, clst, ncl); /* Link it to the previous one if needed */
- }
- if (res == FR_OK) {
- fs->last_clust = ncl; /* Update FSINFO */
- if (fs->free_clust != 0xFFFFFFFF) {
- fs->free_clust--;
- fs->fsi_flag |= 1;
- }
- } else {
- ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1;
- }
-
- return ncl; /* Return new cluster number or error code */
+ DWORD cs, ncl, scl;
+ FRESULT res;
+
+ if (clst == 0) { /* Create a new chain */
+ scl = fs->last_clust; /* Get suggested start point */
+ if (!scl || scl >= fs->n_fatent)
+ scl = 1;
+ } else { /* Stretch the current chain */
+ cs = get_fat(fs, clst); /* Check the cluster status */
+ if (cs < 2)
+ return 1; /* Invalid value */
+ if (cs == 0xFFFFFFFF)
+ return cs; /* A disk error occurred */
+ if (cs < fs->n_fatent)
+ return cs; /* It is already followed by next cluster */
+ scl = clst;
+ }
+
+ ncl = scl; /* Start cluster */
+ for (;;) {
+ ncl++; /* Next cluster */
+ if (ncl >= fs->n_fatent) { /* Check wrap around */
+ ncl = 2;
+ if (ncl > scl)
+ return 0; /* No free cluster */
+ }
+ cs = get_fat(fs, ncl); /* Get the cluster status */
+ if (cs == 0)
+ break; /* Found a free cluster */
+ if (cs == 0xFFFFFFFF || cs == 1) /* An error occurred */
+ return cs;
+ if (ncl == scl)
+ return 0; /* No free cluster */
+ }
+
+ res = put_fat(fs, ncl, 0x0FFFFFFF); /* Mark the new cluster "last link" */
+ if (res == FR_OK && clst != 0) {
+ res =
+ put_fat(fs, clst, ncl); /* Link it to the previous one if needed */
+ }
+ if (res == FR_OK) {
+ fs->last_clust = ncl; /* Update FSINFO */
+ if (fs->free_clust != 0xFFFFFFFF) {
+ fs->free_clust--;
+ fs->fsi_flag |= 1;
+ }
+ } else {
+ ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1;
+ }
+
+ return ncl; /* Return new cluster number or error code */
}
#endif /* !_FS_READONLY */
-
-
-
/*-----------------------------------------------------------------------*/
/* FAT handling - Convert offset into cluster with link map table */
/*-----------------------------------------------------------------------*/
#if _USE_FASTSEEK
-static
-DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */
- FIL* fp, /* Pointer to the file object */
- DWORD ofs /* File offset to be converted to cluster# */
-)
+static DWORD
+clmt_clust( /* <2:Error, >=2:Cluster number */
+ FIL* fp, /* Pointer to the file object */
+ DWORD ofs /* File offset to be converted to cluster# */
+ )
{
- DWORD cl, ncl, *tbl;
-
-
- tbl = fp->cltbl + 1; /* Top of CLMT */
- cl = ofs / SS(fp->fs) / fp->fs->csize; /* Cluster order from top of the file */
- for (;;) {
- ncl = *tbl++; /* Number of cluters in the fragment */
- if (!ncl) return 0; /* End of table? (error) */
- if (cl < ncl) break; /* In this fragment? */
- cl -= ncl; tbl++; /* Next fragment */
- }
- return cl + *tbl; /* Return the cluster number */
+ DWORD cl, ncl, *tbl;
+
+ tbl = fp->cltbl + 1; /* Top of CLMT */
+ cl = ofs / SS(fp->fs) /
+ fp->fs->csize; /* Cluster order from top of the file */
+ for (;;) {
+ ncl = *tbl++; /* Number of cluters in the fragment */
+ if (!ncl)
+ return 0; /* End of table? (error) */
+ if (cl < ncl)
+ break; /* In this fragment? */
+ cl -= ncl;
+ tbl++; /* Next fragment */
+ }
+ return cl + *tbl; /* Return the cluster number */
}
-#endif /* _USE_FASTSEEK */
-
-
-
+#endif /* _USE_FASTSEEK */
/*-----------------------------------------------------------------------*/
/* Directory handling - Set directory index */
/*-----------------------------------------------------------------------*/
-static
-FRESULT dir_sdi (
- DIR* dp, /* Pointer to directory object */
- UINT idx /* Index of directory table */
-)
+static FRESULT
+dir_sdi(DIR* dp, /* Pointer to directory object */
+ UINT idx /* Index of directory table */
+ )
{
- DWORD clst, sect;
- UINT ic;
-
-
- dp->index = (WORD)idx; /* Current index */
- clst = dp->sclust; /* Table start cluster (0:root) */
- if (clst == 1 || clst >= dp->fs->n_fatent) /* Check start cluster range */
- return FR_INT_ERR;
- if (!clst && dp->fs->fs_type == FS_FAT32) /* Replace cluster# 0 with root cluster# if in FAT32 */
- clst = dp->fs->dirbase;
-
- if (clst == 0) { /* Static table (root-directory in FAT12/16) */
- if (idx >= dp->fs->n_rootdir) /* Is index out of range? */
- return FR_INT_ERR;
- sect = dp->fs->dirbase;
- }
- else { /* Dynamic table (root-directory in FAT32 or sub-directory) */
- ic = SS(dp->fs) / SZ_DIRE * dp->fs->csize; /* Entries per cluster */
- while (idx >= ic) { /* Follow cluster chain */
- clst = get_fat(dp->fs, clst); /* Get next cluster */
- if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */
- if (clst < 2 || clst >= dp->fs->n_fatent) /* Reached to end of table or internal error */
- return FR_INT_ERR;
- idx -= ic;
- }
- sect = clust2sect(dp->fs, clst);
- }
- dp->clust = clst; /* Current cluster# */
- if (!sect) return FR_INT_ERR;
- dp->sect = sect + idx / (SS(dp->fs) / SZ_DIRE); /* Sector# of the directory entry */
- dp->dir = dp->fs->win + (idx % (SS(dp->fs) / SZ_DIRE)) * SZ_DIRE; /* Ptr to the entry in the sector */
-
- return FR_OK;
+ DWORD clst, sect;
+ UINT ic;
+
+ dp->index = (WORD)idx; /* Current index */
+ clst = dp->sclust; /* Table start cluster (0:root) */
+ if (clst == 1 || clst >= dp->fs->n_fatent) /* Check start cluster range */
+ return FR_INT_ERR;
+ if (!clst &&
+ dp->fs->fs_type ==
+ FS_FAT32) /* Replace cluster# 0 with root cluster# if in FAT32 */
+ clst = dp->fs->dirbase;
+
+ if (clst == 0) { /* Static table (root-directory in FAT12/16) */
+ if (idx >= dp->fs->n_rootdir) /* Is index out of range? */
+ return FR_INT_ERR;
+ sect = dp->fs->dirbase;
+ } else { /* Dynamic table (root-directory in FAT32 or sub-directory) */
+ ic = SS(dp->fs) / SZ_DIRE * dp->fs->csize; /* Entries per cluster */
+ while (idx >= ic) { /* Follow cluster chain */
+ clst = get_fat(dp->fs, clst); /* Get next cluster */
+ if (clst == 0xFFFFFFFF)
+ return FR_DISK_ERR; /* Disk error */
+ if (clst < 2 ||
+ clst >=
+ dp->fs->n_fatent) /* Reached to end of table or internal
+ error */
+ return FR_INT_ERR;
+ idx -= ic;
+ }
+ sect = clust2sect(dp->fs, clst);
+ }
+ dp->clust = clst; /* Current cluster# */
+ if (!sect)
+ return FR_INT_ERR;
+ dp->sect =
+ sect +
+ idx / (SS(dp->fs) / SZ_DIRE); /* Sector# of the directory entry */
+ dp->dir = dp->fs->win +
+ (idx % (SS(dp->fs) / SZ_DIRE)) *
+ SZ_DIRE; /* Ptr to the entry in the sector */
+
+ return FR_OK;
}
-
-
-
/*-----------------------------------------------------------------------*/
/* Directory handling - Move directory table index next */
/*-----------------------------------------------------------------------*/
-static
-FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:Could not stretch */
- DIR* dp, /* Pointer to the directory object */
- int stretch /* 0: Do not stretch table, 1: Stretch table if needed */
-)
+static FRESULT
+dir_next(/* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:Could not
+ stretch */
+ DIR* dp, /* Pointer to the directory object */
+ int stretch /* 0: Do not stretch table, 1: Stretch table if needed */
+ )
{
- DWORD clst;
- UINT i;
+ DWORD clst;
+ UINT i;
#if !_FS_READONLY
- UINT c;
-#endif
-
-
- i = dp->index + 1;
- if (!(i & 0xFFFF) || !dp->sect) /* Report EOT when index has reached 65535 */
- return FR_NO_FILE;
-
- if (!(i % (SS(dp->fs) / SZ_DIRE))) { /* Sector changed? */
- dp->sect++; /* Next sector */
-
- if (!dp->clust) { /* Static table */
- if (i >= dp->fs->n_rootdir) /* Report EOT if it reached end of static table */
- return FR_NO_FILE;
- }
- else { /* Dynamic table */
- if (((i / (SS(dp->fs) / SZ_DIRE)) & (dp->fs->csize - 1)) == 0) { /* Cluster changed? */
- clst = get_fat(dp->fs, dp->clust); /* Get next cluster */
- if (clst <= 1) return FR_INT_ERR;
- if (clst == 0xFFFFFFFF) return FR_DISK_ERR;
- if (clst >= dp->fs->n_fatent) { /* If it reached end of dynamic table, */
+ UINT c;
+#endif
+
+ i = dp->index + 1;
+ if (!(i & 0xFFFF) ||
+ !dp->sect) /* Report EOT when index has reached 65535 */
+ return FR_NO_FILE;
+
+ if (!(i % (SS(dp->fs) / SZ_DIRE))) { /* Sector changed? */
+ dp->sect++; /* Next sector */
+
+ if (!dp->clust) { /* Static table */
+ if (i >= dp->fs->n_rootdir) /* Report EOT if it reached end of
+ static table */
+ return FR_NO_FILE;
+ } else { /* Dynamic table */
+ if (((i / (SS(dp->fs) / SZ_DIRE)) & (dp->fs->csize - 1)) ==
+ 0) { /* Cluster changed? */
+ clst = get_fat(dp->fs, dp->clust); /* Get next cluster */
+ if (clst <= 1)
+ return FR_INT_ERR;
+ if (clst == 0xFFFFFFFF)
+ return FR_DISK_ERR;
+ if (clst >=
+ dp->fs
+ ->n_fatent) { /* If it reached end of dynamic table, */
#if !_FS_READONLY
- if (!stretch) return FR_NO_FILE; /* If do not stretch, report EOT */
- clst = create_chain(dp->fs, dp->clust); /* Stretch cluster chain */
- if (clst == 0) return FR_DENIED; /* No free cluster */
- if (clst == 1) return FR_INT_ERR;
- if (clst == 0xFFFFFFFF) return FR_DISK_ERR;
- /* Clean-up stretched table */
- if (sync_window(dp->fs)) return FR_DISK_ERR;/* Flush disk access window */
- mem_set(dp->fs->win, 0, SS(dp->fs)); /* Clear window buffer */
- dp->fs->winsect = clust2sect(dp->fs, clst); /* Cluster start sector */
- for (c = 0; c < dp->fs->csize; c++) { /* Fill the new cluster with 0 */
- dp->fs->wflag = 1;
- if (sync_window(dp->fs)) return FR_DISK_ERR;
- dp->fs->winsect++;
- }
- dp->fs->winsect -= c; /* Rewind window offset */
+ if (!stretch)
+ return FR_NO_FILE; /* If do not stretch, report EOT */
+ clst = create_chain(dp->fs,
+ dp->clust); /* Stretch cluster chain */
+ if (clst == 0)
+ return FR_DENIED; /* No free cluster */
+ if (clst == 1)
+ return FR_INT_ERR;
+ if (clst == 0xFFFFFFFF)
+ return FR_DISK_ERR;
+ /* Clean-up stretched table */
+ if (sync_window(dp->fs))
+ return FR_DISK_ERR; /* Flush disk access window */
+ mem_set(dp->fs->win, 0,
+ SS(dp->fs)); /* Clear window buffer */
+ dp->fs->winsect =
+ clust2sect(dp->fs, clst); /* Cluster start sector */
+ for (c = 0; c < dp->fs->csize;
+ c++) { /* Fill the new cluster with 0 */
+ dp->fs->wflag = 1;
+ if (sync_window(dp->fs))
+ return FR_DISK_ERR;
+ dp->fs->winsect++;
+ }
+ dp->fs->winsect -= c; /* Rewind window offset */
#else
- if (!stretch) return FR_NO_FILE; /* If do not stretch, report EOT (this is to suppress warning) */
- return FR_NO_FILE; /* Report EOT */
-#endif
- }
- dp->clust = clst; /* Initialize data for new cluster */
- dp->sect = clust2sect(dp->fs, clst);
- }
- }
- }
-
- dp->index = (WORD)i; /* Current index */
- dp->dir = dp->fs->win + (i % (SS(dp->fs) / SZ_DIRE)) * SZ_DIRE; /* Current entry in the window */
-
- return FR_OK;
+ if (!stretch)
+ return FR_NO_FILE; /* If do not stretch, report EOT
+ (this is to suppress warning) */
+ return FR_NO_FILE; /* Report EOT */
+#endif
+ }
+ dp->clust = clst; /* Initialize data for new cluster */
+ dp->sect = clust2sect(dp->fs, clst);
+ }
+ }
+ }
+
+ dp->index = (WORD)i; /* Current index */
+ dp->dir = dp->fs->win +
+ (i % (SS(dp->fs) / SZ_DIRE)) *
+ SZ_DIRE; /* Current entry in the window */
+
+ return FR_OK;
}
-
-
-
/*-----------------------------------------------------------------------*/
/* Directory handling - Reserve directory entry */
/*-----------------------------------------------------------------------*/
#if !_FS_READONLY
-static
-FRESULT dir_alloc (
- DIR* dp, /* Pointer to the directory object */
- UINT nent /* Number of contiguous entries to allocate (1-21) */
-)
+static FRESULT
+dir_alloc(DIR* dp, /* Pointer to the directory object */
+ UINT nent /* Number of contiguous entries to allocate (1-21) */
+ )
{
- FRESULT res;
- UINT n;
-
-
- res = dir_sdi(dp, 0);
- if (res == FR_OK) {
- n = 0;
- do {
- res = move_window(dp->fs, dp->sect);
- if (res != FR_OK) break;
- if (dp->dir[0] == DDEM || dp->dir[0] == 0) { /* Is it a free entry? */
- if (++n == nent) break; /* A block of contiguous free entries is found */
- } else {
- n = 0; /* Not a blank entry. Restart to search */
- }
- res = dir_next(dp, 1); /* Next entry with table stretch enabled */
- } while (res == FR_OK);
- }
- if (res == FR_NO_FILE) res = FR_DENIED; /* No directory entry to allocate */
- return res;
+ FRESULT res;
+ UINT n;
+
+ res = dir_sdi(dp, 0);
+ if (res == FR_OK) {
+ n = 0;
+ do {
+ res = move_window(dp->fs, dp->sect);
+ if (res != FR_OK)
+ break;
+ if (dp->dir[0] == DDEM ||
+ dp->dir[0] == 0) { /* Is it a free entry? */
+ if (++n == nent)
+ break; /* A block of contiguous free entries is found */
+ } else {
+ n = 0; /* Not a blank entry. Restart to search */
+ }
+ res = dir_next(dp, 1); /* Next entry with table stretch enabled */
+ } while (res == FR_OK);
+ }
+ if (res == FR_NO_FILE)
+ res = FR_DENIED; /* No directory entry to allocate */
+ return res;
}
#endif
-
-
-
/*-----------------------------------------------------------------------*/
/* Directory handling - Load/Store start cluster number */
/*-----------------------------------------------------------------------*/
-static
-DWORD ld_clust (
- FATFS* fs, /* Pointer to the fs object */
- BYTE* dir /* Pointer to the directory entry */
-)
+static DWORD
+ld_clust(FATFS* fs, /* Pointer to the fs object */
+ BYTE* dir /* Pointer to the directory entry */
+ )
{
- DWORD cl;
+ DWORD cl;
- cl = LD_WORD(dir + DIR_FstClusLO);
- if (fs->fs_type == FS_FAT32)
- cl |= (DWORD)LD_WORD(dir + DIR_FstClusHI) << 16;
+ cl = LD_WORD(dir + DIR_FstClusLO);
+ if (fs->fs_type == FS_FAT32)
+ cl |= (DWORD)LD_WORD(dir + DIR_FstClusHI) << 16;
- return cl;
+ return cl;
}
-
#if !_FS_READONLY
-static
-void st_clust (
- BYTE* dir, /* Pointer to the directory entry */
- DWORD cl /* Value to be set */
-)
+static void
+st_clust(BYTE* dir, /* Pointer to the directory entry */
+ DWORD cl /* Value to be set */
+ )
{
- ST_WORD(dir + DIR_FstClusLO, cl);
- ST_WORD(dir + DIR_FstClusHI, cl >> 16);
+ ST_WORD(dir + DIR_FstClusLO, cl);
+ ST_WORD(dir + DIR_FstClusHI, cl >> 16);
}
#endif
-
-
-
/*-----------------------------------------------------------------------*/
/* LFN handling - Test/Pick/Fit an LFN segment from/to directory entry */
/*-----------------------------------------------------------------------*/
#if _USE_LFN
-static
-const BYTE LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30}; /* Offset of LFN characters in the directory entry */
-
-
-static
-int cmp_lfn ( /* 1:Matched, 0:Not matched */
- WCHAR* lfnbuf, /* Pointer to the LFN to be compared */
- BYTE* dir /* Pointer to the directory entry containing a part of LFN */
-)
+static const BYTE LfnOfs[] = {
+ 1, 3, 5, 7, 9, 14, 16, 18, 20, 22, 24, 28, 30
+}; /* Offset of LFN characters in the directory entry */
+
+static int
+cmp_lfn( /* 1:Matched, 0:Not matched */
+ WCHAR* lfnbuf, /* Pointer to the LFN to be compared */
+ BYTE* dir /* Pointer to the directory entry containing a part of LFN */
+ )
{
- UINT i, s;
- WCHAR wc, uc;
-
-
- i = ((dir[LDIR_Ord] & ~LLEF) - 1) * 13; /* Get offset in the LFN buffer */
- s = 0; wc = 1;
- do {
- uc = LD_WORD(dir + LfnOfs[s]); /* Pick an LFN character from the entry */
- if (wc) { /* Last character has not been processed */
- wc = ff_wtoupper(uc); /* Convert it to upper case */
- if (i >= _MAX_LFN || wc != ff_wtoupper(lfnbuf[i++])) /* Compare it */
- return 0; /* Not matched */
- } else {
- if (uc != 0xFFFF) return 0; /* Check filler */
- }
- } while (++s < 13); /* Repeat until all characters in the entry are checked */
-
- if ((dir[LDIR_Ord] & LLEF) && wc && lfnbuf[i]) /* Last segment matched but different length */
- return 0;
-
- return 1; /* The part of LFN matched */
+ UINT i, s;
+ WCHAR wc, uc;
+
+ i = ((dir[LDIR_Ord] & ~LLEF) - 1) * 13; /* Get offset in the LFN buffer */
+ s = 0;
+ wc = 1;
+ do {
+ uc =
+ LD_WORD(dir + LfnOfs[s]); /* Pick an LFN character from the entry */
+ if (wc) { /* Last character has not been processed */
+ wc = ff_wtoupper(uc); /* Convert it to upper case */
+ if (i >= _MAX_LFN ||
+ wc != ff_wtoupper(lfnbuf[i++])) /* Compare it */
+ return 0; /* Not matched */
+ } else {
+ if (uc != 0xFFFF)
+ return 0; /* Check filler */
+ }
+ } while (++s <
+ 13); /* Repeat until all characters in the entry are checked */
+
+ if ((dir[LDIR_Ord] & LLEF) && wc &&
+ lfnbuf[i]) /* Last segment matched but different length */
+ return 0;
+
+ return 1; /* The part of LFN matched */
}
-
-
-static
-int pick_lfn ( /* 1:Succeeded, 0:Buffer overflow */
- WCHAR* lfnbuf, /* Pointer to the Unicode-LFN buffer */
- BYTE* dir /* Pointer to the directory entry */
-)
+static int
+pick_lfn( /* 1:Succeeded, 0:Buffer overflow */
+ WCHAR* lfnbuf, /* Pointer to the Unicode-LFN buffer */
+ BYTE* dir /* Pointer to the directory entry */
+ )
{
- UINT i, s;
- WCHAR wc, uc;
-
-
- i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; /* Offset in the LFN buffer */
-
- s = 0; wc = 1;
- do {
- uc = LD_WORD(dir + LfnOfs[s]); /* Pick an LFN character from the entry */
- if (wc) { /* Last character has not been processed */
- if (i >= _MAX_LFN) return 0; /* Buffer overflow? */
- lfnbuf[i++] = wc = uc; /* Store it */
- } else {
- if (uc != 0xFFFF) return 0; /* Check filler */
- }
- } while (++s < 13); /* Read all character in the entry */
-
- if (dir[LDIR_Ord] & LLEF) { /* Put terminator if it is the last LFN part */
- if (i >= _MAX_LFN) return 0; /* Buffer overflow? */
- lfnbuf[i] = 0;
- }
-
- return 1;
+ UINT i, s;
+ WCHAR wc, uc;
+
+ i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; /* Offset in the LFN buffer */
+
+ s = 0;
+ wc = 1;
+ do {
+ uc =
+ LD_WORD(dir + LfnOfs[s]); /* Pick an LFN character from the entry */
+ if (wc) { /* Last character has not been processed */
+ if (i >= _MAX_LFN)
+ return 0; /* Buffer overflow? */
+ lfnbuf[i++] = wc = uc; /* Store it */
+ } else {
+ if (uc != 0xFFFF)
+ return 0; /* Check filler */
+ }
+ } while (++s < 13); /* Read all character in the entry */
+
+ if (dir[LDIR_Ord] & LLEF) { /* Put terminator if it is the last LFN part */
+ if (i >= _MAX_LFN)
+ return 0; /* Buffer overflow? */
+ lfnbuf[i] = 0;
+ }
+
+ return 1;
}
-
#if !_FS_READONLY
-static
-void fit_lfn (
- const WCHAR* lfnbuf, /* Pointer to the LFN buffer */
- BYTE* dir, /* Pointer to the directory entry */
- BYTE ord, /* LFN order (1-20) */
- BYTE sum /* SFN sum */
-)
+static void
+fit_lfn(const WCHAR* lfnbuf, /* Pointer to the LFN buffer */
+ BYTE* dir, /* Pointer to the directory entry */
+ BYTE ord, /* LFN order (1-20) */
+ BYTE sum /* SFN sum */
+ )
{
- UINT i, s;
- WCHAR wc;
-
-
- dir[LDIR_Chksum] = sum; /* Set check sum */
- dir[LDIR_Attr] = AM_LFN; /* Set attribute. LFN entry */
- dir[LDIR_Type] = 0;
- ST_WORD(dir + LDIR_FstClusLO, 0);
-
- i = (ord - 1) * 13; /* Get offset in the LFN buffer */
- s = wc = 0;
- do {
- if (wc != 0xFFFF) wc = lfnbuf[i++]; /* Get an effective character */
- ST_WORD(dir+LfnOfs[s], wc); /* Put it */
- if (!wc) wc = 0xFFFF; /* Padding characters following last character */
- } while (++s < 13);
- if (wc == 0xFFFF || !lfnbuf[i]) ord |= LLEF; /* Bottom LFN part is the start of LFN sequence */
- dir[LDIR_Ord] = ord; /* Set the LFN order */
+ UINT i, s;
+ WCHAR wc;
+
+ dir[LDIR_Chksum] = sum; /* Set check sum */
+ dir[LDIR_Attr] = AM_LFN; /* Set attribute. LFN entry */
+ dir[LDIR_Type] = 0;
+ ST_WORD(dir + LDIR_FstClusLO, 0);
+
+ i = (ord - 1) * 13; /* Get offset in the LFN buffer */
+ s = wc = 0;
+ do {
+ if (wc != 0xFFFF)
+ wc = lfnbuf[i++]; /* Get an effective character */
+ ST_WORD(dir + LfnOfs[s], wc); /* Put it */
+ if (!wc)
+ wc = 0xFFFF; /* Padding characters following last character */
+ } while (++s < 13);
+ if (wc == 0xFFFF || !lfnbuf[i])
+ ord |= LLEF; /* Bottom LFN part is the start of LFN sequence */
+ dir[LDIR_Ord] = ord; /* Set the LFN order */
}
#endif
#endif
-
-
-
/*-----------------------------------------------------------------------*/
/* Create numbered name */
/*-----------------------------------------------------------------------*/
#if _USE_LFN
-static
-void gen_numname (
- BYTE* dst, /* Pointer to the buffer to store numbered SFN */
- const BYTE* src, /* Pointer to SFN */
- const WCHAR* lfn, /* Pointer to LFN */
- UINT seq /* Sequence number */
-)
+static void
+gen_numname(BYTE* dst, /* Pointer to the buffer to store numbered SFN */
+ const BYTE* src, /* Pointer to SFN */
+ const WCHAR* lfn, /* Pointer to LFN */
+ UINT seq /* Sequence number */
+ )
{
- BYTE ns[8], c;
- UINT i, j;
- WCHAR wc;
- DWORD sr;
-
-
- mem_cpy(dst, src, 11);
-
- if (seq > 5) { /* On many collisions, generate a hash number instead of sequential number */
- sr = seq;
- while (*lfn) { /* Create a CRC */
- wc = *lfn++;
- for (i = 0; i < 16; i++) {
- sr = (sr << 1) + (wc & 1);
- wc >>= 1;
- if (sr & 0x10000) sr ^= 0x11021;
- }
- }
- seq = (UINT)sr;
- }
-
- /* itoa (hexdecimal) */
- i = 7;
- do {
- c = (seq % 16) + '0';
- if (c > '9') c += 7;
- ns[i--] = c;
- seq /= 16;
- } while (seq);
- ns[i] = '~';
-
- /* Append the number */
- for (j = 0; j < i && dst[j] != ' '; j++) {
- if (IsDBCS1(dst[j])) {
- if (j == i - 1) break;
- j++;
- }
- }
- do {
- dst[j++] = (i < 8) ? ns[i++] : ' ';
- } while (j < 8);
+ BYTE ns[8], c;
+ UINT i, j;
+ WCHAR wc;
+ DWORD sr;
+
+ mem_cpy(dst, src, 11);
+
+ if (seq > 5) { /* On many collisions, generate a hash number instead of
+ sequential number */
+ sr = seq;
+ while (*lfn) { /* Create a CRC */
+ wc = *lfn++;
+ for (i = 0; i < 16; i++) {
+ sr = (sr << 1) + (wc & 1);
+ wc >>= 1;
+ if (sr & 0x10000)
+ sr ^= 0x11021;
+ }
+ }
+ seq = (UINT)sr;
+ }
+
+ /* itoa (hexdecimal) */
+ i = 7;
+ do {
+ c = (seq % 16) + '0';
+ if (c > '9')
+ c += 7;
+ ns[i--] = c;
+ seq /= 16;
+ } while (seq);
+ ns[i] = '~';
+
+ /* Append the number */
+ for (j = 0; j < i && dst[j] != ' '; j++) {
+ if (IsDBCS1(dst[j])) {
+ if (j == i - 1)
+ break;
+ j++;
+ }
+ }
+ do {
+ dst[j++] = (i < 8) ? ns[i++] : ' ';
+ } while (j < 8);
}
#endif
-
-
-
/*-----------------------------------------------------------------------*/
/* Calculate sum of an SFN */
/*-----------------------------------------------------------------------*/
#if _USE_LFN
-static
-BYTE sum_sfn (
- const BYTE* dir /* Pointer to the SFN entry */
-)
+static BYTE
+sum_sfn(const BYTE* dir /* Pointer to the SFN entry */
+ )
{
- BYTE sum = 0;
- UINT n = 11;
+ BYTE sum = 0;
+ UINT n = 11;
- do sum = (sum >> 1) + (sum << 7) + *dir++; while (--n);
- return sum;
+ do
+ sum = (sum >> 1) + (sum << 7) + *dir++;
+ while (--n);
+ return sum;
}
#endif
-
-
-
/*-----------------------------------------------------------------------*/
/* Directory handling - Find an object in the directory */
/*-----------------------------------------------------------------------*/
-static
-FRESULT dir_find (
- DIR* dp /* Pointer to the directory object linked to the file name */
-)
+static FRESULT
+dir_find(DIR* dp /* Pointer to the directory object linked to the file name */
+ )
{
- FRESULT res;
- BYTE c, *dir;
+ FRESULT res;
+ BYTE c, *dir;
#if _USE_LFN
- BYTE a, ord, sum;
+ BYTE a, ord, sum;
#endif
- res = dir_sdi(dp, 0); /* Rewind directory object */
- if (res != FR_OK) return res;
+ res = dir_sdi(dp, 0); /* Rewind directory object */
+ if (res != FR_OK)
+ return res;
#if _USE_LFN
- ord = sum = 0xFF; dp->lfn_idx = 0xFFFF; /* Reset LFN sequence */
-#endif
- do {
- res = move_window(dp->fs, dp->sect);
- if (res != FR_OK) break;
- dir = dp->dir; /* Ptr to the directory entry of current index */
- c = dir[DIR_Name];
- if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */
-#if _USE_LFN /* LFN configuration */
- a = dir[DIR_Attr] & AM_MASK;
- if (c == DDEM || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */
- ord = 0xFF; dp->lfn_idx = 0xFFFF; /* Reset LFN sequence */
- } else {
- if (a == AM_LFN) { /* An LFN entry is found */
- if (dp->lfn) {
- if (c & LLEF) { /* Is it start of LFN sequence? */
- sum = dir[LDIR_Chksum];
- c &= ~LLEF; ord = c; /* LFN start order */
- dp->lfn_idx = dp->index; /* Start index of LFN */
- }
- /* Check validity of the LFN entry and compare it with given name */
- ord = (c == ord && sum == dir[LDIR_Chksum] && cmp_lfn(dp->lfn, dir)) ? ord - 1 : 0xFF;
- }
- } else { /* An SFN entry is found */
- if (!ord && sum == sum_sfn(dir)) break; /* LFN matched? */
- if (!(dp->fn[NSFLAG] & NS_LOSS) && !mem_cmp(dir, dp->fn, 11)) break; /* SFN matched? */
- ord = 0xFF; dp->lfn_idx = 0xFFFF; /* Reset LFN sequence */
- }
- }
-#else /* Non LFN configuration */
- if (!(dir[DIR_Attr] & AM_VOL) && !mem_cmp(dir, dp->fn, 11)) /* Is it a valid entry? */
- break;
-#endif
- res = dir_next(dp, 0); /* Next entry */
- } while (res == FR_OK);
-
- return res;
+ ord = sum = 0xFF;
+ dp->lfn_idx = 0xFFFF; /* Reset LFN sequence */
+#endif
+ do {
+ res = move_window(dp->fs, dp->sect);
+ if (res != FR_OK)
+ break;
+ dir = dp->dir; /* Ptr to the directory entry of current index */
+ c = dir[DIR_Name];
+ if (c == 0) {
+ res = FR_NO_FILE;
+ break;
+ } /* Reached to end of table */
+#if _USE_LFN /* LFN configuration */
+ a = dir[DIR_Attr] & AM_MASK;
+ if (c == DDEM ||
+ ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */
+ ord = 0xFF;
+ dp->lfn_idx = 0xFFFF; /* Reset LFN sequence */
+ } else {
+ if (a == AM_LFN) { /* An LFN entry is found */
+ if (dp->lfn) {
+ if (c & LLEF) { /* Is it start of LFN sequence? */
+ sum = dir[LDIR_Chksum];
+ c &= ~LLEF;
+ ord = c; /* LFN start order */
+ dp->lfn_idx = dp->index; /* Start index of LFN */
+ }
+ /* Check validity of the LFN entry and compare it with given
+ * name */
+ ord = (c == ord && sum == dir[LDIR_Chksum] &&
+ cmp_lfn(dp->lfn, dir))
+ ? ord - 1
+ : 0xFF;
+ }
+ } else { /* An SFN entry is found */
+ if (!ord && sum == sum_sfn(dir))
+ break; /* LFN matched? */
+ if (!(dp->fn[NSFLAG] & NS_LOSS) && !mem_cmp(dir, dp->fn, 11))
+ break; /* SFN matched? */
+ ord = 0xFF;
+ dp->lfn_idx = 0xFFFF; /* Reset LFN sequence */
+ }
+ }
+#else /* Non LFN configuration */
+ if (!(dir[DIR_Attr] & AM_VOL) &&
+ !mem_cmp(dir, dp->fn, 11)) /* Is it a valid entry? */
+ break;
+#endif
+ res = dir_next(dp, 0); /* Next entry */
+ } while (res == FR_OK);
+
+ return res;
}
-
-
-
/*-----------------------------------------------------------------------*/
/* Read an object from the directory */
/*-----------------------------------------------------------------------*/
#if _FS_MINIMIZE <= 1 || _USE_LABEL || _FS_RPATH >= 2
-static
-FRESULT dir_read (
- DIR* dp, /* Pointer to the directory object */
- int vol /* Filtered by 0:file/directory or 1:volume label */
-)
+static FRESULT
+dir_read(DIR* dp, /* Pointer to the directory object */
+ int vol /* Filtered by 0:file/directory or 1:volume label */
+ )
{
- FRESULT res;
- BYTE a, c, *dir;
+ FRESULT res;
+ BYTE a, c, *dir;
#if _USE_LFN
- BYTE ord = 0xFF, sum = 0xFF;
-#endif
-
- res = FR_NO_FILE;
- while (dp->sect) {
- res = move_window(dp->fs, dp->sect);
- if (res != FR_OK) break;
- dir = dp->dir; /* Ptr to the directory entry of current index */
- c = dir[DIR_Name];
- if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */
- a = dir[DIR_Attr] & AM_MASK;
-#if _USE_LFN /* LFN configuration */
- if (c == DDEM || (!_FS_RPATH && c == '.') || (int)((a & ~AM_ARC) == AM_VOL) != vol) { /* An entry without valid data */
- ord = 0xFF;
- } else {
- if (a == AM_LFN) { /* An LFN entry is found */
- if (c & LLEF) { /* Is it start of LFN sequence? */
- sum = dir[LDIR_Chksum];
- c &= ~LLEF; ord = c;
- dp->lfn_idx = dp->index;
- }
- /* Check LFN validity and capture it */
- ord = (c == ord && sum == dir[LDIR_Chksum] && pick_lfn(dp->lfn, dir)) ? ord - 1 : 0xFF;
- } else { /* An SFN entry is found */
- if (ord || sum != sum_sfn(dir)) /* Is there a valid LFN? */
- dp->lfn_idx = 0xFFFF; /* It has no LFN. */
- break;
- }
- }
-#else /* Non LFN configuration */
- if (c != DDEM && (_FS_RPATH || c != '.') && a != AM_LFN && (int)((a & ~AM_ARC) == AM_VOL) == vol) /* Is it a valid entry? */
- break;
-#endif
- res = dir_next(dp, 0); /* Next entry */
- if (res != FR_OK) break;
- }
-
- if (res != FR_OK) dp->sect = 0;
-
- return res;
+ BYTE ord = 0xFF, sum = 0xFF;
+#endif
+
+ res = FR_NO_FILE;
+ while (dp->sect) {
+ res = move_window(dp->fs, dp->sect);
+ if (res != FR_OK)
+ break;
+ dir = dp->dir; /* Ptr to the directory entry of current index */
+ c = dir[DIR_Name];
+ if (c == 0) {
+ res = FR_NO_FILE;
+ break;
+ } /* Reached to end of table */
+ a = dir[DIR_Attr] & AM_MASK;
+#if _USE_LFN /* LFN configuration */
+ if (c == DDEM || (!_FS_RPATH && c == '.') ||
+ (int)((a & ~AM_ARC) == AM_VOL) !=
+ vol) { /* An entry without valid data */
+ ord = 0xFF;
+ } else {
+ if (a == AM_LFN) { /* An LFN entry is found */
+ if (c & LLEF) { /* Is it start of LFN sequence? */
+ sum = dir[LDIR_Chksum];
+ c &= ~LLEF;
+ ord = c;
+ dp->lfn_idx = dp->index;
+ }
+ /* Check LFN validity and capture it */
+ ord = (c == ord && sum == dir[LDIR_Chksum] &&
+ pick_lfn(dp->lfn, dir))
+ ? ord - 1
+ : 0xFF;
+ } else { /* An SFN entry is found */
+ if (ord || sum != sum_sfn(dir)) /* Is there a valid LFN? */
+ dp->lfn_idx = 0xFFFF; /* It has no LFN. */
+ break;
+ }
+ }
+#else /* Non LFN configuration */
+ if (c != DDEM && (_FS_RPATH || c != '.') && a != AM_LFN &&
+ (int)((a & ~AM_ARC) == AM_VOL) == vol) /* Is it a valid entry? */
+ break;
+#endif
+ res = dir_next(dp, 0); /* Next entry */
+ if (res != FR_OK)
+ break;
+ }
+
+ if (res != FR_OK)
+ dp->sect = 0;
+
+ return res;
}
-#endif /* _FS_MINIMIZE <= 1 || _USE_LABEL || _FS_RPATH >= 2 */
-
-
-
+#endif /* _FS_MINIMIZE <= 1 || _USE_LABEL || _FS_RPATH >= 2 */
/*-----------------------------------------------------------------------*/
/* Register an object to the directory */
/*-----------------------------------------------------------------------*/
#if !_FS_READONLY
-static
-FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many SFN collision, FR_DISK_ERR:Disk error */
- DIR* dp /* Target directory with object name to be created */
-)
+static FRESULT
+dir_register(/* FR_OK:Successful, FR_DENIED:No free entry or too many SFN
+ collision, FR_DISK_ERR:Disk error */
+ DIR* dp /* Target directory with object name to be created */
+ )
{
- FRESULT res;
-#if _USE_LFN /* LFN configuration */
- UINT n, nent;
- BYTE sn[12], *fn, sum;
- WCHAR *lfn;
-
-
- fn = dp->fn; lfn = dp->lfn;
- mem_cpy(sn, fn, 12);
-
- if (_FS_RPATH && (sn[NSFLAG] & NS_DOT)) /* Cannot create dot entry */
- return FR_INVALID_NAME;
-
- if (sn[NSFLAG] & NS_LOSS) { /* When LFN is out of 8.3 format, generate a numbered name */
- fn[NSFLAG] = 0; dp->lfn = 0; /* Find only SFN */
- for (n = 1; n < 100; n++) {
- gen_numname(fn, sn, lfn, n); /* Generate a numbered name */
- res = dir_find(dp); /* Check if the name collides with existing SFN */
- if (res != FR_OK) break;
- }
- if (n == 100) return FR_DENIED; /* Abort if too many collisions */
- if (res != FR_NO_FILE) return res; /* Abort if the result is other than 'not collided' */
- fn[NSFLAG] = sn[NSFLAG]; dp->lfn = lfn;
- }
-
- if (sn[NSFLAG] & NS_LFN) { /* When LFN is to be created, allocate entries for an SFN + LFNs. */
- for (n = 0; lfn[n]; n++) ;
- nent = (n + 25) / 13;
- } else { /* Otherwise allocate an entry for an SFN */
- nent = 1;
- }
- res = dir_alloc(dp, nent); /* Allocate entries */
-
- if (res == FR_OK && --nent) { /* Set LFN entry if needed */
- res = dir_sdi(dp, dp->index - nent);
- if (res == FR_OK) {
- sum = sum_sfn(dp->fn); /* Sum value of the SFN tied to the LFN */
- do { /* Store LFN entries in bottom first */
- res = move_window(dp->fs, dp->sect);
- if (res != FR_OK) break;
- fit_lfn(dp->lfn, dp->dir, (BYTE)nent, sum);
- dp->fs->wflag = 1;
- res = dir_next(dp, 0); /* Next entry */
- } while (res == FR_OK && --nent);
- }
- }
-#else /* Non LFN configuration */
- res = dir_alloc(dp, 1); /* Allocate an entry for SFN */
-#endif
-
- if (res == FR_OK) { /* Set SFN entry */
- res = move_window(dp->fs, dp->sect);
- if (res == FR_OK) {
- mem_set(dp->dir, 0, SZ_DIRE); /* Clean the entry */
- mem_cpy(dp->dir, dp->fn, 11); /* Put SFN */
+ FRESULT res;
+#if _USE_LFN /* LFN configuration */
+ UINT n, nent;
+ BYTE sn[12], *fn, sum;
+ WCHAR* lfn;
+
+ fn = dp->fn;
+ lfn = dp->lfn;
+ mem_cpy(sn, fn, 12);
+
+ if (_FS_RPATH && (sn[NSFLAG] & NS_DOT)) /* Cannot create dot entry */
+ return FR_INVALID_NAME;
+
+ if (sn[NSFLAG] &
+ NS_LOSS) { /* When LFN is out of 8.3 format, generate a numbered name */
+ fn[NSFLAG] = 0;
+ dp->lfn = 0; /* Find only SFN */
+ for (n = 1; n < 100; n++) {
+ gen_numname(fn, sn, lfn, n); /* Generate a numbered name */
+ res =
+ dir_find(dp); /* Check if the name collides with existing SFN */
+ if (res != FR_OK)
+ break;
+ }
+ if (n == 100)
+ return FR_DENIED; /* Abort if too many collisions */
+ if (res != FR_NO_FILE)
+ return res; /* Abort if the result is other than 'not collided' */
+ fn[NSFLAG] = sn[NSFLAG];
+ dp->lfn = lfn;
+ }
+
+ if (sn[NSFLAG] & NS_LFN) { /* When LFN is to be created, allocate entries
+ for an SFN + LFNs. */
+ for (n = 0; lfn[n]; n++)
+ ;
+ nent = (n + 25) / 13;
+ } else { /* Otherwise allocate an entry for an SFN */
+ nent = 1;
+ }
+ res = dir_alloc(dp, nent); /* Allocate entries */
+
+ if (res == FR_OK && --nent) { /* Set LFN entry if needed */
+ res = dir_sdi(dp, dp->index - nent);
+ if (res == FR_OK) {
+ sum = sum_sfn(dp->fn); /* Sum value of the SFN tied to the LFN */
+ do { /* Store LFN entries in bottom first */
+ res = move_window(dp->fs, dp->sect);
+ if (res != FR_OK)
+ break;
+ fit_lfn(dp->lfn, dp->dir, (BYTE)nent, sum);
+ dp->fs->wflag = 1;
+ res = dir_next(dp, 0); /* Next entry */
+ } while (res == FR_OK && --nent);
+ }
+ }
+#else /* Non LFN configuration */
+ res = dir_alloc(dp, 1); /* Allocate an entry for SFN */
+#endif
+
+ if (res == FR_OK) { /* Set SFN entry */
+ res = move_window(dp->fs, dp->sect);
+ if (res == FR_OK) {
+ mem_set(dp->dir, 0, SZ_DIRE); /* Clean the entry */
+ mem_cpy(dp->dir, dp->fn, 11); /* Put SFN */
#if _USE_LFN
- dp->dir[DIR_NTres] = dp->fn[NSFLAG] & (NS_BODY | NS_EXT); /* Put NT flag */
+ dp->dir[DIR_NTres] =
+ dp->fn[NSFLAG] & (NS_BODY | NS_EXT); /* Put NT flag */
#endif
- dp->fs->wflag = 1;
- }
- }
+ dp->fs->wflag = 1;
+ }
+ }
- return res;
+ return res;
}
#endif /* !_FS_READONLY */
-
-
-
/*-----------------------------------------------------------------------*/
/* Remove an object from the directory */
/*-----------------------------------------------------------------------*/
#if !_FS_READONLY && !_FS_MINIMIZE
-static
-FRESULT dir_remove ( /* FR_OK: Successful, FR_DISK_ERR: A disk error */
- DIR* dp /* Directory object pointing the entry to be removed */
-)
+static FRESULT
+dir_remove( /* FR_OK: Successful, FR_DISK_ERR: A disk error */
+ DIR* dp /* Directory object pointing the entry to be removed */
+ )
{
- FRESULT res;
-#if _USE_LFN /* LFN configuration */
- UINT i;
-
- i = dp->index; /* SFN index */
- res = dir_sdi(dp, (dp->lfn_idx == 0xFFFF) ? i : dp->lfn_idx); /* Goto the SFN or top of the LFN entries */
- if (res == FR_OK) {
- do {
- res = move_window(dp->fs, dp->sect);
- if (res != FR_OK) break;
- mem_set(dp->dir, 0, SZ_DIRE); /* Clear and mark the entry "deleted" */
- *dp->dir = DDEM;
- dp->fs->wflag = 1;
- if (dp->index >= i) break; /* When reached SFN, all entries of the object has been deleted. */
- res = dir_next(dp, 0); /* Next entry */
- } while (res == FR_OK);
- if (res == FR_NO_FILE) res = FR_INT_ERR;
- }
-
-#else /* Non LFN configuration */
- res = dir_sdi(dp, dp->index);
- if (res == FR_OK) {
- res = move_window(dp->fs, dp->sect);
- if (res == FR_OK) {
- mem_set(dp->dir, 0, SZ_DIRE); /* Clear and mark the entry "deleted" */
- *dp->dir = DDEM;
- dp->fs->wflag = 1;
- }
- }
-#endif
-
- return res;
+ FRESULT res;
+#if _USE_LFN /* LFN configuration */
+ UINT i;
+
+ i = dp->index; /* SFN index */
+ res = dir_sdi(
+ dp, (dp->lfn_idx == 0xFFFF)
+ ? i
+ : dp->lfn_idx); /* Goto the SFN or top of the LFN entries */
+ if (res == FR_OK) {
+ do {
+ res = move_window(dp->fs, dp->sect);
+ if (res != FR_OK)
+ break;
+ mem_set(dp->dir, 0,
+ SZ_DIRE); /* Clear and mark the entry "deleted" */
+ *dp->dir = DDEM;
+ dp->fs->wflag = 1;
+ if (dp->index >= i)
+ break; /* When reached SFN, all entries of the object has been
+ deleted. */
+ res = dir_next(dp, 0); /* Next entry */
+ } while (res == FR_OK);
+ if (res == FR_NO_FILE)
+ res = FR_INT_ERR;
+ }
+
+#else /* Non LFN configuration */
+ res = dir_sdi(dp, dp->index);
+ if (res == FR_OK) {
+ res = move_window(dp->fs, dp->sect);
+ if (res == FR_OK) {
+ mem_set(dp->dir, 0,
+ SZ_DIRE); /* Clear and mark the entry "deleted" */
+ *dp->dir = DDEM;
+ dp->fs->wflag = 1;
+ }
+ }
+#endif
+
+ return res;
}
#endif /* !_FS_READONLY */
-
-
-
/*-----------------------------------------------------------------------*/
/* Get file information from directory entry */
/*-----------------------------------------------------------------------*/
#if _FS_MINIMIZE <= 1 || _FS_RPATH >= 2
-static
-void get_fileinfo ( /* No return code */
- DIR* dp, /* Pointer to the directory object */
- FILINFO* fno /* Pointer to the file information to be filled */
-)
+static void
+get_fileinfo( /* No return code */
+ DIR* dp, /* Pointer to the directory object */
+ FILINFO* fno /* Pointer to the file information to be filled */
+ )
{
- UINT i;
- TCHAR *p, c;
- BYTE *dir;
+ UINT i;
+ TCHAR *p, c;
+ BYTE* dir;
#if _USE_LFN
- WCHAR w, *lfn;
-#endif
-
- p = fno->fname;
- if (dp->sect) { /* Get SFN */
- dir = dp->dir;
- i = 0;
- while (i < 11) { /* Copy name body and extension */
- c = (TCHAR)dir[i++];
- if (c == ' ') continue; /* Skip padding spaces */
- if (c == RDDEM) c = (TCHAR)DDEM; /* Restore replaced DDEM character */
- if (i == 9) *p++ = '.'; /* Insert a . if extension is exist */
+ WCHAR w, *lfn;
+#endif
+
+ p = fno->fname;
+ if (dp->sect) { /* Get SFN */
+ dir = dp->dir;
+ i = 0;
+ while (i < 11) { /* Copy name body and extension */
+ c = (TCHAR)dir[i++];
+ if (c == ' ')
+ continue; /* Skip padding spaces */
+ if (c == RDDEM)
+ c = (TCHAR)DDEM; /* Restore replaced DDEM character */
+ if (i == 9)
+ *p++ = '.'; /* Insert a . if extension is exist */
#if _USE_LFN
- if (IsUpper(c) && (dir[DIR_NTres] & (i >= 9 ? NS_EXT : NS_BODY)))
- c += 0x20; /* To lower */
+ if (IsUpper(c) && (dir[DIR_NTres] & (i >= 9 ? NS_EXT : NS_BODY)))
+ c += 0x20; /* To lower */
#if _LFN_UNICODE
- if (IsDBCS1(c) && i != 8 && i != 11 && IsDBCS2(dir[i]))
- c = c << 8 | dir[i++];
- c = ff_convert(c, 1); /* OEM -> Unicode */
- if (!c) c = '?';
-#endif
-#endif
- *p++ = c;
- }
- fno->fattrib = dir[DIR_Attr]; /* Attribute */
- fno->fsize = LD_DWORD(dir + DIR_FileSize); /* Size */
- fno->fdate = LD_WORD(dir + DIR_WrtDate); /* Date */
- fno->ftime = LD_WORD(dir + DIR_WrtTime); /* Time */
- }
- *p = 0; /* Terminate SFN string by a \0 */
+ if (IsDBCS1(c) && i != 8 && i != 11 && IsDBCS2(dir[i]))
+ c = c << 8 | dir[i++];
+ c = ff_convert(c, 1); /* OEM -> Unicode */
+ if (!c)
+ c = '?';
+#endif
+#endif
+ *p++ = c;
+ }
+ fno->fattrib = dir[DIR_Attr]; /* Attribute */
+ fno->fsize = LD_DWORD(dir + DIR_FileSize); /* Size */
+ fno->fdate = LD_WORD(dir + DIR_WrtDate); /* Date */
+ fno->ftime = LD_WORD(dir + DIR_WrtTime); /* Time */
+ }
+ *p = 0; /* Terminate SFN string by a \0 */
#if _USE_LFN
- if (fno->lfname) {
- i = 0; p = fno->lfname;
- if (dp->sect && fno->lfsize && dp->lfn_idx != 0xFFFF) { /* Get LFN if available */
- lfn = dp->lfn;
- while ((w = *lfn++) != 0) { /* Get an LFN character */
+ if (fno->lfname) {
+ i = 0;
+ p = fno->lfname;
+ if (dp->sect && fno->lfsize &&
+ dp->lfn_idx != 0xFFFF) { /* Get LFN if available */
+ lfn = dp->lfn;
+ while ((w = *lfn++) != 0) { /* Get an LFN character */
#if !_LFN_UNICODE
- w = ff_convert(w, 0); /* Unicode -> OEM */
- if (!w) { i = 0; break; } /* No LFN if it could not be converted */
- if (_DF1S && w >= 0x100) /* Put 1st byte if it is a DBC (always false on SBCS cfg) */
- p[i++] = (TCHAR)(w >> 8);
-#endif
- if (i >= fno->lfsize - 1) { i = 0; break; } /* No LFN if buffer overflow */
- p[i++] = (TCHAR)w;
- }
- }
- p[i] = 0; /* Terminate LFN string by a \0 */
- }
+ w = ff_convert(w, 0); /* Unicode -> OEM */
+ if (!w) {
+ i = 0;
+ break;
+ } /* No LFN if it could not be converted */
+ if (_DF1S &&
+ w >=
+ 0x100) /* Put 1st byte if it is a DBC (always false on
+ SBCS cfg) */
+ p[i++] = (TCHAR)(w >> 8);
+#endif
+ if (i >= fno->lfsize - 1) {
+ i = 0;
+ break;
+ } /* No LFN if buffer overflow */
+ p[i++] = (TCHAR)w;
+ }
+ }
+ p[i] = 0; /* Terminate LFN string by a \0 */
+ }
#endif
}
#endif /* _FS_MINIMIZE <= 1 || _FS_RPATH >= 2 */
-
-
-
/*-----------------------------------------------------------------------*/
/* Pattern matching */
/*-----------------------------------------------------------------------*/
#if _USE_FIND && _FS_MINIMIZE <= 1
-static
-WCHAR get_achar ( /* Get a character and advances ptr 1 or 2 */
- const TCHAR** ptr /* Pointer to pointer to the SBCS/DBCS/Unicode string */
-)
+static WCHAR
+get_achar(/* Get a character and advances ptr 1 or 2 */
+ const TCHAR**
+ ptr /* Pointer to pointer to the SBCS/DBCS/Unicode string */
+ )
{
- WCHAR chr;
+ WCHAR chr;
#if !_LFN_UNICODE
- chr = (BYTE)*(*ptr)++; /* Get a byte */
- if (IsLower(chr)) chr -= 0x20; /* To upper ASCII char */
- if (IsDBCS1(chr) && IsDBCS2(**ptr)) /* Get DBC 2nd byte if needed */
- chr = chr << 8 | (BYTE)*(*ptr)++;
+ chr = (BYTE) * (*ptr)++; /* Get a byte */
+ if (IsLower(chr))
+ chr -= 0x20; /* To upper ASCII char */
+ if (IsDBCS1(chr) && IsDBCS2(**ptr)) /* Get DBC 2nd byte if needed */
+ chr = chr << 8 | (BYTE) * (*ptr)++;
#ifdef _EXCVT
- if (chr >= 0x80) chr = ExCvt[chr - 0x80]; /* To upper SBCS extended char */
+ if (chr >= 0x80)
+ chr = ExCvt[chr - 0x80]; /* To upper SBCS extended char */
#endif
#else
- chr = ff_wtoupper(*(*ptr)++); /* Get a word and to upper */
+ chr = ff_wtoupper(*(*ptr)++); /* Get a word and to upper */
#endif
- return chr;
+ return chr;
}
-
-static
-int pattern_matching ( /* Return value: 0:mismatched, 1:matched */
- const TCHAR* pat, /* Matching pattern */
- const TCHAR* nam, /* String to be tested */
- int skip, /* Number of pre-skip chars (number of ?s) */
- int inf /* Infinite search (* specified) */
-)
+static int
+pattern_matching( /* Return value: 0:mismatched, 1:matched */
+ const TCHAR* pat, /* Matching pattern */
+ const TCHAR* nam, /* String to be tested */
+ int skip, /* Number of pre-skip chars (number of ?s) */
+ int inf /* Infinite search (* specified) */
+ )
{
- const TCHAR *pp, *np;
- WCHAR pc, nc;
- int nm, nx;
-
-
- while (skip--) { /* Pre-skip name chars */
- if (!get_achar(&nam)) return 0; /* Branch mismatched if less name chars */
- }
- if (!*pat && inf) return 1; /* (short circuit) */
-
- do {
- pp = pat; np = nam; /* Top of pattern and name to match */
- for (;;) {
- if (*pp == '?' || *pp == '*') { /* Wildcard? */
- nm = nx = 0;
- do { /* Analyze the wildcard chars */
- if (*pp++ == '?') nm++; else nx = 1;
- } while (*pp == '?' || *pp == '*');
- if (pattern_matching(pp, np, nm, nx)) return 1; /* Test new branch (recurs upto number of wildcard blocks in the pattern) */
- nc = *np; break; /* Branch mismatched */
- }
- pc = get_achar(&pp); /* Get a pattern char */
- nc = get_achar(&np); /* Get a name char */
- if (pc != nc) break; /* Branch mismatched? */
- if (!pc) return 1; /* Branch matched? (matched at end of both strings) */
- }
- get_achar(&nam); /* nam++ */
- } while (inf && nc); /* Retry until end of name if infinite search is specified */
-
- return 0;
+ const TCHAR *pp, *np;
+ WCHAR pc, nc;
+ int nm, nx;
+
+ while (skip--) { /* Pre-skip name chars */
+ if (!get_achar(&nam))
+ return 0; /* Branch mismatched if less name chars */
+ }
+ if (!*pat && inf)
+ return 1; /* (short circuit) */
+
+ do {
+ pp = pat;
+ np = nam; /* Top of pattern and name to match */
+ for (;;) {
+ if (*pp == '?' || *pp == '*') { /* Wildcard? */
+ nm = nx = 0;
+ do { /* Analyze the wildcard chars */
+ if (*pp++ == '?')
+ nm++;
+ else
+ nx = 1;
+ } while (*pp == '?' || *pp == '*');
+ if (pattern_matching(pp, np, nm, nx))
+ return 1; /* Test new branch (recurs upto number of wildcard
+ blocks in the pattern) */
+ nc = *np;
+ break; /* Branch mismatched */
+ }
+ pc = get_achar(&pp); /* Get a pattern char */
+ nc = get_achar(&np); /* Get a name char */
+ if (pc != nc)
+ break; /* Branch mismatched? */
+ if (!pc)
+ return 1; /* Branch matched? (matched at end of both strings) */
+ }
+ get_achar(&nam); /* nam++ */
+ } while (inf &&
+ nc); /* Retry until end of name if infinite search is specified */
+
+ return 0;
}
#endif /* _USE_FIND && _FS_MINIMIZE <= 1 */
-
-
-
/*-----------------------------------------------------------------------*/
/* Pick a segment and create the object name in directory form */
/*-----------------------------------------------------------------------*/
-static
-FRESULT create_name (
- DIR* dp, /* Pointer to the directory object */
- const TCHAR** path /* Pointer to pointer to the segment in the path string */
-)
+static FRESULT
+create_name(DIR* dp, /* Pointer to the directory object */
+ const TCHAR**
+ path /* Pointer to pointer to the segment in the path string */
+ )
{
-#if _USE_LFN /* LFN configuration */
- BYTE b, cf;
- WCHAR w, *lfn;
- UINT i, ni, si, di;
- const TCHAR *p;
-
- /* Create LFN in Unicode */
- for (p = *path; *p == '/' || *p == '\\'; p++) ; /* Strip duplicated separator */
- lfn = dp->lfn;
- si = di = 0;
- for (;;) {
- w = p[si++]; /* Get a character */
- if (w < ' ' || w == '/' || w == '\\') break; /* Break on end of segment */
- if (di >= _MAX_LFN) /* Reject too long name */
- return FR_INVALID_NAME;
+#if _USE_LFN /* LFN configuration */
+ BYTE b, cf;
+ WCHAR w, *lfn;
+ UINT i, ni, si, di;
+ const TCHAR* p;
+
+ /* Create LFN in Unicode */
+ for (p = *path; *p == '/' || *p == '\\'; p++)
+ ; /* Strip duplicated separator */
+ lfn = dp->lfn;
+ si = di = 0;
+ for (;;) {
+ w = p[si++]; /* Get a character */
+ if (w < ' ' || w == '/' || w == '\\')
+ break; /* Break on end of segment */
+ if (di >= _MAX_LFN) /* Reject too long name */
+ return FR_INVALID_NAME;
#if !_LFN_UNICODE
- w &= 0xFF;
- if (IsDBCS1(w)) { /* Check if it is a DBC 1st byte (always false on SBCS cfg) */
- b = (BYTE)p[si++]; /* Get 2nd byte */
- w = (w << 8) + b; /* Create a DBC */
- if (!IsDBCS2(b))
- return FR_INVALID_NAME; /* Reject invalid sequence */
- }
- w = ff_convert(w, 1); /* Convert ANSI/OEM to Unicode */
- if (!w) return FR_INVALID_NAME; /* Reject invalid code */
-#endif
- if (w < 0x80 && chk_chr("\"*:<>\?|\x7F", w)) /* Reject illegal characters for LFN */
- return FR_INVALID_NAME;
- lfn[di++] = w; /* Store the Unicode character */
- }
- *path = &p[si]; /* Return pointer to the next segment */
- cf = (w < ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */
+ w &= 0xFF;
+ if (IsDBCS1(
+ w)) { /* Check if it is a DBC 1st byte (always false on SBCS
+ cfg) */
+ b = (BYTE)p[si++]; /* Get 2nd byte */
+ w = (w << 8) + b; /* Create a DBC */
+ if (!IsDBCS2(b))
+ return FR_INVALID_NAME; /* Reject invalid sequence */
+ }
+ w = ff_convert(w, 1); /* Convert ANSI/OEM to Unicode */
+ if (!w)
+ return FR_INVALID_NAME; /* Reject invalid code */
+#endif
+ if (w < 0x80 &&
+ chk_chr("\"*:<>\?|\x7F", w)) /* Reject illegal characters for LFN */
+ return FR_INVALID_NAME;
+ lfn[di++] = w; /* Store the Unicode character */
+ }
+ *path = &p[si]; /* Return pointer to the next segment */
+ cf = (w < ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */
#if _FS_RPATH
- if ((di == 1 && lfn[di - 1] == '.') || /* Is this a dot entry? */
- (di == 2 && lfn[di - 1] == '.' && lfn[di - 2] == '.')) {
- lfn[di] = 0;
- for (i = 0; i < 11; i++)
- dp->fn[i] = (i < di) ? '.' : ' ';
- dp->fn[i] = cf | NS_DOT; /* This is a dot entry */
- return FR_OK;
- }
-#endif
- while (di) { /* Strip trailing spaces and dots */
- w = lfn[di - 1];
- if (w != ' ' && w != '.') break;
- di--;
- }
- if (!di) return FR_INVALID_NAME; /* Reject nul string */
-
- lfn[di] = 0; /* LFN is created */
-
- /* Create SFN in directory form */
- mem_set(dp->fn, ' ', 11);
- for (si = 0; lfn[si] == ' ' || lfn[si] == '.'; si++) ; /* Strip leading spaces and dots */
- if (si) cf |= NS_LOSS | NS_LFN;
- while (di && lfn[di - 1] != '.') di--; /* Find extension (di<=si: no extension) */
-
- b = i = 0; ni = 8;
- for (;;) {
- w = lfn[si++]; /* Get an LFN character */
- if (!w) break; /* Break on end of the LFN */
- if (w == ' ' || (w == '.' && si != di)) { /* Remove spaces and dots */
- cf |= NS_LOSS | NS_LFN; continue;
- }
-
- if (i >= ni || si == di) { /* Extension or end of SFN */
- if (ni == 11) { /* Long extension */
- cf |= NS_LOSS | NS_LFN; break;
- }
- if (si != di) cf |= NS_LOSS | NS_LFN; /* Out of 8.3 format */
- if (si > di) break; /* No extension */
- si = di; i = 8; ni = 11; /* Enter extension section */
- b <<= 2; continue;
- }
-
- if (w >= 0x80) { /* Non ASCII character */
+ if ((di == 1 && lfn[di - 1] == '.') || /* Is this a dot entry? */
+ (di == 2 && lfn[di - 1] == '.' && lfn[di - 2] == '.')) {
+ lfn[di] = 0;
+ for (i = 0; i < 11; i++)
+ dp->fn[i] = (i < di) ? '.' : ' ';
+ dp->fn[i] = cf | NS_DOT; /* This is a dot entry */
+ return FR_OK;
+ }
+#endif
+ while (di) { /* Strip trailing spaces and dots */
+ w = lfn[di - 1];
+ if (w != ' ' && w != '.')
+ break;
+ di--;
+ }
+ if (!di)
+ return FR_INVALID_NAME; /* Reject nul string */
+
+ lfn[di] = 0; /* LFN is created */
+
+ /* Create SFN in directory form */
+ mem_set(dp->fn, ' ', 11);
+ for (si = 0; lfn[si] == ' ' || lfn[si] == '.'; si++)
+ ; /* Strip leading spaces and dots */
+ if (si)
+ cf |= NS_LOSS | NS_LFN;
+ while (di && lfn[di - 1] != '.')
+ di--; /* Find extension (di<=si: no extension) */
+
+ b = i = 0;
+ ni = 8;
+ for (;;) {
+ w = lfn[si++]; /* Get an LFN character */
+ if (!w)
+ break; /* Break on end of the LFN */
+ if (w == ' ' || (w == '.' && si != di)) { /* Remove spaces and dots */
+ cf |= NS_LOSS | NS_LFN;
+ continue;
+ }
+
+ if (i >= ni || si == di) { /* Extension or end of SFN */
+ if (ni == 11) { /* Long extension */
+ cf |= NS_LOSS | NS_LFN;
+ break;
+ }
+ if (si != di)
+ cf |= NS_LOSS | NS_LFN; /* Out of 8.3 format */
+ if (si > di)
+ break; /* No extension */
+ si = di;
+ i = 8;
+ ni = 11; /* Enter extension section */
+ b <<= 2;
+ continue;
+ }
+
+ if (w >= 0x80) { /* Non ASCII character */
#ifdef _EXCVT
- w = ff_convert(w, 0); /* Unicode -> OEM code */
- if (w) w = ExCvt[w - 0x80]; /* Convert extended character to upper (SBCS) */
+ w = ff_convert(w, 0); /* Unicode -> OEM code */
+ if (w)
+ w = ExCvt[w - 0x80]; /* Convert extended character to upper
+ (SBCS) */
#else
- w = ff_convert(ff_wtoupper(w), 0); /* Upper converted Unicode -> OEM code */
-#endif
- cf |= NS_LFN; /* Force create LFN entry */
- }
-
- if (_DF1S && w >= 0x100) { /* DBC (always false at SBCS cfg) */
- if (i >= ni - 1) {
- cf |= NS_LOSS | NS_LFN; i = ni; continue;
- }
- dp->fn[i++] = (BYTE)(w >> 8);
- } else { /* SBC */
- if (!w || chk_chr("+,;=[]", w)) { /* Replace illegal characters for SFN */
- w = '_'; cf |= NS_LOSS | NS_LFN;/* Lossy conversion */
- } else {
- if (IsUpper(w)) { /* ASCII large capital */
- b |= 2;
- } else {
- if (IsLower(w)) { /* ASCII small capital */
- b |= 1; w -= 0x20;
- }
- }
- }
- }
- dp->fn[i++] = (BYTE)w;
- }
-
- if (dp->fn[0] == DDEM) dp->fn[0] = RDDEM; /* If the first character collides with deleted mark, replace it with RDDEM */
-
- if (ni == 8) b <<= 2;
- if ((b & 0x0C) == 0x0C || (b & 0x03) == 0x03) /* Create LFN entry when there are composite capitals */
- cf |= NS_LFN;
- if (!(cf & NS_LFN)) { /* When LFN is in 8.3 format without extended character, NT flags are created */
- if ((b & 0x03) == 0x01) cf |= NS_EXT; /* NT flag (Extension has only small capital) */
- if ((b & 0x0C) == 0x04) cf |= NS_BODY; /* NT flag (Filename has only small capital) */
- }
-
- dp->fn[NSFLAG] = cf; /* SFN is created */
-
- return FR_OK;
-
-
-#else /* Non-LFN configuration */
- BYTE b, c, d, *sfn;
- UINT ni, si, i;
- const char *p;
-
- /* Create file name in directory form */
- for (p = *path; *p == '/' || *p == '\\'; p++) ; /* Strip duplicated separator */
- sfn = dp->fn;
- mem_set(sfn, ' ', 11);
- si = i = b = 0; ni = 8;
+ w = ff_convert(ff_wtoupper(w),
+ 0); /* Upper converted Unicode -> OEM code */
+#endif
+ cf |= NS_LFN; /* Force create LFN entry */
+ }
+
+ if (_DF1S && w >= 0x100) { /* DBC (always false at SBCS cfg) */
+ if (i >= ni - 1) {
+ cf |= NS_LOSS | NS_LFN;
+ i = ni;
+ continue;
+ }
+ dp->fn[i++] = (BYTE)(w >> 8);
+ } else { /* SBC */
+ if (!w ||
+ chk_chr("+,;=[]", w)) { /* Replace illegal characters for SFN */
+ w = '_';
+ cf |= NS_LOSS | NS_LFN; /* Lossy conversion */
+ } else {
+ if (IsUpper(w)) { /* ASCII large capital */
+ b |= 2;
+ } else {
+ if (IsLower(w)) { /* ASCII small capital */
+ b |= 1;
+ w -= 0x20;
+ }
+ }
+ }
+ }
+ dp->fn[i++] = (BYTE)w;
+ }
+
+ if (dp->fn[0] == DDEM)
+ dp
+ ->fn[0] = RDDEM; /* If the first character collides with deleted
+ mark, replace it with RDDEM */
+
+ if (ni == 8)
+ b <<= 2;
+ if ((b & 0x0C) == 0x0C ||
+ (b & 0x03) ==
+ 0x03) /* Create LFN entry when there are composite capitals */
+ cf |= NS_LFN;
+ if (!(cf & NS_LFN)) { /* When LFN is in 8.3 format without extended
+ character, NT flags are created */
+ if ((b & 0x03) == 0x01)
+ cf |= NS_EXT; /* NT flag (Extension has only small capital) */
+ if ((b & 0x0C) == 0x04)
+ cf |= NS_BODY; /* NT flag (Filename has only small capital) */
+ }
+
+ dp->fn[NSFLAG] = cf; /* SFN is created */
+
+ return FR_OK;
+
+#else /* Non-LFN configuration */
+ BYTE b, c, d, *sfn;
+ UINT ni, si, i;
+ const char* p;
+
+ /* Create file name in directory form */
+ for (p = *path; *p == '/' || *p == '\\'; p++)
+ ; /* Strip duplicated separator */
+ sfn = dp->fn;
+ mem_set(sfn, ' ', 11);
+ si = i = b = 0;
+ ni = 8;
#if _FS_RPATH
- if (p[si] == '.') { /* Is this a dot entry? */
- for (;;) {
- c = (BYTE)p[si++];
- if (c != '.' || si >= 3) break;
- sfn[i++] = c;
- }
- if (c != '/' && c != '\\' && c > ' ') return FR_INVALID_NAME;
- *path = &p[si]; /* Return pointer to the next segment */
- sfn[NSFLAG] = (c <= ' ') ? NS_LAST | NS_DOT : NS_DOT; /* Set last segment flag if end of path */
- return FR_OK;
- }
-#endif
- for (;;) {
- c = (BYTE)p[si++];
- if (c <= ' ' || c == '/' || c == '\\') break; /* Break on end of segment */
- if (c == '.' || i >= ni) {
- if (ni != 8 || c != '.') return FR_INVALID_NAME;
- i = 8; ni = 11;
- b <<= 2; continue;
- }
- if (c >= 0x80) { /* Extended character? */
- b |= 3; /* Eliminate NT flag */
+ if (p[si] == '.') { /* Is this a dot entry? */
+ for (;;) {
+ c = (BYTE)p[si++];
+ if (c != '.' || si >= 3)
+ break;
+ sfn[i++] = c;
+ }
+ if (c != '/' && c != '\\' && c > ' ')
+ return FR_INVALID_NAME;
+ *path = &p[si]; /* Return pointer to the next segment */
+ sfn[NSFLAG] = (c <= ' ')
+ ? NS_LAST | NS_DOT
+ : NS_DOT; /* Set last segment flag if end of path */
+ return FR_OK;
+ }
+#endif
+ for (;;) {
+ c = (BYTE)p[si++];
+ if (c <= ' ' || c == '/' || c == '\\')
+ break; /* Break on end of segment */
+ if (c == '.' || i >= ni) {
+ if (ni != 8 || c != '.')
+ return FR_INVALID_NAME;
+ i = 8;
+ ni = 11;
+ b <<= 2;
+ continue;
+ }
+ if (c >= 0x80) { /* Extended character? */
+ b |= 3; /* Eliminate NT flag */
#ifdef _EXCVT
- c = ExCvt[c - 0x80]; /* To upper extended characters (SBCS cfg) */
+ c = ExCvt[c - 0x80]; /* To upper extended characters (SBCS cfg) */
#else
#if !_DF1S
- return FR_INVALID_NAME; /* Reject extended characters (ASCII cfg) */
-#endif
-#endif
- }
- if (IsDBCS1(c)) { /* Check if it is a DBC 1st byte (always false on SBCS cfg) */
- d = (BYTE)p[si++]; /* Get 2nd byte */
- if (!IsDBCS2(d) || i >= ni - 1) /* Reject invalid DBC */
- return FR_INVALID_NAME;
- sfn[i++] = c;
- sfn[i++] = d;
- } else { /* SBC */
- if (chk_chr("\"*+,:;<=>\?[]|\x7F", c)) /* Reject illegal chrs for SFN */
- return FR_INVALID_NAME;
- if (IsUpper(c)) { /* ASCII large capital? */
- b |= 2;
- } else {
- if (IsLower(c)) { /* ASCII small capital? */
- b |= 1; c -= 0x20;
- }
- }
- sfn[i++] = c;
- }
- }
- *path = &p[si]; /* Return pointer to the next segment */
- c = (c <= ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */
-
- if (!i) return FR_INVALID_NAME; /* Reject nul string */
- if (sfn[0] == DDEM) sfn[0] = RDDEM; /* When first character collides with DDEM, replace it with RDDEM */
-
- if (ni == 8) b <<= 2;
- if ((b & 0x03) == 0x01) c |= NS_EXT; /* NT flag (Name extension has only small capital) */
- if ((b & 0x0C) == 0x04) c |= NS_BODY; /* NT flag (Name body has only small capital) */
-
- sfn[NSFLAG] = c; /* Store NT flag, File name is created */
-
- return FR_OK;
+ return FR_INVALID_NAME; /* Reject extended characters (ASCII cfg) */
+#endif
+#endif
+ }
+ if (IsDBCS1(
+ c)) { /* Check if it is a DBC 1st byte (always false on SBCS
+ cfg) */
+ d = (BYTE)p[si++]; /* Get 2nd byte */
+ if (!IsDBCS2(d) || i >= ni - 1) /* Reject invalid DBC */
+ return FR_INVALID_NAME;
+ sfn[i++] = c;
+ sfn[i++] = d;
+ } else { /* SBC */
+ if (chk_chr("\"*+,:;<=>\?[]|\x7F",
+ c)) /* Reject illegal chrs for SFN */
+ return FR_INVALID_NAME;
+ if (IsUpper(c)) { /* ASCII large capital? */
+ b |= 2;
+ } else {
+ if (IsLower(c)) { /* ASCII small capital? */
+ b |= 1;
+ c -= 0x20;
+ }
+ }
+ sfn[i++] = c;
+ }
+ }
+ *path = &p[si]; /* Return pointer to the next segment */
+ c = (c <= ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */
+
+ if (!i)
+ return FR_INVALID_NAME; /* Reject nul string */
+ if (sfn[0] == DDEM)
+ sfn[0] = RDDEM; /* When first character collides with DDEM, replace it
+ with RDDEM */
+
+ if (ni == 8)
+ b <<= 2;
+ if ((b & 0x03) == 0x01)
+ c |= NS_EXT; /* NT flag (Name extension has only small capital) */
+ if ((b & 0x0C) == 0x04)
+ c |= NS_BODY; /* NT flag (Name body has only small capital) */
+
+ sfn[NSFLAG] = c; /* Store NT flag, File name is created */
+
+ return FR_OK;
#endif
}
-
-
-
/*-----------------------------------------------------------------------*/
/* Follow a file path */
/*-----------------------------------------------------------------------*/
-static
-FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */
- DIR* dp, /* Directory object to return last directory and found object */
- const TCHAR* path /* Full-path string to find a file or directory */
-)
+static FRESULT
+follow_path( /* FR_OK(0): successful, !=0: error code */
+ DIR* dp, /* Directory object to return last directory and found
+ object */
+ const TCHAR* path /* Full-path string to find a file or directory */
+ )
{
- FRESULT res;
- BYTE *dir, ns;
-
+ FRESULT res;
+ BYTE *dir, ns;
#if _FS_RPATH
- if (*path == '/' || *path == '\\') { /* There is a heading separator */
- path++; dp->sclust = 0; /* Strip it and start from the root directory */
- } else { /* No heading separator */
- dp->sclust = dp->fs->cdir; /* Start from the current directory */
- }
+ if (*path == '/' || *path == '\\') { /* There is a heading separator */
+ path++;
+ dp->sclust = 0; /* Strip it and start from the root directory */
+ } else { /* No heading separator */
+ dp->sclust = dp->fs->cdir; /* Start from the current directory */
+ }
#else
- if (*path == '/' || *path == '\\') /* Strip heading separator if exist */
- path++;
- dp->sclust = 0; /* Always start from the root directory */
-#endif
-
- if ((UINT)*path < ' ') { /* Null path name is the origin directory itself */
- res = dir_sdi(dp, 0);
- dp->dir = 0;
- } else { /* Follow path */
- for (;;) {
- res = create_name(dp, &path); /* Get a segment name of the path */
- if (res != FR_OK) break;
- res = dir_find(dp); /* Find an object with the sagment name */
- ns = dp->fn[NSFLAG];
- if (res != FR_OK) { /* Failed to find the object */
- if (res == FR_NO_FILE) { /* Object is not found */
- if (_FS_RPATH && (ns & NS_DOT)) { /* If dot entry is not exist, */
- dp->sclust = 0; dp->dir = 0; /* it is the root directory and stay there */
- if (!(ns & NS_LAST)) continue; /* Continue to follow if not last segment */
- res = FR_OK; /* Ended at the root directroy. Function completed. */
- } else { /* Could not find the object */
- if (!(ns & NS_LAST)) res = FR_NO_PATH; /* Adjust error code if not last segment */
- }
- }
- break;
- }
- if (ns & NS_LAST) break; /* Last segment matched. Function completed. */
- dir = dp->dir; /* Follow the sub-directory */
- if (!(dir[DIR_Attr] & AM_DIR)) { /* It is not a sub-directory and cannot follow */
- res = FR_NO_PATH; break;
- }
- dp->sclust = ld_clust(dp->fs, dir);
- }
- }
-
- return res;
+ if (*path == '/' || *path == '\\') /* Strip heading separator if exist */
+ path++;
+ dp->sclust = 0; /* Always start from the root directory */
+#endif
+
+ if ((UINT)*path < ' ') { /* Null path name is the origin directory itself */
+ res = dir_sdi(dp, 0);
+ dp->dir = 0;
+ } else { /* Follow path */
+ for (;;) {
+ res = create_name(dp, &path); /* Get a segment name of the path */
+ if (res != FR_OK)
+ break;
+ res = dir_find(dp); /* Find an object with the sagment name */
+ ns = dp->fn[NSFLAG];
+ if (res != FR_OK) { /* Failed to find the object */
+ if (res == FR_NO_FILE) { /* Object is not found */
+ if (_FS_RPATH &&
+ (ns & NS_DOT)) { /* If dot entry is not exist, */
+ dp->sclust = 0;
+ dp->dir =
+ 0; /* it is the root directory and stay there */
+ if (!(ns & NS_LAST))
+ continue; /* Continue to follow if not last segment
+ */
+ res = FR_OK; /* Ended at the root directroy. Function
+ completed. */
+ } else { /* Could not find the object */
+ if (!(ns & NS_LAST))
+ res = FR_NO_PATH; /* Adjust error code if not last
+ segment */
+ }
+ }
+ break;
+ }
+ if (ns & NS_LAST)
+ break; /* Last segment matched. Function completed. */
+ dir = dp->dir; /* Follow the sub-directory */
+ if (!(dir[DIR_Attr] &
+ AM_DIR)) { /* It is not a sub-directory and cannot follow */
+ res = FR_NO_PATH;
+ break;
+ }
+ dp->sclust = ld_clust(dp->fs, dir);
+ }
+ }
+
+ return res;
}
-
-
-
/*-----------------------------------------------------------------------*/
/* Get logical drive number from path name */
/*-----------------------------------------------------------------------*/
-static
-int get_ldnumber ( /* Returns logical drive number (-1:invalid drive) */
- const TCHAR** path /* Pointer to pointer to the path name */
-)
+static int
+get_ldnumber(/* Returns logical drive number (-1:invalid drive) */
+ const TCHAR** path /* Pointer to pointer to the path name */
+ )
{
- const TCHAR *tp, *tt;
- UINT i;
- int vol = -1;
-#if _STR_VOLUME_ID /* Find string drive id */
- static const char* const str[] = {_VOLUME_STRS};
- const char *sp;
- char c;
- TCHAR tc;
-#endif
-
-
- if (*path) { /* If the pointer is not a null */
- for (tt = *path; (UINT)*tt >= (_USE_LFN ? ' ' : '!') && *tt != ':'; tt++) ; /* Find ':' in the path */
- if (*tt == ':') { /* If a ':' is exist in the path name */
- tp = *path;
- i = *tp++ - '0';
- if (i < 10 && tp == tt) { /* Is there a numeric drive id? */
- if (i < _VOLUMES) { /* If a drive id is found, get the value and strip it */
- vol = (int)i;
- *path = ++tt;
- }
- }
+ const TCHAR *tp, *tt;
+ UINT i;
+ int vol = -1;
+#if _STR_VOLUME_ID /* Find string drive id */
+ static const char* const str[] = { _VOLUME_STRS };
+ const char* sp;
+ char c;
+ TCHAR tc;
+#endif
+
+ if (*path) { /* If the pointer is not a null */
+ for (tt = *path; (UINT)*tt >= (_USE_LFN ? ' ' : '!') && *tt != ':';
+ tt++)
+ ; /* Find ':' in the path */
+ if (*tt == ':') { /* If a ':' is exist in the path name */
+ tp = *path;
+ i = *tp++ - '0';
+ if (i < 10 && tp == tt) { /* Is there a numeric drive id? */
+ if (i <
+ _VOLUMES) { /* If a drive id is found, get the value and
+ strip it */
+ vol = (int)i;
+ *path = ++tt;
+ }
+ }
#if _STR_VOLUME_ID
- else { /* No numeric drive number, find string drive id */
- i = 0; tt++;
- do {
- sp = str[i]; tp = *path;
- do { /* Compare a string drive id with path name */
- c = *sp++; tc = *tp++;
- if (IsLower(tc)) tc -= 0x20;
- } while (c && (TCHAR)c == tc);
- } while ((c || tp != tt) && ++i < _VOLUMES); /* Repeat for each id until pattern match */
- if (i < _VOLUMES) { /* If a drive id is found, get the value and strip it */
- vol = (int)i;
- *path = tt;
- }
- }
-#endif
- return vol;
- }
+ else { /* No numeric drive number, find string drive id */
+ i = 0;
+ tt++;
+ do {
+ sp = str[i];
+ tp = *path;
+ do { /* Compare a string drive id with path name */
+ c = *sp++;
+ tc = *tp++;
+ if (IsLower(tc))
+ tc -= 0x20;
+ } while (c && (TCHAR)c == tc);
+ } while (
+ (c || tp != tt) &&
+ ++i <
+ _VOLUMES); /* Repeat for each id until pattern match */
+ if (i <
+ _VOLUMES) { /* If a drive id is found, get the value and
+ strip it */
+ vol = (int)i;
+ *path = tt;
+ }
+ }
+#endif
+ return vol;
+ }
#if _FS_RPATH && _VOLUMES >= 2
- vol = CurrVol; /* Current drive */
+ vol = CurrVol; /* Current drive */
#else
- vol = 0; /* Drive 0 */
+ vol = 0; /* Drive 0 */
#endif
- }
- return vol;
+ }
+ return vol;
}
-
-
-
/*-----------------------------------------------------------------------*/
/* Load a sector and check if it is an FAT boot sector */
/*-----------------------------------------------------------------------*/
-static
-BYTE check_fs ( /* 0:FAT boor sector, 1:Valid boor sector but not FAT, 2:Not a boot sector, 3:Disk error */
- FATFS* fs, /* File system object */
- DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */
-)
+static BYTE
+check_fs(/* 0:FAT boor sector, 1:Valid boor sector but not FAT, 2:Not a boot
+ sector, 3:Disk error */
+ FATFS* fs, /* File system object */
+ DWORD
+ sect /* Sector# (lba) to check if it is an FAT boot record or not
+ */
+ )
{
- fs->wflag = 0; fs->winsect = 0xFFFFFFFF; /* Invaidate window */
- if (move_window(fs, sect) != FR_OK) /* Load boot record */
- return 3;
-
- if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55) /* Check boot record signature (always placed at offset 510 even if the sector size is >512) */
- return 2;
-
- if ((LD_DWORD(&fs->win[BS_FilSysType]) & 0xFFFFFF) == 0x544146) /* Check "FAT" string */
- return 0;
- if ((LD_DWORD(&fs->win[BS_FilSysType32]) & 0xFFFFFF) == 0x544146) /* Check "FAT" string */
- return 0;
-
- return 1;
+ fs->wflag = 0;
+ fs->winsect = 0xFFFFFFFF; /* Invaidate window */
+ if (move_window(fs, sect) != FR_OK) /* Load boot record */
+ return 3;
+
+ if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55) /* Check boot record signature
+ (always placed at offset 510
+ even if the sector size is
+ >512) */
+ return 2;
+
+ if ((LD_DWORD(&fs->win[BS_FilSysType]) & 0xFFFFFF) ==
+ 0x544146) /* Check "FAT" string */
+ return 0;
+ if ((LD_DWORD(&fs->win[BS_FilSysType32]) & 0xFFFFFF) ==
+ 0x544146) /* Check "FAT" string */
+ return 0;
+
+ return 1;
}
-
-
-
/*-----------------------------------------------------------------------*/
/* Find logical drive and check if the volume is mounted */
/*-----------------------------------------------------------------------*/
-static
-FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */
- FATFS** rfs, /* Pointer to pointer to the found file system object */
- const TCHAR** path, /* Pointer to pointer to the path name (drive number) */
- BYTE wmode /* !=0: Check write protection for write access */
-)
+static FRESULT
+find_volume(/* FR_OK(0): successful, !=0: any error occurred */
+ FATFS**
+ rfs, /* Pointer to pointer to the found file system object */
+ const TCHAR**
+ path, /* Pointer to pointer to the path name (drive number) */
+ BYTE wmode /* !=0: Check write protection for write access */
+ )
{
- BYTE fmt, *pt;
- int vol;
- DSTATUS stat;
- DWORD bsect, fasize, tsect, sysect, nclst, szbfat, br[4];
- WORD nrsv;
- FATFS *fs;
- UINT i;
-
-
- /* Get logical drive number from the path name */
- *rfs = 0;
- vol = get_ldnumber(path);
- if (vol < 0) return FR_INVALID_DRIVE;
-
- /* Check if the file system object is valid or not */
- fs = FatFs[vol]; /* Get pointer to the file system object */
- if (!fs) return FR_NOT_ENABLED; /* Is the file system object available? */
-
- ENTER_FF(fs); /* Lock the volume */
- *rfs = fs; /* Return pointer to the file system object */
-
- if (fs->fs_type) { /* If the volume has been mounted */
- stat = disk_status(fs->drv);
- if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized */
- if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) /* Check write protection if needed */
- return FR_WRITE_PROTECTED;
- return FR_OK; /* The file system object is valid */
- }
- }
-
- /* The file system object is not valid. */
- /* Following code attempts to mount the volume. (analyze BPB and initialize the fs object) */
-
- fs->fs_type = 0; /* Clear the file system object */
- fs->drv = LD2PD(vol); /* Bind the logical drive and a physical drive */
- stat = disk_initialize(fs->drv); /* Initialize the physical drive */
- if (stat & STA_NOINIT) /* Check if the initialization succeeded */
- return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */
- if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) /* Check disk write protection if needed */
- return FR_WRITE_PROTECTED;
-#if _MAX_SS != _MIN_SS /* Get sector size (multiple sector size cfg only) */
- if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK
- || SS(fs) < _MIN_SS || SS(fs) > _MAX_SS) return FR_DISK_ERR;
-#endif
- /* Find an FAT partition on the drive. Supports only generic partitioning, FDISK and SFD. */
- bsect = 0;
- fmt = check_fs(fs, bsect); /* Load sector 0 and check if it is an FAT boot sector as SFD */
- if (fmt == 1 || (!fmt && (LD2PT(vol)))) { /* Not an FAT boot sector or forced partition number */
- for (i = 0; i < 4; i++) { /* Get partition offset */
- pt = fs->win + MBR_Table + i * SZ_PTE;
- br[i] = pt[4] ? LD_DWORD(&pt[8]) : 0;
- }
- i = LD2PT(vol); /* Partition number: 0:auto, 1-4:forced */
- if (i) i--;
- do { /* Find an FAT volume */
- bsect = br[i];
- fmt = bsect ? check_fs(fs, bsect) : 2; /* Check the partition */
- } while (!LD2PT(vol) && fmt && ++i < 4);
- }
- if (fmt == 3) return FR_DISK_ERR; /* An error occured in the disk I/O layer */
- if (fmt) return FR_NO_FILESYSTEM; /* No FAT volume is found */
-
- /* An FAT volume is found. Following code initializes the file system object */
-
- if (LD_WORD(fs->win + BPB_BytsPerSec) != SS(fs)) /* (BPB_BytsPerSec must be equal to the physical sector size) */
- return FR_NO_FILESYSTEM;
-
- fasize = LD_WORD(fs->win + BPB_FATSz16); /* Number of sectors per FAT */
- if (!fasize) fasize = LD_DWORD(fs->win + BPB_FATSz32);
- fs->fsize = fasize;
-
- fs->n_fats = fs->win[BPB_NumFATs]; /* Number of FAT copies */
- if (fs->n_fats != 1 && fs->n_fats != 2) /* (Must be 1 or 2) */
- return FR_NO_FILESYSTEM;
- fasize *= fs->n_fats; /* Number of sectors for FAT area */
-
- fs->csize = fs->win[BPB_SecPerClus]; /* Number of sectors per cluster */
- if (!fs->csize || (fs->csize & (fs->csize - 1))) /* (Must be power of 2) */
- return FR_NO_FILESYSTEM;
-
- fs->n_rootdir = LD_WORD(fs->win + BPB_RootEntCnt); /* Number of root directory entries */
- if (fs->n_rootdir % (SS(fs) / SZ_DIRE)) /* (Must be sector aligned) */
- return FR_NO_FILESYSTEM;
-
- tsect = LD_WORD(fs->win + BPB_TotSec16); /* Number of sectors on the volume */
- if (!tsect) tsect = LD_DWORD(fs->win + BPB_TotSec32);
-
- nrsv = LD_WORD(fs->win + BPB_RsvdSecCnt); /* Number of reserved sectors */
- if (!nrsv) return FR_NO_FILESYSTEM; /* (Must not be 0) */
-
- /* Determine the FAT sub type */
- sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZ_DIRE); /* RSV + FAT + DIR */
- if (tsect < sysect) return FR_NO_FILESYSTEM; /* (Invalid volume size) */
- nclst = (tsect - sysect) / fs->csize; /* Number of clusters */
- if (!nclst) return FR_NO_FILESYSTEM; /* (Invalid volume size) */
- fmt = FS_FAT12;
- if (nclst >= MIN_FAT16) fmt = FS_FAT16;
- if (nclst >= MIN_FAT32) fmt = FS_FAT32;
-
- /* Boundaries and Limits */
- fs->n_fatent = nclst + 2; /* Number of FAT entries */
- fs->volbase = bsect; /* Volume start sector */
- fs->fatbase = bsect + nrsv; /* FAT start sector */
- fs->database = bsect + sysect; /* Data start sector */
- if (fmt == FS_FAT32) {
- if (fs->n_rootdir) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */
- fs->dirbase = LD_DWORD(fs->win + BPB_RootClus); /* Root directory start cluster */
- szbfat = fs->n_fatent * 4; /* (Needed FAT size) */
- } else {
- if (!fs->n_rootdir) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */
- fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */
- szbfat = (fmt == FS_FAT16) ? /* (Needed FAT size) */
- fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1);
- }
- if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) /* (BPB_FATSz must not be less than the size needed) */
- return FR_NO_FILESYSTEM;
+ BYTE fmt, *pt;
+ int vol;
+ DSTATUS stat;
+ DWORD bsect, fasize, tsect, sysect, nclst, szbfat, br[4];
+ WORD nrsv;
+ FATFS* fs;
+ UINT i;
+
+ /* Get logical drive number from the path name */
+ *rfs = 0;
+ vol = get_ldnumber(path);
+ if (vol < 0)
+ return FR_INVALID_DRIVE;
+
+ /* Check if the file system object is valid or not */
+ fs = FatFs[vol]; /* Get pointer to the file system object */
+ if (!fs)
+ return FR_NOT_ENABLED; /* Is the file system object available? */
+
+ ENTER_FF(fs); /* Lock the volume */
+ *rfs = fs; /* Return pointer to the file system object */
+
+ if (fs->fs_type) { /* If the volume has been mounted */
+ stat = disk_status(fs->drv);
+ if (!(stat &
+ STA_NOINIT)) { /* and the physical drive is kept initialized */
+ if (!_FS_READONLY && wmode &&
+ (stat & STA_PROTECT)) /* Check write protection if needed */
+ return FR_WRITE_PROTECTED;
+ return FR_OK; /* The file system object is valid */
+ }
+ }
+
+ /* The file system object is not valid. */
+ /* Following code attempts to mount the volume. (analyze BPB and initialize
+ * the fs object) */
+
+ fs->fs_type = 0; /* Clear the file system object */
+ fs->drv = LD2PD(vol); /* Bind the logical drive and a physical drive */
+ stat = disk_initialize(fs->drv); /* Initialize the physical drive */
+ if (stat & STA_NOINIT) /* Check if the initialization succeeded */
+ return FR_NOT_READY; /* Failed to initialize due to no medium or hard
+ error */
+ if (!_FS_READONLY && wmode &&
+ (stat & STA_PROTECT)) /* Check disk write protection if needed */
+ return FR_WRITE_PROTECTED;
+#if _MAX_SS != _MIN_SS /* Get sector size (multiple sector size cfg only) */
+ if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK ||
+ SS(fs) < _MIN_SS || SS(fs) > _MAX_SS)
+ return FR_DISK_ERR;
+#endif
+ /* Find an FAT partition on the drive. Supports only generic partitioning,
+ * FDISK and SFD. */
+ bsect = 0;
+ fmt = check_fs(
+ fs,
+ bsect); /* Load sector 0 and check if it is an FAT boot sector as SFD */
+ if (fmt == 1 ||
+ (!fmt &&
+ (LD2PT(
+ vol)))) { /* Not an FAT boot sector or forced partition number */
+ for (i = 0; i < 4; i++) { /* Get partition offset */
+ pt = fs->win + MBR_Table + i * SZ_PTE;
+ br[i] = pt[4] ? LD_DWORD(&pt[8]) : 0;
+ }
+ i = LD2PT(vol); /* Partition number: 0:auto, 1-4:forced */
+ if (i)
+ i--;
+ do { /* Find an FAT volume */
+ bsect = br[i];
+ fmt = bsect ? check_fs(fs, bsect) : 2; /* Check the partition */
+ } while (!LD2PT(vol) && fmt && ++i < 4);
+ }
+ if (fmt == 3)
+ return FR_DISK_ERR; /* An error occured in the disk I/O layer */
+ if (fmt)
+ return FR_NO_FILESYSTEM; /* No FAT volume is found */
+
+ /* An FAT volume is found. Following code initializes the file system object
+ */
+
+ if (LD_WORD(fs->win + BPB_BytsPerSec) !=
+ SS(fs)) /* (BPB_BytsPerSec must be equal to the physical sector size) */
+ return FR_NO_FILESYSTEM;
+
+ fasize = LD_WORD(fs->win + BPB_FATSz16); /* Number of sectors per FAT */
+ if (!fasize)
+ fasize = LD_DWORD(fs->win + BPB_FATSz32);
+ fs->fsize = fasize;
+
+ fs->n_fats = fs->win[BPB_NumFATs]; /* Number of FAT copies */
+ if (fs->n_fats != 1 && fs->n_fats != 2) /* (Must be 1 or 2) */
+ return FR_NO_FILESYSTEM;
+ fasize *= fs->n_fats; /* Number of sectors for FAT area */
+
+ fs->csize = fs->win[BPB_SecPerClus]; /* Number of sectors per cluster */
+ if (!fs->csize || (fs->csize & (fs->csize - 1))) /* (Must be power of 2) */
+ return FR_NO_FILESYSTEM;
+
+ fs->n_rootdir = LD_WORD(
+ fs->win + BPB_RootEntCnt); /* Number of root directory entries */
+ if (fs->n_rootdir % (SS(fs) / SZ_DIRE)) /* (Must be sector aligned) */
+ return FR_NO_FILESYSTEM;
+
+ tsect =
+ LD_WORD(fs->win + BPB_TotSec16); /* Number of sectors on the volume */
+ if (!tsect)
+ tsect = LD_DWORD(fs->win + BPB_TotSec32);
+
+ nrsv = LD_WORD(fs->win + BPB_RsvdSecCnt); /* Number of reserved sectors */
+ if (!nrsv)
+ return FR_NO_FILESYSTEM; /* (Must not be 0) */
+
+ /* Determine the FAT sub type */
+ sysect = nrsv + fasize +
+ fs->n_rootdir / (SS(fs) / SZ_DIRE); /* RSV + FAT + DIR */
+ if (tsect < sysect)
+ return FR_NO_FILESYSTEM; /* (Invalid volume size) */
+ nclst = (tsect - sysect) / fs->csize; /* Number of clusters */
+ if (!nclst)
+ return FR_NO_FILESYSTEM; /* (Invalid volume size) */
+ fmt = FS_FAT12;
+ if (nclst >= MIN_FAT16)
+ fmt = FS_FAT16;
+ if (nclst >= MIN_FAT32)
+ fmt = FS_FAT32;
+
+ /* Boundaries and Limits */
+ fs->n_fatent = nclst + 2; /* Number of FAT entries */
+ fs->volbase = bsect; /* Volume start sector */
+ fs->fatbase = bsect + nrsv; /* FAT start sector */
+ fs->database = bsect + sysect; /* Data start sector */
+ if (fmt == FS_FAT32) {
+ if (fs->n_rootdir)
+ return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */
+ fs->dirbase =
+ LD_DWORD(fs->win + BPB_RootClus); /* Root directory start cluster */
+ szbfat = fs->n_fatent * 4; /* (Needed FAT size) */
+ } else {
+ if (!fs->n_rootdir)
+ return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */
+ fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */
+ szbfat = (fmt == FS_FAT16) ? /* (Needed FAT size) */
+ fs->n_fatent * 2
+ : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1);
+ }
+ if (fs->fsize <
+ (szbfat + (SS(fs) - 1)) /
+ SS(fs)) /* (BPB_FATSz must not be less than the size needed) */
+ return FR_NO_FILESYSTEM;
#if !_FS_READONLY
- /* Initialize cluster allocation information */
- fs->last_clust = fs->free_clust = 0xFFFFFFFF;
+ /* Initialize cluster allocation information */
+ fs->last_clust = fs->free_clust = 0xFFFFFFFF;
- /* Get fsinfo if available */
- fs->fsi_flag = 0x80;
+ /* Get fsinfo if available */
+ fs->fsi_flag = 0x80;
#if (_FS_NOFSINFO & 3) != 3
- if (fmt == FS_FAT32 /* Enable FSINFO only if FAT32 and BPB_FSInfo is 1 */
- && LD_WORD(fs->win + BPB_FSInfo) == 1
- && move_window(fs, bsect + 1) == FR_OK)
- {
- fs->fsi_flag = 0;
- if (LD_WORD(fs->win + BS_55AA) == 0xAA55 /* Load FSINFO data if available */
- && LD_DWORD(fs->win + FSI_LeadSig) == 0x41615252
- && LD_DWORD(fs->win + FSI_StrucSig) == 0x61417272)
- {
+ if (fmt == FS_FAT32 /* Enable FSINFO only if FAT32 and BPB_FSInfo is 1 */
+ && LD_WORD(fs->win + BPB_FSInfo) == 1 &&
+ move_window(fs, bsect + 1) == FR_OK) {
+ fs->fsi_flag = 0;
+ if (LD_WORD(fs->win + BS_55AA) ==
+ 0xAA55 /* Load FSINFO data if available */
+ && LD_DWORD(fs->win + FSI_LeadSig) == 0x41615252 &&
+ LD_DWORD(fs->win + FSI_StrucSig) == 0x61417272) {
#if (_FS_NOFSINFO & 1) == 0
- fs->free_clust = LD_DWORD(fs->win + FSI_Free_Count);
+ fs->free_clust = LD_DWORD(fs->win + FSI_Free_Count);
#endif
#if (_FS_NOFSINFO & 2) == 0
- fs->last_clust = LD_DWORD(fs->win + FSI_Nxt_Free);
+ fs->last_clust = LD_DWORD(fs->win + FSI_Nxt_Free);
#endif
- }
- }
+ }
+ }
#endif
#endif
- fs->fs_type = fmt; /* FAT sub-type */
- fs->id = ++Fsid; /* File system mount ID */
+ fs->fs_type = fmt; /* FAT sub-type */
+ fs->id = ++Fsid; /* File system mount ID */
#if _FS_RPATH
- fs->cdir = 0; /* Set current directory to root */
+ fs->cdir = 0; /* Set current directory to root */
#endif
-#if _FS_LOCK /* Clear file lock semaphores */
- clear_lock(fs);
+#if _FS_LOCK /* Clear file lock semaphores */
+ clear_lock(fs);
#endif
- return FR_OK;
+ return FR_OK;
}
-
-
-
/*-----------------------------------------------------------------------*/
/* Check if the file/directory object is valid or not */
/*-----------------------------------------------------------------------*/
-static
-FRESULT validate ( /* FR_OK(0): The object is valid, !=0: Invalid */
- void* obj /* Pointer to the object FIL/DIR to check validity */
-)
+static FRESULT
+validate( /* FR_OK(0): The object is valid, !=0: Invalid */
+ void* obj /* Pointer to the object FIL/DIR to check validity */
+ )
{
- FIL *fil = (FIL*)obj; /* Assuming offset of .fs and .id in the FIL/DIR structure is identical */
-
+ FIL* fil = (FIL*)obj; /* Assuming offset of .fs and .id in the FIL/DIR
+ structure is identical */
- if (!fil || !fil->fs || !fil->fs->fs_type || fil->fs->id != fil->id)
- return FR_INVALID_OBJECT;
+ if (!fil || !fil->fs || !fil->fs->fs_type || fil->fs->id != fil->id)
+ return FR_INVALID_OBJECT;
- ENTER_FF(fil->fs); /* Lock file system */
+ ENTER_FF(fil->fs); /* Lock file system */
- if (disk_status(fil->fs->drv) & STA_NOINIT)
- return FR_NOT_READY;
+ if (disk_status(fil->fs->drv) & STA_NOINIT)
+ return FR_NOT_READY;
- return FR_OK;
+ return FR_OK;
}
-
-
-
/*--------------------------------------------------------------------------
Public Functions
--------------------------------------------------------------------------*/
-
-
/*-----------------------------------------------------------------------*/
/* Mount/Unmount a Logical Drive */
/*-----------------------------------------------------------------------*/
-FRESULT f_mount (
- FATFS* fs, /* Pointer to the file system object (NULL:unmount)*/
- const TCHAR* path, /* Logical drive number to be mounted/unmounted */
- BYTE opt /* 0:Do not mount (delayed mount), 1:Mount immediately */
-)
+FRESULT
+f_mount(FATFS* fs, /* Pointer to the file system object (NULL:unmount)*/
+ const TCHAR* path, /* Logical drive number to be mounted/unmounted */
+ BYTE opt /* 0:Do not mount (delayed mount), 1:Mount immediately */
+ )
{
- FATFS *cfs;
- int vol;
- FRESULT res;
- const TCHAR *rp = path;
-
+ FATFS* cfs;
+ int vol;
+ FRESULT res;
+ const TCHAR* rp = path;
- vol = get_ldnumber(&rp);
- if (vol < 0) return FR_INVALID_DRIVE;
- cfs = FatFs[vol]; /* Pointer to fs object */
+ vol = get_ldnumber(&rp);
+ if (vol < 0)
+ return FR_INVALID_DRIVE;
+ cfs = FatFs[vol]; /* Pointer to fs object */
- if (cfs) {
+ if (cfs) {
#if _FS_LOCK
- clear_lock(cfs);
+ clear_lock(cfs);
#endif
-#if _FS_REENTRANT /* Discard sync object of the current volume */
- if (!ff_del_syncobj(cfs->sobj)) return FR_INT_ERR;
+#if _FS_REENTRANT /* Discard sync object of the current volume */
+ if (!ff_del_syncobj(cfs->sobj))
+ return FR_INT_ERR;
#endif
- cfs->fs_type = 0; /* Clear old fs object */
- }
+ cfs->fs_type = 0; /* Clear old fs object */
+ }
- if (fs) {
- fs->fs_type = 0; /* Clear new fs object */
-#if _FS_REENTRANT /* Create sync object for the new volume */
- if (!ff_cre_syncobj((BYTE)vol, &fs->sobj)) return FR_INT_ERR;
+ if (fs) {
+ fs->fs_type = 0; /* Clear new fs object */
+#if _FS_REENTRANT /* Create sync object for the new volume */
+ if (!ff_cre_syncobj((BYTE)vol, &fs->sobj))
+ return FR_INT_ERR;
#endif
- }
- FatFs[vol] = fs; /* Register new fs object */
+ }
+ FatFs[vol] = fs; /* Register new fs object */
- if (!fs || opt != 1) return FR_OK; /* Do not mount now, it will be mounted later */
+ if (!fs || opt != 1)
+ return FR_OK; /* Do not mount now, it will be mounted later */
- res = find_volume(&fs, &path, 0); /* Force mounted the volume */
- LEAVE_FF(fs, res);
+ res = find_volume(&fs, &path, 0); /* Force mounted the volume */
+ LEAVE_FF(fs, res);
}
-
-
-
/*-----------------------------------------------------------------------*/
/* Open or Create a File */
/*-----------------------------------------------------------------------*/
-FRESULT f_open (
- FIL* fp, /* Pointer to the blank file object */
- const TCHAR* path, /* Pointer to the file name */
- BYTE mode /* Access mode and file open mode flags */
-)
+FRESULT
+f_open(FIL* fp, /* Pointer to the blank file object */
+ const TCHAR* path, /* Pointer to the file name */
+ BYTE mode /* Access mode and file open mode flags */
+ )
{
- FRESULT res;
- DIR dj;
- BYTE *dir;
- DEFINE_NAMEBUF;
+ FRESULT res;
+ DIR dj;
+ BYTE* dir;
+ DEFINE_NAMEBUF;
#if !_FS_READONLY
- DWORD dw, cl;
+ DWORD dw, cl;
#endif
+ if (!fp)
+ return FR_INVALID_OBJECT;
+ fp->fs = 0; /* Clear file object */
- if (!fp) return FR_INVALID_OBJECT;
- fp->fs = 0; /* Clear file object */
-
- /* Get logical drive number */
+/* Get logical drive number */
#if !_FS_READONLY
- mode &= FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW;
- res = find_volume(&dj.fs, &path, (BYTE)(mode & ~FA_READ));
+ mode &=
+ FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW;
+ res = find_volume(&dj.fs, &path, (BYTE)(mode & ~FA_READ));
#else
- mode &= FA_READ;
- res = find_volume(&dj.fs, &path, 0);
-#endif
- if (res == FR_OK) {
- INIT_BUF(dj);
- res = follow_path(&dj, path); /* Follow the file path */
- dir = dj.dir;
-#if !_FS_READONLY /* R/W configuration */
- if (res == FR_OK) {
- if (!dir) /* Default directory itself */
- res = FR_INVALID_NAME;
+ mode &= FA_READ;
+ res = find_volume(&dj.fs, &path, 0);
+#endif
+ if (res == FR_OK) {
+ INIT_BUF(dj);
+ res = follow_path(&dj, path); /* Follow the file path */
+ dir = dj.dir;
+#if !_FS_READONLY /* R/W configuration */
+ if (res == FR_OK) {
+ if (!dir) /* Default directory itself */
+ res = FR_INVALID_NAME;
#if _FS_LOCK
- else
- res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
-#endif
- }
- /* Create or Open a file */
- if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) {
- if (res != FR_OK) { /* No file, create new */
- if (res == FR_NO_FILE) /* There is no file to open, create a new entry */
+ else
+ res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
+#endif
+ }
+ /* Create or Open a file */
+ if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) {
+ if (res != FR_OK) { /* No file, create new */
+ if (res ==
+ FR_NO_FILE) /* There is no file to open, create a new entry
+ */
#if _FS_LOCK
- res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES;
+ res =
+ enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES;
#else
- res = dir_register(&dj);
-#endif
- mode |= FA_CREATE_ALWAYS; /* File is created */
- dir = dj.dir; /* New entry */
- }
- else { /* Any object is already existing */
- if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) { /* Cannot overwrite it (R/O or DIR) */
- res = FR_DENIED;
- } else {
- if (mode & FA_CREATE_NEW) /* Cannot create as new file */
- res = FR_EXIST;
- }
- }
- if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate it if overwrite mode */
- dw = GET_FATTIME(); /* Created time */
- ST_DWORD(dir + DIR_CrtTime, dw);
- dir[DIR_Attr] = 0; /* Reset attribute */
- ST_DWORD(dir + DIR_FileSize, 0);/* size = 0 */
- cl = ld_clust(dj.fs, dir); /* Get start cluster */
- st_clust(dir, 0); /* cluster = 0 */
- dj.fs->wflag = 1;
- if (cl) { /* Remove the cluster chain if exist */
- dw = dj.fs->winsect;
- res = remove_chain(dj.fs, cl);
- if (res == FR_OK) {
- dj.fs->last_clust = cl - 1; /* Reuse the cluster hole */
- res = move_window(dj.fs, dw);
- }
- }
- }
- }
- else { /* Open an existing file */
- if (res == FR_OK) { /* Follow succeeded */
- if (dir[DIR_Attr] & AM_DIR) { /* It is a directory */
- res = FR_NO_FILE;
- } else {
- if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */
- res = FR_DENIED;
- }
- }
- }
- if (res == FR_OK) {
- if (mode & FA_CREATE_ALWAYS) /* Set file change flag if created or overwritten */
- mode |= FA__WRITTEN;
- fp->dir_sect = dj.fs->winsect; /* Pointer to the directory entry */
- fp->dir_ptr = dir;
+ res = dir_register(&dj);
+#endif
+ mode |= FA_CREATE_ALWAYS; /* File is created */
+ dir = dj.dir; /* New entry */
+ } else { /* Any object is already existing */
+ if (dir[DIR_Attr] &
+ (AM_RDO | AM_DIR)) { /* Cannot overwrite it (R/O or DIR) */
+ res = FR_DENIED;
+ } else {
+ if (mode & FA_CREATE_NEW) /* Cannot create as new file */
+ res = FR_EXIST;
+ }
+ }
+ if (res == FR_OK &&
+ (mode & FA_CREATE_ALWAYS)) { /* Truncate it if overwrite mode */
+ dw = GET_FATTIME(); /* Created time */
+ ST_DWORD(dir + DIR_CrtTime, dw);
+ dir[DIR_Attr] = 0; /* Reset attribute */
+ ST_DWORD(dir + DIR_FileSize, 0); /* size = 0 */
+ cl = ld_clust(dj.fs, dir); /* Get start cluster */
+ st_clust(dir, 0); /* cluster = 0 */
+ dj.fs->wflag = 1;
+ if (cl) { /* Remove the cluster chain if exist */
+ dw = dj.fs->winsect;
+ res = remove_chain(dj.fs, cl);
+ if (res == FR_OK) {
+ dj.fs->last_clust = cl - 1; /* Reuse the cluster hole */
+ res = move_window(dj.fs, dw);
+ }
+ }
+ }
+ } else { /* Open an existing file */
+ if (res == FR_OK) { /* Follow succeeded */
+ if (dir[DIR_Attr] & AM_DIR) { /* It is a directory */
+ res = FR_NO_FILE;
+ } else {
+ if ((mode & FA_WRITE) &&
+ (dir[DIR_Attr] & AM_RDO)) /* R/O violation */
+ res = FR_DENIED;
+ }
+ }
+ }
+ if (res == FR_OK) {
+ if (mode & FA_CREATE_ALWAYS) /* Set file change flag if created or
+ overwritten */
+ mode |= FA__WRITTEN;
+ fp->dir_sect = dj.fs->winsect; /* Pointer to the directory entry */
+ fp->dir_ptr = dir;
#if _FS_LOCK
- fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
- if (!fp->lockid) res = FR_INT_ERR;
-#endif
- }
-
-#else /* R/O configuration */
- if (res == FR_OK) { /* Follow succeeded */
- dir = dj.dir;
- if (!dir) { /* Current directory itself */
- res = FR_INVALID_NAME;
- } else {
- if (dir[DIR_Attr] & AM_DIR) /* It is a directory */
- res = FR_NO_FILE;
- }
- }
-#endif
- FREE_BUF();
-
- if (res == FR_OK) {
- fp->flag = mode; /* File access mode */
- fp->err = 0; /* Clear error flag */
- fp->sclust = ld_clust(dj.fs, dir); /* File start cluster */
- fp->fsize = LD_DWORD(dir + DIR_FileSize); /* File size */
- fp->fptr = 0; /* File pointer */
- fp->dsect = 0;
+ fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
+ if (!fp->lockid)
+ res = FR_INT_ERR;
+#endif
+ }
+
+#else /* R/O configuration */
+ if (res == FR_OK) { /* Follow succeeded */
+ dir = dj.dir;
+ if (!dir) { /* Current directory itself */
+ res = FR_INVALID_NAME;
+ } else {
+ if (dir[DIR_Attr] & AM_DIR) /* It is a directory */
+ res = FR_NO_FILE;
+ }
+ }
+#endif
+ FREE_BUF();
+
+ if (res == FR_OK) {
+ fp->flag = mode; /* File access mode */
+ fp->err = 0; /* Clear error flag */
+ fp->sclust = ld_clust(dj.fs, dir); /* File start cluster */
+ fp->fsize = LD_DWORD(dir + DIR_FileSize); /* File size */
+ fp->fptr = 0; /* File pointer */
+ fp->dsect = 0;
#if _USE_FASTSEEK
- fp->cltbl = 0; /* Normal seek mode */
+ fp->cltbl = 0; /* Normal seek mode */
#endif
- fp->fs = dj.fs; /* Validate file object */
- fp->id = fp->fs->id;
- }
- }
+ fp->fs = dj.fs; /* Validate file object */
+ fp->id = fp->fs->id;
+ }
+ }
- LEAVE_FF(dj.fs, res);
+ LEAVE_FF(dj.fs, res);
}
-
-
-
/*-----------------------------------------------------------------------*/
/* Read File */
/*-----------------------------------------------------------------------*/
-FRESULT f_read (
- FIL* fp, /* Pointer to the file object */
- void* buff, /* Pointer to data buffer */
- UINT btr, /* Number of bytes to read */
- UINT* br /* Pointer to number of bytes read */
-)
+FRESULT
+f_read(FIL* fp, /* Pointer to the file object */
+ void* buff, /* Pointer to data buffer */
+ UINT btr, /* Number of bytes to read */
+ UINT* br /* Pointer to number of bytes read */
+ )
{
- FRESULT res;
- DWORD clst, sect, remain;
- UINT rcnt, cc;
- BYTE csect, *rbuff = (BYTE*)buff;
-
-
- *br = 0; /* Clear read byte counter */
-
- res = validate(fp); /* Check validity */
- if (res != FR_OK) LEAVE_FF(fp->fs, res);
- if (fp->err) /* Check error */
- LEAVE_FF(fp->fs, (FRESULT)fp->err);
- if (!(fp->flag & FA_READ)) /* Check access mode */
- LEAVE_FF(fp->fs, FR_DENIED);
- remain = fp->fsize - fp->fptr;
- if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */
-
- for ( ; btr; /* Repeat until all data read */
- rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) {
- if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */
- csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */
- if (!csect) { /* On the cluster boundary? */
- if (fp->fptr == 0) { /* On the top of the file? */
- clst = fp->sclust; /* Follow from the origin */
- } else { /* Middle or end of the file */
+ FRESULT res;
+ DWORD clst, sect, remain;
+ UINT rcnt, cc;
+ BYTE csect, *rbuff = (BYTE *)buff;
+
+ *br = 0; /* Clear read byte counter */
+
+ res = validate(fp); /* Check validity */
+ if (res != FR_OK)
+ LEAVE_FF(fp->fs, res);
+ if (fp->err) /* Check error */
+ LEAVE_FF(fp->fs, (FRESULT)fp->err);
+ if (!(fp->flag & FA_READ)) /* Check access mode */
+ LEAVE_FF(fp->fs, FR_DENIED);
+ remain = fp->fsize - fp->fptr;
+ if (btr > remain)
+ btr = (UINT)remain; /* Truncate btr by remaining bytes */
+
+ for (; btr; /* Repeat until all data read */
+ rbuff += rcnt, fp->fptr += rcnt, * br += rcnt, btr -= rcnt) {
+ if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */
+ csect =
+ (BYTE)(fp->fptr / SS(fp->fs) &
+ (fp->fs->csize - 1)); /* Sector offset in the cluster */
+ if (!csect) { /* On the cluster boundary? */
+ if (fp->fptr == 0) { /* On the top of the file? */
+ clst = fp->sclust; /* Follow from the origin */
+ } else { /* Middle or end of the file */
#if _USE_FASTSEEK
- if (fp->cltbl)
- clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */
- else
-#endif
- clst = get_fat(fp->fs, fp->clust); /* Follow cluster chain on the FAT */
- }
- if (clst < 2) ABORT(fp->fs, FR_INT_ERR);
- if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
- fp->clust = clst; /* Update current cluster */
- }
- sect = clust2sect(fp->fs, fp->clust); /* Get current sector */
- if (!sect) ABORT(fp->fs, FR_INT_ERR);
- sect += csect;
- cc = btr / SS(fp->fs); /* When remaining bytes >= sector size, */
- if (cc) { /* Read maximum contiguous sectors directly */
- if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */
- cc = fp->fs->csize - csect;
- if (disk_read(fp->fs->drv, rbuff, sect, cc) != RES_OK)
- ABORT(fp->fs, FR_DISK_ERR);
-#if !_FS_READONLY && _FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */
+ if (fp->cltbl)
+ clst = clmt_clust(
+ fp, fp->fptr); /* Get cluster# from the CLMT */
+ else
+#endif
+ clst = get_fat(
+ fp->fs,
+ fp->clust); /* Follow cluster chain on the FAT */
+ }
+ if (clst < 2)
+ ABORT(fp->fs, FR_INT_ERR);
+ if (clst == 0xFFFFFFFF)
+ ABORT(fp->fs, FR_DISK_ERR);
+ fp->clust = clst; /* Update current cluster */
+ }
+ sect = clust2sect(fp->fs, fp->clust); /* Get current sector */
+ if (!sect)
+ ABORT(fp->fs, FR_INT_ERR);
+ sect += csect;
+ cc = btr / SS(fp->fs); /* When remaining bytes >= sector size, */
+ if (cc) { /* Read maximum contiguous sectors directly */
+ if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */
+ cc = fp->fs->csize - csect;
+ if (disk_read(fp->fs->drv, rbuff, sect, cc) != RES_OK)
+ ABORT(fp->fs, FR_DISK_ERR);
+#if !_FS_READONLY && \
+ _FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if \
+ it contains a dirty sector */
#if _FS_TINY
- if (fp->fs->wflag && fp->fs->winsect - sect < cc)
- mem_cpy(rbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), fp->fs->win, SS(fp->fs));
+ if (fp->fs->wflag && fp->fs->winsect - sect < cc)
+ mem_cpy(rbuff + ((fp->fs->winsect - sect) * SS(fp->fs)),
+ fp->fs->win, SS(fp->fs));
#else
- if ((fp->flag & FA__DIRTY) && fp->dsect - sect < cc)
- mem_cpy(rbuff + ((fp->dsect - sect) * SS(fp->fs)), fp->buf, SS(fp->fs));
+ if ((fp->flag & FA__DIRTY) && fp->dsect - sect < cc)
+ mem_cpy(rbuff + ((fp->dsect - sect) * SS(fp->fs)), fp->buf,
+ SS(fp->fs));
#endif
#endif
- rcnt = SS(fp->fs) * cc; /* Number of bytes transferred */
- continue;
- }
+ rcnt = SS(fp->fs) * cc; /* Number of bytes transferred */
+ continue;
+ }
#if !_FS_TINY
- if (fp->dsect != sect) { /* Load data sector if not in cache */
+ if (fp->dsect != sect) { /* Load data sector if not in cache */
#if !_FS_READONLY
- if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */
- if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
- ABORT(fp->fs, FR_DISK_ERR);
- fp->flag &= ~FA__DIRTY;
- }
-#endif
- if (disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK) /* Fill sector cache */
- ABORT(fp->fs, FR_DISK_ERR);
- }
-#endif
- fp->dsect = sect;
- }
- rcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs)); /* Get partial sector data from sector buffer */
- if (rcnt > btr) rcnt = btr;
+ if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */
+ if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) !=
+ RES_OK)
+ ABORT(fp->fs, FR_DISK_ERR);
+ fp->flag &= ~FA__DIRTY;
+ }
+#endif
+ if (disk_read(fp->fs->drv, fp->buf, sect, 1) !=
+ RES_OK) /* Fill sector cache */
+ ABORT(fp->fs, FR_DISK_ERR);
+ }
+#endif
+ fp->dsect = sect;
+ }
+ rcnt = SS(fp->fs) -
+ ((UINT)fp->fptr %
+ SS(fp->fs)); /* Get partial sector data from sector buffer */
+ if (rcnt > btr)
+ rcnt = btr;
#if _FS_TINY
- if (move_window(fp->fs, fp->dsect) != FR_OK) /* Move sector window */
- ABORT(fp->fs, FR_DISK_ERR);
- mem_cpy(rbuff, &fp->fs->win[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */
+ if (move_window(fp->fs, fp->dsect) != FR_OK) /* Move sector window */
+ ABORT(fp->fs, FR_DISK_ERR);
+ mem_cpy(rbuff, &fp->fs->win[fp->fptr % SS(fp->fs)],
+ rcnt); /* Pick partial sector */
#else
- mem_cpy(rbuff, &fp->buf[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */
+ mem_cpy(rbuff, &fp->buf[fp->fptr % SS(fp->fs)],
+ rcnt); /* Pick partial sector */
#endif
- }
+ }
- LEAVE_FF(fp->fs, FR_OK);
+ LEAVE_FF(fp->fs, FR_OK);
}
-
-
-
#if !_FS_READONLY
/*-----------------------------------------------------------------------*/
/* Write File */
/*-----------------------------------------------------------------------*/
-FRESULT f_write (
- FIL* fp, /* Pointer to the file object */
- const void *buff, /* Pointer to the data to be written */
- UINT btw, /* Number of bytes to write */
- UINT* bw /* Pointer to number of bytes written */
-)
+FRESULT
+f_write(FIL* fp, /* Pointer to the file object */
+ const void* buff, /* Pointer to the data to be written */
+ UINT btw, /* Number of bytes to write */
+ UINT* bw /* Pointer to number of bytes written */
+ )
{
- FRESULT res;
- DWORD clst, sect;
- UINT wcnt, cc;
- const BYTE *wbuff = (const BYTE*)buff;
- BYTE csect;
-
-
- *bw = 0; /* Clear write byte counter */
-
- res = validate(fp); /* Check validity */
- if (res != FR_OK) LEAVE_FF(fp->fs, res);
- if (fp->err) /* Check error */
- LEAVE_FF(fp->fs, (FRESULT)fp->err);
- if (!(fp->flag & FA_WRITE)) /* Check access mode */
- LEAVE_FF(fp->fs, FR_DENIED);
- if (fp->fptr + btw < fp->fptr) btw = 0; /* File size cannot reach 4GB */
-
- for ( ; btw; /* Repeat until all data written */
- wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt) {
- if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */
- csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */
- if (!csect) { /* On the cluster boundary? */
- if (fp->fptr == 0) { /* On the top of the file? */
- clst = fp->sclust; /* Follow from the origin */
- if (clst == 0) /* When no cluster is allocated, */
- clst = create_chain(fp->fs, 0); /* Create a new cluster chain */
- } else { /* Middle or end of the file */
+ FRESULT res;
+ DWORD clst, sect;
+ UINT wcnt, cc;
+ const BYTE* wbuff = (const BYTE*)buff;
+ BYTE csect;
+
+ *bw = 0; /* Clear write byte counter */
+
+ res = validate(fp); /* Check validity */
+ if (res != FR_OK)
+ LEAVE_FF(fp->fs, res);
+ if (fp->err) /* Check error */
+ LEAVE_FF(fp->fs, (FRESULT)fp->err);
+ if (!(fp->flag & FA_WRITE)) /* Check access mode */
+ LEAVE_FF(fp->fs, FR_DENIED);
+ if (fp->fptr + btw < fp->fptr)
+ btw = 0; /* File size cannot reach 4GB */
+
+ for (; btw; /* Repeat until all data written */
+ wbuff += wcnt, fp->fptr += wcnt, * bw += wcnt, btw -= wcnt) {
+ if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */
+ csect =
+ (BYTE)(fp->fptr / SS(fp->fs) &
+ (fp->fs->csize - 1)); /* Sector offset in the cluster */
+ if (!csect) { /* On the cluster boundary? */
+ if (fp->fptr == 0) { /* On the top of the file? */
+ clst = fp->sclust; /* Follow from the origin */
+ if (clst == 0) /* When no cluster is allocated, */
+ clst = create_chain(fp->fs,
+ 0); /* Create a new cluster chain */
+ } else { /* Middle or end of the file */
#if _USE_FASTSEEK
- if (fp->cltbl)
- clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */
- else
-#endif
- clst = create_chain(fp->fs, fp->clust); /* Follow or stretch cluster chain on the FAT */
- }
- if (clst == 0) break; /* Could not allocate a new cluster (disk full) */
- if (clst == 1) ABORT(fp->fs, FR_INT_ERR);
- if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
- fp->clust = clst; /* Update current cluster */
- if (fp->sclust == 0) fp->sclust = clst; /* Set start cluster if the first write */
- }
+ if (fp->cltbl)
+ clst = clmt_clust(
+ fp, fp->fptr); /* Get cluster# from the CLMT */
+ else
+#endif
+ clst = create_chain(
+ fp->fs, fp->clust); /* Follow or stretch cluster
+ chain on the FAT */
+ }
+ if (clst == 0)
+ break; /* Could not allocate a new cluster (disk full) */
+ if (clst == 1)
+ ABORT(fp->fs, FR_INT_ERR);
+ if (clst == 0xFFFFFFFF)
+ ABORT(fp->fs, FR_DISK_ERR);
+ fp->clust = clst; /* Update current cluster */
+ if (fp->sclust == 0)
+ fp->sclust =
+ clst; /* Set start cluster if the first write */
+ }
#if _FS_TINY
- if (fp->fs->winsect == fp->dsect && sync_window(fp->fs)) /* Write-back sector cache */
- ABORT(fp->fs, FR_DISK_ERR);
+ if (fp->fs->winsect == fp->dsect &&
+ sync_window(fp->fs)) /* Write-back sector cache */
+ ABORT(fp->fs, FR_DISK_ERR);
#else
- if (fp->flag & FA__DIRTY) { /* Write-back sector cache */
- if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
- ABORT(fp->fs, FR_DISK_ERR);
- fp->flag &= ~FA__DIRTY;
- }
-#endif
- sect = clust2sect(fp->fs, fp->clust); /* Get current sector */
- if (!sect) ABORT(fp->fs, FR_INT_ERR);
- sect += csect;
- cc = btw / SS(fp->fs); /* When remaining bytes >= sector size, */
- if (cc) { /* Write maximum contiguous sectors directly */
- if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */
- cc = fp->fs->csize - csect;
- if (disk_write(fp->fs->drv, wbuff, sect, cc) != RES_OK)
- ABORT(fp->fs, FR_DISK_ERR);
+ if (fp->flag & FA__DIRTY) { /* Write-back sector cache */
+ if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
+ ABORT(fp->fs, FR_DISK_ERR);
+ fp->flag &= ~FA__DIRTY;
+ }
+#endif
+ sect = clust2sect(fp->fs, fp->clust); /* Get current sector */
+ if (!sect)
+ ABORT(fp->fs, FR_INT_ERR);
+ sect += csect;
+ cc = btw / SS(fp->fs); /* When remaining bytes >= sector size, */
+ if (cc) { /* Write maximum contiguous sectors directly */
+ if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */
+ cc = fp->fs->csize - csect;
+ if (disk_write(fp->fs->drv, wbuff, sect, cc) != RES_OK)
+ ABORT(fp->fs, FR_DISK_ERR);
#if _FS_MINIMIZE <= 2
#if _FS_TINY
- if (fp->fs->winsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */
- mem_cpy(fp->fs->win, wbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), SS(fp->fs));
- fp->fs->wflag = 0;
- }
+ if (fp->fs->winsect - sect <
+ cc) { /* Refill sector cache if it gets invalidated by the
+ direct write */
+ mem_cpy(fp->fs->win,
+ wbuff + ((fp->fs->winsect - sect) * SS(fp->fs)),
+ SS(fp->fs));
+ fp->fs->wflag = 0;
+ }
#else
- if (fp->dsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */
- mem_cpy(fp->buf, wbuff + ((fp->dsect - sect) * SS(fp->fs)), SS(fp->fs));
- fp->flag &= ~FA__DIRTY;
- }
-#endif
-#endif
- wcnt = SS(fp->fs) * cc; /* Number of bytes transferred */
- continue;
- }
+ if (fp->dsect - sect <
+ cc) { /* Refill sector cache if it gets invalidated by the
+ direct write */
+ mem_cpy(fp->buf, wbuff + ((fp->dsect - sect) * SS(fp->fs)),
+ SS(fp->fs));
+ fp->flag &= ~FA__DIRTY;
+ }
+#endif
+#endif
+ wcnt = SS(fp->fs) * cc; /* Number of bytes transferred */
+ continue;
+ }
#if _FS_TINY
- if (fp->fptr >= fp->fsize) { /* Avoid silly cache filling at growing edge */
- if (sync_window(fp->fs)) ABORT(fp->fs, FR_DISK_ERR);
- fp->fs->winsect = sect;
- }
+ if (fp->fptr >=
+ fp->fsize) { /* Avoid silly cache filling at growing edge */
+ if (sync_window(fp->fs))
+ ABORT(fp->fs, FR_DISK_ERR);
+ fp->fs->winsect = sect;
+ }
#else
- if (fp->dsect != sect) { /* Fill sector cache with file data */
- if (fp->fptr < fp->fsize &&
- disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK)
- ABORT(fp->fs, FR_DISK_ERR);
- }
-#endif
- fp->dsect = sect;
- }
- wcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs));/* Put partial sector into file I/O buffer */
- if (wcnt > btw) wcnt = btw;
+ if (fp->dsect != sect) { /* Fill sector cache with file data */
+ if (fp->fptr < fp->fsize &&
+ disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK)
+ ABORT(fp->fs, FR_DISK_ERR);
+ }
+#endif
+ fp->dsect = sect;
+ }
+ wcnt = SS(fp->fs) -
+ ((UINT)fp->fptr %
+ SS(fp->fs)); /* Put partial sector into file I/O buffer */
+ if (wcnt > btw)
+ wcnt = btw;
#if _FS_TINY
- if (move_window(fp->fs, fp->dsect) != FR_OK) /* Move sector window */
- ABORT(fp->fs, FR_DISK_ERR);
- mem_cpy(&fp->fs->win[fp->fptr % SS(fp->fs)], wbuff, wcnt); /* Fit partial sector */
- fp->fs->wflag = 1;
+ if (move_window(fp->fs, fp->dsect) != FR_OK) /* Move sector window */
+ ABORT(fp->fs, FR_DISK_ERR);
+ mem_cpy(&fp->fs->win[fp->fptr % SS(fp->fs)], wbuff,
+ wcnt); /* Fit partial sector */
+ fp->fs->wflag = 1;
#else
- mem_cpy(&fp->buf[fp->fptr % SS(fp->fs)], wbuff, wcnt); /* Fit partial sector */
- fp->flag |= FA__DIRTY;
+ mem_cpy(&fp->buf[fp->fptr % SS(fp->fs)], wbuff,
+ wcnt); /* Fit partial sector */
+ fp->flag |= FA__DIRTY;
#endif
- }
+ }
- if (fp->fptr > fp->fsize) fp->fsize = fp->fptr; /* Update file size if needed */
- fp->flag |= FA__WRITTEN; /* Set file change flag */
+ if (fp->fptr > fp->fsize)
+ fp->fsize = fp->fptr; /* Update file size if needed */
+ fp->flag |= FA__WRITTEN; /* Set file change flag */
- LEAVE_FF(fp->fs, FR_OK);
+ LEAVE_FF(fp->fs, FR_OK);
}
-
-
-
/*-----------------------------------------------------------------------*/
/* Synchronize the File */
/*-----------------------------------------------------------------------*/
-FRESULT f_sync (
- FIL* fp /* Pointer to the file object */
-)
+FRESULT
+f_sync(FIL* fp /* Pointer to the file object */
+ )
{
- FRESULT res;
- DWORD tm;
- BYTE *dir;
-
-
- res = validate(fp); /* Check validity of the object */
- if (res == FR_OK) {
- if (fp->flag & FA__WRITTEN) { /* Has the file been written? */
- /* Write-back dirty buffer */
+ FRESULT res;
+ DWORD tm;
+ BYTE* dir;
+
+ res = validate(fp); /* Check validity of the object */
+ if (res == FR_OK) {
+ if (fp->flag & FA__WRITTEN) { /* Has the file been written? */
+ /* Write-back dirty buffer */
#if !_FS_TINY
- if (fp->flag & FA__DIRTY) {
- if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
- LEAVE_FF(fp->fs, FR_DISK_ERR);
- fp->flag &= ~FA__DIRTY;
- }
-#endif
- /* Update the directory entry */
- res = move_window(fp->fs, fp->dir_sect);
- if (res == FR_OK) {
- dir = fp->dir_ptr;
- dir[DIR_Attr] |= AM_ARC; /* Set archive bit */
- ST_DWORD(dir + DIR_FileSize, fp->fsize); /* Update file size */
- st_clust(dir, fp->sclust); /* Update start cluster */
- tm = GET_FATTIME(); /* Update updated time */
- ST_DWORD(dir + DIR_WrtTime, tm);
- ST_WORD(dir + DIR_LstAccDate, 0);
- fp->flag &= ~FA__WRITTEN;
- fp->fs->wflag = 1;
- res = sync_fs(fp->fs);
- }
- }
- }
-
- LEAVE_FF(fp->fs, res);
+ if (fp->flag & FA__DIRTY) {
+ if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
+ LEAVE_FF(fp->fs, FR_DISK_ERR);
+ fp->flag &= ~FA__DIRTY;
+ }
+#endif
+ /* Update the directory entry */
+ res = move_window(fp->fs, fp->dir_sect);
+ if (res == FR_OK) {
+ dir = fp->dir_ptr;
+ dir[DIR_Attr] |= AM_ARC; /* Set archive bit */
+ ST_DWORD(dir + DIR_FileSize, fp->fsize); /* Update file size */
+ st_clust(dir, fp->sclust); /* Update start cluster */
+ tm = GET_FATTIME(); /* Update updated time */
+ ST_DWORD(dir + DIR_WrtTime, tm);
+ ST_WORD(dir + DIR_LstAccDate, 0);
+ fp->flag &= ~FA__WRITTEN;
+ fp->fs->wflag = 1;
+ res = sync_fs(fp->fs);
+ }
+ }
+ }
+
+ LEAVE_FF(fp->fs, res);
}
#endif /* !_FS_READONLY */
-
-
-
/*-----------------------------------------------------------------------*/
/* Close File */
/*-----------------------------------------------------------------------*/
-FRESULT f_close (
- FIL *fp /* Pointer to the file object to be closed */
-)
+FRESULT
+f_close(FIL* fp /* Pointer to the file object to be closed */
+ )
{
- FRESULT res;
-
+ FRESULT res;
#if !_FS_READONLY
- res = f_sync(fp); /* Flush cached data */
- if (res == FR_OK)
+ res = f_sync(fp); /* Flush cached data */
+ if (res == FR_OK)
#endif
- {
- res = validate(fp); /* Lock volume */
- if (res == FR_OK) {
+ {
+ res = validate(fp); /* Lock volume */
+ if (res == FR_OK) {
#if _FS_REENTRANT
- FATFS *fs = fp->fs;
+ FATFS* fs = fp->fs;
#endif
#if _FS_LOCK
- res = dec_lock(fp->lockid); /* Decrement file open counter */
- if (res == FR_OK)
+ res = dec_lock(fp->lockid); /* Decrement file open counter */
+ if (res == FR_OK)
#endif
- fp->fs = 0; /* Invalidate file object */
+ fp->fs = 0; /* Invalidate file object */
#if _FS_REENTRANT
- unlock_fs(fs, FR_OK); /* Unlock volume */
+ unlock_fs(fs, FR_OK); /* Unlock volume */
#endif
- }
- }
- return res;
+ }
+ }
+ return res;
}
-
-
-
/*-----------------------------------------------------------------------*/
/* Change Current Directory or Current Drive, Get Current Directory */
/*-----------------------------------------------------------------------*/
#if _FS_RPATH >= 1
#if _VOLUMES >= 2
-FRESULT f_chdrive (
- const TCHAR* path /* Drive number */
-)
+FRESULT
+f_chdrive(const TCHAR* path /* Drive number */
+ )
{
- int vol;
-
+ int vol;
- vol = get_ldnumber(&path);
- if (vol < 0) return FR_INVALID_DRIVE;
+ vol = get_ldnumber(&path);
+ if (vol < 0)
+ return FR_INVALID_DRIVE;
- CurrVol = (BYTE)vol;
+ CurrVol = (BYTE)vol;
- return FR_OK;
+ return FR_OK;
}
#endif
-
-FRESULT f_chdir (
- const TCHAR* path /* Pointer to the directory path */
-)
+FRESULT
+f_chdir(const TCHAR* path /* Pointer to the directory path */
+ )
{
- FRESULT res;
- DIR dj;
- DEFINE_NAMEBUF;
-
-
- /* Get logical drive number */
- res = find_volume(&dj.fs, &path, 0);
- if (res == FR_OK) {
- INIT_BUF(dj);
- res = follow_path(&dj, path); /* Follow the path */
- FREE_BUF();
- if (res == FR_OK) { /* Follow completed */
- if (!dj.dir) {
- dj.fs->cdir = dj.sclust; /* Start directory itself */
- } else {
- if (dj.dir[DIR_Attr] & AM_DIR) /* Reached to the directory */
- dj.fs->cdir = ld_clust(dj.fs, dj.dir);
- else
- res = FR_NO_PATH; /* Reached but a file */
- }
- }
- if (res == FR_NO_FILE) res = FR_NO_PATH;
- }
-
- LEAVE_FF(dj.fs, res);
+ FRESULT res;
+ DIR dj;
+ DEFINE_NAMEBUF;
+
+ /* Get logical drive number */
+ res = find_volume(&dj.fs, &path, 0);
+ if (res == FR_OK) {
+ INIT_BUF(dj);
+ res = follow_path(&dj, path); /* Follow the path */
+ FREE_BUF();
+ if (res == FR_OK) { /* Follow completed */
+ if (!dj.dir) {
+ dj.fs->cdir = dj.sclust; /* Start directory itself */
+ } else {
+ if (dj.dir[DIR_Attr] & AM_DIR) /* Reached to the directory */
+ dj.fs->cdir = ld_clust(dj.fs, dj.dir);
+ else
+ res = FR_NO_PATH; /* Reached but a file */
+ }
+ }
+ if (res == FR_NO_FILE)
+ res = FR_NO_PATH;
+ }
+
+ LEAVE_FF(dj.fs, res);
}
-
#if _FS_RPATH >= 2
-FRESULT f_getcwd (
- TCHAR* buff, /* Pointer to the directory path */
- UINT len /* Size of path */
-)
+FRESULT
+f_getcwd(TCHAR* buff, /* Pointer to the directory path */
+ UINT len /* Size of path */
+ )
{
- FRESULT res;
- DIR dj;
- UINT i, n;
- DWORD ccl;
- TCHAR *tp;
- FILINFO fno;
- DEFINE_NAMEBUF;
-
-
- *buff = 0;
- /* Get logical drive number */
- res = find_volume(&dj.fs, (const TCHAR**)&buff, 0); /* Get current volume */
- if (res == FR_OK) {
- INIT_BUF(dj);
- i = len; /* Bottom of buffer (directory stack base) */
- dj.sclust = dj.fs->cdir; /* Start to follow upper directory from current directory */
- while ((ccl = dj.sclust) != 0) { /* Repeat while current directory is a sub-directory */
- res = dir_sdi(&dj, 1); /* Get parent directory */
- if (res != FR_OK) break;
- res = dir_read(&dj, 0);
- if (res != FR_OK) break;
- dj.sclust = ld_clust(dj.fs, dj.dir); /* Goto parent directory */
- res = dir_sdi(&dj, 0);
- if (res != FR_OK) break;
- do { /* Find the entry links to the child directory */
- res = dir_read(&dj, 0);
- if (res != FR_OK) break;
- if (ccl == ld_clust(dj.fs, dj.dir)) break; /* Found the entry */
- res = dir_next(&dj, 0);
- } while (res == FR_OK);
- if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */
- if (res != FR_OK) break;
+ FRESULT res;
+ DIR dj;
+ UINT i, n;
+ DWORD ccl;
+ TCHAR* tp;
+ FILINFO fno;
+ DEFINE_NAMEBUF;
+
+ *buff = 0;
+ /* Get logical drive number */
+ res = find_volume(&dj.fs, (const TCHAR**)&buff, 0); /* Get current volume */
+ if (res == FR_OK) {
+ INIT_BUF(dj);
+ i = len; /* Bottom of buffer (directory stack base) */
+ dj.sclust =
+ dj.fs->cdir; /* Start to follow upper directory from current
+ directory */
+ while ((ccl = dj.sclust) !=
+ 0) { /* Repeat while current directory is a sub-directory */
+ res = dir_sdi(&dj, 1); /* Get parent directory */
+ if (res != FR_OK)
+ break;
+ res = dir_read(&dj, 0);
+ if (res != FR_OK)
+ break;
+ dj.sclust = ld_clust(dj.fs, dj.dir); /* Goto parent directory */
+ res = dir_sdi(&dj, 0);
+ if (res != FR_OK)
+ break;
+ do { /* Find the entry links to the child directory */
+ res = dir_read(&dj, 0);
+ if (res != FR_OK)
+ break;
+ if (ccl == ld_clust(dj.fs, dj.dir))
+ break; /* Found the entry */
+ res = dir_next(&dj, 0);
+ } while (res == FR_OK);
+ if (res == FR_NO_FILE)
+ res = FR_INT_ERR; /* It cannot be 'not found'. */
+ if (res != FR_OK)
+ break;
#if _USE_LFN
- fno.lfname = buff;
- fno.lfsize = i;
+ fno.lfname = buff;
+ fno.lfsize = i;
#endif
- get_fileinfo(&dj, &fno); /* Get the directory name and push it to the buffer */
- tp = fno.fname;
+ get_fileinfo(
+ &dj,
+ &fno); /* Get the directory name and push it to the buffer */
+ tp = fno.fname;
#if _USE_LFN
- if (*buff) tp = buff;
-#endif
- for (n = 0; tp[n]; n++) ;
- if (i < n + 3) {
- res = FR_NOT_ENOUGH_CORE; break;
- }
- while (n) buff[--i] = tp[--n];
- buff[--i] = '/';
- }
- tp = buff;
- if (res == FR_OK) {
+ if (*buff)
+ tp = buff;
+#endif
+ for (n = 0; tp[n]; n++)
+ ;
+ if (i < n + 3) {
+ res = FR_NOT_ENOUGH_CORE;
+ break;
+ }
+ while (n)
+ buff[--i] = tp[--n];
+ buff[--i] = '/';
+ }
+ tp = buff;
+ if (res == FR_OK) {
#if _VOLUMES >= 2
- *tp++ = '0' + CurrVol; /* Put drive number */
- *tp++ = ':';
-#endif
- if (i == len) { /* Root-directory */
- *tp++ = '/';
- } else { /* Sub-directroy */
- do /* Add stacked path str */
- *tp++ = buff[i++];
- while (i < len);
- }
- }
- *tp = 0;
- FREE_BUF();
- }
-
- LEAVE_FF(dj.fs, res);
+ *tp++ = '0' + CurrVol; /* Put drive number */
+ *tp++ = ':';
+#endif
+ if (i == len) { /* Root-directory */
+ *tp++ = '/';
+ } else { /* Sub-directroy */
+ do /* Add stacked path str */
+ *tp++ = buff[i++];
+ while (i < len);
+ }
+ }
+ *tp = 0;
+ FREE_BUF();
+ }
+
+ LEAVE_FF(dj.fs, res);
}
#endif /* _FS_RPATH >= 2 */
#endif /* _FS_RPATH >= 1 */
-
-
#if _FS_MINIMIZE <= 2
/*-----------------------------------------------------------------------*/
/* Seek File R/W Pointer */
/*-----------------------------------------------------------------------*/
-FRESULT f_lseek (
- FIL* fp, /* Pointer to the file object */
- DWORD ofs /* File pointer from top of file */
-)
+FRESULT
+f_lseek(FIL* fp, /* Pointer to the file object */
+ DWORD ofs /* File pointer from top of file */
+ )
{
- FRESULT res;
- DWORD clst, bcs, nsect, ifptr;
+ FRESULT res;
+ DWORD clst, bcs, nsect, ifptr;
#if _USE_FASTSEEK
- DWORD cl, pcl, ncl, tcl, dsc, tlen, ulen, *tbl;
+ DWORD cl, pcl, ncl, tcl, dsc, tlen, ulen, *tbl;
#endif
-
- res = validate(fp); /* Check validity of the object */
- if (res != FR_OK) LEAVE_FF(fp->fs, res);
- if (fp->err) /* Check error */
- LEAVE_FF(fp->fs, (FRESULT)fp->err);
+ res = validate(fp); /* Check validity of the object */
+ if (res != FR_OK)
+ LEAVE_FF(fp->fs, res);
+ if (fp->err) /* Check error */
+ LEAVE_FF(fp->fs, (FRESULT)fp->err);
#if _USE_FASTSEEK
- if (fp->cltbl) { /* Fast seek */
- if (ofs == CREATE_LINKMAP) { /* Create CLMT */
- tbl = fp->cltbl;
- tlen = *tbl++; ulen = 2; /* Given table size and required table size */
- cl = fp->sclust; /* Top of the chain */
- if (cl) {
- do {
- /* Get a fragment */
- tcl = cl; ncl = 0; ulen += 2; /* Top, length and used items */
- do {
- pcl = cl; ncl++;
- cl = get_fat(fp->fs, cl);
- if (cl <= 1) ABORT(fp->fs, FR_INT_ERR);
- if (cl == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
- } while (cl == pcl + 1);
- if (ulen <= tlen) { /* Store the length and top of the fragment */
- *tbl++ = ncl; *tbl++ = tcl;
- }
- } while (cl < fp->fs->n_fatent); /* Repeat until end of chain */
- }
- *fp->cltbl = ulen; /* Number of items used */
- if (ulen <= tlen)
- *tbl = 0; /* Terminate table */
- else
- res = FR_NOT_ENOUGH_CORE; /* Given table size is smaller than required */
-
- } else { /* Fast seek */
- if (ofs > fp->fsize) /* Clip offset at the file size */
- ofs = fp->fsize;
- fp->fptr = ofs; /* Set file pointer */
- if (ofs) {
- fp->clust = clmt_clust(fp, ofs - 1);
- dsc = clust2sect(fp->fs, fp->clust);
- if (!dsc) ABORT(fp->fs, FR_INT_ERR);
- dsc += (ofs - 1) / SS(fp->fs) & (fp->fs->csize - 1);
- if (fp->fptr % SS(fp->fs) && dsc != fp->dsect) { /* Refill sector cache if needed */
+ if (fp->cltbl) { /* Fast seek */
+ if (ofs == CREATE_LINKMAP) { /* Create CLMT */
+ tbl = fp->cltbl;
+ tlen = *tbl++;
+ ulen = 2; /* Given table size and required table size */
+ cl = fp->sclust; /* Top of the chain */
+ if (cl) {
+ do {
+ /* Get a fragment */
+ tcl = cl;
+ ncl = 0;
+ ulen += 2; /* Top, length and used items */
+ do {
+ pcl = cl;
+ ncl++;
+ cl = get_fat(fp->fs, cl);
+ if (cl <= 1)
+ ABORT(fp->fs, FR_INT_ERR);
+ if (cl == 0xFFFFFFFF)
+ ABORT(fp->fs, FR_DISK_ERR);
+ } while (cl == pcl + 1);
+ if (ulen <=
+ tlen) { /* Store the length and top of the fragment */
+ *tbl++ = ncl;
+ *tbl++ = tcl;
+ }
+ } while (cl < fp->fs->n_fatent); /* Repeat until end of chain */
+ }
+ *fp->cltbl = ulen; /* Number of items used */
+ if (ulen <= tlen)
+ *tbl = 0; /* Terminate table */
+ else
+ res = FR_NOT_ENOUGH_CORE; /* Given table size is smaller than
+ required */
+
+ } else { /* Fast seek */
+ if (ofs > fp->fsize) /* Clip offset at the file size */
+ ofs = fp->fsize;
+ fp->fptr = ofs; /* Set file pointer */
+ if (ofs) {
+ fp->clust = clmt_clust(fp, ofs - 1);
+ dsc = clust2sect(fp->fs, fp->clust);
+ if (!dsc)
+ ABORT(fp->fs, FR_INT_ERR);
+ dsc += (ofs - 1) / SS(fp->fs) & (fp->fs->csize - 1);
+ if (fp->fptr % SS(fp->fs) &&
+ dsc != fp->dsect) { /* Refill sector cache if needed */
#if !_FS_TINY
#if !_FS_READONLY
- if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */
- if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
- ABORT(fp->fs, FR_DISK_ERR);
- fp->flag &= ~FA__DIRTY;
- }
-#endif
- if (disk_read(fp->fs->drv, fp->buf, dsc, 1) != RES_OK) /* Load current sector */
- ABORT(fp->fs, FR_DISK_ERR);
-#endif
- fp->dsect = dsc;
- }
- }
- }
- } else
-#endif
-
- /* Normal Seek */
- {
- if (ofs > fp->fsize /* In read-only mode, clip offset with the file size */
+ if (fp->flag &
+ FA__DIRTY) { /* Write-back dirty sector cache */
+ if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) !=
+ RES_OK)
+ ABORT(fp->fs, FR_DISK_ERR);
+ fp->flag &= ~FA__DIRTY;
+ }
+#endif
+ if (disk_read(fp->fs->drv, fp->buf, dsc, 1) !=
+ RES_OK) /* Load current sector */
+ ABORT(fp->fs, FR_DISK_ERR);
+#endif
+ fp->dsect = dsc;
+ }
+ }
+ }
+ } else
+#endif
+
+ /* Normal Seek */
+ {
+ if (ofs >
+ fp->fsize /* In read-only mode, clip offset with the file size
+ */
#if !_FS_READONLY
- && !(fp->flag & FA_WRITE)
-#endif
- ) ofs = fp->fsize;
-
- ifptr = fp->fptr;
- fp->fptr = nsect = 0;
- if (ofs) {
- bcs = (DWORD)fp->fs->csize * SS(fp->fs); /* Cluster size (byte) */
- if (ifptr > 0 &&
- (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */
- fp->fptr = (ifptr - 1) & ~(bcs - 1); /* start from the current cluster */
- ofs -= fp->fptr;
- clst = fp->clust;
- } else { /* When seek to back cluster, */
- clst = fp->sclust; /* start from the first cluster */
+ && !(fp->flag & FA_WRITE)
+#endif
+ )
+ ofs = fp->fsize;
+
+ ifptr = fp->fptr;
+ fp->fptr = nsect = 0;
+ if (ofs) {
+ bcs = (DWORD)fp->fs->csize * SS(fp->fs); /* Cluster size (byte) */
+ if (ifptr > 0 &&
+ (ofs - 1) / bcs >=
+ (ifptr - 1) /
+ bcs) { /* When seek to same or following cluster, */
+ fp->fptr = (ifptr - 1) &
+ ~(bcs - 1); /* start from the current cluster */
+ ofs -= fp->fptr;
+ clst = fp->clust;
+ } else { /* When seek to back cluster, */
+ clst = fp->sclust; /* start from the first cluster */
#if !_FS_READONLY
- if (clst == 0) { /* If no cluster chain, create a new chain */
- clst = create_chain(fp->fs, 0);
- if (clst == 1) ABORT(fp->fs, FR_INT_ERR);
- if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
- fp->sclust = clst;
- }
-#endif
- fp->clust = clst;
- }
- if (clst != 0) {
- while (ofs > bcs) { /* Cluster following loop */
+ if (clst == 0) { /* If no cluster chain, create a new chain */
+ clst = create_chain(fp->fs, 0);
+ if (clst == 1)
+ ABORT(fp->fs, FR_INT_ERR);
+ if (clst == 0xFFFFFFFF)
+ ABORT(fp->fs, FR_DISK_ERR);
+ fp->sclust = clst;
+ }
+#endif
+ fp->clust = clst;
+ }
+ if (clst != 0) {
+ while (ofs > bcs) { /* Cluster following loop */
#if !_FS_READONLY
- if (fp->flag & FA_WRITE) { /* Check if in write mode or not */
- clst = create_chain(fp->fs, clst); /* Force stretch if in write mode */
- if (clst == 0) { /* When disk gets full, clip file size */
- ofs = bcs; break;
- }
- } else
-#endif
- clst = get_fat(fp->fs, clst); /* Follow cluster chain if not in write mode */
- if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
- if (clst <= 1 || clst >= fp->fs->n_fatent) ABORT(fp->fs, FR_INT_ERR);
- fp->clust = clst;
- fp->fptr += bcs;
- ofs -= bcs;
- }
- fp->fptr += ofs;
- if (ofs % SS(fp->fs)) {
- nsect = clust2sect(fp->fs, clst); /* Current sector */
- if (!nsect) ABORT(fp->fs, FR_INT_ERR);
- nsect += ofs / SS(fp->fs);
- }
- }
- }
- if (fp->fptr % SS(fp->fs) && nsect != fp->dsect) { /* Fill sector cache if needed */
+ if (fp->flag &
+ FA_WRITE) { /* Check if in write mode or not */
+ clst = create_chain(
+ fp->fs, clst); /* Force stretch if in write mode */
+ if (clst ==
+ 0) { /* When disk gets full, clip file size */
+ ofs = bcs;
+ break;
+ }
+ } else
+#endif
+ clst =
+ get_fat(fp->fs, clst); /* Follow cluster chain if
+ not in write mode */
+ if (clst == 0xFFFFFFFF)
+ ABORT(fp->fs, FR_DISK_ERR);
+ if (clst <= 1 || clst >= fp->fs->n_fatent)
+ ABORT(fp->fs, FR_INT_ERR);
+ fp->clust = clst;
+ fp->fptr += bcs;
+ ofs -= bcs;
+ }
+ fp->fptr += ofs;
+ if (ofs % SS(fp->fs)) {
+ nsect = clust2sect(fp->fs, clst); /* Current sector */
+ if (!nsect)
+ ABORT(fp->fs, FR_INT_ERR);
+ nsect += ofs / SS(fp->fs);
+ }
+ }
+ }
+ if (fp->fptr % SS(fp->fs) &&
+ nsect != fp->dsect) { /* Fill sector cache if needed */
#if !_FS_TINY
#if !_FS_READONLY
- if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */
- if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
- ABORT(fp->fs, FR_DISK_ERR);
- fp->flag &= ~FA__DIRTY;
- }
-#endif
- if (disk_read(fp->fs->drv, fp->buf, nsect, 1) != RES_OK) /* Fill sector cache */
- ABORT(fp->fs, FR_DISK_ERR);
-#endif
- fp->dsect = nsect;
- }
+ if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */
+ if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
+ ABORT(fp->fs, FR_DISK_ERR);
+ fp->flag &= ~FA__DIRTY;
+ }
+#endif
+ if (disk_read(fp->fs->drv, fp->buf, nsect, 1) !=
+ RES_OK) /* Fill sector cache */
+ ABORT(fp->fs, FR_DISK_ERR);
+#endif
+ fp->dsect = nsect;
+ }
#if !_FS_READONLY
- if (fp->fptr > fp->fsize) { /* Set file change flag if the file size is extended */
- fp->fsize = fp->fptr;
- fp->flag |= FA__WRITTEN;
- }
+ if (fp->fptr >
+ fp->fsize) { /* Set file change flag if the file size is extended */
+ fp->fsize = fp->fptr;
+ fp->flag |= FA__WRITTEN;
+ }
#endif
- }
+ }
- LEAVE_FF(fp->fs, res);
+ LEAVE_FF(fp->fs, res);
}
-
-
#if _FS_MINIMIZE <= 1
/*-----------------------------------------------------------------------*/
/* Create a Directory Object */
/*-----------------------------------------------------------------------*/
-FRESULT f_opendir (
- DIR* dp, /* Pointer to directory object to create */
- const TCHAR* path /* Pointer to the directory path */
-)
+FRESULT
+f_opendir(DIR* dp, /* Pointer to directory object to create */
+ const TCHAR* path /* Pointer to the directory path */
+ )
{
- FRESULT res;
- FATFS* fs;
- DEFINE_NAMEBUF;
-
-
- if (!dp) return FR_INVALID_OBJECT;
-
- /* Get logical drive number */
- res = find_volume(&fs, &path, 0);
- if (res == FR_OK) {
- dp->fs = fs;
- INIT_BUF(*dp);
- res = follow_path(dp, path); /* Follow the path to the directory */
- FREE_BUF();
- if (res == FR_OK) { /* Follow completed */
- if (dp->dir) { /* It is not the origin directory itself */
- if (dp->dir[DIR_Attr] & AM_DIR) /* The object is a sub directory */
- dp->sclust = ld_clust(fs, dp->dir);
- else /* The object is a file */
- res = FR_NO_PATH;
- }
- if (res == FR_OK) {
- dp->id = fs->id;
- res = dir_sdi(dp, 0); /* Rewind directory */
+ FRESULT res;
+ FATFS* fs;
+ DEFINE_NAMEBUF;
+
+ if (!dp)
+ return FR_INVALID_OBJECT;
+
+ /* Get logical drive number */
+ res = find_volume(&fs, &path, 0);
+ if (res == FR_OK) {
+ dp->fs = fs;
+ INIT_BUF(*dp);
+ res = follow_path(dp, path); /* Follow the path to the directory */
+ FREE_BUF();
+ if (res == FR_OK) { /* Follow completed */
+ if (dp->dir) { /* It is not the origin directory itself */
+ if (dp->dir[DIR_Attr] &
+ AM_DIR) /* The object is a sub directory */
+ dp->sclust = ld_clust(fs, dp->dir);
+ else /* The object is a file */
+ res = FR_NO_PATH;
+ }
+ if (res == FR_OK) {
+ dp->id = fs->id;
+ res = dir_sdi(dp, 0); /* Rewind directory */
#if _FS_LOCK
- if (res == FR_OK) {
- if (dp->sclust) {
- dp->lockid = inc_lock(dp, 0); /* Lock the sub directory */
- if (!dp->lockid)
- res = FR_TOO_MANY_OPEN_FILES;
- } else {
- dp->lockid = 0; /* Root directory need not to be locked */
- }
- }
-#endif
- }
- }
- if (res == FR_NO_FILE) res = FR_NO_PATH;
- }
- if (res != FR_OK) dp->fs = 0; /* Invalidate the directory object if function faild */
-
- LEAVE_FF(fs, res);
+ if (res == FR_OK) {
+ if (dp->sclust) {
+ dp->lockid =
+ inc_lock(dp, 0); /* Lock the sub directory */
+ if (!dp->lockid)
+ res = FR_TOO_MANY_OPEN_FILES;
+ } else {
+ dp->lockid =
+ 0; /* Root directory need not to be locked */
+ }
+ }
+#endif
+ }
+ }
+ if (res == FR_NO_FILE)
+ res = FR_NO_PATH;
+ }
+ if (res != FR_OK)
+ dp->fs = 0; /* Invalidate the directory object if function faild */
+
+ LEAVE_FF(fs, res);
}
-
-
-
/*-----------------------------------------------------------------------*/
/* Close Directory */
/*-----------------------------------------------------------------------*/
-FRESULT f_closedir (
- DIR *dp /* Pointer to the directory object to be closed */
-)
+FRESULT
+f_closedir(DIR* dp /* Pointer to the directory object to be closed */
+ )
{
- FRESULT res;
-
+ FRESULT res;
- res = validate(dp);
- if (res == FR_OK) {
+ res = validate(dp);
+ if (res == FR_OK) {
#if _FS_REENTRANT
- FATFS *fs = dp->fs;
+ FATFS* fs = dp->fs;
#endif
#if _FS_LOCK
- if (dp->lockid) /* Decrement sub-directory open counter */
- res = dec_lock(dp->lockid);
- if (res == FR_OK)
+ if (dp->lockid) /* Decrement sub-directory open counter */
+ res = dec_lock(dp->lockid);
+ if (res == FR_OK)
#endif
- dp->fs = 0; /* Invalidate directory object */
+ dp->fs = 0; /* Invalidate directory object */
#if _FS_REENTRANT
- unlock_fs(fs, FR_OK); /* Unlock volume */
+ unlock_fs(fs, FR_OK); /* Unlock volume */
#endif
- }
- return res;
+ }
+ return res;
}
-
-
-
/*-----------------------------------------------------------------------*/
/* Read Directory Entries in Sequence */
/*-----------------------------------------------------------------------*/
-FRESULT f_readdir (
- DIR* dp, /* Pointer to the open directory object */
- FILINFO* fno /* Pointer to file information to return */
-)
+FRESULT
+f_readdir(DIR* dp, /* Pointer to the open directory object */
+ FILINFO* fno /* Pointer to file information to return */
+ )
{
- FRESULT res;
- DEFINE_NAMEBUF;
-
-
- res = validate(dp); /* Check validity of the object */
- if (res == FR_OK) {
- if (!fno) {
- res = dir_sdi(dp, 0); /* Rewind the directory object */
- } else {
- INIT_BUF(*dp);
- res = dir_read(dp, 0); /* Read an item */
- if (res == FR_NO_FILE) { /* Reached end of directory */
- dp->sect = 0;
- res = FR_OK;
- }
- if (res == FR_OK) { /* A valid entry is found */
- get_fileinfo(dp, fno); /* Get the object information */
- res = dir_next(dp, 0); /* Increment index for next */
- if (res == FR_NO_FILE) {
- dp->sect = 0;
- res = FR_OK;
- }
- }
- FREE_BUF();
- }
- }
-
- LEAVE_FF(dp->fs, res);
+ FRESULT res;
+ DEFINE_NAMEBUF;
+
+ res = validate(dp); /* Check validity of the object */
+ if (res == FR_OK) {
+ if (!fno) {
+ res = dir_sdi(dp, 0); /* Rewind the directory object */
+ } else {
+ INIT_BUF(*dp);
+ res = dir_read(dp, 0); /* Read an item */
+ if (res == FR_NO_FILE) { /* Reached end of directory */
+ dp->sect = 0;
+ res = FR_OK;
+ }
+ if (res == FR_OK) { /* A valid entry is found */
+ get_fileinfo(dp, fno); /* Get the object information */
+ res = dir_next(dp, 0); /* Increment index for next */
+ if (res == FR_NO_FILE) {
+ dp->sect = 0;
+ res = FR_OK;
+ }
+ }
+ FREE_BUF();
+ }
+ }
+
+ LEAVE_FF(dp->fs, res);
}
-
-
#if _USE_FIND
/*-----------------------------------------------------------------------*/
/* Find next file */
/*-----------------------------------------------------------------------*/
-FRESULT f_findnext (
- DIR* dp, /* Pointer to the open directory object */
- FILINFO* fno /* Pointer to the file information structure */
-)
+FRESULT
+f_findnext(DIR* dp, /* Pointer to the open directory object */
+ FILINFO* fno /* Pointer to the file information structure */
+ )
{
- FRESULT res;
+ FRESULT res;
-
- for (;;) {
- res = f_readdir(dp, fno); /* Get a directory item */
- if (res != FR_OK || !fno || !fno->fname[0]) break; /* Terminate if any error or end of directory */
+ for (;;) {
+ res = f_readdir(dp, fno); /* Get a directory item */
+ if (res != FR_OK || !fno || !fno->fname[0])
+ break; /* Terminate if any error or end of directory */
#if _USE_LFN
- if (fno->lfname && pattern_matching(dp->pat, fno->lfname, 0, 0)) break; /* Test for LFN if exist */
+ if (fno->lfname && pattern_matching(dp->pat, fno->lfname, 0, 0))
+ break; /* Test for LFN if exist */
#endif
- if (pattern_matching(dp->pat, fno->fname, 0, 0)) break; /* Test for SFN */
- }
- return res;
-
+ if (pattern_matching(dp->pat, fno->fname, 0, 0))
+ break; /* Test for SFN */
+ }
+ return res;
}
-
-
/*-----------------------------------------------------------------------*/
/* Find first file */
/*-----------------------------------------------------------------------*/
-FRESULT f_findfirst (
- DIR* dp, /* Pointer to the blank directory object */
- FILINFO* fno, /* Pointer to the file information structure */
- const TCHAR* path, /* Pointer to the directory to open */
- const TCHAR* pattern /* Pointer to the matching pattern */
-)
+FRESULT
+f_findfirst(DIR* dp, /* Pointer to the blank directory object */
+ FILINFO* fno, /* Pointer to the file information structure */
+ const TCHAR* path, /* Pointer to the directory to open */
+ const TCHAR* pattern /* Pointer to the matching pattern */
+ )
{
- FRESULT res;
+ FRESULT res;
-
- dp->pat = pattern; /* Save pointer to pattern string */
- res = f_opendir(dp, path); /* Open the target directory */
- if (res == FR_OK)
- res = f_findnext(dp, fno); /* Find the first item */
- return res;
+ dp->pat = pattern; /* Save pointer to pattern string */
+ res = f_opendir(dp, path); /* Open the target directory */
+ if (res == FR_OK)
+ res = f_findnext(dp, fno); /* Find the first item */
+ return res;
}
-#endif /* _USE_FIND */
-
-
+#endif /* _USE_FIND */
#if _FS_MINIMIZE == 0
/*-----------------------------------------------------------------------*/
/* Get File Status */
/*-----------------------------------------------------------------------*/
-FRESULT f_stat (
- const TCHAR* path, /* Pointer to the file path */
- FILINFO* fno /* Pointer to file information to return */
-)
+FRESULT
+f_stat(const TCHAR* path, /* Pointer to the file path */
+ FILINFO* fno /* Pointer to file information to return */
+ )
{
- FRESULT res;
- DIR dj;
- DEFINE_NAMEBUF;
-
-
- /* Get logical drive number */
- res = find_volume(&dj.fs, &path, 0);
- if (res == FR_OK) {
- INIT_BUF(dj);
- res = follow_path(&dj, path); /* Follow the file path */
- if (res == FR_OK) { /* Follow completed */
- if (dj.dir) { /* Found an object */
- if (fno) get_fileinfo(&dj, fno);
- } else { /* It is root directory */
- res = FR_INVALID_NAME;
- }
- }
- FREE_BUF();
- }
-
- LEAVE_FF(dj.fs, res);
+ FRESULT res;
+ DIR dj;
+ DEFINE_NAMEBUF;
+
+ /* Get logical drive number */
+ res = find_volume(&dj.fs, &path, 0);
+ if (res == FR_OK) {
+ INIT_BUF(dj);
+ res = follow_path(&dj, path); /* Follow the file path */
+ if (res == FR_OK) { /* Follow completed */
+ if (dj.dir) { /* Found an object */
+ if (fno)
+ get_fileinfo(&dj, fno);
+ } else { /* It is root directory */
+ res = FR_INVALID_NAME;
+ }
+ }
+ FREE_BUF();
+ }
+
+ LEAVE_FF(dj.fs, res);
}
-
-
#if !_FS_READONLY
/*-----------------------------------------------------------------------*/
/* Get Number of Free Clusters */
/*-----------------------------------------------------------------------*/
-FRESULT f_getfree (
- const TCHAR* path, /* Path name of the logical drive number */
- DWORD* nclst, /* Pointer to a variable to return number of free clusters */
- FATFS** fatfs /* Pointer to return pointer to corresponding file system object */
-)
+FRESULT
+f_getfree(
+ const TCHAR* path, /* Path name of the logical drive number */
+ DWORD* nclst, /* Pointer to a variable to return number of free clusters */
+ FATFS** fatfs /* Pointer to return pointer to corresponding file system
+ object */
+ )
{
- FRESULT res;
- FATFS *fs;
- DWORD n, clst, sect, stat;
- UINT i;
- BYTE fat, *p;
-
-
- /* Get logical drive number */
- res = find_volume(fatfs, &path, 0);
- fs = *fatfs;
- if (res == FR_OK) {
- /* If free_clust is valid, return it without full cluster scan */
- if (fs->free_clust <= fs->n_fatent - 2) {
- *nclst = fs->free_clust;
- } else {
- /* Get number of free clusters */
- fat = fs->fs_type;
- n = 0;
- if (fat == FS_FAT12) {
- clst = 2;
- do {
- stat = get_fat(fs, clst);
- if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; }
- if (stat == 1) { res = FR_INT_ERR; break; }
- if (stat == 0) n++;
- } while (++clst < fs->n_fatent);
- } else {
- clst = fs->n_fatent;
- sect = fs->fatbase;
- i = 0; p = 0;
- do {
- if (!i) {
- res = move_window(fs, sect++);
- if (res != FR_OK) break;
- p = fs->win;
- i = SS(fs);
- }
- if (fat == FS_FAT16) {
- if (LD_WORD(p) == 0) n++;
- p += 2; i -= 2;
- } else {
- if ((LD_DWORD(p) & 0x0FFFFFFF) == 0) n++;
- p += 4; i -= 4;
- }
- } while (--clst);
- }
- fs->free_clust = n;
- fs->fsi_flag |= 1;
- *nclst = n;
- }
- }
- LEAVE_FF(fs, res);
+ FRESULT res;
+ FATFS* fs;
+ DWORD n, clst, sect, stat;
+ UINT i;
+ BYTE fat, *p;
+
+ /* Get logical drive number */
+ res = find_volume(fatfs, &path, 0);
+ fs = *fatfs;
+ if (res == FR_OK) {
+ /* If free_clust is valid, return it without full cluster scan */
+ if (fs->free_clust <= fs->n_fatent - 2) {
+ *nclst = fs->free_clust;
+ } else {
+ /* Get number of free clusters */
+ fat = fs->fs_type;
+ n = 0;
+ if (fat == FS_FAT12) {
+ clst = 2;
+ do {
+ stat = get_fat(fs, clst);
+ if (stat == 0xFFFFFFFF) {
+ res = FR_DISK_ERR;
+ break;
+ }
+ if (stat == 1) {
+ res = FR_INT_ERR;
+ break;
+ }
+ if (stat == 0)
+ n++;
+ } while (++clst < fs->n_fatent);
+ } else {
+ clst = fs->n_fatent;
+ sect = fs->fatbase;
+ i = 0;
+ p = 0;
+ do {
+ if (!i) {
+ res = move_window(fs, sect++);
+ if (res != FR_OK)
+ break;
+ p = fs->win;
+ i = SS(fs);
+ }
+ if (fat == FS_FAT16) {
+ if (LD_WORD(p) == 0)
+ n++;
+ p += 2;
+ i -= 2;
+ } else {
+ if ((LD_DWORD(p) & 0x0FFFFFFF) == 0)
+ n++;
+ p += 4;
+ i -= 4;
+ }
+ } while (--clst);
+ }
+ fs->free_clust = n;
+ fs->fsi_flag |= 1;
+ *nclst = n;
+ }
+ }
+ LEAVE_FF(fs, res);
}
-
-
-
/*-----------------------------------------------------------------------*/
/* Truncate File */
/*-----------------------------------------------------------------------*/
-FRESULT f_truncate (
- FIL* fp /* Pointer to the file object */
-)
+FRESULT
+f_truncate(FIL* fp /* Pointer to the file object */
+ )
{
- FRESULT res;
- DWORD ncl;
-
-
- res = validate(fp); /* Check validity of the object */
- if (res == FR_OK) {
- if (fp->err) { /* Check error */
- res = (FRESULT)fp->err;
- } else {
- if (!(fp->flag & FA_WRITE)) /* Check access mode */
- res = FR_DENIED;
- }
- }
- if (res == FR_OK) {
- if (fp->fsize > fp->fptr) {
- fp->fsize = fp->fptr; /* Set file size to current R/W point */
- fp->flag |= FA__WRITTEN;
- if (fp->fptr == 0) { /* When set file size to zero, remove entire cluster chain */
- res = remove_chain(fp->fs, fp->sclust);
- fp->sclust = 0;
- } else { /* When truncate a part of the file, remove remaining clusters */
- ncl = get_fat(fp->fs, fp->clust);
- res = FR_OK;
- if (ncl == 0xFFFFFFFF) res = FR_DISK_ERR;
- if (ncl == 1) res = FR_INT_ERR;
- if (res == FR_OK && ncl < fp->fs->n_fatent) {
- res = put_fat(fp->fs, fp->clust, 0x0FFFFFFF);
- if (res == FR_OK) res = remove_chain(fp->fs, ncl);
- }
- }
+ FRESULT res;
+ DWORD ncl;
+
+ res = validate(fp); /* Check validity of the object */
+ if (res == FR_OK) {
+ if (fp->err) { /* Check error */
+ res = (FRESULT)fp->err;
+ } else {
+ if (!(fp->flag & FA_WRITE)) /* Check access mode */
+ res = FR_DENIED;
+ }
+ }
+ if (res == FR_OK) {
+ if (fp->fsize > fp->fptr) {
+ fp->fsize = fp->fptr; /* Set file size to current R/W point */
+ fp->flag |= FA__WRITTEN;
+ if (fp->fptr == 0) { /* When set file size to zero, remove entire
+ cluster chain */
+ res = remove_chain(fp->fs, fp->sclust);
+ fp->sclust = 0;
+ } else { /* When truncate a part of the file, remove remaining
+ clusters */
+ ncl = get_fat(fp->fs, fp->clust);
+ res = FR_OK;
+ if (ncl == 0xFFFFFFFF)
+ res = FR_DISK_ERR;
+ if (ncl == 1)
+ res = FR_INT_ERR;
+ if (res == FR_OK && ncl < fp->fs->n_fatent) {
+ res = put_fat(fp->fs, fp->clust, 0x0FFFFFFF);
+ if (res == FR_OK)
+ res = remove_chain(fp->fs, ncl);
+ }
+ }
#if !_FS_TINY
- if (res == FR_OK && (fp->flag & FA__DIRTY)) {
- if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
- res = FR_DISK_ERR;
- else
- fp->flag &= ~FA__DIRTY;
- }
-#endif
- }
- if (res != FR_OK) fp->err = (FRESULT)res;
- }
-
- LEAVE_FF(fp->fs, res);
+ if (res == FR_OK && (fp->flag & FA__DIRTY)) {
+ if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
+ res = FR_DISK_ERR;
+ else
+ fp->flag &= ~FA__DIRTY;
+ }
+#endif
+ }
+ if (res != FR_OK)
+ fp->err = (FRESULT)res;
+ }
+
+ LEAVE_FF(fp->fs, res);
}
-
-
-
/*-----------------------------------------------------------------------*/
/* Delete a File or Directory */
/*-----------------------------------------------------------------------*/
-FRESULT f_unlink (
- const TCHAR* path /* Pointer to the file or directory path */
-)
+FRESULT
+f_unlink(const TCHAR* path /* Pointer to the file or directory path */
+ )
{
- FRESULT res;
- DIR dj, sdj;
- BYTE *dir;
- DWORD dclst = 0;
- DEFINE_NAMEBUF;
-
-
- /* Get logical drive number */
- res = find_volume(&dj.fs, &path, 1);
- if (res == FR_OK) {
- INIT_BUF(dj);
- res = follow_path(&dj, path); /* Follow the file path */
- if (_FS_RPATH && res == FR_OK && (dj.fn[NSFLAG] & NS_DOT))
- res = FR_INVALID_NAME; /* Cannot remove dot entry */
+ FRESULT res;
+ DIR dj, sdj;
+ BYTE* dir;
+ DWORD dclst = 0;
+ DEFINE_NAMEBUF;
+
+ /* Get logical drive number */
+ res = find_volume(&dj.fs, &path, 1);
+ if (res == FR_OK) {
+ INIT_BUF(dj);
+ res = follow_path(&dj, path); /* Follow the file path */
+ if (_FS_RPATH && res == FR_OK && (dj.fn[NSFLAG] & NS_DOT))
+ res = FR_INVALID_NAME; /* Cannot remove dot entry */
#if _FS_LOCK
- if (res == FR_OK) res = chk_lock(&dj, 2); /* Cannot remove open object */
-#endif
- if (res == FR_OK) { /* The object is accessible */
- dir = dj.dir;
- if (!dir) {
- res = FR_INVALID_NAME; /* Cannot remove the origin directory */
- } else {
- if (dir[DIR_Attr] & AM_RDO)
- res = FR_DENIED; /* Cannot remove R/O object */
- }
- if (res == FR_OK) {
- dclst = ld_clust(dj.fs, dir);
- if (dclst && (dir[DIR_Attr] & AM_DIR)) { /* Is it a sub-directory ? */
+ if (res == FR_OK)
+ res = chk_lock(&dj, 2); /* Cannot remove open object */
+#endif
+ if (res == FR_OK) { /* The object is accessible */
+ dir = dj.dir;
+ if (!dir) {
+ res = FR_INVALID_NAME; /* Cannot remove the origin directory */
+ } else {
+ if (dir[DIR_Attr] & AM_RDO)
+ res = FR_DENIED; /* Cannot remove R/O object */
+ }
+ if (res == FR_OK) {
+ dclst = ld_clust(dj.fs, dir);
+ if (dclst &&
+ (dir[DIR_Attr] & AM_DIR)) { /* Is it a sub-directory ? */
#if _FS_RPATH
- if (dclst == dj.fs->cdir) { /* Is it the current directory? */
- res = FR_DENIED;
- } else
-#endif
- {
- mem_cpy(&sdj, &dj, sizeof (DIR)); /* Open the sub-directory */
- sdj.sclust = dclst;
- res = dir_sdi(&sdj, 2);
- if (res == FR_OK) {
- res = dir_read(&sdj, 0); /* Read an item (excluding dot entries) */
- if (res == FR_OK) res = FR_DENIED; /* Not empty? (cannot remove) */
- if (res == FR_NO_FILE) res = FR_OK; /* Empty? (can remove) */
- }
- }
- }
- }
- if (res == FR_OK) {
- res = dir_remove(&dj); /* Remove the directory entry */
- if (res == FR_OK && dclst) /* Remove the cluster chain if exist */
- res = remove_chain(dj.fs, dclst);
- if (res == FR_OK) res = sync_fs(dj.fs);
- }
- }
- FREE_BUF();
- }
-
- LEAVE_FF(dj.fs, res);
+ if (dclst ==
+ dj.fs->cdir) { /* Is it the current directory? */
+ res = FR_DENIED;
+ } else
+#endif
+ {
+ mem_cpy(&sdj, &dj,
+ sizeof(DIR)); /* Open the sub-directory */
+ sdj.sclust = dclst;
+ res = dir_sdi(&sdj, 2);
+ if (res == FR_OK) {
+ res = dir_read(
+ &sdj,
+ 0); /* Read an item (excluding dot entries) */
+ if (res == FR_OK)
+ res =
+ FR_DENIED; /* Not empty? (cannot remove) */
+ if (res == FR_NO_FILE)
+ res = FR_OK; /* Empty? (can remove) */
+ }
+ }
+ }
+ }
+ if (res == FR_OK) {
+ res = dir_remove(&dj); /* Remove the directory entry */
+ if (res == FR_OK &&
+ dclst) /* Remove the cluster chain if exist */
+ res = remove_chain(dj.fs, dclst);
+ if (res == FR_OK)
+ res = sync_fs(dj.fs);
+ }
+ }
+ FREE_BUF();
+ }
+
+ LEAVE_FF(dj.fs, res);
}
-
-
-
/*-----------------------------------------------------------------------*/
/* Create a Directory */
/*-----------------------------------------------------------------------*/
-FRESULT f_mkdir (
- const TCHAR* path /* Pointer to the directory path */
-)
+FRESULT
+f_mkdir(const TCHAR* path /* Pointer to the directory path */
+ )
{
- FRESULT res;
- DIR dj;
- BYTE *dir, n;
- DWORD dsc, dcl, pcl, tm = GET_FATTIME();
- DEFINE_NAMEBUF;
-
-
- /* Get logical drive number */
- res = find_volume(&dj.fs, &path, 1);
- if (res == FR_OK) {
- INIT_BUF(dj);
- res = follow_path(&dj, path); /* Follow the file path */
- if (res == FR_OK) res = FR_EXIST; /* Any object with same name is already existing */
- if (_FS_RPATH && res == FR_NO_FILE && (dj.fn[NSFLAG] & NS_DOT))
- res = FR_INVALID_NAME;
- if (res == FR_NO_FILE) { /* Can create a new directory */
- dcl = create_chain(dj.fs, 0); /* Allocate a cluster for the new directory table */
- res = FR_OK;
- if (dcl == 0) res = FR_DENIED; /* No space to allocate a new cluster */
- if (dcl == 1) res = FR_INT_ERR;
- if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR;
- if (res == FR_OK) /* Flush FAT */
- res = sync_window(dj.fs);
- if (res == FR_OK) { /* Initialize the new directory table */
- dsc = clust2sect(dj.fs, dcl);
- dir = dj.fs->win;
- mem_set(dir, 0, SS(dj.fs));
- mem_set(dir + DIR_Name, ' ', 11); /* Create "." entry */
- dir[DIR_Name] = '.';
- dir[DIR_Attr] = AM_DIR;
- ST_DWORD(dir + DIR_WrtTime, tm);
- st_clust(dir, dcl);
- mem_cpy(dir + SZ_DIRE, dir, SZ_DIRE); /* Create ".." entry */
- dir[SZ_DIRE + 1] = '.'; pcl = dj.sclust;
- if (dj.fs->fs_type == FS_FAT32 && pcl == dj.fs->dirbase)
- pcl = 0;
- st_clust(dir + SZ_DIRE, pcl);
- for (n = dj.fs->csize; n; n--) { /* Write dot entries and clear following sectors */
- dj.fs->winsect = dsc++;
- dj.fs->wflag = 1;
- res = sync_window(dj.fs);
- if (res != FR_OK) break;
- mem_set(dir, 0, SS(dj.fs));
- }
- }
- if (res == FR_OK) res = dir_register(&dj); /* Register the object to the directoy */
- if (res != FR_OK) {
- remove_chain(dj.fs, dcl); /* Could not register, remove cluster chain */
- } else {
- dir = dj.dir;
- dir[DIR_Attr] = AM_DIR; /* Attribute */
- ST_DWORD(dir + DIR_WrtTime, tm); /* Created time */
- st_clust(dir, dcl); /* Table start cluster */
- dj.fs->wflag = 1;
- res = sync_fs(dj.fs);
- }
- }
- FREE_BUF();
- }
-
- LEAVE_FF(dj.fs, res);
+ FRESULT res;
+ DIR dj;
+ BYTE *dir, n;
+ DWORD dsc, dcl, pcl, tm = GET_FATTIME();
+ DEFINE_NAMEBUF;
+
+ /* Get logical drive number */
+ res = find_volume(&dj.fs, &path, 1);
+ if (res == FR_OK) {
+ INIT_BUF(dj);
+ res = follow_path(&dj, path); /* Follow the file path */
+ if (res == FR_OK)
+ res = FR_EXIST; /* Any object with same name is already existing */
+ if (_FS_RPATH && res == FR_NO_FILE && (dj.fn[NSFLAG] & NS_DOT))
+ res = FR_INVALID_NAME;
+ if (res == FR_NO_FILE) { /* Can create a new directory */
+ dcl = create_chain(
+ dj.fs, 0); /* Allocate a cluster for the new directory table */
+ res = FR_OK;
+ if (dcl == 0)
+ res = FR_DENIED; /* No space to allocate a new cluster */
+ if (dcl == 1)
+ res = FR_INT_ERR;
+ if (dcl == 0xFFFFFFFF)
+ res = FR_DISK_ERR;
+ if (res == FR_OK) /* Flush FAT */
+ res = sync_window(dj.fs);
+ if (res == FR_OK) { /* Initialize the new directory table */
+ dsc = clust2sect(dj.fs, dcl);
+ dir = dj.fs->win;
+ mem_set(dir, 0, SS(dj.fs));
+ mem_set(dir + DIR_Name, ' ', 11); /* Create "." entry */
+ dir[DIR_Name] = '.';
+ dir[DIR_Attr] = AM_DIR;
+ ST_DWORD(dir + DIR_WrtTime, tm);
+ st_clust(dir, dcl);
+ mem_cpy(dir + SZ_DIRE, dir, SZ_DIRE); /* Create ".." entry */
+ dir[SZ_DIRE + 1] = '.';
+ pcl = dj.sclust;
+ if (dj.fs->fs_type == FS_FAT32 && pcl == dj.fs->dirbase)
+ pcl = 0;
+ st_clust(dir + SZ_DIRE, pcl);
+ for (n = dj.fs->csize; n;
+ n--) { /* Write dot entries and clear following sectors */
+ dj.fs->winsect = dsc++;
+ dj.fs->wflag = 1;
+ res = sync_window(dj.fs);
+ if (res != FR_OK)
+ break;
+ mem_set(dir, 0, SS(dj.fs));
+ }
+ }
+ if (res == FR_OK)
+ res =
+ dir_register(&dj); /* Register the object to the directoy */
+ if (res != FR_OK) {
+ remove_chain(
+ dj.fs, dcl); /* Could not register, remove cluster chain */
+ } else {
+ dir = dj.dir;
+ dir[DIR_Attr] = AM_DIR; /* Attribute */
+ ST_DWORD(dir + DIR_WrtTime, tm); /* Created time */
+ st_clust(dir, dcl); /* Table start cluster */
+ dj.fs->wflag = 1;
+ res = sync_fs(dj.fs);
+ }
+ }
+ FREE_BUF();
+ }
+
+ LEAVE_FF(dj.fs, res);
}
-
-
-
/*-----------------------------------------------------------------------*/
/* Change Attribute */
/*-----------------------------------------------------------------------*/
-FRESULT f_chmod (
- const TCHAR* path, /* Pointer to the file path */
- BYTE attr, /* Attribute bits */
- BYTE mask /* Attribute mask to change */
-)
+FRESULT
+f_chmod(const TCHAR* path, /* Pointer to the file path */
+ BYTE attr, /* Attribute bits */
+ BYTE mask /* Attribute mask to change */
+ )
{
- FRESULT res;
- DIR dj;
- BYTE *dir;
- DEFINE_NAMEBUF;
-
-
- /* Get logical drive number */
- res = find_volume(&dj.fs, &path, 1);
- if (res == FR_OK) {
- INIT_BUF(dj);
- res = follow_path(&dj, path); /* Follow the file path */
- FREE_BUF();
- if (_FS_RPATH && res == FR_OK && (dj.fn[NSFLAG] & NS_DOT))
- res = FR_INVALID_NAME;
- if (res == FR_OK) {
- dir = dj.dir;
- if (!dir) { /* Is it a root directory? */
- res = FR_INVALID_NAME;
- } else { /* File or sub directory */
- mask &= AM_RDO|AM_HID|AM_SYS|AM_ARC; /* Valid attribute mask */
- dir[DIR_Attr] = (attr & mask) | (dir[DIR_Attr] & (BYTE)~mask); /* Apply attribute change */
- dj.fs->wflag = 1;
- res = sync_fs(dj.fs);
- }
- }
- }
-
- LEAVE_FF(dj.fs, res);
+ FRESULT res;
+ DIR dj;
+ BYTE* dir;
+ DEFINE_NAMEBUF;
+
+ /* Get logical drive number */
+ res = find_volume(&dj.fs, &path, 1);
+ if (res == FR_OK) {
+ INIT_BUF(dj);
+ res = follow_path(&dj, path); /* Follow the file path */
+ FREE_BUF();
+ if (_FS_RPATH && res == FR_OK && (dj.fn[NSFLAG] & NS_DOT))
+ res = FR_INVALID_NAME;
+ if (res == FR_OK) {
+ dir = dj.dir;
+ if (!dir) { /* Is it a root directory? */
+ res = FR_INVALID_NAME;
+ } else { /* File or sub directory */
+ mask &= AM_RDO | AM_HID | AM_SYS |
+ AM_ARC; /* Valid attribute mask */
+ dir[DIR_Attr] =
+ (attr & mask) |
+ (dir[DIR_Attr] & (BYTE)~mask); /* Apply attribute change */
+ dj.fs->wflag = 1;
+ res = sync_fs(dj.fs);
+ }
+ }
+ }
+
+ LEAVE_FF(dj.fs, res);
}
-
-
-
/*-----------------------------------------------------------------------*/
/* Rename File/Directory */
/*-----------------------------------------------------------------------*/
-FRESULT f_rename (
- const TCHAR* path_old, /* Pointer to the object to be renamed */
- const TCHAR* path_new /* Pointer to the new name */
-)
+FRESULT
+f_rename(const TCHAR* path_old, /* Pointer to the object to be renamed */
+ const TCHAR* path_new /* Pointer to the new name */
+ )
{
- FRESULT res;
- DIR djo, djn;
- BYTE buf[21], *dir;
- DWORD dw;
- DEFINE_NAMEBUF;
-
-
- /* Get logical drive number of the source object */
- res = find_volume(&djo.fs, &path_old, 1);
- if (res == FR_OK) {
- djn.fs = djo.fs;
- INIT_BUF(djo);
- res = follow_path(&djo, path_old); /* Check old object */
- if (_FS_RPATH && res == FR_OK && (djo.fn[NSFLAG] & NS_DOT))
- res = FR_INVALID_NAME;
+ FRESULT res;
+ DIR djo, djn;
+ BYTE buf[21], *dir;
+ DWORD dw;
+ DEFINE_NAMEBUF;
+
+ /* Get logical drive number of the source object */
+ res = find_volume(&djo.fs, &path_old, 1);
+ if (res == FR_OK) {
+ djn.fs = djo.fs;
+ INIT_BUF(djo);
+ res = follow_path(&djo, path_old); /* Check old object */
+ if (_FS_RPATH && res == FR_OK && (djo.fn[NSFLAG] & NS_DOT))
+ res = FR_INVALID_NAME;
#if _FS_LOCK
- if (res == FR_OK) res = chk_lock(&djo, 2);
-#endif
- if (res == FR_OK) { /* Old object is found */
- if (!djo.dir) { /* Is root dir? */
- res = FR_NO_FILE;
- } else {
- mem_cpy(buf, djo.dir + DIR_Attr, 21); /* Save information about object except name */
- mem_cpy(&djn, &djo, sizeof (DIR)); /* Duplicate the directory object */
- if (get_ldnumber(&path_new) >= 0) /* Snip drive number off and ignore it */
- res = follow_path(&djn, path_new); /* and make sure if new object name is not conflicting */
- else
- res = FR_INVALID_DRIVE;
- if (res == FR_OK) res = FR_EXIST; /* The new object name is already existing */
- if (res == FR_NO_FILE) { /* It is a valid path and no name collision */
- res = dir_register(&djn); /* Register the new entry */
- if (res == FR_OK) {
-/* Start of critical section where any interruption can cause a cross-link */
- dir = djn.dir; /* Copy information about object except name */
- mem_cpy(dir + 13, buf + 2, 19);
- dir[DIR_Attr] = buf[0] | AM_ARC;
- djo.fs->wflag = 1;
- if ((dir[DIR_Attr] & AM_DIR) && djo.sclust != djn.sclust) { /* Update .. entry in the sub-directory if needed */
- dw = clust2sect(djo.fs, ld_clust(djo.fs, dir));
- if (!dw) {
- res = FR_INT_ERR;
- } else {
- res = move_window(djo.fs, dw);
- dir = djo.fs->win + SZ_DIRE * 1; /* Ptr to .. entry */
- if (res == FR_OK && dir[1] == '.') {
- st_clust(dir, djn.sclust);
- djo.fs->wflag = 1;
- }
- }
- }
- if (res == FR_OK) {
- res = dir_remove(&djo); /* Remove old entry */
- if (res == FR_OK)
- res = sync_fs(djo.fs);
- }
-/* End of critical section */
- }
- }
- }
- }
- FREE_BUF();
- }
-
- LEAVE_FF(djo.fs, res);
+ if (res == FR_OK)
+ res = chk_lock(&djo, 2);
+#endif
+ if (res == FR_OK) { /* Old object is found */
+ if (!djo.dir) { /* Is root dir? */
+ res = FR_NO_FILE;
+ } else {
+ mem_cpy(buf, djo.dir + DIR_Attr,
+ 21); /* Save information about object except name */
+ mem_cpy(&djn, &djo,
+ sizeof(DIR)); /* Duplicate the directory object */
+ if (get_ldnumber(&path_new) >=
+ 0) /* Snip drive number off and ignore it */
+ res = follow_path(&djn, path_new); /* and make sure if new
+ object name is not
+ conflicting */
+ else
+ res = FR_INVALID_DRIVE;
+ if (res == FR_OK)
+ res =
+ FR_EXIST; /* The new object name is already existing */
+ if (res ==
+ FR_NO_FILE) { /* It is a valid path and no name collision */
+ res = dir_register(&djn); /* Register the new entry */
+ if (res == FR_OK) {
+ /* Start of critical section where any interruption can
+ * cause a cross-link */
+ dir = djn.dir; /* Copy information about object except
+ name */
+ mem_cpy(dir + 13, buf + 2, 19);
+ dir[DIR_Attr] = buf[0] | AM_ARC;
+ djo.fs->wflag = 1;
+ if ((dir[DIR_Attr] & AM_DIR) &&
+ djo.sclust !=
+ djn.sclust) { /* Update .. entry in the
+ sub-directory if needed */
+ dw = clust2sect(djo.fs, ld_clust(djo.fs, dir));
+ if (!dw) {
+ res = FR_INT_ERR;
+ } else {
+ res = move_window(djo.fs, dw);
+ dir = djo.fs->win +
+ SZ_DIRE * 1; /* Ptr to .. entry */
+ if (res == FR_OK && dir[1] == '.') {
+ st_clust(dir, djn.sclust);
+ djo.fs->wflag = 1;
+ }
+ }
+ }
+ if (res == FR_OK) {
+ res = dir_remove(&djo); /* Remove old entry */
+ if (res == FR_OK)
+ res = sync_fs(djo.fs);
+ }
+ /* End of critical section */
+ }
+ }
+ }
+ }
+ FREE_BUF();
+ }
+
+ LEAVE_FF(djo.fs, res);
}
-
-
-
/*-----------------------------------------------------------------------*/
/* Change Timestamp */
/*-----------------------------------------------------------------------*/
-FRESULT f_utime (
- const TCHAR* path, /* Pointer to the file/directory name */
- const FILINFO* fno /* Pointer to the time stamp to be set */
-)
+FRESULT
+f_utime(const TCHAR* path, /* Pointer to the file/directory name */
+ const FILINFO* fno /* Pointer to the time stamp to be set */
+ )
{
- FRESULT res;
- DIR dj;
- BYTE *dir;
- DEFINE_NAMEBUF;
-
-
- /* Get logical drive number */
- res = find_volume(&dj.fs, &path, 1);
- if (res == FR_OK) {
- INIT_BUF(dj);
- res = follow_path(&dj, path); /* Follow the file path */
- FREE_BUF();
- if (_FS_RPATH && res == FR_OK && (dj.fn[NSFLAG] & NS_DOT))
- res = FR_INVALID_NAME;
- if (res == FR_OK) {
- dir = dj.dir;
- if (!dir) { /* Root directory */
- res = FR_INVALID_NAME;
- } else { /* File or sub-directory */
- ST_WORD(dir + DIR_WrtTime, fno->ftime);
- ST_WORD(dir + DIR_WrtDate, fno->fdate);
- dj.fs->wflag = 1;
- res = sync_fs(dj.fs);
- }
- }
- }
-
- LEAVE_FF(dj.fs, res);
+ FRESULT res;
+ DIR dj;
+ BYTE* dir;
+ DEFINE_NAMEBUF;
+
+ /* Get logical drive number */
+ res = find_volume(&dj.fs, &path, 1);
+ if (res == FR_OK) {
+ INIT_BUF(dj);
+ res = follow_path(&dj, path); /* Follow the file path */
+ FREE_BUF();
+ if (_FS_RPATH && res == FR_OK && (dj.fn[NSFLAG] & NS_DOT))
+ res = FR_INVALID_NAME;
+ if (res == FR_OK) {
+ dir = dj.dir;
+ if (!dir) { /* Root directory */
+ res = FR_INVALID_NAME;
+ } else { /* File or sub-directory */
+ ST_WORD(dir + DIR_WrtTime, fno->ftime);
+ ST_WORD(dir + DIR_WrtDate, fno->fdate);
+ dj.fs->wflag = 1;
+ res = sync_fs(dj.fs);
+ }
+ }
+ }
+
+ LEAVE_FF(dj.fs, res);
}
#endif /* !_FS_READONLY */
#endif /* _FS_MINIMIZE <= 1 */
#endif /* _FS_MINIMIZE <= 2 */
-
-
-
#if _USE_LABEL
/*-----------------------------------------------------------------------*/
/* Get volume label */
/*-----------------------------------------------------------------------*/
-FRESULT f_getlabel (
- const TCHAR* path, /* Path name of the logical drive number */
- TCHAR* label, /* Pointer to a buffer to return the volume label */
- DWORD* vsn /* Pointer to a variable to return the volume serial number */
-)
+FRESULT
+f_getlabel(
+ const TCHAR* path, /* Path name of the logical drive number */
+ TCHAR* label, /* Pointer to a buffer to return the volume label */
+ DWORD* vsn /* Pointer to a variable to return the volume serial number */
+ )
{
- FRESULT res;
- DIR dj;
- UINT i, j;
+ FRESULT res;
+ DIR dj;
+ UINT i, j;
#if _USE_LFN && _LFN_UNICODE
- WCHAR w;
+ WCHAR w;
#endif
+ /* Get logical drive number */
+ res = find_volume(&dj.fs, &path, 0);
- /* Get logical drive number */
- res = find_volume(&dj.fs, &path, 0);
-
- /* Get volume label */
- if (res == FR_OK && label) {
- dj.sclust = 0; /* Open root directory */
- res = dir_sdi(&dj, 0);
- if (res == FR_OK) {
- res = dir_read(&dj, 1); /* Get an entry with AM_VOL */
- if (res == FR_OK) { /* A volume label is exist */
+ /* Get volume label */
+ if (res == FR_OK && label) {
+ dj.sclust = 0; /* Open root directory */
+ res = dir_sdi(&dj, 0);
+ if (res == FR_OK) {
+ res = dir_read(&dj, 1); /* Get an entry with AM_VOL */
+ if (res == FR_OK) { /* A volume label is exist */
#if _USE_LFN && _LFN_UNICODE
- i = j = 0;
- do {
- w = (i < 11) ? dj.dir[i++] : ' ';
- if (IsDBCS1(w) && i < 11 && IsDBCS2(dj.dir[i]))
- w = w << 8 | dj.dir[i++];
- label[j++] = ff_convert(w, 1); /* OEM -> Unicode */
- } while (j < 11);
+ i = j = 0;
+ do {
+ w = (i < 11) ? dj.dir[i++] : ' ';
+ if (IsDBCS1(w) && i < 11 && IsDBCS2(dj.dir[i]))
+ w = w << 8 | dj.dir[i++];
+ label[j++] = ff_convert(w, 1); /* OEM -> Unicode */
+ } while (j < 11);
#else
- mem_cpy(label, dj.dir, 11);
-#endif
- j = 11;
- do {
- label[j] = 0;
- if (!j) break;
- } while (label[--j] == ' ');
- }
- if (res == FR_NO_FILE) { /* No label, return nul string */
- label[0] = 0;
- res = FR_OK;
- }
- }
- }
-
- /* Get volume serial number */
- if (res == FR_OK && vsn) {
- res = move_window(dj.fs, dj.fs->volbase);
- if (res == FR_OK) {
- i = dj.fs->fs_type == FS_FAT32 ? BS_VolID32 : BS_VolID;
- *vsn = LD_DWORD(&dj.fs->win[i]);
- }
- }
-
- LEAVE_FF(dj.fs, res);
+ mem_cpy(label, dj.dir, 11);
+#endif
+ j = 11;
+ do {
+ label[j] = 0;
+ if (!j)
+ break;
+ } while (label[--j] == ' ');
+ }
+ if (res == FR_NO_FILE) { /* No label, return nul string */
+ label[0] = 0;
+ res = FR_OK;
+ }
+ }
+ }
+
+ /* Get volume serial number */
+ if (res == FR_OK && vsn) {
+ res = move_window(dj.fs, dj.fs->volbase);
+ if (res == FR_OK) {
+ i = dj.fs->fs_type == FS_FAT32 ? BS_VolID32 : BS_VolID;
+ *vsn = LD_DWORD(&dj.fs->win[i]);
+ }
+ }
+
+ LEAVE_FF(dj.fs, res);
}
-
-
#if !_FS_READONLY
/*-----------------------------------------------------------------------*/
/* Set volume label */
/*-----------------------------------------------------------------------*/
-FRESULT f_setlabel (
- const TCHAR* label /* Pointer to the volume label to set */
-)
+FRESULT
+f_setlabel(const TCHAR* label /* Pointer to the volume label to set */
+ )
{
- FRESULT res;
- DIR dj;
- BYTE vn[11];
- UINT i, j, sl;
- WCHAR w;
- DWORD tm;
-
-
- /* Get logical drive number */
- res = find_volume(&dj.fs, &label, 1);
- if (res) LEAVE_FF(dj.fs, res);
-
- /* Create a volume label in directory form */
- vn[0] = 0;
- for (sl = 0; label[sl]; sl++) ; /* Get name length */
- for ( ; sl && label[sl - 1] == ' '; sl--) ; /* Remove trailing spaces */
- if (sl) { /* Create volume label in directory form */
- i = j = 0;
- do {
+ FRESULT res;
+ DIR dj;
+ BYTE vn[11];
+ UINT i, j, sl;
+ WCHAR w;
+ DWORD tm;
+
+ /* Get logical drive number */
+ res = find_volume(&dj.fs, &label, 1);
+ if (res)
+ LEAVE_FF(dj.fs, res);
+
+ /* Create a volume label in directory form */
+ vn[0] = 0;
+ for (sl = 0; label[sl]; sl++)
+ ; /* Get name length */
+ for (; sl && label[sl - 1] == ' '; sl--)
+ ; /* Remove trailing spaces */
+ if (sl) { /* Create volume label in directory form */
+ i = j = 0;
+ do {
#if _USE_LFN && _LFN_UNICODE
- w = ff_convert(ff_wtoupper(label[i++]), 0);
+ w = ff_convert(ff_wtoupper(label[i++]), 0);
#else
- w = (BYTE)label[i++];
- if (IsDBCS1(w))
- w = (j < 10 && i < sl && IsDBCS2(label[i])) ? w << 8 | (BYTE)label[i++] : 0;
+ w = (BYTE)label[i++];
+ if (IsDBCS1(w))
+ w = (j < 10 && i < sl && IsDBCS2(label[i]))
+ ? w << 8 | (BYTE)label[i++]
+ : 0;
#if _USE_LFN
- w = ff_convert(ff_wtoupper(ff_convert(w, 1)), 0);
+ w = ff_convert(ff_wtoupper(ff_convert(w, 1)), 0);
#else
- if (IsLower(w)) w -= 0x20; /* To upper ASCII characters */
+ if (IsLower(w))
+ w -= 0x20; /* To upper ASCII characters */
#ifdef _EXCVT
- if (w >= 0x80) w = ExCvt[w - 0x80]; /* To upper extended characters (SBCS cfg) */
+ if (w >= 0x80)
+ w = ExCvt[w -
+ 0x80]; /* To upper extended characters (SBCS cfg) */
#else
- if (!_DF1S && w >= 0x80) w = 0; /* Reject extended characters (ASCII cfg) */
-#endif
-#endif
-#endif
- if (!w || chk_chr("\"*+,.:;<=>\?[]|\x7F", w) || j >= (UINT)((w >= 0x100) ? 10 : 11)) /* Reject invalid characters for volume label */
- LEAVE_FF(dj.fs, FR_INVALID_NAME);
- if (w >= 0x100) vn[j++] = (BYTE)(w >> 8);
- vn[j++] = (BYTE)w;
- } while (i < sl);
- while (j < 11) vn[j++] = ' '; /* Fill remaining name field */
- if (vn[0] == DDEM) LEAVE_FF(dj.fs, FR_INVALID_NAME); /* Reject illegal name (heading DDEM) */
- }
-
- /* Set volume label */
- dj.sclust = 0; /* Open root directory */
- res = dir_sdi(&dj, 0);
- if (res == FR_OK) {
- res = dir_read(&dj, 1); /* Get an entry with AM_VOL */
- if (res == FR_OK) { /* A volume label is found */
- if (vn[0]) {
- mem_cpy(dj.dir, vn, 11); /* Change the volume label name */
- tm = GET_FATTIME();
- ST_DWORD(dj.dir + DIR_WrtTime, tm);
- } else {
- dj.dir[0] = DDEM; /* Remove the volume label */
- }
- dj.fs->wflag = 1;
- res = sync_fs(dj.fs);
- } else { /* No volume label is found or error */
- if (res == FR_NO_FILE) {
- res = FR_OK;
- if (vn[0]) { /* Create volume label as new */
- res = dir_alloc(&dj, 1); /* Allocate an entry for volume label */
- if (res == FR_OK) {
- mem_set(dj.dir, 0, SZ_DIRE); /* Set volume label */
- mem_cpy(dj.dir, vn, 11);
- dj.dir[DIR_Attr] = AM_VOL;
- tm = GET_FATTIME();
- ST_DWORD(dj.dir + DIR_WrtTime, tm);
- dj.fs->wflag = 1;
- res = sync_fs(dj.fs);
- }
- }
- }
- }
- }
-
- LEAVE_FF(dj.fs, res);
+ if (!_DF1S && w >= 0x80)
+ w = 0; /* Reject extended characters (ASCII cfg) */
+#endif
+#endif
+#endif
+ if (!w || chk_chr("\"*+,.:;<=>\?[]|\x7F", w) ||
+ j >= (UINT)((w >= 0x100) ? 10 : 11)) /* Reject invalid
+ characters for volume
+ label */
+ LEAVE_FF(dj.fs, FR_INVALID_NAME);
+ if (w >= 0x100)
+ vn[j++] = (BYTE)(w >> 8);
+ vn[j++] = (BYTE)w;
+ } while (i < sl);
+ while (j < 11)
+ vn[j++] = ' '; /* Fill remaining name field */
+ if (vn[0] == DDEM)
+ LEAVE_FF(dj.fs,
+ FR_INVALID_NAME); /* Reject illegal name (heading DDEM) */
+ }
+
+ /* Set volume label */
+ dj.sclust = 0; /* Open root directory */
+ res = dir_sdi(&dj, 0);
+ if (res == FR_OK) {
+ res = dir_read(&dj, 1); /* Get an entry with AM_VOL */
+ if (res == FR_OK) { /* A volume label is found */
+ if (vn[0]) {
+ mem_cpy(dj.dir, vn, 11); /* Change the volume label name */
+ tm = GET_FATTIME();
+ ST_DWORD(dj.dir + DIR_WrtTime, tm);
+ } else {
+ dj.dir[0] = DDEM; /* Remove the volume label */
+ }
+ dj.fs->wflag = 1;
+ res = sync_fs(dj.fs);
+ } else { /* No volume label is found or error */
+ if (res == FR_NO_FILE) {
+ res = FR_OK;
+ if (vn[0]) { /* Create volume label as new */
+ res = dir_alloc(&dj,
+ 1); /* Allocate an entry for volume label */
+ if (res == FR_OK) {
+ mem_set(dj.dir, 0, SZ_DIRE); /* Set volume label */
+ mem_cpy(dj.dir, vn, 11);
+ dj.dir[DIR_Attr] = AM_VOL;
+ tm = GET_FATTIME();
+ ST_DWORD(dj.dir + DIR_WrtTime, tm);
+ dj.fs->wflag = 1;
+ res = sync_fs(dj.fs);
+ }
+ }
+ }
+ }
+ }
+
+ LEAVE_FF(dj.fs, res);
}
#endif /* !_FS_READONLY */
#endif /* _USE_LABEL */
-
-
/*-----------------------------------------------------------------------*/
/* Forward data to the stream directly (available on only tiny cfg) */
/*-----------------------------------------------------------------------*/
#if _USE_FORWARD && _FS_TINY
-FRESULT f_forward (
- FIL* fp, /* Pointer to the file object */
- UINT (*func)(const BYTE*,UINT), /* Pointer to the streaming function */
- UINT btf, /* Number of bytes to forward */
- UINT* bf /* Pointer to number of bytes forwarded */
-)
+FRESULT
+f_forward(FIL* fp, /* Pointer to the file object */
+ UINT (*func)(const BYTE*,
+ UINT), /* Pointer to the streaming function */
+ UINT btf, /* Number of bytes to forward */
+ UINT* bf /* Pointer to number of bytes forwarded */
+ )
{
- FRESULT res;
- DWORD remain, clst, sect;
- UINT rcnt;
- BYTE csect;
-
-
- *bf = 0; /* Clear transfer byte counter */
-
- res = validate(fp); /* Check validity of the object */
- if (res != FR_OK) LEAVE_FF(fp->fs, res);
- if (fp->err) /* Check error */
- LEAVE_FF(fp->fs, (FRESULT)fp->err);
- if (!(fp->flag & FA_READ)) /* Check access mode */
- LEAVE_FF(fp->fs, FR_DENIED);
-
- remain = fp->fsize - fp->fptr;
- if (btf > remain) btf = (UINT)remain; /* Truncate btf by remaining bytes */
-
- for ( ; btf && (*func)(0, 0); /* Repeat until all data transferred or stream becomes busy */
- fp->fptr += rcnt, *bf += rcnt, btf -= rcnt) {
- csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */
- if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */
- if (!csect) { /* On the cluster boundary? */
- clst = (fp->fptr == 0) ? /* On the top of the file? */
- fp->sclust : get_fat(fp->fs, fp->clust);
- if (clst <= 1) ABORT(fp->fs, FR_INT_ERR);
- if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
- fp->clust = clst; /* Update current cluster */
- }
- }
- sect = clust2sect(fp->fs, fp->clust); /* Get current data sector */
- if (!sect) ABORT(fp->fs, FR_INT_ERR);
- sect += csect;
- if (move_window(fp->fs, sect) != FR_OK) /* Move sector window */
- ABORT(fp->fs, FR_DISK_ERR);
- fp->dsect = sect;
- rcnt = SS(fp->fs) - (WORD)(fp->fptr % SS(fp->fs)); /* Forward data from sector window */
- if (rcnt > btf) rcnt = btf;
- rcnt = (*func)(&fp->fs->win[(WORD)fp->fptr % SS(fp->fs)], rcnt);
- if (!rcnt) ABORT(fp->fs, FR_INT_ERR);
- }
-
- LEAVE_FF(fp->fs, FR_OK);
+ FRESULT res;
+ DWORD remain, clst, sect;
+ UINT rcnt;
+ BYTE csect;
+
+ *bf = 0; /* Clear transfer byte counter */
+
+ res = validate(fp); /* Check validity of the object */
+ if (res != FR_OK)
+ LEAVE_FF(fp->fs, res);
+ if (fp->err) /* Check error */
+ LEAVE_FF(fp->fs, (FRESULT)fp->err);
+ if (!(fp->flag & FA_READ)) /* Check access mode */
+ LEAVE_FF(fp->fs, FR_DENIED);
+
+ remain = fp->fsize - fp->fptr;
+ if (btf > remain)
+ btf = (UINT)remain; /* Truncate btf by remaining bytes */
+
+ for (;
+ btf &&
+ (*func)(
+ 0,
+ 0); /* Repeat until all data transferred or stream becomes busy */
+ fp->fptr += rcnt, * bf += rcnt, btf -= rcnt) {
+ csect = (BYTE)(fp->fptr / SS(fp->fs) &
+ (fp->fs->csize - 1)); /* Sector offset in the cluster */
+ if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */
+ if (!csect) { /* On the cluster boundary? */
+ clst = (fp->fptr == 0) ? /* On the top of the file? */
+ fp->sclust
+ : get_fat(fp->fs, fp->clust);
+ if (clst <= 1)
+ ABORT(fp->fs, FR_INT_ERR);
+ if (clst == 0xFFFFFFFF)
+ ABORT(fp->fs, FR_DISK_ERR);
+ fp->clust = clst; /* Update current cluster */
+ }
+ }
+ sect = clust2sect(fp->fs, fp->clust); /* Get current data sector */
+ if (!sect)
+ ABORT(fp->fs, FR_INT_ERR);
+ sect += csect;
+ if (move_window(fp->fs, sect) != FR_OK) /* Move sector window */
+ ABORT(fp->fs, FR_DISK_ERR);
+ fp->dsect = sect;
+ rcnt =
+ SS(fp->fs) -
+ (WORD)(fp->fptr % SS(fp->fs)); /* Forward data from sector window */
+ if (rcnt > btf)
+ rcnt = btf;
+ rcnt = (*func)(&fp->fs->win[(WORD)fp->fptr % SS(fp->fs)], rcnt);
+ if (!rcnt)
+ ABORT(fp->fs, FR_INT_ERR);
+ }
+
+ LEAVE_FF(fp->fs, FR_OK);
}
#endif /* _USE_FORWARD */
-
-
#if _USE_MKFS && !_FS_READONLY
/*-----------------------------------------------------------------------*/
/* Create file system on the logical drive */
/*-----------------------------------------------------------------------*/
-#define N_ROOTDIR 512 /* Number of root directory entries for FAT12/16 */
-#define N_FATS 1 /* Number of FATs (1 or 2) */
-
-
-FRESULT f_mkfs (
- const TCHAR* path, /* Logical drive number */
- BYTE sfd, /* Partitioning rule 0:FDISK, 1:SFD */
- UINT au /* Size of allocation unit in unit of byte or sector */
-)
+#define N_ROOTDIR 512 /* Number of root directory entries for FAT12/16 */
+#define N_FATS 1 /* Number of FATs (1 or 2) */
+
+FRESULT
+f_mkfs(const TCHAR* path, /* Logical drive number */
+ BYTE sfd, /* Partitioning rule 0:FDISK, 1:SFD */
+ UINT au /* Size of allocation unit in unit of byte or sector */
+ )
{
- static const WORD vst[] = { 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 0};
- static const WORD cst[] = {32768, 16384, 8192, 4096, 2048, 16384, 8192, 4096, 2048, 1024, 512};
- int vol;
- BYTE fmt, md, sys, *tbl, pdrv, part;
- DWORD n_clst, vs, n, wsect;
- UINT i;
- DWORD b_vol, b_fat, b_dir, b_data; /* LBA */
- DWORD n_vol, n_rsv, n_fat, n_dir; /* Size */
- FATFS *fs;
- DSTATUS stat;
+ static const WORD vst[] = { 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 0 };
+ static const WORD cst[] = { 32768, 16384, 8192, 4096, 2048, 16384,
+ 8192, 4096, 2048, 1024, 512 };
+ int vol;
+ BYTE fmt, md, sys, *tbl, pdrv, part;
+ DWORD n_clst, vs, n, wsect;
+ UINT i;
+ DWORD b_vol, b_fat, b_dir, b_data; /* LBA */
+ DWORD n_vol, n_rsv, n_fat, n_dir; /* Size */
+ FATFS* fs;
+ DSTATUS stat;
#if _USE_TRIM
- DWORD eb[2];
-#endif
-
-
- /* Check mounted drive and clear work area */
- if (sfd > 1) return FR_INVALID_PARAMETER;
- vol = get_ldnumber(&path);
- if (vol < 0) return FR_INVALID_DRIVE;
- fs = FatFs[vol];
- if (!fs) return FR_NOT_ENABLED;
- fs->fs_type = 0;
- pdrv = LD2PD(vol); /* Physical drive */
- part = LD2PT(vol); /* Partition (0:auto detect, 1-4:get from partition table)*/
-
- /* Get disk statics */
- stat = disk_initialize(pdrv);
- if (stat & STA_NOINIT) return FR_NOT_READY;
- if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
-#if _MAX_SS != _MIN_SS /* Get disk sector size */
- if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK || SS(fs) > _MAX_SS || SS(fs) < _MIN_SS)
- return FR_DISK_ERR;
-#endif
- if (_MULTI_PARTITION && part) {
- /* Get partition information from partition table in the MBR */
- if (disk_read(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR;
- if (LD_WORD(fs->win + BS_55AA) != 0xAA55) return FR_MKFS_ABORTED;
- tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE];
- if (!tbl[4]) return FR_MKFS_ABORTED; /* No partition? */
- b_vol = LD_DWORD(tbl + 8); /* Volume start sector */
- n_vol = LD_DWORD(tbl + 12); /* Volume size */
- } else {
- /* Create a partition in this function */
- if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128)
- return FR_DISK_ERR;
- b_vol = (sfd) ? 0 : 63; /* Volume start sector */
- n_vol -= b_vol; /* Volume size */
- }
-
- if (au & (au - 1)) au = 0;
- if (!au) { /* AU auto selection */
- vs = n_vol / (2000 / (SS(fs) / 512));
- for (i = 0; vs < vst[i]; i++) ;
- au = cst[i];
- }
- if (au >= _MIN_SS) au /= SS(fs); /* Number of sectors per cluster */
- if (!au) au = 1;
- if (au > 128) au = 128;
-
- /* Pre-compute number of clusters and FAT sub-type */
- n_clst = n_vol / au;
- fmt = FS_FAT12;
- if (n_clst >= MIN_FAT16) fmt = FS_FAT16;
- if (n_clst >= MIN_FAT32) fmt = FS_FAT32;
-
- /* Determine offset and size of FAT structure */
- if (fmt == FS_FAT32) {
- n_fat = ((n_clst * 4) + 8 + SS(fs) - 1) / SS(fs);
- n_rsv = 32;
- n_dir = 0;
- } else {
- n_fat = (fmt == FS_FAT12) ? (n_clst * 3 + 1) / 2 + 3 : (n_clst * 2) + 4;
- n_fat = (n_fat + SS(fs) - 1) / SS(fs);
- n_rsv = 1;
- n_dir = (DWORD)N_ROOTDIR * SZ_DIRE / SS(fs);
- }
- b_fat = b_vol + n_rsv; /* FAT area start sector */
- b_dir = b_fat + n_fat * N_FATS; /* Directory area start sector */
- b_data = b_dir + n_dir; /* Data area start sector */
- if (n_vol < b_data + au - b_vol) return FR_MKFS_ABORTED; /* Too small volume */
-
- /* Align data start sector to erase block boundary (for flash memory media) */
- if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &n) != RES_OK || !n || n > 32768) n = 1;
- n = (b_data + n - 1) & ~(n - 1); /* Next nearest erase block from current data start */
- n = (n - b_data) / N_FATS;
- if (fmt == FS_FAT32) { /* FAT32: Move FAT offset */
- n_rsv += n;
- b_fat += n;
- } else { /* FAT12/16: Expand FAT size */
- n_fat += n;
- }
-
- /* Determine number of clusters and final check of validity of the FAT sub-type */
- n_clst = (n_vol - n_rsv - n_fat * N_FATS - n_dir) / au;
- if ( (fmt == FS_FAT16 && n_clst < MIN_FAT16)
- || (fmt == FS_FAT32 && n_clst < MIN_FAT32))
- return FR_MKFS_ABORTED;
-
- /* Determine system ID in the partition table */
- if (fmt == FS_FAT32) {
- sys = 0x0C; /* FAT32X */
- } else {
- if (fmt == FS_FAT12 && n_vol < 0x10000) {
- sys = 0x01; /* FAT12(<65536) */
- } else {
- sys = (n_vol < 0x10000) ? 0x04 : 0x06; /* FAT16(<65536) : FAT12/16(>=65536) */
- }
- }
-
- if (_MULTI_PARTITION && part) {
- /* Update system ID in the partition table */
- tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE];
- tbl[4] = sys;
- if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) /* Write it to teh MBR */
- return FR_DISK_ERR;
- md = 0xF8;
- } else {
- if (sfd) { /* No partition table (SFD) */
- md = 0xF0;
- } else { /* Create partition table (FDISK) */
- mem_set(fs->win, 0, SS(fs));
- tbl = fs->win + MBR_Table; /* Create partition table for single partition in the drive */
- tbl[1] = 1; /* Partition start head */
- tbl[2] = 1; /* Partition start sector */
- tbl[3] = 0; /* Partition start cylinder */
- tbl[4] = sys; /* System type */
- tbl[5] = 254; /* Partition end head */
- n = (b_vol + n_vol) / 63 / 255;
- tbl[6] = (BYTE)(n >> 2 | 63); /* Partition end sector */
- tbl[7] = (BYTE)n; /* End cylinder */
- ST_DWORD(tbl + 8, 63); /* Partition start in LBA */
- ST_DWORD(tbl + 12, n_vol); /* Partition size in LBA */
- ST_WORD(fs->win + BS_55AA, 0xAA55); /* MBR signature */
- if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) /* Write it to the MBR */
- return FR_DISK_ERR;
- md = 0xF8;
- }
- }
-
- /* Create BPB in the VBR */
- tbl = fs->win; /* Clear sector */
- mem_set(tbl, 0, SS(fs));
- mem_cpy(tbl, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code, OEM name */
- i = SS(fs); /* Sector size */
- ST_WORD(tbl + BPB_BytsPerSec, i);
- tbl[BPB_SecPerClus] = (BYTE)au; /* Sectors per cluster */
- ST_WORD(tbl + BPB_RsvdSecCnt, n_rsv); /* Reserved sectors */
- tbl[BPB_NumFATs] = N_FATS; /* Number of FATs */
- i = (fmt == FS_FAT32) ? 0 : N_ROOTDIR; /* Number of root directory entries */
- ST_WORD(tbl + BPB_RootEntCnt, i);
- if (n_vol < 0x10000) { /* Number of total sectors */
- ST_WORD(tbl + BPB_TotSec16, n_vol);
- } else {
- ST_DWORD(tbl + BPB_TotSec32, n_vol);
- }
- tbl[BPB_Media] = md; /* Media descriptor */
- ST_WORD(tbl + BPB_SecPerTrk, 63); /* Number of sectors per track */
- ST_WORD(tbl + BPB_NumHeads, 255); /* Number of heads */
- ST_DWORD(tbl + BPB_HiddSec, b_vol); /* Hidden sectors */
- n = GET_FATTIME(); /* Use current time as VSN */
- if (fmt == FS_FAT32) {
- ST_DWORD(tbl + BS_VolID32, n); /* VSN */
- ST_DWORD(tbl + BPB_FATSz32, n_fat); /* Number of sectors per FAT */
- ST_DWORD(tbl + BPB_RootClus, 2); /* Root directory start cluster (2) */
- ST_WORD(tbl + BPB_FSInfo, 1); /* FSINFO record offset (VBR + 1) */
- ST_WORD(tbl + BPB_BkBootSec, 6); /* Backup boot record offset (VBR + 6) */
- tbl[BS_DrvNum32] = 0x80; /* Drive number */
- tbl[BS_BootSig32] = 0x29; /* Extended boot signature */
- mem_cpy(tbl + BS_VolLab32, "NO NAME " "FAT32 ", 19); /* Volume label, FAT signature */
- } else {
- ST_DWORD(tbl + BS_VolID, n); /* VSN */
- ST_WORD(tbl + BPB_FATSz16, n_fat); /* Number of sectors per FAT */
- tbl[BS_DrvNum] = 0x80; /* Drive number */
- tbl[BS_BootSig] = 0x29; /* Extended boot signature */
- mem_cpy(tbl + BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */
- }
- ST_WORD(tbl + BS_55AA, 0xAA55); /* Signature (Offset is fixed here regardless of sector size) */
- if (disk_write(pdrv, tbl, b_vol, 1) != RES_OK) /* Write it to the VBR sector */
- return FR_DISK_ERR;
- if (fmt == FS_FAT32) /* Write backup VBR if needed (VBR + 6) */
- disk_write(pdrv, tbl, b_vol + 6, 1);
-
- /* Initialize FAT area */
- wsect = b_fat;
- for (i = 0; i < N_FATS; i++) { /* Initialize each FAT copy */
- mem_set(tbl, 0, SS(fs)); /* 1st sector of the FAT */
- n = md; /* Media descriptor byte */
- if (fmt != FS_FAT32) {
- n |= (fmt == FS_FAT12) ? 0x00FFFF00 : 0xFFFFFF00;
- ST_DWORD(tbl + 0, n); /* Reserve cluster #0-1 (FAT12/16) */
- } else {
- n |= 0xFFFFFF00;
- ST_DWORD(tbl + 0, n); /* Reserve cluster #0-1 (FAT32) */
- ST_DWORD(tbl + 4, 0xFFFFFFFF);
- ST_DWORD(tbl + 8, 0x0FFFFFFF); /* Reserve cluster #2 for root directory */
- }
- if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)
- return FR_DISK_ERR;
- mem_set(tbl, 0, SS(fs)); /* Fill following FAT entries with zero */
- for (n = 1; n < n_fat; n++) { /* This loop may take a time on FAT32 volume due to many single sector writes */
- if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)
- return FR_DISK_ERR;
- }
- }
-
- /* Initialize root directory */
- i = (fmt == FS_FAT32) ? au : (UINT)n_dir;
- do {
- if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)
- return FR_DISK_ERR;
- } while (--i);
-
-#if _USE_TRIM /* Erase data area if needed */
- {
- eb[0] = wsect; eb[1] = wsect + (n_clst - ((fmt == FS_FAT32) ? 1 : 0)) * au - 1;
- disk_ioctl(pdrv, CTRL_TRIM, eb);
- }
-#endif
-
- /* Create FSINFO if needed */
- if (fmt == FS_FAT32) {
- ST_DWORD(tbl + FSI_LeadSig, 0x41615252);
- ST_DWORD(tbl + FSI_StrucSig, 0x61417272);
- ST_DWORD(tbl + FSI_Free_Count, n_clst - 1); /* Number of free clusters */
- ST_DWORD(tbl + FSI_Nxt_Free, 2); /* Last allocated cluster# */
- ST_WORD(tbl + BS_55AA, 0xAA55);
- disk_write(pdrv, tbl, b_vol + 1, 1); /* Write original (VBR + 1) */
- disk_write(pdrv, tbl, b_vol + 7, 1); /* Write backup (VBR + 7) */
- }
-
- return (disk_ioctl(pdrv, CTRL_SYNC, 0) == RES_OK) ? FR_OK : FR_DISK_ERR;
+ DWORD eb[2];
+#endif
+
+ /* Check mounted drive and clear work area */
+ if (sfd > 1)
+ return FR_INVALID_PARAMETER;
+ vol = get_ldnumber(&path);
+ if (vol < 0)
+ return FR_INVALID_DRIVE;
+ fs = FatFs[vol];
+ if (!fs)
+ return FR_NOT_ENABLED;
+ fs->fs_type = 0;
+ pdrv = LD2PD(vol); /* Physical drive */
+ part =
+ LD2PT(vol); /* Partition (0:auto detect, 1-4:get from partition table)*/
+
+ /* Get disk statics */
+ stat = disk_initialize(pdrv);
+ if (stat & STA_NOINIT)
+ return FR_NOT_READY;
+ if (stat & STA_PROTECT)
+ return FR_WRITE_PROTECTED;
+#if _MAX_SS != _MIN_SS /* Get disk sector size */
+ if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK ||
+ SS(fs) > _MAX_SS || SS(fs) < _MIN_SS)
+ return FR_DISK_ERR;
+#endif
+ if (_MULTI_PARTITION && part) {
+ /* Get partition information from partition table in the MBR */
+ if (disk_read(pdrv, fs->win, 0, 1) != RES_OK)
+ return FR_DISK_ERR;
+ if (LD_WORD(fs->win + BS_55AA) != 0xAA55)
+ return FR_MKFS_ABORTED;
+ tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE];
+ if (!tbl[4])
+ return FR_MKFS_ABORTED; /* No partition? */
+ b_vol = LD_DWORD(tbl + 8); /* Volume start sector */
+ n_vol = LD_DWORD(tbl + 12); /* Volume size */
+ } else {
+ /* Create a partition in this function */
+ if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128)
+ return FR_DISK_ERR;
+ b_vol = (sfd) ? 0 : 63; /* Volume start sector */
+ n_vol -= b_vol; /* Volume size */
+ }
+
+ if (au & (au - 1))
+ au = 0;
+ if (!au) { /* AU auto selection */
+ vs = n_vol / (2000 / (SS(fs) / 512));
+ for (i = 0; vs < vst[i]; i++)
+ ;
+ au = cst[i];
+ }
+ if (au >= _MIN_SS)
+ au /= SS(fs); /* Number of sectors per cluster */
+ if (!au)
+ au = 1;
+ if (au > 128)
+ au = 128;
+
+ /* Pre-compute number of clusters and FAT sub-type */
+ n_clst = n_vol / au;
+ fmt = FS_FAT12;
+ if (n_clst >= MIN_FAT16)
+ fmt = FS_FAT16;
+ if (n_clst >= MIN_FAT32)
+ fmt = FS_FAT32;
+
+ /* Determine offset and size of FAT structure */
+ if (fmt == FS_FAT32) {
+ n_fat = ((n_clst * 4) + 8 + SS(fs) - 1) / SS(fs);
+ n_rsv = 32;
+ n_dir = 0;
+ } else {
+ n_fat = (fmt == FS_FAT12) ? (n_clst * 3 + 1) / 2 + 3 : (n_clst * 2) + 4;
+ n_fat = (n_fat + SS(fs) - 1) / SS(fs);
+ n_rsv = 1;
+ n_dir = (DWORD)N_ROOTDIR * SZ_DIRE / SS(fs);
+ }
+ b_fat = b_vol + n_rsv; /* FAT area start sector */
+ b_dir = b_fat + n_fat * N_FATS; /* Directory area start sector */
+ b_data = b_dir + n_dir; /* Data area start sector */
+ if (n_vol < b_data + au - b_vol)
+ return FR_MKFS_ABORTED; /* Too small volume */
+
+ /* Align data start sector to erase block boundary (for flash memory media)
+ */
+ if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &n) != RES_OK || !n || n > 32768)
+ n = 1;
+ n = (b_data + n - 1) &
+ ~(n - 1); /* Next nearest erase block from current data start */
+ n = (n - b_data) / N_FATS;
+ if (fmt == FS_FAT32) { /* FAT32: Move FAT offset */
+ n_rsv += n;
+ b_fat += n;
+ } else { /* FAT12/16: Expand FAT size */
+ n_fat += n;
+ }
+
+ /* Determine number of clusters and final check of validity of the FAT
+ * sub-type */
+ n_clst = (n_vol - n_rsv - n_fat * N_FATS - n_dir) / au;
+ if ((fmt == FS_FAT16 && n_clst < MIN_FAT16) ||
+ (fmt == FS_FAT32 && n_clst < MIN_FAT32))
+ return FR_MKFS_ABORTED;
+
+ /* Determine system ID in the partition table */
+ if (fmt == FS_FAT32) {
+ sys = 0x0C; /* FAT32X */
+ } else {
+ if (fmt == FS_FAT12 && n_vol < 0x10000) {
+ sys = 0x01; /* FAT12(<65536) */
+ } else {
+ sys = (n_vol < 0x10000)
+ ? 0x04
+ : 0x06; /* FAT16(<65536) : FAT12/16(>=65536) */
+ }
+ }
+
+ if (_MULTI_PARTITION && part) {
+ /* Update system ID in the partition table */
+ tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE];
+ tbl[4] = sys;
+ if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) /* Write it to teh MBR */
+ return FR_DISK_ERR;
+ md = 0xF8;
+ } else {
+ if (sfd) { /* No partition table (SFD) */
+ md = 0xF0;
+ } else { /* Create partition table (FDISK) */
+ mem_set(fs->win, 0, SS(fs));
+ tbl = fs->win + MBR_Table; /* Create partition table for single
+ partition in the drive */
+ tbl[1] = 1; /* Partition start head */
+ tbl[2] = 1; /* Partition start sector */
+ tbl[3] = 0; /* Partition start cylinder */
+ tbl[4] = sys; /* System type */
+ tbl[5] = 254; /* Partition end head */
+ n = (b_vol + n_vol) / 63 / 255;
+ tbl[6] = (BYTE)(n >> 2 | 63); /* Partition end sector */
+ tbl[7] = (BYTE)n; /* End cylinder */
+ ST_DWORD(tbl + 8, 63); /* Partition start in LBA */
+ ST_DWORD(tbl + 12, n_vol); /* Partition size in LBA */
+ ST_WORD(fs->win + BS_55AA, 0xAA55); /* MBR signature */
+ if (disk_write(pdrv, fs->win, 0, 1) !=
+ RES_OK) /* Write it to the MBR */
+ return FR_DISK_ERR;
+ md = 0xF8;
+ }
+ }
+
+ /* Create BPB in the VBR */
+ tbl = fs->win; /* Clear sector */
+ mem_set(tbl, 0, SS(fs));
+ mem_cpy(tbl, "\xEB\xFE\x90"
+ "MSDOS5.0",
+ 11); /* Boot jump code, OEM name */
+ i = SS(fs); /* Sector size */
+ ST_WORD(tbl + BPB_BytsPerSec, i);
+ tbl[BPB_SecPerClus] = (BYTE)au; /* Sectors per cluster */
+ ST_WORD(tbl + BPB_RsvdSecCnt, n_rsv); /* Reserved sectors */
+ tbl[BPB_NumFATs] = N_FATS; /* Number of FATs */
+ i = (fmt == FS_FAT32) ? 0
+ : N_ROOTDIR; /* Number of root directory entries */
+ ST_WORD(tbl + BPB_RootEntCnt, i);
+ if (n_vol < 0x10000) { /* Number of total sectors */
+ ST_WORD(tbl + BPB_TotSec16, n_vol);
+ } else {
+ ST_DWORD(tbl + BPB_TotSec32, n_vol);
+ }
+ tbl[BPB_Media] = md; /* Media descriptor */
+ ST_WORD(tbl + BPB_SecPerTrk, 63); /* Number of sectors per track */
+ ST_WORD(tbl + BPB_NumHeads, 255); /* Number of heads */
+ ST_DWORD(tbl + BPB_HiddSec, b_vol); /* Hidden sectors */
+ n = GET_FATTIME(); /* Use current time as VSN */
+ if (fmt == FS_FAT32) {
+ ST_DWORD(tbl + BS_VolID32, n); /* VSN */
+ ST_DWORD(tbl + BPB_FATSz32, n_fat); /* Number of sectors per FAT */
+ ST_DWORD(tbl + BPB_RootClus, 2); /* Root directory start cluster (2) */
+ ST_WORD(tbl + BPB_FSInfo, 1); /* FSINFO record offset (VBR + 1) */
+ ST_WORD(tbl + BPB_BkBootSec,
+ 6); /* Backup boot record offset (VBR + 6) */
+ tbl[BS_DrvNum32] = 0x80; /* Drive number */
+ tbl[BS_BootSig32] = 0x29; /* Extended boot signature */
+ mem_cpy(tbl + BS_VolLab32, "NO NAME "
+ "FAT32 ",
+ 19); /* Volume label, FAT signature */
+ } else {
+ ST_DWORD(tbl + BS_VolID, n); /* VSN */
+ ST_WORD(tbl + BPB_FATSz16, n_fat); /* Number of sectors per FAT */
+ tbl[BS_DrvNum] = 0x80; /* Drive number */
+ tbl[BS_BootSig] = 0x29; /* Extended boot signature */
+ mem_cpy(tbl + BS_VolLab, "NO NAME "
+ "FAT ",
+ 19); /* Volume label, FAT signature */
+ }
+ ST_WORD(tbl + BS_55AA, 0xAA55); /* Signature (Offset is fixed here
+ regardless of sector size) */
+ if (disk_write(pdrv, tbl, b_vol, 1) !=
+ RES_OK) /* Write it to the VBR sector */
+ return FR_DISK_ERR;
+ if (fmt == FS_FAT32) /* Write backup VBR if needed (VBR + 6) */
+ disk_write(pdrv, tbl, b_vol + 6, 1);
+
+ /* Initialize FAT area */
+ wsect = b_fat;
+ for (i = 0; i < N_FATS; i++) { /* Initialize each FAT copy */
+ mem_set(tbl, 0, SS(fs)); /* 1st sector of the FAT */
+ n = md; /* Media descriptor byte */
+ if (fmt != FS_FAT32) {
+ n |= (fmt == FS_FAT12) ? 0x00FFFF00 : 0xFFFFFF00;
+ ST_DWORD(tbl + 0, n); /* Reserve cluster #0-1 (FAT12/16) */
+ } else {
+ n |= 0xFFFFFF00;
+ ST_DWORD(tbl + 0, n); /* Reserve cluster #0-1 (FAT32) */
+ ST_DWORD(tbl + 4, 0xFFFFFFFF);
+ ST_DWORD(tbl + 8,
+ 0x0FFFFFFF); /* Reserve cluster #2 for root directory */
+ }
+ if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)
+ return FR_DISK_ERR;
+ mem_set(tbl, 0, SS(fs)); /* Fill following FAT entries with zero */
+ for (n = 1; n < n_fat;
+ n++) { /* This loop may take a time on FAT32 volume due to many
+ single sector writes */
+ if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)
+ return FR_DISK_ERR;
+ }
+ }
+
+ /* Initialize root directory */
+ i = (fmt == FS_FAT32) ? au : (UINT)n_dir;
+ do {
+ if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)
+ return FR_DISK_ERR;
+ } while (--i);
+
+#if _USE_TRIM /* Erase data area if needed */
+ {
+ eb[0] = wsect;
+ eb[1] = wsect + (n_clst - ((fmt == FS_FAT32) ? 1 : 0)) * au - 1;
+ disk_ioctl(pdrv, CTRL_TRIM, eb);
+ }
+#endif
+
+ /* Create FSINFO if needed */
+ if (fmt == FS_FAT32) {
+ ST_DWORD(tbl + FSI_LeadSig, 0x41615252);
+ ST_DWORD(tbl + FSI_StrucSig, 0x61417272);
+ ST_DWORD(tbl + FSI_Free_Count,
+ n_clst - 1); /* Number of free clusters */
+ ST_DWORD(tbl + FSI_Nxt_Free, 2); /* Last allocated cluster# */
+ ST_WORD(tbl + BS_55AA, 0xAA55);
+ disk_write(pdrv, tbl, b_vol + 1, 1); /* Write original (VBR + 1) */
+ disk_write(pdrv, tbl, b_vol + 7, 1); /* Write backup (VBR + 7) */
+ }
+
+ return (disk_ioctl(pdrv, CTRL_SYNC, 0) == RES_OK) ? FR_OK : FR_DISK_ERR;
}
-
-
#if _MULTI_PARTITION
/*-----------------------------------------------------------------------*/
/* Create partition table on the physical drive */
/*-----------------------------------------------------------------------*/
-FRESULT f_fdisk (
- BYTE pdrv, /* Physical drive number */
- const DWORD szt[], /* Pointer to the size table for each partitions */
- void* work /* Pointer to the working buffer */
-)
+FRESULT
+f_fdisk(BYTE pdrv, /* Physical drive number */
+ const DWORD szt[], /* Pointer to the size table for each partitions */
+ void* work /* Pointer to the working buffer */
+ )
{
- UINT i, n, sz_cyl, tot_cyl, b_cyl, e_cyl, p_cyl;
- BYTE s_hd, e_hd, *p, *buf = (BYTE*)work;
- DSTATUS stat;
- DWORD sz_disk, sz_part, s_part;
-
-
- stat = disk_initialize(pdrv);
- if (stat & STA_NOINIT) return FR_NOT_READY;
- if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
- if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_disk)) return FR_DISK_ERR;
-
- /* Determine CHS in the table regardless of the drive geometry */
- for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ;
- if (n == 256) n--;
- e_hd = n - 1;
- sz_cyl = 63 * n;
- tot_cyl = sz_disk / sz_cyl;
-
- /* Create partition table */
- mem_set(buf, 0, _MAX_SS);
- p = buf + MBR_Table; b_cyl = 0;
- for (i = 0; i < 4; i++, p += SZ_PTE) {
- p_cyl = (szt[i] <= 100U) ? (DWORD)tot_cyl * szt[i] / 100 : szt[i] / sz_cyl;
- if (!p_cyl) continue;
- s_part = (DWORD)sz_cyl * b_cyl;
- sz_part = (DWORD)sz_cyl * p_cyl;
- if (i == 0) { /* Exclude first track of cylinder 0 */
- s_hd = 1;
- s_part += 63; sz_part -= 63;
- } else {
- s_hd = 0;
- }
- e_cyl = b_cyl + p_cyl - 1;
- if (e_cyl >= tot_cyl) return FR_INVALID_PARAMETER;
-
- /* Set partition table */
- p[1] = s_hd; /* Start head */
- p[2] = (BYTE)((b_cyl >> 2) + 1); /* Start sector */
- p[3] = (BYTE)b_cyl; /* Start cylinder */
- p[4] = 0x06; /* System type (temporary setting) */
- p[5] = e_hd; /* End head */
- p[6] = (BYTE)((e_cyl >> 2) + 63); /* End sector */
- p[7] = (BYTE)e_cyl; /* End cylinder */
- ST_DWORD(p + 8, s_part); /* Start sector in LBA */
- ST_DWORD(p + 12, sz_part); /* Partition size */
-
- /* Next partition */
- b_cyl += p_cyl;
- }
- ST_WORD(p, 0xAA55);
-
- /* Write it to the MBR */
- return (disk_write(pdrv, buf, 0, 1) != RES_OK || disk_ioctl(pdrv, CTRL_SYNC, 0) != RES_OK) ? FR_DISK_ERR : FR_OK;
+ UINT i, n, sz_cyl, tot_cyl, b_cyl, e_cyl, p_cyl;
+ BYTE s_hd, e_hd, *p, *buf = (BYTE *)work;
+ DSTATUS stat;
+ DWORD sz_disk, sz_part, s_part;
+
+ stat = disk_initialize(pdrv);
+ if (stat & STA_NOINIT)
+ return FR_NOT_READY;
+ if (stat & STA_PROTECT)
+ return FR_WRITE_PROTECTED;
+ if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_disk))
+ return FR_DISK_ERR;
+
+ /* Determine CHS in the table regardless of the drive geometry */
+ for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2)
+ ;
+ if (n == 256)
+ n--;
+ e_hd = n - 1;
+ sz_cyl = 63 * n;
+ tot_cyl = sz_disk / sz_cyl;
+
+ /* Create partition table */
+ mem_set(buf, 0, _MAX_SS);
+ p = buf + MBR_Table;
+ b_cyl = 0;
+ for (i = 0; i < 4; i++, p += SZ_PTE) {
+ p_cyl =
+ (szt[i] <= 100U) ? (DWORD)tot_cyl * szt[i] / 100 : szt[i] / sz_cyl;
+ if (!p_cyl)
+ continue;
+ s_part = (DWORD)sz_cyl * b_cyl;
+ sz_part = (DWORD)sz_cyl * p_cyl;
+ if (i == 0) { /* Exclude first track of cylinder 0 */
+ s_hd = 1;
+ s_part += 63;
+ sz_part -= 63;
+ } else {
+ s_hd = 0;
+ }
+ e_cyl = b_cyl + p_cyl - 1;
+ if (e_cyl >= tot_cyl)
+ return FR_INVALID_PARAMETER;
+
+ /* Set partition table */
+ p[1] = s_hd; /* Start head */
+ p[2] = (BYTE)((b_cyl >> 2) + 1); /* Start sector */
+ p[3] = (BYTE)b_cyl; /* Start cylinder */
+ p[4] = 0x06; /* System type (temporary setting) */
+ p[5] = e_hd; /* End head */
+ p[6] = (BYTE)((e_cyl >> 2) + 63); /* End sector */
+ p[7] = (BYTE)e_cyl; /* End cylinder */
+ ST_DWORD(p + 8, s_part); /* Start sector in LBA */
+ ST_DWORD(p + 12, sz_part); /* Partition size */
+
+ /* Next partition */
+ b_cyl += p_cyl;
+ }
+ ST_WORD(p, 0xAA55);
+
+ /* Write it to the MBR */
+ return (disk_write(pdrv, buf, 0, 1) != RES_OK ||
+ disk_ioctl(pdrv, CTRL_SYNC, 0) != RES_OK)
+ ? FR_DISK_ERR
+ : FR_OK;
}
-
#endif /* _MULTI_PARTITION */
#endif /* _USE_MKFS && !_FS_READONLY */
-
-
-
#if _USE_STRFUNC
/*-----------------------------------------------------------------------*/
/* Get a string from the file */
/*-----------------------------------------------------------------------*/
-TCHAR* f_gets (
- TCHAR* buff, /* Pointer to the string buffer to read */
- int len, /* Size of string buffer (characters) */
- FIL* fp /* Pointer to the file object */
-)
+TCHAR*
+f_gets(TCHAR* buff, /* Pointer to the string buffer to read */
+ int len, /* Size of string buffer (characters) */
+ FIL* fp /* Pointer to the file object */
+ )
{
- int n = 0;
- TCHAR c, *p = buff;
- BYTE s[2];
- UINT rc;
-
+ int n = 0;
+ TCHAR c, *p = buff;
+ BYTE s[2];
+ UINT rc;
- while (n < len - 1) { /* Read characters until buffer gets filled */
+ while (n < len - 1) { /* Read characters until buffer gets filled */
#if _USE_LFN && _LFN_UNICODE
-#if _STRF_ENCODE == 3 /* Read a character in UTF-8 */
- f_read(fp, s, 1, &rc);
- if (rc != 1) break;
- c = s[0];
- if (c >= 0x80) {
- if (c < 0xC0) continue; /* Skip stray trailer */
- if (c < 0xE0) { /* Two-byte sequence */
- f_read(fp, s, 1, &rc);
- if (rc != 1) break;
- c = (c & 0x1F) << 6 | (s[0] & 0x3F);
- if (c < 0x80) c = '?';
- } else {
- if (c < 0xF0) { /* Three-byte sequence */
- f_read(fp, s, 2, &rc);
- if (rc != 2) break;
- c = c << 12 | (s[0] & 0x3F) << 6 | (s[1] & 0x3F);
- if (c < 0x800) c = '?';
- } else { /* Reject four-byte sequence */
- c = '?';
- }
- }
- }
-#elif _STRF_ENCODE == 2 /* Read a character in UTF-16BE */
- f_read(fp, s, 2, &rc);
- if (rc != 2) break;
- c = s[1] + (s[0] << 8);
-#elif _STRF_ENCODE == 1 /* Read a character in UTF-16LE */
- f_read(fp, s, 2, &rc);
- if (rc != 2) break;
- c = s[0] + (s[1] << 8);
-#else /* Read a character in ANSI/OEM */
- f_read(fp, s, 1, &rc);
- if (rc != 1) break;
- c = s[0];
- if (IsDBCS1(c)) {
- f_read(fp, s, 1, &rc);
- if (rc != 1) break;
- c = (c << 8) + s[0];
- }
- c = ff_convert(c, 1); /* OEM -> Unicode */
- if (!c) c = '?';
-#endif
-#else /* Read a character without conversion */
- f_read(fp, s, 1, &rc);
- if (rc != 1) break;
- c = s[0];
-#endif
- if (_USE_STRFUNC == 2 && c == '\r') continue; /* Strip '\r' */
- *p++ = c;
- n++;
- if (c == '\n') break; /* Break on EOL */
- }
- *p = 0;
- return n ? buff : 0; /* When no data read (eof or error), return with error. */
+#if _STRF_ENCODE == 3 /* Read a character in UTF-8 */
+ f_read(fp, s, 1, &rc);
+ if (rc != 1)
+ break;
+ c = s[0];
+ if (c >= 0x80) {
+ if (c < 0xC0)
+ continue; /* Skip stray trailer */
+ if (c < 0xE0) { /* Two-byte sequence */
+ f_read(fp, s, 1, &rc);
+ if (rc != 1)
+ break;
+ c = (c & 0x1F) << 6 | (s[0] & 0x3F);
+ if (c < 0x80)
+ c = '?';
+ } else {
+ if (c < 0xF0) { /* Three-byte sequence */
+ f_read(fp, s, 2, &rc);
+ if (rc != 2)
+ break;
+ c = c << 12 | (s[0] & 0x3F) << 6 | (s[1] & 0x3F);
+ if (c < 0x800)
+ c = '?';
+ } else { /* Reject four-byte sequence */
+ c = '?';
+ }
+ }
+ }
+#elif _STRF_ENCODE == 2 /* Read a character in UTF-16BE */
+ f_read(fp, s, 2, &rc);
+ if (rc != 2)
+ break;
+ c = s[1] + (s[0] << 8);
+#elif _STRF_ENCODE == 1 /* Read a character in UTF-16LE */
+ f_read(fp, s, 2, &rc);
+ if (rc != 2)
+ break;
+ c = s[0] + (s[1] << 8);
+#else /* Read a character in ANSI/OEM */
+ f_read(fp, s, 1, &rc);
+ if (rc != 1)
+ break;
+ c = s[0];
+ if (IsDBCS1(c)) {
+ f_read(fp, s, 1, &rc);
+ if (rc != 1)
+ break;
+ c = (c << 8) + s[0];
+ }
+ c = ff_convert(c, 1); /* OEM -> Unicode */
+ if (!c)
+ c = '?';
+#endif
+#else /* Read a character without conversion */
+ f_read(fp, s, 1, &rc);
+ if (rc != 1)
+ break;
+ c = s[0];
+#endif
+ if (_USE_STRFUNC == 2 && c == '\r')
+ continue; /* Strip '\r' */
+ *p++ = c;
+ n++;
+ if (c == '\n')
+ break; /* Break on EOL */
+ }
+ *p = 0;
+ return n ? buff
+ : 0; /* When no data read (eof or error), return with error. */
}
-
-
-
#if !_FS_READONLY
#include <stdarg.h>
/*-----------------------------------------------------------------------*/
/* Put a character to the file */
/*-----------------------------------------------------------------------*/
-typedef struct {
- FIL* fp;
- int idx, nchr;
- BYTE buf[64];
+typedef struct
+{
+ FIL* fp;
+ int idx, nchr;
+ BYTE buf[64];
} putbuff;
-
-static
-void putc_bfd (
- putbuff* pb,
- TCHAR c
-)
+static void
+putc_bfd(putbuff* pb, TCHAR c)
{
- UINT bw;
- int i;
-
+ UINT bw;
+ int i;
- if (_USE_STRFUNC == 2 && c == '\n') /* LF -> CRLF conversion */
- putc_bfd(pb, '\r');
+ if (_USE_STRFUNC == 2 && c == '\n') /* LF -> CRLF conversion */
+ putc_bfd(pb, '\r');
- i = pb->idx; /* Buffer write index (-1:error) */
- if (i < 0) return;
+ i = pb->idx; /* Buffer write index (-1:error) */
+ if (i < 0)
+ return;
#if _USE_LFN && _LFN_UNICODE
-#if _STRF_ENCODE == 3 /* Write a character in UTF-8 */
- if (c < 0x80) { /* 7-bit */
- pb->buf[i++] = (BYTE)c;
- } else {
- if (c < 0x800) { /* 11-bit */
- pb->buf[i++] = (BYTE)(0xC0 | c >> 6);
- } else { /* 16-bit */
- pb->buf[i++] = (BYTE)(0xE0 | c >> 12);
- pb->buf[i++] = (BYTE)(0x80 | (c >> 6 & 0x3F));
- }
- pb->buf[i++] = (BYTE)(0x80 | (c & 0x3F));
- }
-#elif _STRF_ENCODE == 2 /* Write a character in UTF-16BE */
- pb->buf[i++] = (BYTE)(c >> 8);
- pb->buf[i++] = (BYTE)c;
-#elif _STRF_ENCODE == 1 /* Write a character in UTF-16LE */
- pb->buf[i++] = (BYTE)c;
- pb->buf[i++] = (BYTE)(c >> 8);
-#else /* Write a character in ANSI/OEM */
- c = ff_convert(c, 0); /* Unicode -> OEM */
- if (!c) c = '?';
- if (c >= 0x100)
- pb->buf[i++] = (BYTE)(c >> 8);
- pb->buf[i++] = (BYTE)c;
-#endif
-#else /* Write a character without conversion */
- pb->buf[i++] = (BYTE)c;
-#endif
-
- if (i >= (int)(sizeof pb->buf) - 3) { /* Write buffered characters to the file */
- f_write(pb->fp, pb->buf, (UINT)i, &bw);
- i = (bw == (UINT)i) ? 0 : -1;
- }
- pb->idx = i;
- pb->nchr++;
+#if _STRF_ENCODE == 3 /* Write a character in UTF-8 */
+ if (c < 0x80) { /* 7-bit */
+ pb->buf[i++] = (BYTE)c;
+ } else {
+ if (c < 0x800) { /* 11-bit */
+ pb->buf[i++] = (BYTE)(0xC0 | c >> 6);
+ } else { /* 16-bit */
+ pb->buf[i++] = (BYTE)(0xE0 | c >> 12);
+ pb->buf[i++] = (BYTE)(0x80 | (c >> 6 & 0x3F));
+ }
+ pb->buf[i++] = (BYTE)(0x80 | (c & 0x3F));
+ }
+#elif _STRF_ENCODE == 2 /* Write a character in UTF-16BE */
+ pb->buf[i++] = (BYTE)(c >> 8);
+ pb->buf[i++] = (BYTE)c;
+#elif _STRF_ENCODE == 1 /* Write a character in UTF-16LE */
+ pb->buf[i++] = (BYTE)c;
+ pb->buf[i++] = (BYTE)(c >> 8);
+#else /* Write a character in ANSI/OEM */
+ c = ff_convert(c, 0); /* Unicode -> OEM */
+ if (!c)
+ c = '?';
+ if (c >= 0x100)
+ pb->buf[i++] = (BYTE)(c >> 8);
+ pb->buf[i++] = (BYTE)c;
+#endif
+#else /* Write a character without conversion */
+ pb->buf[i++] = (BYTE)c;
+#endif
+
+ if (i >=
+ (int)(sizeof pb->buf) - 3) { /* Write buffered characters to the file */
+ f_write(pb->fp, pb->buf, (UINT)i, &bw);
+ i = (bw == (UINT)i) ? 0 : -1;
+ }
+ pb->idx = i;
+ pb->nchr++;
}
-
-
-int f_putc (
- TCHAR c, /* A character to be output */
- FIL* fp /* Pointer to the file object */
-)
+int
+f_putc(TCHAR c, /* A character to be output */
+ FIL* fp /* Pointer to the file object */
+ )
{
- putbuff pb;
- UINT nw;
+ putbuff pb;
+ UINT nw;
+ pb.fp = fp; /* Initialize output buffer */
+ pb.nchr = pb.idx = 0;
- pb.fp = fp; /* Initialize output buffer */
- pb.nchr = pb.idx = 0;
+ putc_bfd(&pb, c); /* Put a character */
- putc_bfd(&pb, c); /* Put a character */
-
- if ( pb.idx >= 0 /* Flush buffered characters to the file */
- && f_write(pb.fp, pb.buf, (UINT)pb.idx, &nw) == FR_OK
- && (UINT)pb.idx == nw) return pb.nchr;
- return EOF;
+ if (pb.idx >= 0 /* Flush buffered characters to the file */
+ && f_write(pb.fp, pb.buf, (UINT)pb.idx, &nw) == FR_OK &&
+ (UINT)pb.idx == nw)
+ return pb.nchr;
+ return EOF;
}
-
-
-
/*-----------------------------------------------------------------------*/
/* Put a string to the file */
/*-----------------------------------------------------------------------*/
-int f_puts (
- const TCHAR* str, /* Pointer to the string to be output */
- FIL* fp /* Pointer to the file object */
-)
+int
+f_puts(const TCHAR* str, /* Pointer to the string to be output */
+ FIL* fp /* Pointer to the file object */
+ )
{
- putbuff pb;
- UINT nw;
+ putbuff pb;
+ UINT nw;
+ pb.fp = fp; /* Initialize output buffer */
+ pb.nchr = pb.idx = 0;
- pb.fp = fp; /* Initialize output buffer */
- pb.nchr = pb.idx = 0;
+ while (*str) /* Put the string */
+ putc_bfd(&pb, *str++);
- while (*str) /* Put the string */
- putc_bfd(&pb, *str++);
-
- if ( pb.idx >= 0 /* Flush buffered characters to the file */
- && f_write(pb.fp, pb.buf, (UINT)pb.idx, &nw) == FR_OK
- && (UINT)pb.idx == nw) return pb.nchr;
- return EOF;
+ if (pb.idx >= 0 /* Flush buffered characters to the file */
+ && f_write(pb.fp, pb.buf, (UINT)pb.idx, &nw) == FR_OK &&
+ (UINT)pb.idx == nw)
+ return pb.nchr;
+ return EOF;
}
-
-
-
/*-----------------------------------------------------------------------*/
/* Put a formatted string to the file */
/*-----------------------------------------------------------------------*/
-int f_printf (
- FIL* fp, /* Pointer to the file object */
- const TCHAR* fmt, /* Pointer to the format string */
- ... /* Optional arguments... */
-)
+int
+f_printf(FIL* fp, /* Pointer to the file object */
+ const TCHAR* fmt, /* Pointer to the format string */
+ ... /* Optional arguments... */
+ )
{
- va_list arp;
- BYTE f, r;
- UINT nw, i, j, w;
- DWORD v;
- TCHAR c, d, s[16], *p;
- putbuff pb;
-
-
- pb.fp = fp; /* Initialize output buffer */
- pb.nchr = pb.idx = 0;
-
- va_start(arp, fmt);
-
- for (;;) {
- c = *fmt++;
- if (c == 0) break; /* End of string */
- if (c != '%') { /* Non escape character */
- putc_bfd(&pb, c);
- continue;
- }
- w = f = 0;
- c = *fmt++;
- if (c == '0') { /* Flag: '0' padding */
- f = 1; c = *fmt++;
- } else {
- if (c == '-') { /* Flag: left justified */
- f = 2; c = *fmt++;
- }
- }
- while (IsDigit(c)) { /* Precision */
- w = w * 10 + c - '0';
- c = *fmt++;
- }
- if (c == 'l' || c == 'L') { /* Prefix: Size is long int */
- f |= 4; c = *fmt++;
- }
- if (!c) break;
- d = c;
- if (IsLower(d)) d -= 0x20;
- switch (d) { /* Type is... */
- case 'S' : /* String */
- p = va_arg(arp, TCHAR*);
- for (j = 0; p[j]; j++) ;
- if (!(f & 2)) {
- while (j++ < w) putc_bfd(&pb, ' ');
- }
- while (*p) putc_bfd(&pb, *p++);
- while (j++ < w) putc_bfd(&pb, ' ');
- continue;
- case 'C' : /* Character */
- putc_bfd(&pb, (TCHAR)va_arg(arp, int)); continue;
- case 'B' : /* Binary */
- r = 2; break;
- case 'O' : /* Octal */
- r = 8; break;
- case 'D' : /* Signed decimal */
- case 'U' : /* Unsigned decimal */
- r = 10; break;
- case 'X' : /* Hexdecimal */
- r = 16; break;
- default: /* Unknown type (pass-through) */
- putc_bfd(&pb, c); continue;
- }
-
- /* Get an argument and put it in numeral */
- v = (f & 4) ? (DWORD)va_arg(arp, long) : ((d == 'D') ? (DWORD)(long)va_arg(arp, int) : (DWORD)va_arg(arp, unsigned int));
- if (d == 'D' && (v & 0x80000000)) {
- v = 0 - v;
- f |= 8;
- }
- i = 0;
- do {
- d = (TCHAR)(v % r); v /= r;
- if (d > 9) d += (c == 'x') ? 0x27 : 0x07;
- s[i++] = d + '0';
- } while (v && i < sizeof s / sizeof s[0]);
- if (f & 8) s[i++] = '-';
- j = i; d = (f & 1) ? '0' : ' ';
- while (!(f & 2) && j++ < w) putc_bfd(&pb, d);
- do putc_bfd(&pb, s[--i]); while (i);
- while (j++ < w) putc_bfd(&pb, d);
- }
-
- va_end(arp);
-
- if ( pb.idx >= 0 /* Flush buffered characters to the file */
- && f_write(pb.fp, pb.buf, (UINT)pb.idx, &nw) == FR_OK
- && (UINT)pb.idx == nw) return pb.nchr;
- return EOF;
+ va_list arp;
+ BYTE f, r;
+ UINT nw, i, j, w;
+ DWORD v;
+ TCHAR c, d, s[16], *p;
+ putbuff pb;
+
+ pb.fp = fp; /* Initialize output buffer */
+ pb.nchr = pb.idx = 0;
+
+ va_start(arp, fmt);
+
+ for (;;) {
+ c = *fmt++;
+ if (c == 0)
+ break; /* End of string */
+ if (c != '%') { /* Non escape character */
+ putc_bfd(&pb, c);
+ continue;
+ }
+ w = f = 0;
+ c = *fmt++;
+ if (c == '0') { /* Flag: '0' padding */
+ f = 1;
+ c = *fmt++;
+ } else {
+ if (c == '-') { /* Flag: left justified */
+ f = 2;
+ c = *fmt++;
+ }
+ }
+ while (IsDigit(c)) { /* Precision */
+ w = w * 10 + c - '0';
+ c = *fmt++;
+ }
+ if (c == 'l' || c == 'L') { /* Prefix: Size is long int */
+ f |= 4;
+ c = *fmt++;
+ }
+ if (!c)
+ break;
+ d = c;
+ if (IsLower(d))
+ d -= 0x20;
+ switch (d) { /* Type is... */
+ case 'S': /* String */
+ p = va_arg(arp, TCHAR*);
+ for (j = 0; p[j]; j++)
+ ;
+ if (!(f & 2)) {
+ while (j++ < w)
+ putc_bfd(&pb, ' ');
+ }
+ while (*p)
+ putc_bfd(&pb, *p++);
+ while (j++ < w)
+ putc_bfd(&pb, ' ');
+ continue;
+ case 'C': /* Character */
+ putc_bfd(&pb, (TCHAR)va_arg(arp, int));
+ continue;
+ case 'B': /* Binary */
+ r = 2;
+ break;
+ case 'O': /* Octal */
+ r = 8;
+ break;
+ case 'D': /* Signed decimal */
+ case 'U': /* Unsigned decimal */
+ r = 10;
+ break;
+ case 'X': /* Hexdecimal */
+ r = 16;
+ break;
+ default: /* Unknown type (pass-through) */
+ putc_bfd(&pb, c);
+ continue;
+ }
+
+ /* Get an argument and put it in numeral */
+ v = (f & 4) ? (DWORD)va_arg(arp, long)
+ : ((d == 'D') ? (DWORD)(long)va_arg(arp, int)
+ : (DWORD)va_arg(arp, unsigned int));
+ if (d == 'D' && (v & 0x80000000)) {
+ v = 0 - v;
+ f |= 8;
+ }
+ i = 0;
+ do {
+ d = (TCHAR)(v % r);
+ v /= r;
+ if (d > 9)
+ d += (c == 'x') ? 0x27 : 0x07;
+ s[i++] = d + '0';
+ } while (v && i < sizeof s / sizeof s[0]);
+ if (f & 8)
+ s[i++] = '-';
+ j = i;
+ d = (f & 1) ? '0' : ' ';
+ while (!(f & 2) && j++ < w)
+ putc_bfd(&pb, d);
+ do
+ putc_bfd(&pb, s[--i]);
+ while (i);
+ while (j++ < w)
+ putc_bfd(&pb, d);
+ }
+
+ va_end(arp);
+
+ if (pb.idx >= 0 /* Flush buffered characters to the file */
+ && f_write(pb.fp, pb.buf, (UINT)pb.idx, &nw) == FR_OK &&
+ (UINT)pb.idx == nw)
+ return pb.nchr;
+ return EOF;
}
#endif /* !_FS_READONLY */
/ by use of this software.
/---------------------------------------------------------------------------*/
-
#ifndef _FATFS
-#define _FATFS 32020 /* Revision ID */
+#define _FATFS 32020 /* Revision ID */
#ifdef __cplusplus
extern "C" {
#endif
-#include "integer.h" /* Basic integer types */
-#include "ffconf.h" /* FatFs configuration options */
+#include "integer.h" /* Basic integer types */
+#include "ffconf.h" /* FatFs configuration options */
#if _FATFS != _FFCONF
#error Wrong configuration file (ffconf.h).
#endif
-
-
/* Definitions of volume management */
-#if _MULTI_PARTITION /* Multiple partition configuration */
-typedef struct {
- BYTE pd; /* Physical drive number */
- BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
+#if _MULTI_PARTITION /* Multiple partition configuration */
+typedef struct
+{
+ BYTE pd; /* Physical drive number */
+ BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
} PARTITION;
-extern PARTITION VolToPart[]; /* Volume - Partition resolution table */
-#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive number */
-#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition index */
+extern PARTITION VolToPart[]; /* Volume - Partition resolution table */
+#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive number */
+#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition index */
-#else /* Single partition configuration */
-#define LD2PD(vol) (BYTE)(vol) /* Each logical drive is bound to the same physical drive number */
-#define LD2PT(vol) 0 /* Find first valid partition or in SFD */
+#else /* Single partition configuration */
+#define LD2PD(vol) \
+ (BYTE)(vol) /* Each logical drive is bound to the same physical drive \
+ number */
+#define LD2PT(vol) 0 /* Find first valid partition or in SFD */
#endif
-
-
/* Type of path name strings on FatFs API */
-#if _LFN_UNICODE /* Unicode string */
+#if _LFN_UNICODE /* Unicode string */
#if !_USE_LFN
#error _LFN_UNICODE must be 0 at non-LFN cfg.
#endif
#ifndef _INC_TCHAR
typedef WCHAR TCHAR;
-#define _T(x) L ## x
-#define _TEXT(x) L ## x
+#define _T(x) L##x
+#define _TEXT(x) L##x
#endif
-#else /* ANSI/OEM string */
+#else /* ANSI/OEM string */
#ifndef _INC_TCHAR
typedef char TCHAR;
#define _T(x) x
#endif
-
-
/* File system object structure (FATFS) */
-typedef struct {
- BYTE fs_type; /* FAT sub-type (0:Not mounted) */
- BYTE drv; /* Physical drive number */
- BYTE csize; /* Sectors per cluster (1,2,4...128) */
- BYTE n_fats; /* Number of FAT copies (1 or 2) */
- BYTE wflag; /* win[] flag (b0:dirty) */
- BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
- WORD id; /* File system mount ID */
- WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
+typedef struct
+{
+ BYTE fs_type; /* FAT sub-type (0:Not mounted) */
+ BYTE drv; /* Physical drive number */
+ BYTE csize; /* Sectors per cluster (1,2,4...128) */
+ BYTE n_fats; /* Number of FAT copies (1 or 2) */
+ BYTE wflag; /* win[] flag (b0:dirty) */
+ BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
+ WORD id; /* File system mount ID */
+ WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
#if _MAX_SS != _MIN_SS
- WORD ssize; /* Bytes per sector (512, 1024, 2048 or 4096) */
+ WORD ssize; /* Bytes per sector (512, 1024, 2048 or 4096) */
#endif
#if _FS_REENTRANT
- _SYNC_t sobj; /* Identifier of sync object */
+ _SYNC_t sobj; /* Identifier of sync object */
#endif
#if !_FS_READONLY
- DWORD last_clust; /* Last allocated cluster */
- DWORD free_clust; /* Number of free clusters */
+ DWORD last_clust; /* Last allocated cluster */
+ DWORD free_clust; /* Number of free clusters */
#endif
#if _FS_RPATH
- DWORD cdir; /* Current directory start cluster (0:root) */
+ DWORD cdir; /* Current directory start cluster (0:root) */
#endif
- DWORD n_fatent; /* Number of FAT entries, = number of clusters + 2 */
- DWORD fsize; /* Sectors per FAT */
- DWORD volbase; /* Volume start sector */
- DWORD fatbase; /* FAT start sector */
- DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */
- DWORD database; /* Data start sector */
- DWORD winsect; /* Current sector appearing in the win[] */
- BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
+ DWORD n_fatent; /* Number of FAT entries, = number of clusters + 2 */
+ DWORD fsize; /* Sectors per FAT */
+ DWORD volbase; /* Volume start sector */
+ DWORD fatbase; /* FAT start sector */
+ DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */
+ DWORD database; /* Data start sector */
+ DWORD winsect; /* Current sector appearing in the win[] */
+ BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and file data
+ at tiny cfg) */
} FATFS;
-
-
/* File object structure (FIL) */
-typedef struct {
- FATFS* fs; /* Pointer to the related file system object (**do not change order**) */
- WORD id; /* Owner file system mount ID (**do not change order**) */
- BYTE flag; /* Status flags */
- BYTE err; /* Abort flag (error code) */
- DWORD fptr; /* File read/write pointer (Zeroed on file open) */
- DWORD fsize; /* File size */
- DWORD sclust; /* File start cluster (0:no cluster chain, always 0 when fsize is 0) */
- DWORD clust; /* Current cluster of fpter (not valid when fprt is 0) */
- DWORD dsect; /* Sector number appearing in buf[] (0:invalid) */
+typedef struct
+{
+ FATFS* fs; /* Pointer to the related file system object (**do not change
+ order**) */
+ WORD id; /* Owner file system mount ID (**do not change order**) */
+ BYTE flag; /* Status flags */
+ BYTE err; /* Abort flag (error code) */
+ DWORD fptr; /* File read/write pointer (Zeroed on file open) */
+ DWORD fsize; /* File size */
+ DWORD
+ sclust; /* File start cluster (0:no cluster chain, always 0 when fsize
+ is 0) */
+ DWORD clust; /* Current cluster of fpter (not valid when fprt is 0) */
+ DWORD dsect; /* Sector number appearing in buf[] (0:invalid) */
#if !_FS_READONLY
- DWORD dir_sect; /* Sector number containing the directory entry */
- BYTE* dir_ptr; /* Pointer to the directory entry in the win[] */
+ DWORD dir_sect; /* Sector number containing the directory entry */
+ BYTE* dir_ptr; /* Pointer to the directory entry in the win[] */
#endif
#if _USE_FASTSEEK
- DWORD* cltbl; /* Pointer to the cluster link map table (Nulled on file open) */
+ DWORD*
+ cltbl; /* Pointer to the cluster link map table (Nulled on file open) */
#endif
#if _FS_LOCK
- UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */
+ UINT lockid; /* File lock ID origin from 1 (index of file semaphore table
+ Files[]) */
#endif
#if !_FS_TINY
- BYTE buf[_MAX_SS]; /* File private data read/write window */
+ BYTE buf[_MAX_SS]; /* File private data read/write window */
#endif
} FIL;
-
-
/* Directory object structure (DIR) */
-typedef struct {
- FATFS* fs; /* Pointer to the owner file system object (**do not change order**) */
- WORD id; /* Owner file system mount ID (**do not change order**) */
- WORD index; /* Current read/write index number */
- DWORD sclust; /* Table start cluster (0:Root dir) */
- DWORD clust; /* Current cluster */
- DWORD sect; /* Current sector */
- BYTE* dir; /* Pointer to the current SFN entry in the win[] */
- BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
+typedef struct
+{
+ FATFS* fs; /* Pointer to the owner file system object (**do not change
+ order**) */
+ WORD id; /* Owner file system mount ID (**do not change order**) */
+ WORD index; /* Current read/write index number */
+ DWORD sclust; /* Table start cluster (0:Root dir) */
+ DWORD clust; /* Current cluster */
+ DWORD sect; /* Current sector */
+ BYTE* dir; /* Pointer to the current SFN entry in the win[] */
+ BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
#if _FS_LOCK
- UINT lockid; /* File lock ID (index of file semaphore table Files[]) */
+ UINT lockid; /* File lock ID (index of file semaphore table Files[]) */
#endif
#if _USE_LFN
- WCHAR* lfn; /* Pointer to the LFN working buffer */
- WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */
+ WCHAR* lfn; /* Pointer to the LFN working buffer */
+ WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */
#endif
#if _USE_FIND
- const TCHAR* pat; /* Pointer to the name matching pattern */
+ const TCHAR* pat; /* Pointer to the name matching pattern */
#endif
} DIR;
-
-
/* File information structure (FILINFO) */
-typedef struct {
- DWORD fsize; /* File size */
- WORD fdate; /* Last modified date */
- WORD ftime; /* Last modified time */
- BYTE fattrib; /* Attribute */
- TCHAR fname[13]; /* Short file name (8.3 format) */
+typedef struct
+{
+ DWORD fsize; /* File size */
+ WORD fdate; /* Last modified date */
+ WORD ftime; /* Last modified time */
+ BYTE fattrib; /* Attribute */
+ TCHAR fname[13]; /* Short file name (8.3 format) */
#if _USE_LFN
- TCHAR* lfname; /* Pointer to the LFN buffer */
- UINT lfsize; /* Size of LFN buffer in TCHAR */
+ TCHAR* lfname; /* Pointer to the LFN buffer */
+ UINT lfsize; /* Size of LFN buffer in TCHAR */
#endif
} FILINFO;
-
-
/* File function return code (FRESULT) */
typedef enum {
- FR_OK = 0, /* (0) Succeeded */
- FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
- FR_INT_ERR, /* (2) Assertion failed */
- FR_NOT_READY, /* (3) The physical drive cannot work */
- FR_NO_FILE, /* (4) Could not find the file */
- FR_NO_PATH, /* (5) Could not find the path */
- FR_INVALID_NAME, /* (6) The path name format is invalid */
- FR_DENIED, /* (7) Access denied due to prohibited access or directory full */
- FR_EXIST, /* (8) Access denied due to prohibited access */
- FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
- FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
- FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
- FR_NOT_ENABLED, /* (12) The volume has no work area */
- FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
- FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */
- FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
- FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
- FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
- FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_SHARE */
- FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
+ FR_OK = 0, /* (0) Succeeded */
+ FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
+ FR_INT_ERR, /* (2) Assertion failed */
+ FR_NOT_READY, /* (3) The physical drive cannot work */
+ FR_NO_FILE, /* (4) Could not find the file */
+ FR_NO_PATH, /* (5) Could not find the path */
+ FR_INVALID_NAME, /* (6) The path name format is invalid */
+ FR_DENIED, /* (7) Access denied due to prohibited access or directory full
+ */
+ FR_EXIST, /* (8) Access denied due to prohibited access */
+ FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
+ FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
+ FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
+ FR_NOT_ENABLED, /* (12) The volume has no work area */
+ FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
+ FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */
+ FR_TIMEOUT, /* (15) Could not get a grant to access the volume within
+ defined period */
+ FR_LOCKED, /* (16) The operation is rejected according to the file sharing
+ policy */
+ FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
+ FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_SHARE */
+ FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
} FRESULT;
-
-
/*--------------------------------------------------------------*/
/* FatFs module application interface */
-FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */
-FRESULT f_close (FIL* fp); /* Close an open file object */
-FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from a file */
-FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to a file */
-FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */
-FRESULT f_lseek (FIL* fp, DWORD ofs); /* Move file pointer of a file object */
-FRESULT f_truncate (FIL* fp); /* Truncate file */
-FRESULT f_sync (FIL* fp); /* Flush cached data of a writing file */
-FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */
-FRESULT f_closedir (DIR* dp); /* Close an open directory */
-FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */
-FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern); /* Find first file */
-FRESULT f_findnext (DIR* dp, FILINFO* fno); /* Find next file */
-FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */
-FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */
-FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */
-FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */
-FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of the file/dir */
-FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change times-tamp of the file/dir */
-FRESULT f_chdir (const TCHAR* path); /* Change current directory */
-FRESULT f_chdrive (const TCHAR* path); /* Change current drive */
-FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */
-FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */
-FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */
-FRESULT f_setlabel (const TCHAR* label); /* Set volume label */
-FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */
-FRESULT f_mkfs (const TCHAR* path, BYTE sfd, UINT au); /* Create a file system on the volume */
-FRESULT f_fdisk (BYTE pdrv, const DWORD szt[], void* work); /* Divide a physical drive into some partitions */
-int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */
-int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */
-int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */
-TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */
+FRESULT f_open(FIL* fp, const TCHAR* path,
+ BYTE mode); /* Open or create a file */
+FRESULT f_close(FIL* fp); /* Close an open file object */
+FRESULT f_read(FIL* fp, void* buff, UINT btr,
+ UINT* br); /* Read data from a file */
+FRESULT f_write(FIL* fp, const void* buff, UINT btw,
+ UINT* bw); /* Write data to a file */
+FRESULT f_forward(FIL* fp, UINT (*func)(const BYTE*, UINT), UINT btf,
+ UINT* bf); /* Forward data to the stream */
+FRESULT f_lseek(FIL* fp, DWORD ofs); /* Move file pointer of a file object */
+FRESULT f_truncate(FIL* fp); /* Truncate file */
+FRESULT f_sync(FIL* fp); /* Flush cached data of a writing file */
+FRESULT f_opendir(DIR* dp, const TCHAR* path); /* Open a directory */
+FRESULT f_closedir(DIR* dp); /* Close an open directory */
+FRESULT f_readdir(DIR* dp, FILINFO* fno); /* Read a directory item */
+FRESULT f_findfirst(DIR* dp, FILINFO* fno, const TCHAR* path,
+ const TCHAR* pattern); /* Find first file */
+FRESULT f_findnext(DIR* dp, FILINFO* fno); /* Find next file */
+FRESULT f_mkdir(const TCHAR* path); /* Create a sub directory */
+FRESULT f_unlink(const TCHAR* path); /* Delete an existing file or directory */
+FRESULT f_rename(const TCHAR* path_old,
+ const TCHAR* path_new); /* Rename/Move a file or directory */
+FRESULT f_stat(const TCHAR* path, FILINFO* fno); /* Get file status */
+FRESULT f_chmod(const TCHAR* path, BYTE attr,
+ BYTE mask); /* Change attribute of the file/dir */
+FRESULT f_utime(const TCHAR* path,
+ const FILINFO* fno); /* Change times-tamp of the file/dir */
+FRESULT f_chdir(const TCHAR* path); /* Change current directory */
+FRESULT f_chdrive(const TCHAR* path); /* Change current drive */
+FRESULT f_getcwd(TCHAR* buff, UINT len); /* Get current directory */
+FRESULT f_getfree(const TCHAR* path, DWORD* nclst,
+ FATFS** fatfs); /* Get number of free clusters on the drive */
+FRESULT f_getlabel(const TCHAR* path, TCHAR* label,
+ DWORD* vsn); /* Get volume label */
+FRESULT f_setlabel(const TCHAR* label); /* Set volume label */
+FRESULT f_mount(FATFS* fs, const TCHAR* path,
+ BYTE opt); /* Mount/Unmount a logical drive */
+FRESULT f_mkfs(const TCHAR* path, BYTE sfd,
+ UINT au); /* Create a file system on the volume */
+FRESULT f_fdisk(BYTE pdrv, const DWORD szt[],
+ void* work); /* Divide a physical drive into some partitions */
+int f_putc(TCHAR c, FIL* fp); /* Put a character to the file */
+int f_puts(const TCHAR* str, FIL* cp); /* Put a string to the file */
+int f_printf(FIL* fp, const TCHAR* str,
+ ...); /* Put a formatted string to the file */
+TCHAR* f_gets(TCHAR* buff, int len, FIL* fp); /* Get a string from the file */
#define f_eof(fp) ((int)((fp)->fptr == (fp)->fsize))
#define f_error(fp) ((fp)->err)
#define EOF (-1)
#endif
-
-
-
/*--------------------------------------------------------------*/
/* Additional user defined functions */
/* RTC function */
#if !_FS_READONLY && !_FS_NORTC
-DWORD get_fattime (void);
+DWORD get_fattime(void);
#endif
/* Unicode support functions */
-#if _USE_LFN /* Unicode - OEM code conversion */
-WCHAR ff_convert (WCHAR chr, UINT dir); /* OEM-Unicode bidirectional conversion */
-WCHAR ff_wtoupper (WCHAR chr); /* Unicode upper-case conversion */
-#if _USE_LFN == 3 /* Memory functions */
-void* ff_memalloc (UINT msize); /* Allocate memory block */
-void ff_memfree (void* mblock); /* Free memory block */
+#if _USE_LFN /* Unicode - OEM code conversion */
+WCHAR ff_convert(WCHAR chr,
+ UINT dir); /* OEM-Unicode bidirectional conversion */
+WCHAR ff_wtoupper(WCHAR chr); /* Unicode upper-case conversion */
+#if _USE_LFN == 3 /* Memory functions */
+void* ff_memalloc(UINT msize); /* Allocate memory block */
+void ff_memfree(void* mblock); /* Free memory block */
#endif
#endif
/* Sync functions */
#if _FS_REENTRANT
-int ff_cre_syncobj (BYTE vol, _SYNC_t* sobj); /* Create a sync object */
-int ff_req_grant (_SYNC_t sobj); /* Lock sync object */
-void ff_rel_grant (_SYNC_t sobj); /* Unlock sync object */
-int ff_del_syncobj (_SYNC_t sobj); /* Delete a sync object */
+int ff_cre_syncobj(BYTE vol, _SYNC_t* sobj); /* Create a sync object */
+int ff_req_grant(_SYNC_t sobj); /* Lock sync object */
+void ff_rel_grant(_SYNC_t sobj); /* Unlock sync object */
+int ff_del_syncobj(_SYNC_t sobj); /* Delete a sync object */
#endif
-
-
-
/*--------------------------------------------------------------*/
/* Flags and offset address */
-
/* File access control and file status flags (FIL.flag) */
-#define FA_READ 0x01
-#define FA_OPEN_EXISTING 0x00
+#define FA_READ 0x01
+#define FA_OPEN_EXISTING 0x00
#if !_FS_READONLY
-#define FA_WRITE 0x02
-#define FA_CREATE_NEW 0x04
-#define FA_CREATE_ALWAYS 0x08
-#define FA_OPEN_ALWAYS 0x10
-#define FA__WRITTEN 0x20
-#define FA__DIRTY 0x40
+#define FA_WRITE 0x02
+#define FA_CREATE_NEW 0x04
+#define FA_CREATE_ALWAYS 0x08
+#define FA_OPEN_ALWAYS 0x10
+#define FA__WRITTEN 0x20
+#define FA__DIRTY 0x40
#endif
-
/* FAT sub type (FATFS.fs_type) */
-#define FS_FAT12 1
-#define FS_FAT16 2
-#define FS_FAT32 3
-
+#define FS_FAT12 1
+#define FS_FAT16 2
+#define FS_FAT32 3
/* File attribute bits for directory entry */
-#define AM_RDO 0x01 /* Read only */
-#define AM_HID 0x02 /* Hidden */
-#define AM_SYS 0x04 /* System */
-#define AM_VOL 0x08 /* Volume label */
-#define AM_LFN 0x0F /* LFN entry */
-#define AM_DIR 0x10 /* Directory */
-#define AM_ARC 0x20 /* Archive */
-#define AM_MASK 0x3F /* Mask of defined bits */
-
+#define AM_RDO 0x01 /* Read only */
+#define AM_HID 0x02 /* Hidden */
+#define AM_SYS 0x04 /* System */
+#define AM_VOL 0x08 /* Volume label */
+#define AM_LFN 0x0F /* LFN entry */
+#define AM_DIR 0x10 /* Directory */
+#define AM_ARC 0x20 /* Archive */
+#define AM_MASK 0x3F /* Mask of defined bits */
/* Fast seek feature */
-#define CREATE_LINKMAP 0xFFFFFFFF
-
-
+#define CREATE_LINKMAP 0xFFFFFFFF
/*--------------------------------*/
/* Multi-byte word access macros */
-#if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */
-#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr))
-#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr))
-#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val)
-#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val)
-#else /* Use byte-by-byte access to the FAT structure */
-#define LD_WORD(ptr) (WORD)(((WORD)*((BYTE*)(ptr)+1)<<8)|(WORD)*(BYTE*)(ptr))
-#define LD_DWORD(ptr) (DWORD)(((DWORD)*((BYTE*)(ptr)+3)<<24)|((DWORD)*((BYTE*)(ptr)+2)<<16)|((WORD)*((BYTE*)(ptr)+1)<<8)|*(BYTE*)(ptr))
-#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8)
-#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8); *((BYTE*)(ptr)+2)=(BYTE)((DWORD)(val)>>16); *((BYTE*)(ptr)+3)=(BYTE)((DWORD)(val)>>24)
+#if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */
+#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr))
+#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr))
+#define ST_WORD(ptr, val) *(WORD*)(BYTE*)(ptr) = (WORD)(val)
+#define ST_DWORD(ptr, val) *(DWORD*)(BYTE*)(ptr) = (DWORD)(val)
+#else /* Use byte-by-byte access to the FAT structure */
+#define LD_WORD(ptr) \
+ (WORD)(((WORD) * ((BYTE*)(ptr) + 1) << 8) | (WORD) * (BYTE*)(ptr))
+#define LD_DWORD(ptr) \
+ (DWORD)(((DWORD) * ((BYTE*)(ptr) + 3) << 24) | \
+ ((DWORD) * ((BYTE*)(ptr) + 2) << 16) | \
+ ((WORD) * ((BYTE*)(ptr) + 1) << 8) | *(BYTE*)(ptr))
+#define ST_WORD(ptr, val) \
+ *(BYTE*)(ptr) = (BYTE)(val); \
+ *((BYTE*)(ptr) + 1) = (BYTE)((WORD)(val) >> 8)
+#define ST_DWORD(ptr, val) \
+ *(BYTE*)(ptr) = (BYTE)(val); \
+ *((BYTE*)(ptr) + 1) = (BYTE)((WORD)(val) >> 8); \
+ *((BYTE*)(ptr) + 2) = (BYTE)((DWORD)(val) >> 16); \
+ *((BYTE*)(ptr) + 3) = (BYTE)((DWORD)(val) >> 24)
#endif
#ifdef __cplusplus
/ FatFs - FAT file system module configuration file R0.11 (C)ChaN, 2015
/---------------------------------------------------------------------------*/
-#define _FFCONF 32020 /* Revision ID */
+#define _FFCONF 32020 /* Revision ID */
/*---------------------------------------------------------------------------/
/ Functions and Buffer Configurations
/---------------------------------------------------------------------------*/
-#define _FS_TINY 0
+#define _FS_TINY 0
/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
/ At the tiny configuration, size of the file object (FIL) is reduced _MAX_SS
/ bytes. Instead of private sector buffer eliminated from the file object,
/ common sector buffer in the file system object (FATFS) is used for the file
/ data transfer. */
-
-#define _FS_READONLY 0
+#define _FS_READONLY 0
/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
/ Read-only configuration removes writing API functions, f_write(), f_sync(),
/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
/ and optional writing functions as well. */
-
-#define _FS_MINIMIZE 0
+#define _FS_MINIMIZE 0
/* This option defines minimization level to remove some basic API functions.
/
/ 0: All basic functions are enabled.
/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
/ 3: f_lseek() function is removed in addition to 2. */
-
-#define _USE_STRFUNC 0
+#define _USE_STRFUNC 0
/* This option switches string functions, f_gets(), f_putc(), f_puts() and
/ f_printf().
/
/ 1: Enable without LF-CRLF conversion.
/ 2: Enable with LF-CRLF conversion. */
-
-#define _USE_FIND 0
+#define _USE_FIND 0
/* This option switches filtered directory read feature and related functions,
/ f_findfirst() and f_findnext(). (0:Disable or 1:Enable) */
-
-#define _USE_MKFS 0
+#define _USE_MKFS 0
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
-
-#define _USE_FASTSEEK 0
+#define _USE_FASTSEEK 0
/* This option switches fast seek feature. (0:Disable or 1:Enable) */
-
-#define _USE_LABEL 0
+#define _USE_LABEL 0
/* This option switches volume label functions, f_getlabel() and f_setlabel().
/ (0:Disable or 1:Enable) */
-
-#define _USE_FORWARD 0
+#define _USE_FORWARD 0
/* This option switches f_forward() function. (0:Disable or 1:Enable)
/ To enable it, also _FS_TINY need to be set to 1. */
-
/*---------------------------------------------------------------------------/
/ Locale and Namespace Configurations
/---------------------------------------------------------------------------*/
-#define _CODE_PAGE 437
+#define _CODE_PAGE 437
/* This option specifies the OEM code page to be used on the target system.
/ Incorrect setting of the code page can cause a file open failure.
/
/ 950 - Traditional Chinese Big5 (DBCS)
*/
-
-#define _USE_LFN 2
-#define _MAX_LFN 255
+#define _USE_LFN 2
+#define _MAX_LFN 255
/* The _USE_LFN option switches the LFN feature.
/
/ 0: Disable LFN feature. _MAX_LFN has no effect.
/ 2: Enable LFN with dynamic working buffer on the STACK.
/ 3: Enable LFN with dynamic working buffer on the HEAP.
/
-/ When enable the LFN feature, Unicode handling functions (option/unicode.c) must
-/ be added to the project. The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes.
-/ When use stack for the working buffer, take care on stack overflow. When use heap
+/ When enable the LFN feature, Unicode handling functions (option/unicode.c)
+must
+/ be added to the project. The LFN working buffer occupies (_MAX_LFN + 1) * 2
+bytes.
+/ When use stack for the working buffer, take care on stack overflow. When use
+heap
/ memory for the working buffer, memory management functions, ff_memalloc() and
/ ff_memfree(), must be added to the project. */
-
-#define _LFN_UNICODE 0
+#define _LFN_UNICODE 0
/* This option switches character encoding on the API. (0:ANSI/OEM or 1:Unicode)
-/ To use Unicode string for the path name, enable LFN feature and set _LFN_UNICODE
+/ To use Unicode string for the path name, enable LFN feature and set
+_LFN_UNICODE
/ to 1. This option also affects behavior of string I/O functions. */
-
-#define _STRF_ENCODE 0
-/* When _LFN_UNICODE is 1, this option selects the character encoding on the file to
-/ be read/written via string I/O functions, f_gets(), f_putc(), f_puts and f_printf().
+#define _STRF_ENCODE 0
+/* When _LFN_UNICODE is 1, this option selects the character encoding on the
+file to
+/ be read/written via string I/O functions, f_gets(), f_putc(), f_puts and
+f_printf().
/
/ 0: ANSI/OEM
/ 1: UTF-16LE
/
/ When _LFN_UNICODE is 0, this option has no effect. */
-
-#define _FS_RPATH 1
+#define _FS_RPATH 1
/* This option configures relative path feature.
/
/ 0: Disable relative path feature and remove related functions.
/ 1: Enable relative path feature. f_chdir() and f_chdrive() are available.
/ 2: f_getcwd() function is available in addition to 1.
/
-/ Note that directory items read via f_readdir() are affected by this option. */
-
+/ Note that directory items read via f_readdir() are affected by this option.
+*/
/*---------------------------------------------------------------------------/
/ Drive/Volume Configurations
/---------------------------------------------------------------------------*/
-#define _VOLUMES 1
+#define _VOLUMES 1
/* Number of volumes (logical drives) to be used. */
-
-#define _STR_VOLUME_ID 0
-#define _VOLUME_STRS "RAM","NAND","CF","SD1","SD2","USB1","USB2","USB3"
+#define _STR_VOLUME_ID 0
+#define _VOLUME_STRS "RAM", "NAND", "CF", "SD1", "SD2", "USB1", "USB2", "USB3"
/* _STR_VOLUME_ID option switches string volume ID feature.
-/ When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
+/ When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as
+drive
/ number in the path name. _VOLUME_STRS defines the drive ID strings for each
-/ logical drives. Number of items must be equal to _VOLUMES. Valid characters for
+/ logical drives. Number of items must be equal to _VOLUMES. Valid characters
+for
/ the drive ID strings are: A-Z and 0-9. */
-
-#define _MULTI_PARTITION 0
-/* This option switches multi-partition feature. By default (0), each logical drive
-/ number is bound to the same physical drive number and only an FAT volume found on
-/ the physical drive will be mounted. When multi-partition feature is enabled (1),
+#define _MULTI_PARTITION 0
+/* This option switches multi-partition feature. By default (0), each logical
+drive
+/ number is bound to the same physical drive number and only an FAT volume
+found on
+/ the physical drive will be mounted. When multi-partition feature is enabled
+(1),
/ each logical drive number is bound to arbitrary physical drive and partition
/ listed in the VolToPart[]. Also f_fdisk() funciton will be available. */
-
-#define _MIN_SS 512
-#define _MAX_SS 512
+#define _MIN_SS 512
+#define _MAX_SS 512
/* These options configure the range of sector size to be supported. (512, 1024,
-/ 2048 or 4096) Always set both 512 for most systems, all type of memory cards and
-/ harddisk. But a larger value may be required for on-board flash memory and some
-/ type of optical media. When _MAX_SS is larger than _MIN_SS, FatFs is configured
-/ to variable sector size and GET_SECTOR_SIZE command must be implemented to the
+/ 2048 or 4096) Always set both 512 for most systems, all type of memory cards
+and
+/ harddisk. But a larger value may be required for on-board flash memory and
+some
+/ type of optical media. When _MAX_SS is larger than _MIN_SS, FatFs is
+configured
+/ to variable sector size and GET_SECTOR_SIZE command must be implemented to
+the
/ disk_ioctl() function. */
-
-#define _USE_TRIM 0
+#define _USE_TRIM 0
/* This option switches ATA-TRIM feature. (0:Disable or 1:Enable)
/ To enable Trim feature, also CTRL_TRIM command should be implemented to the
/ disk_ioctl() function. */
-
-#define _FS_NOFSINFO 0
+#define _FS_NOFSINFO 0
/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
/ option, and f_getfree() function at first time after volume mount will force
/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
/ bit1=1: Do not trust last allocated cluster number in the FSINFO.
*/
-
-
/*---------------------------------------------------------------------------/
/ System Configurations
/---------------------------------------------------------------------------*/
-#define _FS_NORTC 1
-#define _NORTC_MON 2
-#define _NORTC_MDAY 1
-#define _NORTC_YEAR 2015
+#define _FS_NORTC 1
+#define _NORTC_MON 2
+#define _NORTC_MDAY 1
+#define _NORTC_YEAR 2015
/* The _FS_NORTC option switches timestamp feature. If the system does not have
-/ an RTC function or valid timestamp is not needed, set _FS_NORTC to 1 to disable
-/ the timestamp feature. All objects modified by FatFs will have a fixed timestamp
+/ an RTC function or valid timestamp is not needed, set _FS_NORTC to 1 to
+disable
+/ the timestamp feature. All objects modified by FatFs will have a fixed
+timestamp
/ defined by _NORTC_MON, _NORTC_MDAY and _NORTC_YEAR.
-/ When timestamp feature is enabled (_FS_NORTC == 0), get_fattime() function need
+/ When timestamp feature is enabled (_FS_NORTC == 0), get_fattime() function
+need
/ to be added to the project to read current time form RTC. _NORTC_MON,
/ _NORTC_MDAY and _NORTC_YEAR have no effect.
-/ These options have no effect at read-only configuration (_FS_READONLY == 1). */
-
+/ These options have no effect at read-only configuration (_FS_READONLY == 1).
+*/
-#define _FS_LOCK 0
-/* The _FS_LOCK option switches file lock feature to control duplicated file open
-/ and illegal operation to open objects. This option must be 0 when _FS_READONLY
+#define _FS_LOCK 0
+/* The _FS_LOCK option switches file lock feature to control duplicated file
+open
+/ and illegal operation to open objects. This option must be 0 when
+_FS_READONLY
/ is 1.
/
-/ 0: Disable file lock feature. To avoid volume corruption, application program
+/ 0: Disable file lock feature. To avoid volume corruption, application
+program
/ should avoid illegal open, remove and rename to the open objects.
-/ >0: Enable file lock feature. The value defines how many files/sub-directories
+/ >0: Enable file lock feature. The value defines how many
+files/sub-directories
/ can be opened simultaneously under file lock control. Note that the file
/ lock feature is independent of re-entrancy. */
-
-#define _FS_REENTRANT 0
-#define _FS_TIMEOUT 1000
-#define _SYNC_t HANDLE
+#define _FS_REENTRANT 0
+#define _FS_TIMEOUT 1000
+#define _SYNC_t HANDLE
/* The _FS_REENTRANT option switches the re-entrancy (thread safe) of the FatFs
/ module itself. Note that regardless of this option, file access to different
/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
/ option/syscall.c.
/
/ The _FS_TIMEOUT defines timeout period in unit of time tick.
-/ The _SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
+/ The _SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID,
+OS_EVENT*,
/ SemaphoreHandle_t and etc.. A header file for O/S definitions needs to be
/ included somewhere in the scope of ff.c. */
-
-#define _WORD_ACCESS 0
+#define _WORD_ACCESS 0
/* The _WORD_ACCESS option is an only platform dependent option. It defines
/ which access method is used to the word data on the FAT volume.
/
/ 0: Byte-by-byte access. Always compatible with all platforms.
-/ 1: Word access. Do not choose this unless under both the following conditions.
+/ 1: Word access. Do not choose this unless under both the following
+conditions.
/
/ * Address misaligned memory access is always allowed to ALL instructions.
/ * Byte order on the memory is little-endian.
/ *2:Unaligned memory access is not supported.
/ *3:Some compilers generate LDM/STM for mem_cpy function.
*/
-
#ifndef _FF_INTEGER
#define _FF_INTEGER
-#ifdef _WIN32 /* FatFs development platform */
+#ifdef _WIN32 /* FatFs development platform */
#include <windows.h>
#include <tchar.h>
-#else /* Embedded platform */
+#else /* Embedded platform */
/* This type MUST be 8 bit */
-typedef unsigned char BYTE;
+typedef unsigned char BYTE;
/* These types MUST be 16 bit */
-typedef short SHORT;
-typedef unsigned short WORD;
-typedef unsigned short WCHAR;
+typedef short SHORT;
+typedef unsigned short WORD;
+typedef unsigned short WCHAR;
/* These types MUST be 16 bit or 32 bit */
-typedef int INT;
-typedef unsigned int UINT;
+typedef int INT;
+typedef unsigned int UINT;
/* These types MUST be 32 bit */
-typedef long LONG;
-typedef unsigned long DWORD;
+typedef long LONG;
+typedef unsigned long DWORD;
#endif
#include "sdmmc.h"
//#include "DrawCharacter.h"
-//Uncomment to enable 32bit fifo support?
-//not currently working
+// Uncomment to enable 32bit fifo support?
+// not currently working
//#define DATA32_SUPPORT
#define TRUE 1
#define bool int
-#define NO_INLINE __attribute__ ((noinline))
+#define NO_INLINE __attribute__((noinline))
-#define RGB(r,g,b) (r<<24|b<<16|g<<8|r)
+#define RGB(r, g, b) (r << 24 | b << 16 | g << 8 | r)
#ifdef __cplusplus
extern "C" {
#endif
- void waitcycles(uint32_t val);
+void waitcycles(uint32_t val);
#ifdef __cplusplus
};
#endif
//#define DEBUG_SDMMC
#ifdef DEBUG_SDMMC
- extern uint8_t* topScreen;
- extern void DrawHexWithName(unsigned char *screen, const char *str, unsigned int hex, int x, int y, int color, int bgcolor);
- #define DEBUGPRINT(scr,str,hex,x,y,color,bg) DrawHexWithName(scr,str,hex,x,y,color,bg)
+extern uint8_t* topScreen;
+extern void DrawHexWithName(unsigned char* screen, const char* str,
+ unsigned int hex, int x, int y, int color,
+ int bgcolor);
+#define DEBUGPRINT(scr, str, hex, x, y, color, bg) \
+ DrawHexWithName(scr, str, hex, x, y, color, bg)
#else
- #define DEBUGPRINT(...)
+#define DEBUGPRINT(...)
#endif
-//extern "C" void sdmmc_send_command(struct mmcdevice *ctx, uint32_t cmd, uint32_t args);
-//extern "C" void inittarget(struct mmcdevice *ctx);
-//extern "C" int SD_Init();
-//extern "C" int SD_Init2();
-//extern "C" int Nand_Init2();
-//extern "C" void InitSD();
+// extern "C" void sdmmc_send_command(struct mmcdevice *ctx, uint32_t cmd,
+// uint32_t args);
+// extern "C" void inittarget(struct mmcdevice *ctx);
+// extern "C" int SD_Init();
+// extern "C" int SD_Init2();
+// extern "C" int Nand_Init2();
+// extern "C" void InitSD();
struct mmcdevice handelNAND;
struct mmcdevice handelSD;
-mmcdevice *getMMCDevice(int drive)
+mmcdevice*
+getMMCDevice(int drive)
{
- if(drive==0) return &handelNAND;
- return &handelSD;
+ if (drive == 0)
+ return &handelNAND;
+ return &handelSD;
}
-int geterror(struct mmcdevice *ctx)
+int
+geterror(struct mmcdevice* ctx)
{
- return (ctx->error << 29) >> 31;
+ return (ctx->error << 29) >> 31;
}
-
-void inittarget(struct mmcdevice *ctx)
+void
+inittarget(struct mmcdevice* ctx)
{
- sdmmc_mask16(REG_SDPORTSEL,0x3,(uint16_t)ctx->devicenumber);
- setckl(ctx->clk);
- if(ctx->SDOPT == 0)
- {
- sdmmc_mask16(REG_SDOPT,0,0x8000);
- }
- else
- {
- sdmmc_mask16(REG_SDOPT,0x8000,0);
- }
-
+ sdmmc_mask16(REG_SDPORTSEL, 0x3, (uint16_t)ctx->devicenumber);
+ setckl(ctx->clk);
+ if (ctx->SDOPT == 0) {
+ sdmmc_mask16(REG_SDOPT, 0, 0x8000);
+ } else {
+ sdmmc_mask16(REG_SDOPT, 0x8000, 0);
+ }
}
-
-void NO_INLINE sdmmc_send_command(struct mmcdevice *ctx, uint32_t cmd, uint32_t args)
+void NO_INLINE
+sdmmc_send_command(struct mmcdevice* ctx, uint32_t cmd, uint32_t args)
{
- bool getSDRESP = (cmd << 15) >> 31;
- uint16_t flags = (cmd << 15) >> 31;
- const bool readdata = cmd & 0x20000;
- const bool writedata = cmd & 0x40000;
-
- if(readdata || writedata)
- {
- flags |= TMIO_STAT0_DATAEND;
- }
-
- ctx->error = 0;
- while((sdmmc_read16(REG_SDSTATUS1) & TMIO_STAT1_CMD_BUSY)); //mmc working?
- sdmmc_write16(REG_SDIRMASK0,0);
- sdmmc_write16(REG_SDIRMASK1,0);
- sdmmc_write16(REG_SDSTATUS0,0);
- sdmmc_write16(REG_SDSTATUS1,0);
+ bool getSDRESP = (cmd << 15) >> 31;
+ uint16_t flags = (cmd << 15) >> 31;
+ const bool readdata = cmd & 0x20000;
+ const bool writedata = cmd & 0x40000;
+
+ if (readdata || writedata) {
+ flags |= TMIO_STAT0_DATAEND;
+ }
+
+ ctx->error = 0;
+ while ((sdmmc_read16(REG_SDSTATUS1) & TMIO_STAT1_CMD_BUSY))
+ ; // mmc working?
+ sdmmc_write16(REG_SDIRMASK0, 0);
+ sdmmc_write16(REG_SDIRMASK1, 0);
+ sdmmc_write16(REG_SDSTATUS0, 0);
+ sdmmc_write16(REG_SDSTATUS1, 0);
#ifdef DATA32_SUPPORT
// if(readdata)sdmmc_mask16(REG_DATACTL32, 0x1000, 0x800);
// if(writedata)sdmmc_mask16(REG_DATACTL32, 0x800, 0x1000);
// sdmmc_mask16(REG_DATACTL32,0x1800,2);
#else
- sdmmc_mask16(REG_DATACTL32,0x1800,0);
+ sdmmc_mask16(REG_DATACTL32, 0x1800, 0);
#endif
- sdmmc_write16(REG_SDCMDARG0,args &0xFFFF);
- sdmmc_write16(REG_SDCMDARG1,args >> 16);
- sdmmc_write16(REG_SDCMD,cmd &0xFFFF);
-
- uint32_t size = ctx->size;
- uint16_t *dataPtr = (uint16_t*)ctx->data;
+ sdmmc_write16(REG_SDCMDARG0, args & 0xFFFF);
+ sdmmc_write16(REG_SDCMDARG1, args >> 16);
+ sdmmc_write16(REG_SDCMD, cmd & 0xFFFF);
+
+ uint32_t size = ctx->size;
+ uint16_t* dataPtr = (uint16_t*)ctx->data;
#ifdef DATA32_SUPPORT
- uint32_t *dataPtr32 = (uint32_t*)ctx->data;
+ uint32_t* dataPtr32 = (uint32_t*)ctx->data;
#endif
-
- bool useBuf = ( NULL != dataPtr );
+
+ bool useBuf = (NULL != dataPtr);
#ifdef DATA32_SUPPORT
- bool useBuf32 = (useBuf && (0 == (3 & ((uint32_t)dataPtr))));
+ bool useBuf32 = (useBuf && (0 == (3 & ((uint32_t)dataPtr))));
#endif
-
- uint16_t status0 = 0;
- while(1)
- {
- volatile uint16_t status1 = sdmmc_read16(REG_SDSTATUS1);
+
+ uint16_t status0 = 0;
+ while (1) {
+ volatile uint16_t status1 = sdmmc_read16(REG_SDSTATUS1);
#ifdef DATA32_SUPPORT
- volatile uint16_t ctl32 = sdmmc_read16(REG_DATACTL32);
- if((ctl32 & 0x100))
+ volatile uint16_t ctl32 = sdmmc_read16(REG_DATACTL32);
+ if ((ctl32 & 0x100))
#else
- if((status1 & TMIO_STAT1_RXRDY))
+ if ((status1 & TMIO_STAT1_RXRDY))
#endif
- {
- if(readdata)
- {
- if(useBuf)
- {
- sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_RXRDY, 0);
- //sdmmc_write16(REG_SDSTATUS1,~TMIO_STAT1_RXRDY);
- if(size > 0x1FF)
- {
- #ifdef DATA32_SUPPORT
- if(useBuf32)
- {
- for(int i = 0; i<0x200; i+=4)
- {
- *dataPtr32++ = sdmmc_read32(REG_SDFIFO32);
- }
- }
- else
- {
- #endif
- for(int i = 0; i<0x200; i+=2)
- {
- *dataPtr++ = sdmmc_read16(REG_SDFIFO);
- }
- #ifdef DATA32_SUPPORT
- }
- #endif
- size -= 0x200;
- }
- }
-
- sdmmc_mask16(REG_DATACTL32, 0x800, 0);
- }
- }
+ {
+ if (readdata) {
+ if (useBuf) {
+ sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_RXRDY, 0);
+ // sdmmc_write16(REG_SDSTATUS1,~TMIO_STAT1_RXRDY);
+ if (size > 0x1FF) {
#ifdef DATA32_SUPPORT
- if(!(ctl32 & 0x200))
+ if (useBuf32) {
+ for (int i = 0; i < 0x200; i += 4) {
+ *dataPtr32++ = sdmmc_read32(REG_SDFIFO32);
+ }
+ } else {
+#endif
+ for (int i = 0; i < 0x200; i += 2) {
+ *dataPtr++ = sdmmc_read16(REG_SDFIFO);
+ }
+#ifdef DATA32_SUPPORT
+ }
+#endif
+ size -= 0x200;
+ }
+ }
+
+ sdmmc_mask16(REG_DATACTL32, 0x800, 0);
+ }
+ }
+#ifdef DATA32_SUPPORT
+ if (!(ctl32 & 0x200))
#else
- if((status1 & TMIO_STAT1_TXRQ))
+ if ((status1 & TMIO_STAT1_TXRQ))
#endif
- {
- if(writedata)
- {
- if(useBuf)
- {
- sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_TXRQ, 0);
- //sdmmc_write16(REG_SDSTATUS1,~TMIO_STAT1_TXRQ);
- if(size > 0x1FF)
- {
- #ifdef DATA32_SUPPORT
- for(int i = 0; i<0x200; i+=4)
- {
- sdmmc_write32(REG_SDFIFO32,*dataPtr32++);
- }
- #else
- for(int i = 0; i<0x200; i+=2)
- {
- sdmmc_write16(REG_SDFIFO,*dataPtr++);
- }
- #endif
- size -= 0x200;
- }
- }
-
- sdmmc_mask16(REG_DATACTL32, 0x1000, 0);
- }
- }
- if(status1 & TMIO_MASK_GW)
- {
- ctx->error |= 4;
- break;
- }
-
- if(!(status1 & TMIO_STAT1_CMD_BUSY))
- {
- status0 = sdmmc_read16(REG_SDSTATUS0);
- if(sdmmc_read16(REG_SDSTATUS0) & TMIO_STAT0_CMDRESPEND)
- {
- ctx->error |= 0x1;
- }
- if(status0 & TMIO_STAT0_DATAEND)
- {
- ctx->error |= 0x2;
- }
-
- if((status0 & flags) == flags)
- break;
- }
- }
- ctx->stat0 = sdmmc_read16(REG_SDSTATUS0);
- ctx->stat1 = sdmmc_read16(REG_SDSTATUS1);
- sdmmc_write16(REG_SDSTATUS0,0);
- sdmmc_write16(REG_SDSTATUS1,0);
-
- if(getSDRESP != 0)
- {
- ctx->ret[0] = sdmmc_read16(REG_SDRESP0) | (sdmmc_read16(REG_SDRESP1) << 16);
- ctx->ret[1] = sdmmc_read16(REG_SDRESP2) | (sdmmc_read16(REG_SDRESP3) << 16);
- ctx->ret[2] = sdmmc_read16(REG_SDRESP4) | (sdmmc_read16(REG_SDRESP5) << 16);
- ctx->ret[3] = sdmmc_read16(REG_SDRESP6) | (sdmmc_read16(REG_SDRESP7) << 16);
- }
+ {
+ if (writedata) {
+ if (useBuf) {
+ sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_TXRQ, 0);
+ // sdmmc_write16(REG_SDSTATUS1,~TMIO_STAT1_TXRQ);
+ if (size > 0x1FF) {
+#ifdef DATA32_SUPPORT
+ for (int i = 0; i < 0x200; i += 4) {
+ sdmmc_write32(REG_SDFIFO32, *dataPtr32++);
+ }
+#else
+ for (int i = 0; i < 0x200; i += 2) {
+ sdmmc_write16(REG_SDFIFO, *dataPtr++);
+ }
+#endif
+ size -= 0x200;
+ }
+ }
+
+ sdmmc_mask16(REG_DATACTL32, 0x1000, 0);
+ }
+ }
+ if (status1 & TMIO_MASK_GW) {
+ ctx->error |= 4;
+ break;
+ }
+
+ if (!(status1 & TMIO_STAT1_CMD_BUSY)) {
+ status0 = sdmmc_read16(REG_SDSTATUS0);
+ if (sdmmc_read16(REG_SDSTATUS0) & TMIO_STAT0_CMDRESPEND) {
+ ctx->error |= 0x1;
+ }
+ if (status0 & TMIO_STAT0_DATAEND) {
+ ctx->error |= 0x2;
+ }
+
+ if ((status0 & flags) == flags)
+ break;
+ }
+ }
+ ctx->stat0 = sdmmc_read16(REG_SDSTATUS0);
+ ctx->stat1 = sdmmc_read16(REG_SDSTATUS1);
+ sdmmc_write16(REG_SDSTATUS0, 0);
+ sdmmc_write16(REG_SDSTATUS1, 0);
+
+ if (getSDRESP != 0) {
+ ctx->ret[0] =
+ sdmmc_read16(REG_SDRESP0) | (sdmmc_read16(REG_SDRESP1) << 16);
+ ctx->ret[1] =
+ sdmmc_read16(REG_SDRESP2) | (sdmmc_read16(REG_SDRESP3) << 16);
+ ctx->ret[2] =
+ sdmmc_read16(REG_SDRESP4) | (sdmmc_read16(REG_SDRESP5) << 16);
+ ctx->ret[3] =
+ sdmmc_read16(REG_SDRESP6) | (sdmmc_read16(REG_SDRESP7) << 16);
+ }
}
-int NO_INLINE sdmmc_sdcard_writesectors(uint32_t sector_no, uint32_t numsectors, uint8_t *in)
+int NO_INLINE
+sdmmc_sdcard_writesectors(uint32_t sector_no, uint32_t numsectors, uint8_t* in)
{
- if(handelSD.isSDHC == 0) sector_no <<= 9;
- inittarget(&handelSD);
- sdmmc_write16(REG_SDSTOP,0x100);
+ if (handelSD.isSDHC == 0)
+ sector_no <<= 9;
+ inittarget(&handelSD);
+ sdmmc_write16(REG_SDSTOP, 0x100);
#ifdef DATA32_SUPPORT
- sdmmc_write16(REG_SDBLKCOUNT32,numsectors);
- sdmmc_write16(REG_SDBLKLEN32,0x200);
+ sdmmc_write16(REG_SDBLKCOUNT32, numsectors);
+ sdmmc_write16(REG_SDBLKLEN32, 0x200);
#endif
- sdmmc_write16(REG_SDBLKCOUNT,numsectors);
- handelSD.data = in;
- handelSD.size = numsectors << 9;
- sdmmc_send_command(&handelSD,0x52C19,sector_no);
- return geterror(&handelSD);
+ sdmmc_write16(REG_SDBLKCOUNT, numsectors);
+ handelSD.data = in;
+ handelSD.size = numsectors << 9;
+ sdmmc_send_command(&handelSD, 0x52C19, sector_no);
+ return geterror(&handelSD);
}
-int NO_INLINE sdmmc_sdcard_readsectors(uint32_t sector_no, uint32_t numsectors, uint8_t *out)
+int NO_INLINE
+sdmmc_sdcard_readsectors(uint32_t sector_no, uint32_t numsectors, uint8_t* out)
{
- if(handelSD.isSDHC == 0) sector_no <<= 9;
- inittarget(&handelSD);
- sdmmc_write16(REG_SDSTOP,0x100);
+ if (handelSD.isSDHC == 0)
+ sector_no <<= 9;
+ inittarget(&handelSD);
+ sdmmc_write16(REG_SDSTOP, 0x100);
#ifdef DATA32_SUPPORT
- sdmmc_write16(REG_SDBLKCOUNT32,numsectors);
- sdmmc_write16(REG_SDBLKLEN32,0x200);
+ sdmmc_write16(REG_SDBLKCOUNT32, numsectors);
+ sdmmc_write16(REG_SDBLKLEN32, 0x200);
#endif
- sdmmc_write16(REG_SDBLKCOUNT,numsectors);
- handelSD.data = out;
- handelSD.size = numsectors << 9;
- sdmmc_send_command(&handelSD,0x33C12,sector_no);
- return geterror(&handelSD);
+ sdmmc_write16(REG_SDBLKCOUNT, numsectors);
+ handelSD.data = out;
+ handelSD.size = numsectors << 9;
+ sdmmc_send_command(&handelSD, 0x33C12, sector_no);
+ return geterror(&handelSD);
}
-
-
-int NO_INLINE sdmmc_nand_readsectors(uint32_t sector_no, uint32_t numsectors, uint8_t *out)
+int NO_INLINE
+sdmmc_nand_readsectors(uint32_t sector_no, uint32_t numsectors, uint8_t* out)
{
- if(handelNAND.isSDHC == 0) sector_no <<= 9;
- inittarget(&handelNAND);
- sdmmc_write16(REG_SDSTOP,0x100);
+ if (handelNAND.isSDHC == 0)
+ sector_no <<= 9;
+ inittarget(&handelNAND);
+ sdmmc_write16(REG_SDSTOP, 0x100);
#ifdef DATA32_SUPPORT
- sdmmc_write16(REG_SDBLKCOUNT32,numsectors);
- sdmmc_write16(REG_SDBLKLEN32,0x200);
+ sdmmc_write16(REG_SDBLKCOUNT32, numsectors);
+ sdmmc_write16(REG_SDBLKLEN32, 0x200);
#endif
- sdmmc_write16(REG_SDBLKCOUNT,numsectors);
- handelNAND.data = out;
- handelNAND.size = numsectors << 9;
- sdmmc_send_command(&handelNAND,0x33C12,sector_no);
- inittarget(&handelSD);
- return geterror(&handelNAND);
+ sdmmc_write16(REG_SDBLKCOUNT, numsectors);
+ handelNAND.data = out;
+ handelNAND.size = numsectors << 9;
+ sdmmc_send_command(&handelNAND, 0x33C12, sector_no);
+ inittarget(&handelSD);
+ return geterror(&handelNAND);
}
-int NO_INLINE sdmmc_nand_writesectors(uint32_t sector_no, uint32_t numsectors, uint8_t *in) //experimental
+int NO_INLINE sdmmc_nand_writesectors(uint32_t sector_no, uint32_t numsectors,
+ uint8_t* in) // experimental
{
- if(handelNAND.isSDHC == 0) sector_no <<= 9;
- inittarget(&handelNAND);
- sdmmc_write16(REG_SDSTOP,0x100);
+ if (handelNAND.isSDHC == 0)
+ sector_no <<= 9;
+ inittarget(&handelNAND);
+ sdmmc_write16(REG_SDSTOP, 0x100);
#ifdef DATA32_SUPPORT
- sdmmc_write16(REG_SDBLKCOUNT32,numsectors);
- sdmmc_write16(REG_SDBLKLEN32,0x200);
+ sdmmc_write16(REG_SDBLKCOUNT32, numsectors);
+ sdmmc_write16(REG_SDBLKLEN32, 0x200);
#endif
- sdmmc_write16(REG_SDBLKCOUNT,numsectors);
- handelNAND.data = in;
- handelNAND.size = numsectors << 9;
- sdmmc_send_command(&handelNAND,0x52C19,sector_no);
- inittarget(&handelSD);
- return geterror(&handelNAND);
+ sdmmc_write16(REG_SDBLKCOUNT, numsectors);
+ handelNAND.data = in;
+ handelNAND.size = numsectors << 9;
+ sdmmc_send_command(&handelNAND, 0x52C19, sector_no);
+ inittarget(&handelSD);
+ return geterror(&handelNAND);
}
-static uint32_t calcSDSize(uint8_t* csd, int type)
+static uint32_t
+calcSDSize(uint8_t* csd, int type)
{
- uint32_t result=0;
- if(type == -1) type = csd[14] >> 6;
- switch(type)
- {
- case 0:
- {
- uint32_t block_len=csd[9]&0xf;
- block_len=1<<block_len;
- uint32_t mult=(csd[4]>>7)|((csd[5]&3)<<1);
- mult=1<<(mult+2);
- result=csd[8]&3;
- result=(result<<8)|csd[7];
- result=(result<<2)|(csd[6]>>6);
- result=(result+1)*mult*block_len/512;
- }
- break;
- case 1:
- result=csd[7]&0x3f;
- result=(result<<8)|csd[6];
- result=(result<<8)|csd[5];
- result=(result+1)*1024;
- break;
- }
- return result;
+ uint32_t result = 0;
+ if (type == -1)
+ type = csd[14] >> 6;
+ switch (type) {
+ case 0: {
+ uint32_t block_len = csd[9] & 0xf;
+ block_len = 1 << block_len;
+ uint32_t mult = (csd[4] >> 7) | ((csd[5] & 3) << 1);
+ mult = 1 << (mult + 2);
+ result = csd[8] & 3;
+ result = (result << 8) | csd[7];
+ result = (result << 2) | (csd[6] >> 6);
+ result = (result + 1) * mult * block_len / 512;
+ } break;
+ case 1:
+ result = csd[7] & 0x3f;
+ result = (result << 8) | csd[6];
+ result = (result << 8) | csd[5];
+ result = (result + 1) * 1024;
+ break;
+ }
+ return result;
}
-void InitSD()
+void
+InitSD()
{
- //NAND
- handelNAND.isSDHC = 0;
- handelNAND.SDOPT = 0;
- handelNAND.res = 0;
- handelNAND.initarg = 1;
- handelNAND.clk = 0x80;
- handelNAND.devicenumber = 1;
-
- //SD
- handelSD.isSDHC = 0;
- handelSD.SDOPT = 0;
- handelSD.res = 0;
- handelSD.initarg = 0;
- handelSD.clk = 0x80;
- handelSD.devicenumber = 0;
-
- //sdmmc_mask16(0x100,0x800,0);
- //sdmmc_mask16(0x100,0x1000,0);
- //sdmmc_mask16(0x100,0x0,0x402);
- //sdmmc_mask16(0xD8,0x22,0x2);
- //sdmmc_mask16(0x100,0x2,0);
- //sdmmc_mask16(0xD8,0x22,0);
- //sdmmc_write16(0x104,0);
- //sdmmc_write16(0x108,1);
- //sdmmc_mask16(REG_SDRESET,1,0); //not in new Version -- nintendo's code does this
- //sdmmc_mask16(REG_SDRESET,0,1); //not in new Version -- nintendo's code does this
- //sdmmc_mask16(0x20,0,0x31D);
- //sdmmc_mask16(0x22,0,0x837F);
- //sdmmc_mask16(0xFC,0,0xDB);
- //sdmmc_mask16(0xFE,0,0xDB);
- ////sdmmc_write16(REG_SDCLKCTL,0x20);
- ////sdmmc_write16(REG_SDOPT,0x40EE);
- ////sdmmc_mask16(0x02,0x3,0);
- //sdmmc_write16(REG_SDCLKCTL,0x40);
- //sdmmc_write16(REG_SDOPT,0x40EB);
- //sdmmc_mask16(0x02,0x3,0);
- //sdmmc_write16(REG_SDBLKLEN,0x200);
- //sdmmc_write16(REG_SDSTOP,0);
-
- *(volatile uint16_t*)0x10006100 &= 0xF7FFu; //SDDATACTL32
- *(volatile uint16_t*)0x10006100 &= 0xEFFFu; //SDDATACTL32
+ // NAND
+ handelNAND.isSDHC = 0;
+ handelNAND.SDOPT = 0;
+ handelNAND.res = 0;
+ handelNAND.initarg = 1;
+ handelNAND.clk = 0x80;
+ handelNAND.devicenumber = 1;
+
+ // SD
+ handelSD.isSDHC = 0;
+ handelSD.SDOPT = 0;
+ handelSD.res = 0;
+ handelSD.initarg = 0;
+ handelSD.clk = 0x80;
+ handelSD.devicenumber = 0;
+
+ // sdmmc_mask16(0x100,0x800,0);
+ // sdmmc_mask16(0x100,0x1000,0);
+ // sdmmc_mask16(0x100,0x0,0x402);
+ // sdmmc_mask16(0xD8,0x22,0x2);
+ // sdmmc_mask16(0x100,0x2,0);
+ // sdmmc_mask16(0xD8,0x22,0);
+ // sdmmc_write16(0x104,0);
+ // sdmmc_write16(0x108,1);
+ // sdmmc_mask16(REG_SDRESET,1,0); //not in new Version -- nintendo's code
+ // does this
+ // sdmmc_mask16(REG_SDRESET,0,1); //not in new Version -- nintendo's code
+ // does this
+ // sdmmc_mask16(0x20,0,0x31D);
+ // sdmmc_mask16(0x22,0,0x837F);
+ // sdmmc_mask16(0xFC,0,0xDB);
+ // sdmmc_mask16(0xFE,0,0xDB);
+ ////sdmmc_write16(REG_SDCLKCTL,0x20);
+ ////sdmmc_write16(REG_SDOPT,0x40EE);
+ ////sdmmc_mask16(0x02,0x3,0);
+ // sdmmc_write16(REG_SDCLKCTL,0x40);
+ // sdmmc_write16(REG_SDOPT,0x40EB);
+ // sdmmc_mask16(0x02,0x3,0);
+ // sdmmc_write16(REG_SDBLKLEN,0x200);
+ // sdmmc_write16(REG_SDSTOP,0);
+
+ *(volatile uint16_t*)0x10006100 &= 0xF7FFu; // SDDATACTL32
+ *(volatile uint16_t*)0x10006100 &= 0xEFFFu; // SDDATACTL32
#ifdef DATA32_SUPPORT
- *(volatile uint16_t*)0x10006100 |= 0x402u; //SDDATACTL32
+ *(volatile uint16_t*)0x10006100 |= 0x402u; // SDDATACTL32
#else
- *(volatile uint16_t*)0x10006100 |= 0x402u; //SDDATACTL32
+ *(volatile uint16_t*)0x10006100 |= 0x402u; // SDDATACTL32
#endif
- *(volatile uint16_t*)0x100060D8 = (*(volatile uint16_t*)0x100060D8 & 0xFFDD) | 2;
+ *(volatile uint16_t*)0x100060D8 =
+ (*(volatile uint16_t*)0x100060D8 & 0xFFDD) | 2;
#ifdef DATA32_SUPPORT
- *(volatile uint16_t*)0x10006100 &= 0xFFFFu; //SDDATACTL32
- *(volatile uint16_t*)0x100060D8 &= 0xFFDFu; //SDDATACTL
- *(volatile uint16_t*)0x10006104 = 512; //SDBLKLEN32
+ *(volatile uint16_t*)0x10006100 &= 0xFFFFu; // SDDATACTL32
+ *(volatile uint16_t*)0x100060D8 &= 0xFFDFu; // SDDATACTL
+ *(volatile uint16_t*)0x10006104 = 512; // SDBLKLEN32
#else
- *(volatile uint16_t*)0x10006100 &= 0xFFFDu; //SDDATACTL32
- *(volatile uint16_t*)0x100060D8 &= 0xFFDDu; //SDDATACTL
- *(volatile uint16_t*)0x10006104 = 0; //SDBLKLEN32
+ *(volatile uint16_t*)0x10006100 &= 0xFFFDu; // SDDATACTL32
+ *(volatile uint16_t*)0x100060D8 &= 0xFFDDu; // SDDATACTL
+ *(volatile uint16_t*)0x10006104 = 0; // SDBLKLEN32
#endif
- *(volatile uint16_t*)0x10006108 = 1; //SDBLKCOUNT32
- *(volatile uint16_t*)0x100060E0 &= 0xFFFEu; //SDRESET
- *(volatile uint16_t*)0x100060E0 |= 1u; //SDRESET
- *(volatile uint16_t*)0x10006020 |= TMIO_MASK_ALL; //SDIR_MASK0
- *(volatile uint16_t*)0x10006022 |= TMIO_MASK_ALL>>16; //SDIR_MASK1
- *(volatile uint16_t*)0x100060FC |= 0xDBu; //SDCTL_RESERVED7
- *(volatile uint16_t*)0x100060FE |= 0xDBu; //SDCTL_RESERVED8
- *(volatile uint16_t*)0x10006002 &= 0xFFFCu; //SDPORTSEL
+ *(volatile uint16_t*)0x10006108 = 1; // SDBLKCOUNT32
+ *(volatile uint16_t*)0x100060E0 &= 0xFFFEu; // SDRESET
+ *(volatile uint16_t*)0x100060E0 |= 1u; // SDRESET
+ *(volatile uint16_t*)0x10006020 |= TMIO_MASK_ALL; // SDIR_MASK0
+ *(volatile uint16_t*)0x10006022 |= TMIO_MASK_ALL >> 16; // SDIR_MASK1
+ *(volatile uint16_t*)0x100060FC |= 0xDBu; // SDCTL_RESERVED7
+ *(volatile uint16_t*)0x100060FE |= 0xDBu; // SDCTL_RESERVED8
+ *(volatile uint16_t*)0x10006002 &= 0xFFFCu; // SDPORTSEL
#ifdef DATA32_SUPPORT
- *(volatile uint16_t*)0x10006024 = 0x20;
- *(volatile uint16_t*)0x10006028 = 0x40EE;
+ *(volatile uint16_t*)0x10006024 = 0x20;
+ *(volatile uint16_t*)0x10006028 = 0x40EE;
#else
- *(volatile uint16_t*)0x10006024 = 0x40; //Nintendo sets this to 0x20
- *(volatile uint16_t*)0x10006028 = 0x40EB; //Nintendo sets this to 0x40EE
+ *(volatile uint16_t*)0x10006024 = 0x40; // Nintendo sets this to 0x20
+ *(volatile uint16_t*)0x10006028 = 0x40EB; // Nintendo sets this to 0x40EE
#endif
- *(volatile uint16_t*)0x10006002 &= 0xFFFCu; ////SDPORTSEL
- *(volatile uint16_t*)0x10006026 = 512; //SDBLKLEN
- *(volatile uint16_t*)0x10006008 = 0; //SDSTOP
-
- inittarget(&handelSD);
+ *(volatile uint16_t*)0x10006002 &= 0xFFFCu; ////SDPORTSEL
+ *(volatile uint16_t*)0x10006026 = 512; // SDBLKLEN
+ *(volatile uint16_t*)0x10006008 = 0; // SDSTOP
+
+ inittarget(&handelSD);
}
-int Nand_Init()
+int
+Nand_Init()
{
- inittarget(&handelNAND);
- waitcycles(0xF000);
-
- DEBUGPRINT(topScreen, "0x00000 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
-
- sdmmc_send_command(&handelNAND,0,0);
-
- DEBUGPRINT(topScreen, "0x10701 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
-
- do
- {
- do
- {
- sdmmc_send_command(&handelNAND,0x10701,0x100000);
- DEBUGPRINT(topScreen, "error ", handelNAND.error, 10, 20 + 17*8, RGB(40, 40, 40), RGB(208, 208, 208));
- DEBUGPRINT(topScreen, "ret: ", handelNAND.ret[0], 10, 20 + 18*8, RGB(40, 40, 40), RGB(208, 208, 208));
- DEBUGPRINT(topScreen, "test ", 3, 10, 20 + 19*8, RGB(40, 40, 40), RGB(208, 208, 208));
- } while ( !(handelNAND.error & 1) );
- }
- while((handelNAND.ret[0] & 0x80000000) == 0);
-
- DEBUGPRINT(topScreen, "0x10602 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
-
- sdmmc_send_command(&handelNAND,0x10602,0x0);
- if((handelNAND.error & 0x4))return -1;
-
- DEBUGPRINT(topScreen, "0x10403 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
-
- sdmmc_send_command(&handelNAND,0x10403,handelNAND.initarg << 0x10);
- if((handelNAND.error & 0x4))return -1;
-
- DEBUGPRINT(topScreen, "0x10609 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
-
- sdmmc_send_command(&handelNAND,0x10609,handelNAND.initarg << 0x10);
- if((handelNAND.error & 0x4))return -1;
-
- DEBUGPRINT(topScreen, "0x10407 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
-
- handelNAND.total_size = calcSDSize((uint8_t*)&handelNAND.ret[0],0);
- handelNAND.clk = 1;
- setckl(1);
-
- sdmmc_send_command(&handelNAND,0x10407,handelNAND.initarg << 0x10);
- if((handelNAND.error & 0x4))return -1;
-
- DEBUGPRINT(topScreen, "0x10506 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
-
- handelNAND.SDOPT = 1;
-
- sdmmc_send_command(&handelNAND,0x10506,0x3B70100);
- if((handelNAND.error & 0x4))return -1;
-
- DEBUGPRINT(topScreen, "0x10506 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
-
- sdmmc_send_command(&handelNAND,0x10506,0x3B90100);
- if((handelNAND.error & 0x4))return -1;
-
- DEBUGPRINT(topScreen, "0x1040D ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
-
- sdmmc_send_command(&handelNAND,0x1040D,handelNAND.initarg << 0x10);
- if((handelNAND.error & 0x4))return -1;
-
- DEBUGPRINT(topScreen, "0x10410 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
-
- sdmmc_send_command(&handelNAND,0x10410,0x200);
- if((handelNAND.error & 0x4))return -1;
-
- handelNAND.clk |= 0x200;
-
- inittarget(&handelSD);
-
- return 0;
+ inittarget(&handelNAND);
+ waitcycles(0xF000);
+
+ DEBUGPRINT(topScreen, "0x00000 ", handelNAND.error, 10, 20 + 13 * 8,
+ RGB(40, 40, 40), RGB(208, 208, 208));
+
+ sdmmc_send_command(&handelNAND, 0, 0);
+
+ DEBUGPRINT(topScreen, "0x10701 ", handelNAND.error, 10, 20 + 13 * 8,
+ RGB(40, 40, 40), RGB(208, 208, 208));
+
+ do {
+ do {
+ sdmmc_send_command(&handelNAND, 0x10701, 0x100000);
+ DEBUGPRINT(topScreen, "error ", handelNAND.error, 10, 20 + 17 * 8,
+ RGB(40, 40, 40), RGB(208, 208, 208));
+ DEBUGPRINT(topScreen, "ret: ", handelNAND.ret[0], 10, 20 + 18 * 8,
+ RGB(40, 40, 40), RGB(208, 208, 208));
+ DEBUGPRINT(topScreen, "test ", 3, 10, 20 + 19 * 8, RGB(40, 40, 40),
+ RGB(208, 208, 208));
+ } while (!(handelNAND.error & 1));
+ } while ((handelNAND.ret[0] & 0x80000000) == 0);
+
+ DEBUGPRINT(topScreen, "0x10602 ", handelNAND.error, 10, 20 + 13 * 8,
+ RGB(40, 40, 40), RGB(208, 208, 208));
+
+ sdmmc_send_command(&handelNAND, 0x10602, 0x0);
+ if ((handelNAND.error & 0x4))
+ return -1;
+
+ DEBUGPRINT(topScreen, "0x10403 ", handelNAND.error, 10, 20 + 13 * 8,
+ RGB(40, 40, 40), RGB(208, 208, 208));
+
+ sdmmc_send_command(&handelNAND, 0x10403, handelNAND.initarg << 0x10);
+ if ((handelNAND.error & 0x4))
+ return -1;
+
+ DEBUGPRINT(topScreen, "0x10609 ", handelNAND.error, 10, 20 + 13 * 8,
+ RGB(40, 40, 40), RGB(208, 208, 208));
+
+ sdmmc_send_command(&handelNAND, 0x10609, handelNAND.initarg << 0x10);
+ if ((handelNAND.error & 0x4))
+ return -1;
+
+ DEBUGPRINT(topScreen, "0x10407 ", handelNAND.error, 10, 20 + 13 * 8,
+ RGB(40, 40, 40), RGB(208, 208, 208));
+
+ handelNAND.total_size = calcSDSize((uint8_t*)&handelNAND.ret[0], 0);
+ handelNAND.clk = 1;
+ setckl(1);
+
+ sdmmc_send_command(&handelNAND, 0x10407, handelNAND.initarg << 0x10);
+ if ((handelNAND.error & 0x4))
+ return -1;
+
+ DEBUGPRINT(topScreen, "0x10506 ", handelNAND.error, 10, 20 + 13 * 8,
+ RGB(40, 40, 40), RGB(208, 208, 208));
+
+ handelNAND.SDOPT = 1;
+
+ sdmmc_send_command(&handelNAND, 0x10506, 0x3B70100);
+ if ((handelNAND.error & 0x4))
+ return -1;
+
+ DEBUGPRINT(topScreen, "0x10506 ", handelNAND.error, 10, 20 + 13 * 8,
+ RGB(40, 40, 40), RGB(208, 208, 208));
+
+ sdmmc_send_command(&handelNAND, 0x10506, 0x3B90100);
+ if ((handelNAND.error & 0x4))
+ return -1;
+
+ DEBUGPRINT(topScreen, "0x1040D ", handelNAND.error, 10, 20 + 13 * 8,
+ RGB(40, 40, 40), RGB(208, 208, 208));
+
+ sdmmc_send_command(&handelNAND, 0x1040D, handelNAND.initarg << 0x10);
+ if ((handelNAND.error & 0x4))
+ return -1;
+
+ DEBUGPRINT(topScreen, "0x10410 ", handelNAND.error, 10, 20 + 13 * 8,
+ RGB(40, 40, 40), RGB(208, 208, 208));
+
+ sdmmc_send_command(&handelNAND, 0x10410, 0x200);
+ if ((handelNAND.error & 0x4))
+ return -1;
+
+ handelNAND.clk |= 0x200;
+
+ inittarget(&handelSD);
+
+ return 0;
}
-int SD_Init()
+int
+SD_Init()
{
- inittarget(&handelSD);
- //waitcycles(0x3E8);
- //waitcycles(0xF000);
-
- waitcycles(1u << 19); //Card needs a little bit of time to be detected, it seems
- if (!(*((volatile uint16_t*)0x1000601c) & TMIO_STAT0_SIGSTATE)) return -1; // check if card inserted
-
- DEBUGPRINT(topScreen, "0x00000 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
- sdmmc_send_command(&handelSD,0,0);
- DEBUGPRINT(topScreen, "0x10408 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
- sdmmc_send_command(&handelSD,0x10408,0x1AA);
- //uint32_t temp = (handelSD.ret[0] == 0x1AA) << 0x1E;
- uint32_t temp = (handelSD.error & 0x1) << 0x1E;
-
- DEBUGPRINT(topScreen, "0x10769 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
- DEBUGPRINT(topScreen, "sd ret: ", handelSD.ret[0], 10, 20 + 15*8, RGB(40, 40, 40), RGB(208, 208, 208));
- DEBUGPRINT(topScreen, "temp: ", temp, 10, 20 + 16*8, RGB(40, 40, 40), RGB(208, 208, 208));
-
- //int count = 0;
- uint32_t temp2 = 0;
- do
- {
- do
- {
- sdmmc_send_command(&handelSD,0x10437,handelSD.initarg << 0x10);
- sdmmc_send_command(&handelSD,0x10769,0x00FF8000 | temp);
- temp2 = 1;
- } while ( !(handelSD.error & 1) );
-
- //DEBUGPRINT(topScreen, "sd error ", handelSD.error, 10, 20 + 17*8, RGB(40, 40, 40), RGB(208, 208, 208));
- //DEBUGPRINT(topScreen, "sd ret: ", handelSD.ret[0], 10, 20 + 18*8, RGB(40, 40, 40), RGB(208, 208, 208));
- //DEBUGPRINT(topScreen, "count: ", count++, 10, 20 + 19*8, RGB(40, 40, 40), RGB(208, 208, 208));
- }
- while((handelSD.ret[0] & 0x80000000) == 0);
- //do
- //{
- // sdmmc_send_command(&handelSD,0x10437,handelSD.initarg << 0x10);
- // sdmmc_send_command(&handelSD,0x10769,0x00FF8000 | temp);
- //
- // DEBUGPRINT(topScreen, "sd error ", handelSD.error, 10, 20 + 17*8, RGB(40, 40, 40), RGB(208, 208, 208));
- // DEBUGPRINT(topScreen, "sd ret: ", handelSD.ret[0], 10, 20 + 18*8, RGB(40, 40, 40), RGB(208, 208, 208));
- // DEBUGPRINT(topScreen, "count: ", count++, 10, 20 + 19*8, RGB(40, 40, 40), RGB(208, 208, 208));
- //}
- //while(!(handelSD.ret[0] & 0x80000000));
-
- if(!((handelSD.ret[0] >> 30) & 1) || !temp)
- temp2 = 0;
-
- handelSD.isSDHC = temp2;
- //handelSD.isSDHC = (handelSD.ret[0] & 0x40000000);
-
- DEBUGPRINT(topScreen, "0x10602 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
-
- sdmmc_send_command(&handelSD,0x10602,0);
- if((handelSD.error & 0x4)) return -1;
-
- DEBUGPRINT(topScreen, "0x10403 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
-
- sdmmc_send_command(&handelSD,0x10403,0);
- if((handelSD.error & 0x4)) return -1;
- handelSD.initarg = handelSD.ret[0] >> 0x10;
-
- DEBUGPRINT(topScreen, "0x10609 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
-
- sdmmc_send_command(&handelSD,0x10609,handelSD.initarg << 0x10);
- if((handelSD.error & 0x4)) return -1;
-
- handelSD.total_size = calcSDSize((uint8_t*)&handelSD.ret[0],-1);
- handelSD.clk = 1;
- setckl(1);
-
- DEBUGPRINT(topScreen, "0x10507 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
-
- sdmmc_send_command(&handelSD,0x10507,handelSD.initarg << 0x10);
- if((handelSD.error & 0x4)) return -1;
-
- DEBUGPRINT(topScreen, "0x10437 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
-
- sdmmc_send_command(&handelSD,0x10437,handelSD.initarg << 0x10);
- if((handelSD.error & 0x4)) return -1;
-
- DEBUGPRINT(topScreen, "0x10446 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
-
- handelSD.SDOPT = 1;
- sdmmc_send_command(&handelSD,0x10446,0x2);
- if((handelSD.error & 0x4)) return -1;
-
- DEBUGPRINT(topScreen, "0x1040D ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
-
- sdmmc_send_command(&handelSD,0x1040D,handelSD.initarg << 0x10);
- if((handelSD.error & 0x4)) return -1;
-
- DEBUGPRINT(topScreen, "0x10410 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
-
- sdmmc_send_command(&handelSD,0x10410,0x200);
- if((handelSD.error & 0x4)) return -1;
- handelSD.clk |= 0x200;
-
- return 0;
+ inittarget(&handelSD);
+ // waitcycles(0x3E8);
+ // waitcycles(0xF000);
+
+ waitcycles(
+ 1u << 19); // Card needs a little bit of time to be detected, it seems
+ if (!(*((volatile uint16_t*)0x1000601c) & TMIO_STAT0_SIGSTATE))
+ return -1; // check if card inserted
+
+ DEBUGPRINT(topScreen, "0x00000 ", handelSD.error, 10, 20 + 14 * 8,
+ RGB(40, 40, 40), RGB(208, 208, 208));
+ sdmmc_send_command(&handelSD, 0, 0);
+ DEBUGPRINT(topScreen, "0x10408 ", handelSD.error, 10, 20 + 14 * 8,
+ RGB(40, 40, 40), RGB(208, 208, 208));
+ sdmmc_send_command(&handelSD, 0x10408, 0x1AA);
+ // uint32_t temp = (handelSD.ret[0] == 0x1AA) << 0x1E;
+ uint32_t temp = (handelSD.error & 0x1) << 0x1E;
+
+ DEBUGPRINT(topScreen, "0x10769 ", handelSD.error, 10, 20 + 14 * 8,
+ RGB(40, 40, 40), RGB(208, 208, 208));
+ DEBUGPRINT(topScreen, "sd ret: ", handelSD.ret[0], 10, 20 + 15 * 8,
+ RGB(40, 40, 40), RGB(208, 208, 208));
+ DEBUGPRINT(topScreen, "temp: ", temp, 10, 20 + 16 * 8, RGB(40, 40, 40),
+ RGB(208, 208, 208));
+
+ // int count = 0;
+ uint32_t temp2 = 0;
+ do {
+ do {
+ sdmmc_send_command(&handelSD, 0x10437, handelSD.initarg << 0x10);
+ sdmmc_send_command(&handelSD, 0x10769, 0x00FF8000 | temp);
+ temp2 = 1;
+ } while (!(handelSD.error & 1));
+
+ // DEBUGPRINT(topScreen, "sd error ", handelSD.error, 10, 20 + 17*8,
+ // RGB(40, 40, 40), RGB(208, 208, 208));
+ // DEBUGPRINT(topScreen, "sd ret: ", handelSD.ret[0], 10, 20 + 18*8,
+ // RGB(40, 40, 40), RGB(208, 208, 208));
+ // DEBUGPRINT(topScreen, "count: ", count++, 10, 20 + 19*8, RGB(40, 40,
+ // 40), RGB(208, 208, 208));
+ } while ((handelSD.ret[0] & 0x80000000) == 0);
+ // do
+ //{
+ // sdmmc_send_command(&handelSD,0x10437,handelSD.initarg << 0x10);
+ // sdmmc_send_command(&handelSD,0x10769,0x00FF8000 | temp);
+ //
+ // DEBUGPRINT(topScreen, "sd error ", handelSD.error, 10, 20 + 17*8,
+ //RGB(40, 40, 40), RGB(208, 208, 208));
+ // DEBUGPRINT(topScreen, "sd ret: ", handelSD.ret[0], 10, 20 + 18*8,
+ //RGB(40, 40, 40), RGB(208, 208, 208));
+ // DEBUGPRINT(topScreen, "count: ", count++, 10, 20 + 19*8, RGB(40, 40,
+ //40), RGB(208, 208, 208));
+ //}
+ // while(!(handelSD.ret[0] & 0x80000000));
+
+ if (!((handelSD.ret[0] >> 30) & 1) || !temp)
+ temp2 = 0;
+
+ handelSD.isSDHC = temp2;
+ // handelSD.isSDHC = (handelSD.ret[0] & 0x40000000);
+
+ DEBUGPRINT(topScreen, "0x10602 ", handelSD.error, 10, 20 + 14 * 8,
+ RGB(40, 40, 40), RGB(208, 208, 208));
+
+ sdmmc_send_command(&handelSD, 0x10602, 0);
+ if ((handelSD.error & 0x4))
+ return -1;
+
+ DEBUGPRINT(topScreen, "0x10403 ", handelSD.error, 10, 20 + 14 * 8,
+ RGB(40, 40, 40), RGB(208, 208, 208));
+
+ sdmmc_send_command(&handelSD, 0x10403, 0);
+ if ((handelSD.error & 0x4))
+ return -1;
+ handelSD.initarg = handelSD.ret[0] >> 0x10;
+
+ DEBUGPRINT(topScreen, "0x10609 ", handelSD.error, 10, 20 + 14 * 8,
+ RGB(40, 40, 40), RGB(208, 208, 208));
+
+ sdmmc_send_command(&handelSD, 0x10609, handelSD.initarg << 0x10);
+ if ((handelSD.error & 0x4))
+ return -1;
+
+ handelSD.total_size = calcSDSize((uint8_t*)&handelSD.ret[0], -1);
+ handelSD.clk = 1;
+ setckl(1);
+
+ DEBUGPRINT(topScreen, "0x10507 ", handelSD.error, 10, 20 + 14 * 8,
+ RGB(40, 40, 40), RGB(208, 208, 208));
+
+ sdmmc_send_command(&handelSD, 0x10507, handelSD.initarg << 0x10);
+ if ((handelSD.error & 0x4))
+ return -1;
+
+ DEBUGPRINT(topScreen, "0x10437 ", handelSD.error, 10, 20 + 14 * 8,
+ RGB(40, 40, 40), RGB(208, 208, 208));
+
+ sdmmc_send_command(&handelSD, 0x10437, handelSD.initarg << 0x10);
+ if ((handelSD.error & 0x4))
+ return -1;
+
+ DEBUGPRINT(topScreen, "0x10446 ", handelSD.error, 10, 20 + 14 * 8,
+ RGB(40, 40, 40), RGB(208, 208, 208));
+
+ handelSD.SDOPT = 1;
+ sdmmc_send_command(&handelSD, 0x10446, 0x2);
+ if ((handelSD.error & 0x4))
+ return -1;
+
+ DEBUGPRINT(topScreen, "0x1040D ", handelSD.error, 10, 20 + 14 * 8,
+ RGB(40, 40, 40), RGB(208, 208, 208));
+
+ sdmmc_send_command(&handelSD, 0x1040D, handelSD.initarg << 0x10);
+ if ((handelSD.error & 0x4))
+ return -1;
+
+ DEBUGPRINT(topScreen, "0x10410 ", handelSD.error, 10, 20 + 14 * 8,
+ RGB(40, 40, 40), RGB(208, 208, 208));
+
+ sdmmc_send_command(&handelSD, 0x10410, 0x200);
+ if ((handelSD.error & 0x4))
+ return -1;
+ handelSD.clk |= 0x200;
+
+ return 0;
}
-int sdmmc_sdcard_init()
+int
+sdmmc_sdcard_init()
{
- DEBUGPRINT(topScreen, "sdmmc_sdcard_init ", handelSD.error, 10, 20 + 2*8, RGB(40, 40, 40), RGB(208, 208, 208));
- InitSD();
- //SD_Init2();
- //Nand_Init();
- Nand_Init();
- DEBUGPRINT(topScreen, "nand_res ", nand_res, 10, 20 + 3*8, RGB(40, 40, 40), RGB(208, 208, 208));
- if (SD_Init() != 0) return FALSE;
- DEBUGPRINT(topScreen, "sd_res ", sd_res, 10, 20 + 4*8, RGB(40, 40, 40), RGB(208, 208, 208));
-
+ DEBUGPRINT(topScreen, "sdmmc_sdcard_init ", handelSD.error, 10, 20 + 2 * 8,
+ RGB(40, 40, 40), RGB(208, 208, 208));
+ InitSD();
+ // SD_Init2();
+ // Nand_Init();
+ Nand_Init();
+ DEBUGPRINT(topScreen, "nand_res ", nand_res, 10, 20 + 3 * 8,
+ RGB(40, 40, 40), RGB(208, 208, 208));
+ if (SD_Init() != 0)
+ return FALSE;
+ DEBUGPRINT(topScreen, "sd_res ", sd_res, 10, 20 + 4 * 8, RGB(40, 40, 40),
+ RGB(208, 208, 208));
+
return TRUE;
}
-int sdmmc_get_cid( int isNand, uint32_t *info)
+int
+sdmmc_get_cid(int isNand, uint32_t* info)
{
- struct mmcdevice *device;
- if(isNand)
- device = &handelNAND;
- else
- device = &handelSD;
-
- inittarget(device);
- // use cmd7 to put sd card in standby mode
- // CMD7
- {
- sdmmc_send_command(device,0x10507,0);
- //if((device->error & 0x4)) return -1;
- }
-
- // get sd card info
- // use cmd10 to read CID
- {
- sdmmc_send_command(device,0x1060A,device->initarg << 0x10);
- //if((device->error & 0x4)) return -2;
-
- for( int i = 0; i < 4; ++i ) {
- info[i] = device->ret[i];
- }
- }
-
- // put sd card back to transfer mode
- // CMD7
- {
- sdmmc_send_command(device,0x10507,device->initarg << 0x10);
- //if((device->error & 0x4)) return -3;
- }
-
- if(isNand)
- {
- inittarget(&handelSD);
- }
-
- return 0;
+ struct mmcdevice* device;
+ if (isNand)
+ device = &handelNAND;
+ else
+ device = &handelSD;
+
+ inittarget(device);
+ // use cmd7 to put sd card in standby mode
+ // CMD7
+ {
+ sdmmc_send_command(device, 0x10507, 0);
+ // if((device->error & 0x4)) return -1;
+ }
+
+ // get sd card info
+ // use cmd10 to read CID
+ {
+ sdmmc_send_command(device, 0x1060A, device->initarg << 0x10);
+ // if((device->error & 0x4)) return -2;
+
+ for (int i = 0; i < 4; ++i) {
+ info[i] = device->ret[i];
+ }
+ }
+
+ // put sd card back to transfer mode
+ // CMD7
+ {
+ sdmmc_send_command(device, 0x10507, device->initarg << 0x10);
+ // if((device->error & 0x4)) return -3;
+ }
+
+ if (isNand) {
+ inittarget(&handelSD);
+ }
+
+ return 0;
}
#include <stdint.h>
-#define SDMMC_BASE 0x10006000
-
-#define REG_SDCMD 0x00
-#define REG_SDPORTSEL 0x02
-#define REG_SDCMDARG 0x04
-#define REG_SDCMDARG0 0x04
-#define REG_SDCMDARG1 0x06
-#define REG_SDSTOP 0x08
-#define REG_SDBLKCOUNT 0x0a
-
-#define REG_SDRESP0 0x0c
-#define REG_SDRESP1 0x0e
-#define REG_SDRESP2 0x10
-#define REG_SDRESP3 0x12
-#define REG_SDRESP4 0x14
-#define REG_SDRESP5 0x16
-#define REG_SDRESP6 0x18
-#define REG_SDRESP7 0x1a
-
-#define REG_SDSTATUS0 0x1c
-#define REG_SDSTATUS1 0x1e
-
-#define REG_SDIRMASK0 0x20
-#define REG_SDIRMASK1 0x22
-#define REG_SDCLKCTL 0x24
-
-#define REG_SDBLKLEN 0x26
-#define REG_SDOPT 0x28
-#define REG_SDFIFO 0x30
-
-#define REG_DATACTL 0xd8
-#define REG_SDRESET 0xe0
-#define REG_SDPROTECTED 0xf6 //bit 0 determines if sd is protected or not?
-
-#define REG_DATACTL32 0x100
-#define REG_SDBLKLEN32 0x104
-#define REG_SDBLKCOUNT32 0x108
-#define REG_SDFIFO32 0x10C
-
-#define REG_CLK_AND_WAIT_CTL 0x138
-#define REG_RESET_SDIO 0x1e0
-
-#define TMIO_STAT0_CMDRESPEND 0x0001
-#define TMIO_STAT0_DATAEND 0x0004
-#define TMIO_STAT0_CARD_REMOVE 0x0008
-#define TMIO_STAT0_CARD_INSERT 0x0010
-#define TMIO_STAT0_SIGSTATE 0x0020
-#define TMIO_STAT0_WRPROTECT 0x0080
+#define SDMMC_BASE 0x10006000
+
+#define REG_SDCMD 0x00
+#define REG_SDPORTSEL 0x02
+#define REG_SDCMDARG 0x04
+#define REG_SDCMDARG0 0x04
+#define REG_SDCMDARG1 0x06
+#define REG_SDSTOP 0x08
+#define REG_SDBLKCOUNT 0x0a
+
+#define REG_SDRESP0 0x0c
+#define REG_SDRESP1 0x0e
+#define REG_SDRESP2 0x10
+#define REG_SDRESP3 0x12
+#define REG_SDRESP4 0x14
+#define REG_SDRESP5 0x16
+#define REG_SDRESP6 0x18
+#define REG_SDRESP7 0x1a
+
+#define REG_SDSTATUS0 0x1c
+#define REG_SDSTATUS1 0x1e
+
+#define REG_SDIRMASK0 0x20
+#define REG_SDIRMASK1 0x22
+#define REG_SDCLKCTL 0x24
+
+#define REG_SDBLKLEN 0x26
+#define REG_SDOPT 0x28
+#define REG_SDFIFO 0x30
+
+#define REG_DATACTL 0xd8
+#define REG_SDRESET 0xe0
+#define REG_SDPROTECTED 0xf6 // bit 0 determines if sd is protected or not?
+
+#define REG_DATACTL32 0x100
+#define REG_SDBLKLEN32 0x104
+#define REG_SDBLKCOUNT32 0x108
+#define REG_SDFIFO32 0x10C
+
+#define REG_CLK_AND_WAIT_CTL 0x138
+#define REG_RESET_SDIO 0x1e0
+
+#define TMIO_STAT0_CMDRESPEND 0x0001
+#define TMIO_STAT0_DATAEND 0x0004
+#define TMIO_STAT0_CARD_REMOVE 0x0008
+#define TMIO_STAT0_CARD_INSERT 0x0010
+#define TMIO_STAT0_SIGSTATE 0x0020
+#define TMIO_STAT0_WRPROTECT 0x0080
#define TMIO_STAT0_CARD_REMOVE_A 0x0100
#define TMIO_STAT0_CARD_INSERT_A 0x0200
-#define TMIO_STAT0_SIGSTATE_A 0x0400
-#define TMIO_STAT1_CMD_IDX_ERR 0x0001
-#define TMIO_STAT1_CRCFAIL 0x0002
-#define TMIO_STAT1_STOPBIT_ERR 0x0004
-#define TMIO_STAT1_DATATIMEOUT 0x0008
-#define TMIO_STAT1_RXOVERFLOW 0x0010
-#define TMIO_STAT1_TXUNDERRUN 0x0020
-#define TMIO_STAT1_CMDTIMEOUT 0x0040
-#define TMIO_STAT1_RXRDY 0x0100
-#define TMIO_STAT1_TXRQ 0x0200
-#define TMIO_STAT1_ILL_FUNC 0x2000
-#define TMIO_STAT1_CMD_BUSY 0x4000
-#define TMIO_STAT1_ILL_ACCESS 0x8000
-
-//Comes from TWLSDK mongoose.tef DWARF info
-#define SDMC_NORMAL 0x00000000
-#define SDMC_ERR_COMMAND 0x00000001
-#define SDMC_ERR_CRC 0x00000002
-#define SDMC_ERR_END 0x00000004
-#define SDMC_ERR_TIMEOUT 0x00000008
-#define SDMC_ERR_FIFO_OVF 0x00000010
-#define SDMC_ERR_FIFO_UDF 0x00000020
-#define SDMC_ERR_WP 0x00000040
-#define SDMC_ERR_ABORT 0x00000080
-#define SDMC_ERR_FPGA_TIMEOUT 0x00000100
-#define SDMC_ERR_PARAM 0x00000200
-#define SDMC_ERR_R1_STATUS 0x00000800
-#define SDMC_ERR_NUM_WR_SECTORS 0x00001000
-#define SDMC_ERR_RESET 0x00002000
-#define SDMC_ERR_ILA 0x00004000
-#define SDMC_ERR_INFO_DETECT 0x00008000
-
-#define SDMC_STAT_ERR_UNKNOWN 0x00080000
-#define SDMC_STAT_ERR_CC 0x00100000
+#define TMIO_STAT0_SIGSTATE_A 0x0400
+#define TMIO_STAT1_CMD_IDX_ERR 0x0001
+#define TMIO_STAT1_CRCFAIL 0x0002
+#define TMIO_STAT1_STOPBIT_ERR 0x0004
+#define TMIO_STAT1_DATATIMEOUT 0x0008
+#define TMIO_STAT1_RXOVERFLOW 0x0010
+#define TMIO_STAT1_TXUNDERRUN 0x0020
+#define TMIO_STAT1_CMDTIMEOUT 0x0040
+#define TMIO_STAT1_RXRDY 0x0100
+#define TMIO_STAT1_TXRQ 0x0200
+#define TMIO_STAT1_ILL_FUNC 0x2000
+#define TMIO_STAT1_CMD_BUSY 0x4000
+#define TMIO_STAT1_ILL_ACCESS 0x8000
+
+// Comes from TWLSDK mongoose.tef DWARF info
+#define SDMC_NORMAL 0x00000000
+#define SDMC_ERR_COMMAND 0x00000001
+#define SDMC_ERR_CRC 0x00000002
+#define SDMC_ERR_END 0x00000004
+#define SDMC_ERR_TIMEOUT 0x00000008
+#define SDMC_ERR_FIFO_OVF 0x00000010
+#define SDMC_ERR_FIFO_UDF 0x00000020
+#define SDMC_ERR_WP 0x00000040
+#define SDMC_ERR_ABORT 0x00000080
+#define SDMC_ERR_FPGA_TIMEOUT 0x00000100
+#define SDMC_ERR_PARAM 0x00000200
+#define SDMC_ERR_R1_STATUS 0x00000800
+#define SDMC_ERR_NUM_WR_SECTORS 0x00001000
+#define SDMC_ERR_RESET 0x00002000
+#define SDMC_ERR_ILA 0x00004000
+#define SDMC_ERR_INFO_DETECT 0x00008000
+
+#define SDMC_STAT_ERR_UNKNOWN 0x00080000
+#define SDMC_STAT_ERR_CC 0x00100000
#define SDMC_STAT_ERR_ECC_FAILED 0x00200000
-#define SDMC_STAT_ERR_CRC 0x00800000
-#define SDMC_STAT_ERR_OTHER 0xf9c70008
+#define SDMC_STAT_ERR_CRC 0x00800000
+#define SDMC_STAT_ERR_OTHER 0xf9c70008
-#define TMIO_MASK_ALL 0x837f031d
+#define TMIO_MASK_ALL 0x837f031d
-#define TMIO_MASK_GW (TMIO_STAT1_ILL_ACCESS | TMIO_STAT1_CMDTIMEOUT | TMIO_STAT1_TXUNDERRUN | TMIO_STAT1_RXOVERFLOW | \
- TMIO_STAT1_DATATIMEOUT | TMIO_STAT1_STOPBIT_ERR | TMIO_STAT1_CRCFAIL | TMIO_STAT1_CMD_IDX_ERR)
+#define TMIO_MASK_GW \
+ (TMIO_STAT1_ILL_ACCESS | TMIO_STAT1_CMDTIMEOUT | TMIO_STAT1_TXUNDERRUN | \
+ TMIO_STAT1_RXOVERFLOW | TMIO_STAT1_DATATIMEOUT | TMIO_STAT1_STOPBIT_ERR | \
+ TMIO_STAT1_CRCFAIL | TMIO_STAT1_CMD_IDX_ERR)
-#define TMIO_MASK_READOP (TMIO_STAT1_RXRDY | TMIO_STAT1_DATAEND)
+#define TMIO_MASK_READOP (TMIO_STAT1_RXRDY | TMIO_STAT1_DATAEND)
#define TMIO_MASK_WRITEOP (TMIO_STAT1_TXRQ | TMIO_STAT1_DATAEND)
#ifdef __cplusplus
extern "C" {
#endif
- typedef struct mmcdevice {
- uint8_t* data;
- uint32_t size;
- uint32_t error;
- uint16_t stat0;
- uint16_t stat1;
- uint32_t ret[4];
- uint32_t initarg;
- uint32_t isSDHC;
- uint32_t clk;
- uint32_t SDOPT;
- uint32_t devicenumber;
- uint32_t total_size; //size in sectors of the device
- uint32_t res;
- } mmcdevice;
-
- int sdmmc_sdcard_init();
- int sdmmc_sdcard_readsector(uint32_t sector_no, uint8_t *out);
- int sdmmc_sdcard_readsectors(uint32_t sector_no, uint32_t numsectors, uint8_t *out);
- int sdmmc_sdcard_writesector(uint32_t sector_no, uint8_t *in);
- int sdmmc_sdcard_writesectors(uint32_t sector_no, uint32_t numsectors, uint8_t *in);
-
- int sdmmc_nand_readsectors(uint32_t sector_no, uint32_t numsectors, uint8_t *out);
- int sdmmc_nand_writesectors(uint32_t sector_no, uint32_t numsectors, uint8_t *in);
-
- int sdmmc_get_cid( int isNand, uint32_t *info);
-
- mmcdevice *getMMCDevice(int drive);
-
- void InitSD();
- int Nand_Init();
- int SD_Init();
+typedef struct mmcdevice
+{
+ uint8_t* data;
+ uint32_t size;
+ uint32_t error;
+ uint16_t stat0;
+ uint16_t stat1;
+ uint32_t ret[4];
+ uint32_t initarg;
+ uint32_t isSDHC;
+ uint32_t clk;
+ uint32_t SDOPT;
+ uint32_t devicenumber;
+ uint32_t total_size; // size in sectors of the device
+ uint32_t res;
+} mmcdevice;
+
+int sdmmc_sdcard_init();
+int sdmmc_sdcard_readsector(uint32_t sector_no, uint8_t* out);
+int sdmmc_sdcard_readsectors(uint32_t sector_no, uint32_t numsectors,
+ uint8_t* out);
+int sdmmc_sdcard_writesector(uint32_t sector_no, uint8_t* in);
+int sdmmc_sdcard_writesectors(uint32_t sector_no, uint32_t numsectors,
+ uint8_t* in);
+
+int sdmmc_nand_readsectors(uint32_t sector_no, uint32_t numsectors,
+ uint8_t* out);
+int sdmmc_nand_writesectors(uint32_t sector_no, uint32_t numsectors,
+ uint8_t* in);
+
+int sdmmc_get_cid(int isNand, uint32_t* info);
+
+mmcdevice* getMMCDevice(int drive);
+
+void InitSD();
+int Nand_Init();
+int SD_Init();
#ifdef __cplusplus
};
#endif
//---------------------------------------------------------------------------------
-static inline uint16_t sdmmc_read16(uint16_t reg) {
-//---------------------------------------------------------------------------------
- return *(volatile uint16_t*)(SDMMC_BASE + reg);
+static inline uint16_t
+sdmmc_read16(uint16_t reg)
+{
+ //---------------------------------------------------------------------------------
+ return *(volatile uint16_t*)(SDMMC_BASE + reg);
}
//---------------------------------------------------------------------------------
-static inline void sdmmc_write16(uint16_t reg, uint16_t val) {
-//---------------------------------------------------------------------------------
- *(volatile uint16_t*)(SDMMC_BASE + reg) = val;
+static inline void
+sdmmc_write16(uint16_t reg, uint16_t val)
+{
+ //---------------------------------------------------------------------------------
+ *(volatile uint16_t*)(SDMMC_BASE + reg) = val;
}
//---------------------------------------------------------------------------------
-static inline uint32_t sdmmc_read32(uint16_t reg) {
-//---------------------------------------------------------------------------------
- return *(volatile uint32_t*)(SDMMC_BASE + reg);
+static inline uint32_t
+sdmmc_read32(uint16_t reg)
+{
+ //---------------------------------------------------------------------------------
+ return *(volatile uint32_t*)(SDMMC_BASE + reg);
}
//---------------------------------------------------------------------------------
-static inline void sdmmc_write32(uint16_t reg, uint32_t val) {
-//---------------------------------------------------------------------------------
- *(volatile uint32_t*)(SDMMC_BASE + reg) = val;
+static inline void
+sdmmc_write32(uint16_t reg, uint32_t val)
+{
+ //---------------------------------------------------------------------------------
+ *(volatile uint32_t*)(SDMMC_BASE + reg) = val;
}
//---------------------------------------------------------------------------------
-static inline void sdmmc_mask16(uint16_t reg, const uint16_t clear, const uint16_t set) {
-//---------------------------------------------------------------------------------
- uint16_t val = sdmmc_read16(reg);
- val &= ~clear;
- val |= set;
- sdmmc_write16(reg, val);
+static inline void
+sdmmc_mask16(uint16_t reg, const uint16_t clear, const uint16_t set)
+{
+ //---------------------------------------------------------------------------------
+ uint16_t val = sdmmc_read16(reg);
+ val &= ~clear;
+ val |= set;
+ sdmmc_write16(reg, val);
}
-static inline void setckl(uint32_t data)
+static inline void
+setckl(uint32_t data)
{
- sdmmc_mask16(REG_SDCLKCTL,0x100,0);
- sdmmc_mask16(REG_SDCLKCTL,0x2FF,data&0x2FF);
- sdmmc_mask16(REG_SDCLKCTL,0x0,0x100);
+ sdmmc_mask16(REG_SDCLKCTL, 0x100, 0);
+ sdmmc_mask16(REG_SDCLKCTL, 0x2FF, data & 0x2FF);
+ sdmmc_mask16(REG_SDCLKCTL, 0x0, 0x100);
}
#endif
/* original version by megazig */
#ifndef __thumb__
-#define BSWAP32(x) {\
- __asm__\
- (\
- "eor r1, %1, %1, ror #16\n\t"\
- "bic r1, r1, #0xFF0000\n\t"\
- "mov %0, %1, ror #8\n\t"\
- "eor %0, %0, r1, lsr #8\n\t"\
- :"=r"(x)\
- :"0"(x)\
- :"r1"\
- );\
-};
-
-#define ADD_u128_uint32_t(u128_0, u128_1, u128_2, u128_3, uint32_t_0) {\
-__asm__\
- (\
- "adds %0, %4\n\t"\
- "addcss %1, %1, #1\n\t"\
- "addcss %2, %2, #1\n\t"\
- "addcs %3, %3, #1\n\t"\
- : "+r"(u128_0), "+r"(u128_1), "+r"(u128_2), "+r"(u128_3)\
- : "r"(uint32_t_0)\
- : "cc"\
- );\
-}
+#define BSWAP32(x) \
+ { \
+ __asm__("eor r1, %1, %1, ror #16\n\t" \
+ "bic r1, r1, #0xFF0000\n\t" \
+ "mov %0, %1, ror #8\n\t" \
+ "eor %0, %0, r1, lsr #8\n\t" \
+ : "=r"(x) \
+ : "0"(x) \
+ : "r1"); \
+ };
+
+#define ADD_u128_uint32_t(u128_0, u128_1, u128_2, u128_3, uint32_t_0) \
+ { \
+ __asm__("adds %0, %4\n\t" \
+ "addcss %1, %1, #1\n\t" \
+ "addcss %2, %2, #1\n\t" \
+ "addcs %3, %3, #1\n\t" \
+ : "+r"(u128_0), "+r"(u128_1), "+r"(u128_2), "+r"(u128_3) \
+ : "r"(uint32_t_0) \
+ : "cc"); \
+ }
#else
-#define BSWAP32(x) {x = __builtin_bswap32(x);}
-
-#define ADD_u128_uint32_t(u128_0, u128_1, u128_2, u128_3, uint32_t_0) {\
-__asm__\
- (\
- "mov r4, #0\n\t"\
- "add %0, %0, %4\n\t"\
- "adc %1, %1, r4\n\t"\
- "adc %2, %2, r4\n\t"\
- "adc %3, %3, r4\n\t"\
- : "+r"(u128_0), "+r"(u128_1), "+r"(u128_2), "+r"(u128_3)\
- : "r"(uint32_t_0)\
- : "cc", "r4"\
- );\
-}
+#define BSWAP32(x) \
+ { \
+ x = __builtin_bswap32(x); \
+ }
+
+#define ADD_u128_uint32_t(u128_0, u128_1, u128_2, u128_3, uint32_t_0) \
+ { \
+ __asm__("mov r4, #0\n\t" \
+ "add %0, %0, %4\n\t" \
+ "adc %1, %1, r4\n\t" \
+ "adc %2, %2, r4\n\t" \
+ "adc %3, %3, r4\n\t" \
+ : "+r"(u128_0), "+r"(u128_1), "+r"(u128_2), "+r"(u128_3) \
+ : "r"(uint32_t_0) \
+ : "cc", "r4"); \
+ }
#endif /*__thumb__*/
-void aes_setkey(uint8_t keyslot, const void* key, uint32_t keyType, uint32_t mode)
+void
+aes_setkey(uint8_t keyslot, const void* key, uint32_t keyType, uint32_t mode)
{
- if(keyslot <= 0x03) return; // Ignore TWL keys for now
-
- uint32_t* key32 = (uint32_t*)key;
- *REG_AESCNT = (*REG_AESCNT & ~(AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER)) | mode;
- *REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | AES_KEYCNT_WRITE;
-
- REG_AESKEYFIFO[keyType] = key32[0];
- REG_AESKEYFIFO[keyType] = key32[1];
- REG_AESKEYFIFO[keyType] = key32[2];
- REG_AESKEYFIFO[keyType] = key32[3];
+ if (keyslot <= 0x03)
+ return; // Ignore TWL keys for now
+
+ uint32_t* key32 = (uint32_t*)key;
+ *REG_AESCNT =
+ (*REG_AESCNT & ~(AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER)) | mode;
+ *REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | AES_KEYCNT_WRITE;
+
+ REG_AESKEYFIFO[keyType] = key32[0];
+ REG_AESKEYFIFO[keyType] = key32[1];
+ REG_AESKEYFIFO[keyType] = key32[2];
+ REG_AESKEYFIFO[keyType] = key32[3];
}
-void aes_use_keyslot(uint8_t keyslot)
+void
+aes_use_keyslot(uint8_t keyslot)
{
- if(keyslot > 0x3F)
- return;
+ if (keyslot > 0x3F)
+ return;
- *REG_AESKEYSEL = keyslot;
- *REG_AESCNT = *REG_AESCNT | 0x04000000; /* mystery bit */
+ *REG_AESKEYSEL = keyslot;
+ *REG_AESCNT = *REG_AESCNT | 0x04000000; /* mystery bit */
}
-void aes_setiv(const void* iv, uint32_t mode)
+void
+aes_setiv(const void* iv, uint32_t mode)
{
- const uint32_t* iv32 = (const uint32_t*)iv;
- *REG_AESCNT = (*REG_AESCNT & ~(AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER)) | mode;
-
- // Word order for IV can't be changed in REG_AESCNT and always default to reversed
- if(mode & AES_INPUT_NORMAL)
- {
- REG_AESCTR[0] = iv32[3];
- REG_AESCTR[1] = iv32[2];
- REG_AESCTR[2] = iv32[1];
- REG_AESCTR[3] = iv32[0];
- }
- else
- {
- REG_AESCTR[0] = iv32[0];
- REG_AESCTR[1] = iv32[1];
- REG_AESCTR[2] = iv32[2];
- REG_AESCTR[3] = iv32[3];
- }
+ const uint32_t* iv32 = (const uint32_t*)iv;
+ *REG_AESCNT =
+ (*REG_AESCNT & ~(AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER)) | mode;
+
+ // Word order for IV can't be changed in REG_AESCNT and always default to
+ // reversed
+ if (mode & AES_INPUT_NORMAL) {
+ REG_AESCTR[0] = iv32[3];
+ REG_AESCTR[1] = iv32[2];
+ REG_AESCTR[2] = iv32[1];
+ REG_AESCTR[3] = iv32[0];
+ } else {
+ REG_AESCTR[0] = iv32[0];
+ REG_AESCTR[1] = iv32[1];
+ REG_AESCTR[2] = iv32[2];
+ REG_AESCTR[3] = iv32[3];
+ }
}
-void aes_advctr(void* ctr, uint32_t val, uint32_t mode)
+void
+aes_advctr(void* ctr, uint32_t val, uint32_t mode)
{
- uint32_t* ctr32 = (uint32_t*)ctr;
-
- int i;
- if(mode & AES_INPUT_BE)
- {
- for(i = 0; i < 4; ++i) // Endian swap
- BSWAP32(ctr32[i]);
- }
-
- if(mode & AES_INPUT_NORMAL)
- {
- ADD_u128_uint32_t(ctr32[3], ctr32[2], ctr32[1], ctr32[0], val);
- }
- else
- {
- ADD_u128_uint32_t(ctr32[0], ctr32[1], ctr32[2], ctr32[3], val);
- }
-
- if(mode & AES_INPUT_BE)
- {
- for(i = 0; i < 4; ++i) // Endian swap
- BSWAP32(ctr32[i]);
- }
+ uint32_t* ctr32 = (uint32_t*)ctr;
+
+ int i;
+ if (mode & AES_INPUT_BE) {
+ for (i = 0; i < 4; ++i) // Endian swap
+ BSWAP32(ctr32[i]);
+ }
+
+ if (mode & AES_INPUT_NORMAL) {
+ ADD_u128_uint32_t(ctr32[3], ctr32[2], ctr32[1], ctr32[0], val);
+ } else {
+ ADD_u128_uint32_t(ctr32[0], ctr32[1], ctr32[2], ctr32[3], val);
+ }
+
+ if (mode & AES_INPUT_BE) {
+ for (i = 0; i < 4; ++i) // Endian swap
+ BSWAP32(ctr32[i]);
+ }
}
-void aes_change_ctrmode(void* ctr, uint32_t fromMode, uint32_t toMode)
+void
+aes_change_ctrmode(void* ctr, uint32_t fromMode, uint32_t toMode)
{
- uint32_t* ctr32 = (uint32_t*)ctr;
- int i;
- if((fromMode ^ toMode) & AES_CNT_INPUT_ENDIAN)
- {
- for(i = 0; i < 4; ++i)
- BSWAP32(ctr32[i]);
- }
-
- if((fromMode ^ toMode) & AES_CNT_INPUT_ORDER)
- {
- uint32_t temp = ctr32[0];
- ctr32[0] = ctr32[3];
- ctr32[3] = temp;
-
- temp = ctr32[1];
- ctr32[1] = ctr32[2];
- ctr32[2] = temp;
- }
+ uint32_t* ctr32 = (uint32_t*)ctr;
+ int i;
+ if ((fromMode ^ toMode) & AES_CNT_INPUT_ENDIAN) {
+ for (i = 0; i < 4; ++i)
+ BSWAP32(ctr32[i]);
+ }
+
+ if ((fromMode ^ toMode) & AES_CNT_INPUT_ORDER) {
+ uint32_t temp = ctr32[0];
+ ctr32[0] = ctr32[3];
+ ctr32[3] = temp;
+
+ temp = ctr32[1];
+ ctr32[1] = ctr32[2];
+ ctr32[2] = temp;
+ }
}
-void aes_batch(void* dst, const void* src, uint32_t blockCount)
+void
+aes_batch(void* dst, const void* src, uint32_t blockCount)
{
- *REG_AESBLKCNT = blockCount << 16;
- *REG_AESCNT |= AES_CNT_START;
-
- const uint32_t* src32 = (const uint32_t*)src;
- uint32_t* dst32 = (uint32_t*)dst;
-
- uint32_t wbc = blockCount;
- uint32_t rbc = blockCount;
-
- while(rbc)
- {
- if(wbc && ((*REG_AESCNT & 0x1F) <= 0xC)) // There's space for at least 4 ints
- {
- *REG_AESWRFIFO = *src32++;
- *REG_AESWRFIFO = *src32++;
- *REG_AESWRFIFO = *src32++;
- *REG_AESWRFIFO = *src32++;
- wbc--;
- }
-
- if(rbc && ((*REG_AESCNT & (0x1F << 0x5)) >= (0x4 << 0x5))) // At least 4 ints available for read
- {
- *dst32++ = *REG_AESRDFIFO;
- *dst32++ = *REG_AESRDFIFO;
- *dst32++ = *REG_AESRDFIFO;
- *dst32++ = *REG_AESRDFIFO;
- rbc--;
- }
- }
+ *REG_AESBLKCNT = blockCount << 16;
+ *REG_AESCNT |= AES_CNT_START;
+
+ const uint32_t* src32 = (const uint32_t*)src;
+ uint32_t* dst32 = (uint32_t*)dst;
+
+ uint32_t wbc = blockCount;
+ uint32_t rbc = blockCount;
+
+ while (rbc) {
+ if (wbc &&
+ ((*REG_AESCNT & 0x1F) <= 0xC)) // There's space for at least 4 ints
+ {
+ *REG_AESWRFIFO = *src32++;
+ *REG_AESWRFIFO = *src32++;
+ *REG_AESWRFIFO = *src32++;
+ *REG_AESWRFIFO = *src32++;
+ wbc--;
+ }
+
+ if (rbc && ((*REG_AESCNT & (0x1F << 0x5)) >=
+ (0x4 << 0x5))) // At least 4 ints available for read
+ {
+ *dst32++ = *REG_AESRDFIFO;
+ *dst32++ = *REG_AESRDFIFO;
+ *dst32++ = *REG_AESRDFIFO;
+ *dst32++ = *REG_AESRDFIFO;
+ rbc--;
+ }
+ }
}
-inline void aes_setmode(uint32_t mode)
+inline void
+aes_setmode(uint32_t mode)
{
- *REG_AESCNT = mode |
- AES_CNT_INPUT_ORDER | AES_CNT_OUTPUT_ORDER |
- AES_CNT_INPUT_ENDIAN | AES_CNT_OUTPUT_ENDIAN |
- AES_CNT_FLUSH_READ | AES_CNT_FLUSH_WRITE;
+ *REG_AESCNT = mode | AES_CNT_INPUT_ORDER | AES_CNT_OUTPUT_ORDER |
+ AES_CNT_INPUT_ENDIAN | AES_CNT_OUTPUT_ENDIAN |
+ AES_CNT_FLUSH_READ | AES_CNT_FLUSH_WRITE;
}
-void aes(void* dst, const void* src, uint32_t blockCount, void* iv, uint32_t mode, uint32_t ivMode)
+void
+aes(void* dst, const void* src, uint32_t blockCount, void* iv, uint32_t mode,
+ uint32_t ivMode)
{
- aes_setmode(mode);
-
- uint32_t blocks;
- while(blockCount != 0)
- {
- if((mode & AES_ALL_MODES) != AES_ECB_ENCRYPT_MODE
- && (mode & AES_ALL_MODES) != AES_ECB_DECRYPT_MODE)
- aes_setiv(iv, ivMode);
-
- blocks = (blockCount >= 0xFFFF) ? 0xFFFF : blockCount;
-
- // Save the last block for the next decryption CBC batch's iv
- if((mode & AES_ALL_MODES) == AES_CBC_DECRYPT_MODE)
- {
- memcpy(iv, src + (blocks - 1) * AES_BLOCK_SIZE, AES_BLOCK_SIZE);
- aes_change_ctrmode(iv, AES_INPUT_BE | AES_INPUT_NORMAL, ivMode);
- }
-
- // Process the current batch
- aes_batch(dst, src, blocks);
-
- // Save the last block for the next encryption CBC batch's iv
- if((mode & AES_ALL_MODES) == AES_CBC_ENCRYPT_MODE)
- {
- memcpy(iv, dst + (blocks - 1) * AES_BLOCK_SIZE, AES_BLOCK_SIZE);
- aes_change_ctrmode(iv, AES_INPUT_BE | AES_INPUT_NORMAL, ivMode);
- }
-
- // Advance counter for CTR mode
- else if((mode & AES_ALL_MODES) == AES_CTR_MODE)
- aes_advctr(iv, blocks, ivMode);
-
- src += blocks * AES_BLOCK_SIZE;
- dst += blocks * AES_BLOCK_SIZE;
- blockCount -= blocks;
- }
+ aes_setmode(mode);
+
+ uint32_t blocks;
+ while (blockCount != 0) {
+ if ((mode & AES_ALL_MODES) != AES_ECB_ENCRYPT_MODE &&
+ (mode & AES_ALL_MODES) != AES_ECB_DECRYPT_MODE)
+ aes_setiv(iv, ivMode);
+
+ blocks = (blockCount >= 0xFFFF) ? 0xFFFF : blockCount;
+
+ // Save the last block for the next decryption CBC batch's iv
+ if ((mode & AES_ALL_MODES) == AES_CBC_DECRYPT_MODE) {
+ memcpy(iv, src + (blocks - 1) * AES_BLOCK_SIZE, AES_BLOCK_SIZE);
+ aes_change_ctrmode(iv, AES_INPUT_BE | AES_INPUT_NORMAL, ivMode);
+ }
+
+ // Process the current batch
+ aes_batch(dst, src, blocks);
+
+ // Save the last block for the next encryption CBC batch's iv
+ if ((mode & AES_ALL_MODES) == AES_CBC_ENCRYPT_MODE) {
+ memcpy(iv, dst + (blocks - 1) * AES_BLOCK_SIZE, AES_BLOCK_SIZE);
+ aes_change_ctrmode(iv, AES_INPUT_BE | AES_INPUT_NORMAL, ivMode);
+ }
+
+ // Advance counter for CTR mode
+ else if ((mode & AES_ALL_MODES) == AES_CTR_MODE)
+ aes_advctr(iv, blocks, ivMode);
+
+ src += blocks * AES_BLOCK_SIZE;
+ dst += blocks * AES_BLOCK_SIZE;
+ blockCount -= blocks;
+ }
}
-void ncch_getctr(const ncch_h* ncch, uint8_t* ctr, uint8_t type)
+void
+ncch_getctr(const ncch_h* ncch, uint8_t* ctr, uint8_t type)
{
- uint32_t version = ncch->version;
- const uint8_t* partitionID = ncch->partitionID;
-
- int i;
- for(i = 0; i < 16; i++)
- ctr[i] = 0x00;
-
- if(version == 2 || version == 0)
- {
- for(i=0; i<8; i++)
- ctr[i] = partitionID[7 - i]; // Convert to big endian & normal input
- ctr[8] = type;
- }
- else if(version == 1)
- {
- int x = 0;
- if(type == NCCHTYPE_EXHEADER)
- x = MEDIA_UNITS;
- else if(type == NCCHTYPE_EXEFS)
- x = ncch->exeFSOffset * MEDIA_UNITS;
- else if (type == NCCHTYPE_ROMFS)
- x = ncch->exeFSOffset * MEDIA_UNITS;
-
- for(i = 0; i < 8; i++)
- ctr[i] = partitionID[i];
- for(i = 0; i < 4; i++)
- ctr[i + 12] = (x >> ((3 - i) * 8)) & 0xFF;
- }
+ uint32_t version = ncch->version;
+ const uint8_t* partitionID = ncch->partitionID;
+
+ int i;
+ for (i = 0; i < 16; i++)
+ ctr[i] = 0x00;
+
+ if (version == 2 || version == 0) {
+ for (i = 0; i < 8; i++)
+ ctr[i] = partitionID[7 - i]; // Convert to big endian & normal input
+ ctr[8] = type;
+ } else if (version == 1) {
+ int x = 0;
+ if (type == NCCHTYPE_EXHEADER)
+ x = MEDIA_UNITS;
+ else if (type == NCCHTYPE_EXEFS)
+ x = ncch->exeFSOffset * MEDIA_UNITS;
+ else if (type == NCCHTYPE_ROMFS)
+ x = ncch->exeFSOffset * MEDIA_UNITS;
+
+ for (i = 0; i < 8; i++)
+ ctr[i] = partitionID[i];
+ for (i = 0; i < 4; i++)
+ ctr[i + 12] = (x >> ((3 - i) * 8)) & 0xFF;
+ }
}
-void sha_wait_idle()
+void
+sha_wait_idle()
{
- while(*REG_SHA_CNT & 1);
+ while (*REG_SHA_CNT & 1)
+ ;
}
-void sha(void* res, const void* src, uint32_t size, uint32_t mode)
+void
+sha(void* res, const void* src, uint32_t size, uint32_t mode)
{
- sha_wait_idle();
- *REG_SHA_CNT = mode | SHA_CNT_OUTPUT_ENDIAN | SHA_NORMAL_ROUND;
-
- const uint32_t* src32 = (const uint32_t*)src;
- int i;
- while(size >= 0x40)
- {
- sha_wait_idle();
- for(i = 0; i < 4; ++i)
- {
- *REG_SHA_INFIFO = *src32++;
- *REG_SHA_INFIFO = *src32++;
- *REG_SHA_INFIFO = *src32++;
- *REG_SHA_INFIFO = *src32++;
- }
-
- size -= 0x40;
- }
-
- sha_wait_idle();
- memcpy((void*)REG_SHA_INFIFO, src32, size);
-
- *REG_SHA_CNT = (*REG_SHA_CNT & ~SHA_NORMAL_ROUND) | SHA_FINAL_ROUND;
-
- while(*REG_SHA_CNT & SHA_FINAL_ROUND);
- sha_wait_idle();
-
- uint32_t hashSize = SHA_256_HASH_SIZE;
- if(mode == SHA_224_MODE)
- hashSize = SHA_224_HASH_SIZE;
- else if(mode == SHA_1_MODE)
- hashSize = SHA_1_HASH_SIZE;
-
- memcpy(res, (void*)REG_SHA_HASH, hashSize);
+ sha_wait_idle();
+ *REG_SHA_CNT = mode | SHA_CNT_OUTPUT_ENDIAN | SHA_NORMAL_ROUND;
+
+ const uint32_t* src32 = (const uint32_t*)src;
+ int i;
+ while (size >= 0x40) {
+ sha_wait_idle();
+ for (i = 0; i < 4; ++i) {
+ *REG_SHA_INFIFO = *src32++;
+ *REG_SHA_INFIFO = *src32++;
+ *REG_SHA_INFIFO = *src32++;
+ *REG_SHA_INFIFO = *src32++;
+ }
+
+ size -= 0x40;
+ }
+
+ sha_wait_idle();
+ memcpy((void*)REG_SHA_INFIFO, src32, size);
+
+ *REG_SHA_CNT = (*REG_SHA_CNT & ~SHA_NORMAL_ROUND) | SHA_FINAL_ROUND;
+
+ while (*REG_SHA_CNT & SHA_FINAL_ROUND)
+ ;
+ sha_wait_idle();
+
+ uint32_t hashSize = SHA_256_HASH_SIZE;
+ if (mode == SHA_224_MODE)
+ hashSize = SHA_224_HASH_SIZE;
+ else if (mode == SHA_1_MODE)
+ hashSize = SHA_1_HASH_SIZE;
+
+ memcpy(res, (void*)REG_SHA_HASH, hashSize);
}
-void rsa_wait_idle()
+void
+rsa_wait_idle()
{
- while(*REG_RSA_CNT & 1);
+ while (*REG_RSA_CNT & 1)
+ ;
}
-void rsa_use_keyslot(uint32_t keyslot)
+void
+rsa_use_keyslot(uint32_t keyslot)
{
- *REG_RSA_CNT = (*REG_RSA_CNT & ~RSA_CNT_KEYSLOTS) | (keyslot << 4);
+ *REG_RSA_CNT = (*REG_RSA_CNT & ~RSA_CNT_KEYSLOTS) | (keyslot << 4);
}
-void rsa_setkey(uint32_t keyslot, const void* mod, const void* exp, uint32_t mode)
+void
+rsa_setkey(uint32_t keyslot, const void* mod, const void* exp, uint32_t mode)
{
- rsa_wait_idle();
- *REG_RSA_CNT = (*REG_RSA_CNT & ~RSA_CNT_KEYSLOTS) | (keyslot << 4) | RSA_IO_BE | RSA_IO_NORMAL;
-
- uint32_t size = mode * 4;
-
- volatile uint32_t* keyslotCnt = REG_RSA_SLOT0 + (keyslot << 4);
- keyslotCnt[0] &= ~(RSA_SLOTCNT_KEY_SET | RSA_SLOTCNT_WPROTECT);
- keyslotCnt[1] = mode;
-
- memcpy((void*)REG_RSA_MOD_END - size, mod, size);
-
- if(exp == NULL)
- {
- size -= 4;
- while(size)
- {
- *REG_RSA_EXPFIFO = 0;
- size -= 4;
- }
- *REG_RSA_EXPFIFO = 0x01000100; // 0x00010001 byteswapped
- }
- else
- {
- const uint32_t* exp32 = (const uint32_t*)exp;
- while(size)
- {
- *REG_RSA_EXPFIFO = *exp32++;
- size -= 4;
- }
- }
+ rsa_wait_idle();
+ *REG_RSA_CNT = (*REG_RSA_CNT & ~RSA_CNT_KEYSLOTS) | (keyslot << 4) |
+ RSA_IO_BE | RSA_IO_NORMAL;
+
+ uint32_t size = mode * 4;
+
+ volatile uint32_t* keyslotCnt = REG_RSA_SLOT0 + (keyslot << 4);
+ keyslotCnt[0] &= ~(RSA_SLOTCNT_KEY_SET | RSA_SLOTCNT_WPROTECT);
+ keyslotCnt[1] = mode;
+
+ memcpy((void*)REG_RSA_MOD_END - size, mod, size);
+
+ if (exp == NULL) {
+ size -= 4;
+ while (size) {
+ *REG_RSA_EXPFIFO = 0;
+ size -= 4;
+ }
+ *REG_RSA_EXPFIFO = 0x01000100; // 0x00010001 byteswapped
+ } else {
+ const uint32_t* exp32 = (const uint32_t*)exp;
+ while (size) {
+ *REG_RSA_EXPFIFO = *exp32++;
+ size -= 4;
+ }
+ }
}
-int rsa_iskeyset(uint32_t keyslot)
+int
+rsa_iskeyset(uint32_t keyslot)
{
- return *(REG_RSA_SLOT0 + (keyslot << 4)) & 1;
+ return *(REG_RSA_SLOT0 + (keyslot << 4)) & 1;
}
-void rsa(void* dst, const void* src, uint32_t size)
+void
+rsa(void* dst, const void* src, uint32_t size)
{
- uint32_t keyslot = (*REG_RSA_CNT & RSA_CNT_KEYSLOTS) >> 4;
- if(rsa_iskeyset(keyslot) == 0)
- return;
-
- rsa_wait_idle();
- *REG_RSA_CNT |= RSA_IO_BE | RSA_IO_NORMAL;
-
- // Pad the message with zeroes so that it's a multiple of 8
- // and write the message with the end aligned with the register
- uint32_t padSize = ((size + 7) & ~7) - size;
- memset((void*)REG_RSA_TXT_END - (size + padSize), 0, padSize);
- memcpy((void*)REG_RSA_TXT_END - size, src, size);
-
- // Start
- *REG_RSA_CNT |= RSA_CNT_START;
-
- rsa_wait_idle();
- memcpy(dst, (void*)REG_RSA_TXT_END - size, size);
+ uint32_t keyslot = (*REG_RSA_CNT & RSA_CNT_KEYSLOTS) >> 4;
+ if (rsa_iskeyset(keyslot) == 0)
+ return;
+
+ rsa_wait_idle();
+ *REG_RSA_CNT |= RSA_IO_BE | RSA_IO_NORMAL;
+
+ // Pad the message with zeroes so that it's a multiple of 8
+ // and write the message with the end aligned with the register
+ uint32_t padSize = ((size + 7) & ~7) - size;
+ memset((void*)REG_RSA_TXT_END - (size + padSize), 0, padSize);
+ memcpy((void*)REG_RSA_TXT_END - size, src, size);
+
+ // Start
+ *REG_RSA_CNT |= RSA_CNT_START;
+
+ rsa_wait_idle();
+ memcpy(dst, (void*)REG_RSA_TXT_END - size, size);
}
-int rsa_verify(const void* data, uint32_t size, const void* sig, uint32_t mode)
+int
+rsa_verify(const void* data, uint32_t size, const void* sig, uint32_t mode)
{
- uint8_t dataHash[SHA_256_HASH_SIZE];
- sha(dataHash, data, size, SHA_256_MODE);
-
- uint8_t decSig[0x100]; // Way too big, need to request a work area
-
- uint32_t sigSize = mode * 4;
- rsa(decSig, sig, sigSize);
-
- return memcmp(dataHash, decSig + (sigSize - SHA_256_HASH_SIZE), SHA_256_HASH_SIZE) == 0;
+ uint8_t dataHash[SHA_256_HASH_SIZE];
+ sha(dataHash, data, size, SHA_256_MODE);
+
+ uint8_t decSig[0x100]; // Way too big, need to request a work area
+
+ uint32_t sigSize = mode * 4;
+ rsa(decSig, sig, sigSize);
+
+ return memcmp(dataHash, decSig + (sigSize - SHA_256_HASH_SIZE),
+ SHA_256_HASH_SIZE) == 0;
}
#include "headers.h"
/**************************AES****************************/
-#define REG_AESCNT ((volatile uint32_t*)0x10009000)
-#define REG_AESBLKCNT ((volatile uint32_t*)0x10009004)
-#define REG_AESWRFIFO ((volatile uint32_t*)0x10009008)
-#define REG_AESRDFIFO ((volatile uint32_t*)0x1000900C)
-#define REG_AESKEYSEL ((volatile uint8_t *)0x10009010)
-#define REG_AESKEYCNT ((volatile uint8_t *)0x10009011)
-#define REG_AESCTR ((volatile uint32_t*)0x10009020)
-
-#define REG_AESKEYFIFO ((volatile uint32_t*)0x10009100)
-#define REG_AESKEYXFIFO ((volatile uint32_t*)0x10009104)
-#define REG_AESKEYYFIFO ((volatile uint32_t*)0x10009108)
-
-#define AES_CCM_DECRYPT_MODE (0u << 27)
-#define AES_CCM_ENCRYPT_MODE (1u << 27)
-#define AES_CTR_MODE (2u << 27)
-#define AES_CTR_MODE (2u << 27)
-#define AES_CBC_DECRYPT_MODE (4u << 27)
-#define AES_CBC_ENCRYPT_MODE (5u << 27)
-#define AES_ECB_DECRYPT_MODE (6u << 27)
-#define AES_ECB_ENCRYPT_MODE (7u << 27)
-#define AES_ALL_MODES (7u << 27)
-
-#define AES_CNT_START 0x80000000
-#define AES_CNT_INPUT_ORDER 0x02000000
-#define AES_CNT_OUTPUT_ORDER 0x01000000
-#define AES_CNT_INPUT_ENDIAN 0x00800000
-#define AES_CNT_OUTPUT_ENDIAN 0x00400000
-#define AES_CNT_FLUSH_READ 0x00000800
-#define AES_CNT_FLUSH_WRITE 0x00000400
-
-#define AES_INPUT_BE (AES_CNT_INPUT_ENDIAN)
-#define AES_INPUT_LE 0
-#define AES_INPUT_NORMAL (AES_CNT_INPUT_ORDER)
-#define AES_INPUT_REVERSED 0
-
-#define AES_TEMP_KEYSLOT 0x11
-
-#define AES_BLOCK_SIZE 0x10
-
-#define AES_KEYCNT_WRITE (1 << 0x7)
-#define AES_KEYNORMAL 0
-#define AES_KEYX 1
-#define AES_KEYY 2
+#define REG_AESCNT ((volatile uint32_t*)0x10009000)
+#define REG_AESBLKCNT ((volatile uint32_t*)0x10009004)
+#define REG_AESWRFIFO ((volatile uint32_t*)0x10009008)
+#define REG_AESRDFIFO ((volatile uint32_t*)0x1000900C)
+#define REG_AESKEYSEL ((volatile uint8_t*)0x10009010)
+#define REG_AESKEYCNT ((volatile uint8_t*)0x10009011)
+#define REG_AESCTR ((volatile uint32_t*)0x10009020)
+
+#define REG_AESKEYFIFO ((volatile uint32_t*)0x10009100)
+#define REG_AESKEYXFIFO ((volatile uint32_t*)0x10009104)
+#define REG_AESKEYYFIFO ((volatile uint32_t*)0x10009108)
+
+#define AES_CCM_DECRYPT_MODE (0u << 27)
+#define AES_CCM_ENCRYPT_MODE (1u << 27)
+#define AES_CTR_MODE (2u << 27)
+#define AES_CTR_MODE (2u << 27)
+#define AES_CBC_DECRYPT_MODE (4u << 27)
+#define AES_CBC_ENCRYPT_MODE (5u << 27)
+#define AES_ECB_DECRYPT_MODE (6u << 27)
+#define AES_ECB_ENCRYPT_MODE (7u << 27)
+#define AES_ALL_MODES (7u << 27)
+
+#define AES_CNT_START 0x80000000
+#define AES_CNT_INPUT_ORDER 0x02000000
+#define AES_CNT_OUTPUT_ORDER 0x01000000
+#define AES_CNT_INPUT_ENDIAN 0x00800000
+#define AES_CNT_OUTPUT_ENDIAN 0x00400000
+#define AES_CNT_FLUSH_READ 0x00000800
+#define AES_CNT_FLUSH_WRITE 0x00000400
+
+#define AES_INPUT_BE (AES_CNT_INPUT_ENDIAN)
+#define AES_INPUT_LE 0
+#define AES_INPUT_NORMAL (AES_CNT_INPUT_ORDER)
+#define AES_INPUT_REVERSED 0
+
+#define AES_TEMP_KEYSLOT 0x11
+
+#define AES_BLOCK_SIZE 0x10
+
+#define AES_KEYCNT_WRITE (1 << 0x7)
+#define AES_KEYNORMAL 0
+#define AES_KEYX 1
+#define AES_KEYY 2
/**************************SHA****************************/
-#define REG_SHA_CNT ((volatile uint32_t*)0x1000A000)
-#define REG_SHA_BLKCNT ((volatile uint32_t*)0x1000A004)
-#define REG_SHA_HASH ((volatile uint32_t*)0x1000A040)
-#define REG_SHA_INFIFO ((volatile uint32_t*)0x1000A080)
+#define REG_SHA_CNT ((volatile uint32_t*)0x1000A000)
+#define REG_SHA_BLKCNT ((volatile uint32_t*)0x1000A004)
+#define REG_SHA_HASH ((volatile uint32_t*)0x1000A040)
+#define REG_SHA_INFIFO ((volatile uint32_t*)0x1000A080)
-#define SHA_CNT_STATE 0x00000003
-#define SHA_CNT_UNK2 0x00000004
-#define SHA_CNT_OUTPUT_ENDIAN 0x00000008
-#define SHA_CNT_MODE 0x00000030
-#define SHA_CNT_ENABLE 0x00010000
-#define SHA_CNT_ACTIVE 0x00020000
+#define SHA_CNT_STATE 0x00000003
+#define SHA_CNT_UNK2 0x00000004
+#define SHA_CNT_OUTPUT_ENDIAN 0x00000008
+#define SHA_CNT_MODE 0x00000030
+#define SHA_CNT_ENABLE 0x00010000
+#define SHA_CNT_ACTIVE 0x00020000
-#define SHA_HASH_READY 0x00000000
-#define SHA_NORMAL_ROUND 0x00000001
-#define SHA_FINAL_ROUND 0x00000002
+#define SHA_HASH_READY 0x00000000
+#define SHA_NORMAL_ROUND 0x00000001
+#define SHA_FINAL_ROUND 0x00000002
-#define SHA_OUTPUT_BE SHA_CNT_OUTPUT_ENDIAN
-#define SHA_OUTPUT_LE 0
+#define SHA_OUTPUT_BE SHA_CNT_OUTPUT_ENDIAN
+#define SHA_OUTPUT_LE 0
-#define SHA_256_MODE 0
-#define SHA_224_MODE 0x00000010
-#define SHA_1_MODE 0x00000020
+#define SHA_256_MODE 0
+#define SHA_224_MODE 0x00000010
+#define SHA_1_MODE 0x00000020
-#define SHA_256_HASH_SIZE (256 / 8)
-#define SHA_224_HASH_SIZE (224 / 8)
-#define SHA_1_HASH_SIZE (160 / 8)
+#define SHA_256_HASH_SIZE (256 / 8)
+#define SHA_224_HASH_SIZE (224 / 8)
+#define SHA_1_HASH_SIZE (160 / 8)
/**************************RSA****************************/
-#define REG_RSA_CNT ((volatile uint32_t*)0x1000B000)
-#define REG_RSA_SLOT0 ((volatile uint32_t*)0x1000B100)
-#define REG_RSA_SLOT1 ((volatile uint32_t*)0x1000B110)
-#define REG_RSA_SLOT2 ((volatile uint32_t*)0x1000B120)
-#define REG_RSA_SLOT3 ((volatile uint32_t*)0x1000B130)
-#define REG_RSA_EXPFIFO ((volatile uint32_t*)0x1000B200)
-#define REG_RSA_MOD_END ((volatile uint32_t*)0x1000B500)
-#define REG_RSA_TXT_END ((volatile uint32_t*)0x1000B900)
-
-#define RSA_CNT_START 0x00000001
-#define RSA_CNT_KEYSLOTS 0x000000F0
-#define RSA_CNT_IO_ENDIAN 0x00000100
-#define RSA_CNT_IO_ORDER 0x00000200
-
-#define RSA_SLOTCNT_KEY_SET 0x00000001
-#define RSA_SLOTCNT_WPROTECT 0x00000002 // Write protect
-
-#define RSA_IO_BE RSA_CNT_IO_ENDIAN
-#define RSA_IO_LE 0
-#define RSA_IO_NORMAL RSA_CNT_IO_ORDER
-#define RSA_IO_REVERSED 0
-
-#define RSA_TEMP_KEYSLOT 0
-
-#define RSA_1024_MODE 0x20
-#define RSA_2048_MODE 0x40
-
-void aes_setkey(uint8_t keyslot, const void* key, uint32_t keyType, uint32_t mode);
+#define REG_RSA_CNT ((volatile uint32_t*)0x1000B000)
+#define REG_RSA_SLOT0 ((volatile uint32_t*)0x1000B100)
+#define REG_RSA_SLOT1 ((volatile uint32_t*)0x1000B110)
+#define REG_RSA_SLOT2 ((volatile uint32_t*)0x1000B120)
+#define REG_RSA_SLOT3 ((volatile uint32_t*)0x1000B130)
+#define REG_RSA_EXPFIFO ((volatile uint32_t*)0x1000B200)
+#define REG_RSA_MOD_END ((volatile uint32_t*)0x1000B500)
+#define REG_RSA_TXT_END ((volatile uint32_t*)0x1000B900)
+
+#define RSA_CNT_START 0x00000001
+#define RSA_CNT_KEYSLOTS 0x000000F0
+#define RSA_CNT_IO_ENDIAN 0x00000100
+#define RSA_CNT_IO_ORDER 0x00000200
+
+#define RSA_SLOTCNT_KEY_SET 0x00000001
+#define RSA_SLOTCNT_WPROTECT 0x00000002 // Write protect
+
+#define RSA_IO_BE RSA_CNT_IO_ENDIAN
+#define RSA_IO_LE 0
+#define RSA_IO_NORMAL RSA_CNT_IO_ORDER
+#define RSA_IO_REVERSED 0
+
+#define RSA_TEMP_KEYSLOT 0
+
+#define RSA_1024_MODE 0x20
+#define RSA_2048_MODE 0x40
+
+void aes_setkey(uint8_t keyslot, const void* key, uint32_t keyType,
+ uint32_t mode);
void aes_use_keyslot(uint8_t keyslot);
-void aes(void* dst, const void* src, uint32_t blockCount, void* iv, uint32_t mode, uint32_t ivMode);
+void aes(void* dst, const void* src, uint32_t blockCount, void* iv,
+ uint32_t mode, uint32_t ivMode);
void aes_setiv(const void* iv, uint32_t mode);
void aes_advctr(void* ctr, uint32_t val, uint32_t mode);
void sha(void* res, const void* src, uint32_t size, uint32_t mode);
-void rsa_setkey(uint32_t keyslot, const void* mod, const void* exp, uint32_t mode);
+void rsa_setkey(uint32_t keyslot, const void* mod, const void* exp,
+ uint32_t mode);
void rsa_use_keyslot(uint32_t keyslot);
int rsa_verify(const void* data, uint32_t size, const void* sig, uint32_t mode);
-typedef enum
-{
- NCCHTYPE_EXHEADER = 1,
- NCCHTYPE_EXEFS = 2,
- NCCHTYPE_ROMFS = 3,
+typedef enum {
+ NCCHTYPE_EXHEADER = 1,
+ NCCHTYPE_EXEFS = 2,
+ NCCHTYPE_ROMFS = 3,
} ctr_ncchtypes;
void ncch_getctr(const ncch_h* ncch, uint8_t* ctr, uint8_t type);
#include "fcram.h"
-void *fcram_temp = (void *)0x23000000;
+void* fcram_temp = (void*)0x23000000;
#include "../std/unused.h"
-extern void *fcram_temp;
+extern void* fcram_temp;
// Space between most of the locations
#define FCRAM_SPACING 0x100000
// firm.c
#define FCRAM_FIRM_LOC FCRAM_START
-#define FCRAM_TWL_FIRM_LOC (FCRAM_START + FCRAM_SPACING) // Double size
+#define FCRAM_TWL_FIRM_LOC (FCRAM_START + FCRAM_SPACING) // Double size
#define FCRAM_AGB_FIRM_LOC (FCRAM_START + FCRAM_SPACING * 3)
// patch.c
#include "../common.h"
-firm_h *firm_loc = (firm_h *)FCRAM_FIRM_LOC;
+firm_h* firm_loc = (firm_h*)FCRAM_FIRM_LOC;
static uint32_t firm_size = FCRAM_SPACING;
firm_section_h firm_proc9;
-exefs_h *firm_p9_exefs;
+exefs_h* firm_p9_exefs;
-firm_h *twl_firm_loc = (firm_h *)FCRAM_TWL_FIRM_LOC;
+firm_h* twl_firm_loc = (firm_h*)FCRAM_TWL_FIRM_LOC;
static uint32_t twl_firm_size = FCRAM_SPACING * 2;
firm_section_h twl_firm_proc9;
-exefs_h *twl_firm_p9_exefs;
+exefs_h* twl_firm_p9_exefs;
-firm_h *agb_firm_loc = (firm_h *)FCRAM_AGB_FIRM_LOC;
+firm_h* agb_firm_loc = (firm_h*)FCRAM_AGB_FIRM_LOC;
static uint32_t agb_firm_size = FCRAM_SPACING;
firm_section_h agb_firm_proc9;
-exefs_h *agb_firm_p9_exefs;
+exefs_h* agb_firm_p9_exefs;
static int update_96_keys = 0;
-static volatile uint32_t *const a11_entry = (volatile uint32_t *)0x1FFFFFF8;
+static volatile uint32_t* const a11_entry = (volatile uint32_t*)0x1FFFFFF8;
-void slot0x11key96_init()
+void
+slot0x11key96_init()
{
// 9.6 crypto may need us to get the key from somewhere else.
// Unless the console already has the key initialized, that is.
// Tell boot_firm it needs to regenerate the keys.
update_96_keys = 1;
}
- // If we can't read the key, we assume it's not needed, and the firmware is the right version.
- // Otherwise, we make sure the error message for decrypting arm9bin mentions this.
+ // If we can't read the key, we assume it's not needed, and the firmware is
+ // the right version.
+ // Otherwise, we make sure the error message for decrypting arm9bin mentions
+ // this.
}
-int decrypt_firm_title(firm_h *dest, ncch_h *ncch, uint32_t *size, void *key) {
- uint8_t firm_iv[16] = {0};
- uint8_t exefs_key[16] = {0};
- uint8_t exefs_iv[16] = {0};
+int
+decrypt_firm_title(firm_h* dest, ncch_h* ncch, uint32_t* size, void* key)
+{
+ uint8_t firm_iv[16] = { 0 };
+ uint8_t exefs_key[16] = { 0 };
+ uint8_t exefs_iv[16] = { 0 };
fprintf(BOTTOM_SCREEN, " Decrypting the NCCH\n");
aes_setkey(0x16, key, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_use_keyslot(0x16);
- aes(ncch, ncch, *size / AES_BLOCK_SIZE, firm_iv, AES_CBC_DECRYPT_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
+ aes(ncch, ncch, *size / AES_BLOCK_SIZE, firm_iv, AES_CBC_DECRYPT_MODE,
+ AES_INPUT_BE | AES_INPUT_NORMAL);
if (ncch->magic != NCCH_MAGIC)
return 1;
ncch_getctr(ncch, exefs_iv, NCCHTYPE_EXEFS);
// Get the exefs offset and size from the NCCH
- exefs_h *exefs = (exefs_h *)((void *)ncch + ncch->exeFSOffset * MEDIA_UNITS);
+ exefs_h* exefs = (exefs_h*)((void*)ncch + ncch->exeFSOffset * MEDIA_UNITS);
uint32_t exefs_size = ncch->exeFSSize * MEDIA_UNITS;
fprintf(BOTTOM_SCREEN, " Decrypting the exefs\n");
aes_setkey(0x2C, exefs_key, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_use_keyslot(0x2C);
- aes(exefs, exefs, exefs_size / AES_BLOCK_SIZE, exefs_iv, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
+ aes(exefs, exefs, exefs_size / AES_BLOCK_SIZE, exefs_iv, AES_CTR_MODE,
+ AES_INPUT_BE | AES_INPUT_NORMAL);
// Get the decrypted FIRM
// We assume the firm.bin is always the first file
- firm_h *firm = (firm_h *)&exefs[1]; // The offset right behind the exefs header; the first file.
+ firm_h* firm = (firm_h*)&exefs[1]; // The offset right behind the exefs
+ // header; the first file.
*size = exefs->fileHeaders[0].size;
if (firm->magic != FIRM_MAGIC)
return 0;
}
-int decrypt_arm9bin(arm9bin_h *header, uint64_t firm_title, uint8_t version) {
+int
+decrypt_arm9bin(arm9bin_h* header, uint64_t firm_title, uint8_t version)
+{
uint8_t slot = 0x15;
fprintf(BOTTOM_SCREEN, " Decrypting ARM9 FIRM binary\n");
slot = 0x16;
aes_use_keyslot(0x11);
- aes(decrypted_keyx, header->slot0x16keyX, 1, NULL, AES_ECB_DECRYPT_MODE, 0);
- aes_setkey(slot, decrypted_keyx, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
+ aes(decrypted_keyx, header->slot0x16keyX, 1, NULL, AES_ECB_DECRYPT_MODE,
+ 0);
+ aes_setkey(slot, decrypted_keyx, AES_KEYX,
+ AES_INPUT_BE | AES_INPUT_NORMAL);
}
aes_setkey(slot, header->keyy, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_setiv(header->ctr, AES_INPUT_BE | AES_INPUT_NORMAL);
- void *arm9bin = (uint8_t *)header + 0x800;
+ void* arm9bin = (uint8_t*)header + 0x800;
int size = atoi(header->size);
aes_use_keyslot(slot);
- aes(arm9bin, arm9bin, size / AES_BLOCK_SIZE, header->ctr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
+ aes(arm9bin, arm9bin, size / AES_BLOCK_SIZE, header->ctr, AES_CTR_MODE,
+ AES_INPUT_BE | AES_INPUT_NORMAL);
if (firm_title == NATIVE_FIRM_TITLEID)
- return *(uint32_t *)arm9bin != ARM9BIN_MAGIC;
+ return *(uint32_t*)arm9bin != ARM9BIN_MAGIC;
else if (firm_title == AGB_FIRM_TITLEID || firm_title == TWL_FIRM_TITLEID)
- return *(uint32_t *)arm9bin != LGY_ARM9BIN_MAGIC;
- else return 0;
+ return *(uint32_t*)arm9bin != LGY_ARM9BIN_MAGIC;
+ else
+ return 0;
}
-int decrypt_firm(firm_h *dest, char *path_firmkey, uint32_t *size) {
+int
+decrypt_firm(firm_h* dest, char* path_firmkey, uint32_t* size)
+{
uint8_t firm_key[AES_BLOCK_SIZE];
// Firmware is likely encrypted. Decrypt.
}
fprintf(BOTTOM_SCREEN, " Decrypting FIRM\n");
- if (decrypt_firm_title(dest, (void *)dest, size, firm_key) != 0) {
+ if (decrypt_firm_title(dest, (void*)dest, size, firm_key) != 0) {
fprintf(BOTTOM_SCREEN, "Failed to decrypt the firmware\n");
return 1;
}
- return 0;
+ return 0;
}
extern int patch_services();
-int load_firm(firm_h *dest, char *path, char *path_firmkey, uint32_t *size, uint64_t firm_title) {
+int
+load_firm(firm_h* dest, char* path, char* path_firmkey, uint32_t* size,
+ uint64_t firm_title)
+{
int status = 0;
int firmware_changed = 0;
goto exit_error;
}
- // Check and decrypt FIRM if it is encrypted.
+ // Check and decrypt FIRM if it is encrypted.
if (dest->magic != FIRM_MAGIC) {
status = decrypt_firm(dest, path_firmkey, size);
if (status != 0) {
if (firm_title == NATIVE_FIRM_TITLEID) {
fprintf(BOTTOM_SCREEN, "Failed to decrypt firmware.\n"
"This is fatal. Aborting.\n");
- status = 1;
- goto exit_error;
+ status = 1;
+ goto exit_error;
}
}
firmware_changed = 1; // Decryption performed.
fprintf(BOTTOM_SCREEN, " FIRM not encrypted\n");
}
- struct firm_signature* fsig = get_firm_info(dest);
+ struct firm_signature* fsig = get_firm_info(dest);
- fprintf(BOTTOM_SCREEN, " FIRM version: %s\n", fsig->version_string);
+ fprintf(BOTTOM_SCREEN, " FIRM version: %s\n", fsig->version_string);
// The N3DS firm has an additional encryption layer for ARM9
- if (fsig->console == console_n3ds) {
+ if (fsig->console == console_n3ds) {
// Look for the arm9 section
- for (firm_section_h *section = dest->section;
- section < dest->section + 4; section++) {
+ for (firm_section_h* section = dest->section;
+ section < dest->section + 4; section++) {
if (section->type == FIRM_TYPE_ARM9) {
// Check whether the arm9bin is encrypted.
int arm9bin_iscrypt = 0;
- uint32_t magic = *(uint32_t*)((uintptr_t)dest + section->offset + 0x800);
+ uint32_t magic =
+ *(uint32_t*)((uintptr_t)dest + section->offset + 0x800);
if (firm_title == NATIVE_FIRM_TITLEID)
arm9bin_iscrypt = (magic != ARM9BIN_MAGIC);
- else if (firm_title == AGB_FIRM_TITLEID || firm_title == TWL_FIRM_TITLEID)
+ else if (firm_title == AGB_FIRM_TITLEID ||
+ firm_title == TWL_FIRM_TITLEID)
arm9bin_iscrypt = (magic != LGY_ARM9BIN_MAGIC);
if (arm9bin_iscrypt) {
// Decrypt the arm9bin.
- if (decrypt_arm9bin((arm9bin_h *)((uintptr_t)dest + section->offset), firm_title, fsig->version)) {
- fprintf(BOTTOM_SCREEN, "Couldn't decrypt ARM9 FIRM binary.\n"
- "Check if you have the needed key at:\n"
- " " PATH_SLOT0X11KEY96 "\n");
+ if (decrypt_arm9bin(
+ (arm9bin_h*)((uintptr_t)dest + section->offset),
+ firm_title, fsig->version)) {
+ fprintf(BOTTOM_SCREEN,
+ "Couldn't decrypt ARM9 FIRM binary.\n"
+ "Check if you have the needed key at:\n"
+ " " PATH_SLOT0X11KEY96 "\n");
status = 1;
goto exit_error;
}
firmware_changed = 1; // Decryption of arm9bin performed.
} else {
- fprintf(BOTTOM_SCREEN, " ARM9 FIRM binary not encrypted\n");
- if (firm_title == NATIVE_FIRM_TITLEID && fsig->version > 0x0F) {
- slot0x11key96_init(); // This has to be loaded regardless, otherwise boot will fail.
+ fprintf(BOTTOM_SCREEN,
+ " ARM9 FIRM binary not encrypted\n");
+ if (firm_title == NATIVE_FIRM_TITLEID &&
+ fsig->version > 0x0F) {
+ slot0x11key96_init(); // This has to be loaded
+ // regardless, otherwise boot will
+ // fail.
}
}
return status;
}
-void __attribute__((naked)) disable_lcds() {
- *a11_entry = 0; // Don't wait for us
+void __attribute__((naked)) disable_lcds()
+{
+ *a11_entry = 0; // Don't wait for us
- *(volatile uint32_t *)0x10202A44 = 0;
- *(volatile uint32_t *)0x10202244 = 0;
- *(volatile uint32_t *)0x1020200C = 0;
- *(volatile uint32_t *)0x10202014 = 0;
+ *(volatile uint32_t*)0x10202A44 = 0;
+ *(volatile uint32_t*)0x10202244 = 0;
+ *(volatile uint32_t*)0x1020200C = 0;
+ *(volatile uint32_t*)0x10202014 = 0;
- while (!*a11_entry);
- ((void (*)())*a11_entry)();
+ while (!*a11_entry)
+ ;
+ ((void (*)()) * a11_entry)();
}
extern void wait();
-void boot_firm() {
- struct firm_signature* fsig = get_firm_info(firm_loc);
+void
+boot_firm()
+{
+ struct firm_signature* fsig = get_firm_info(firm_loc);
- // Set up the keys needed to boot a few firmwares, due to them being unset, depending on which firmware you're booting from.
+ // Set up the keys needed to boot a few firmwares, due to them being unset,
+ // depending on which firmware you're booting from.
// TODO: Don't use the hardcoded offset.
- if (update_96_keys && fsig->console == console_n3ds && fsig->version > 0x0F) {
- void *keydata = NULL;
- if (fsig->version == 0x1B || fsig->version == 0x1F) {
- keydata = (void *)((uintptr_t)firm_loc + firm_loc->section[2].offset + 0x89814);
- } else if (fsig->version == 0x21) {
- keydata = (void *)((uintptr_t)firm_loc + firm_loc->section[2].offset + 0x89A14);
- }
+ if (update_96_keys && fsig->console == console_n3ds &&
+ fsig->version > 0x0F) {
+ void* keydata = NULL;
+ if (fsig->version == 0x1B || fsig->version == 0x1F) {
+ keydata = (void*)((uintptr_t)firm_loc +
+ firm_loc->section[2].offset + 0x89814);
+ } else if (fsig->version == 0x21) {
+ keydata = (void*)((uintptr_t)firm_loc +
+ firm_loc->section[2].offset + 0x89A14);
+ }
aes_use_keyslot(0x11);
uint8_t keyx[AES_BLOCK_SIZE];
for (int slot = 0x19; slot < 0x20; slot++) {
aes(keyx, keydata, 1, NULL, AES_ECB_DECRYPT_MODE, 0);
aes_setkey(slot, keyx, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
- *(uint8_t *)(keydata + 0xF) += 1;
+ *(uint8_t*)(keydata + 0xF) += 1;
}
fprintf(BOTTOM_SCREEN, "Updated keyX keyslots\n");
}
- fumount(); // Unmount SD. No longer needed.
- fprintf(BOTTOM_SCREEN, "SD Unmounted.\n");
+ fumount(); // Unmount SD. No longer needed.
+ fprintf(BOTTOM_SCREEN, "SD Unmounted.\n");
- for (firm_section_h *section = firm_loc->section;
- section < firm_loc->section + 4 && section->address != 0; section++) {
- memcpy((void *)section->address, (void *)firm_loc + section->offset, section->size);
+ for (firm_section_h* section = firm_loc->section;
+ section < firm_loc->section + 4 && section->address != 0; section++) {
+ memcpy((void*)section->address, (void*)firm_loc + section->offset,
+ section->size);
}
fprintf(BOTTOM_SCREEN, "Copied FIRM\n");
- wait();
+ wait();
- // No fprintf will work from here on out.
+ // No fprintf will work from here on out.
*a11_entry = (uint32_t)disable_lcds;
- while (*a11_entry); // Make sure it jumped there correctly before changing it.
+ while (*a11_entry)
+ ; // Make sure it jumped there correctly before changing it.
*a11_entry = (uint32_t)firm_loc->a11Entry;
((void (*)())firm_loc->a9Entry)();
}
-int find_proc9(firm_h* firm, firm_section_h* process9, exefs_h** p9exefs) {
- for (firm_section_h *section = firm->section; section < firm->section + 4; section++) {
- if (section->address == 0)
- break;
-
- if (section->type == FIRM_TYPE_ARM9) {
- void* arm9section = (void*)firm + section->offset;
- while (arm9section < arm9section + section->size) {
- if (!memcmp(arm9section, "Process9", 8)) { // Process9
- ncch_h *ncch = (ncch_h*)(arm9section - sizeof(ncch_h));
- if (ncch->magic == NCCH_MAGIC) {
- // Found Process9
- ncch_ex_h *p9exheader = (ncch_ex_h *)(ncch + 1);
- *p9exefs = (exefs_h *)(p9exheader + 1);
- process9->address = p9exheader->sci.textCodeSet.address;
- process9->size = (*p9exefs)->fileHeaders[0].size;
- process9->offset = (void*)((*p9exefs) + 1) - (void*)firm;
- fprintf(BOTTOM_SCREEN, " Found Process9 for FIRM.\n");
- return 0;
- }
- }
- ++arm9section;
- }
- }
- }
- fprintf(BOTTOM_SCREEN, " Couldn't find Process9?\n");
- return 1;
+int
+find_proc9(firm_h* firm, firm_section_h* process9, exefs_h** p9exefs)
+{
+ for (firm_section_h* section = firm->section; section < firm->section + 4;
+ section++) {
+ if (section->address == 0)
+ break;
+
+ if (section->type == FIRM_TYPE_ARM9) {
+ void* arm9section = (void*)firm + section->offset;
+ while (arm9section < arm9section + section->size) {
+ if (!memcmp(arm9section, "Process9", 8)) { // Process9
+ ncch_h* ncch = (ncch_h*)(arm9section - sizeof(ncch_h));
+ if (ncch->magic == NCCH_MAGIC) {
+ // Found Process9
+ ncch_ex_h* p9exheader = (ncch_ex_h*)(ncch + 1);
+ *p9exefs = (exefs_h*)(p9exheader + 1);
+ process9->address = p9exheader->sci.textCodeSet.address;
+ process9->size = (*p9exefs)->fileHeaders[0].size;
+ process9->offset =
+ (void*)((*p9exefs) + 1) - (void*)firm;
+ fprintf(BOTTOM_SCREEN, " Found Process9 for FIRM.\n");
+ return 0;
+ }
+ }
+ ++arm9section;
+ }
+ }
+ }
+ fprintf(BOTTOM_SCREEN, " Couldn't find Process9?\n");
+ return 1;
}
-int load_firms() {
+int
+load_firms()
+{
fprintf(BOTTOM_SCREEN, "Loading FIRM...\n");
fprintf(BOTTOM_SCREEN, "Loading NATIVE_FIRM\n");
- if (load_firm(firm_loc, PATH_NATIVE_F, PATH_NATIVE_FIRMKEY, &firm_size, NATIVE_FIRM_TITLEID) != 0)
+ if (load_firm(firm_loc, PATH_NATIVE_F, PATH_NATIVE_FIRMKEY, &firm_size,
+ NATIVE_FIRM_TITLEID) != 0)
return 1;
find_proc9(firm_loc, &firm_proc9, &firm_p9_exefs);
fprintf(BOTTOM_SCREEN, "Loading TWL_FIRM\n");
- if(load_firm(twl_firm_loc, PATH_TWL_F, PATH_TWL_FIRMKEY, &twl_firm_size, TWL_FIRM_TITLEID))
+ if (load_firm(twl_firm_loc, PATH_TWL_F, PATH_TWL_FIRMKEY, &twl_firm_size,
+ TWL_FIRM_TITLEID))
fprintf(BOTTOM_SCREEN, " TWL_FIRM failed to load.\n");
- else
- find_proc9(twl_firm_loc, &twl_firm_proc9, &twl_firm_p9_exefs);
+ else
+ find_proc9(twl_firm_loc, &twl_firm_proc9, &twl_firm_p9_exefs);
fprintf(BOTTOM_SCREEN, "Loading AGB_FIRM\n");
- if(load_firm(agb_firm_loc, PATH_AGB_F, PATH_AGB_FIRMKEY, &agb_firm_size, AGB_FIRM_TITLEID))
+ if (load_firm(agb_firm_loc, PATH_AGB_F, PATH_AGB_FIRMKEY, &agb_firm_size,
+ AGB_FIRM_TITLEID))
fprintf(BOTTOM_SCREEN, " AGB_FIRM failed to load.\n");
- else
- find_proc9(agb_firm_loc, &agb_firm_proc9, &agb_firm_p9_exefs);
+ else
+ find_proc9(agb_firm_loc, &agb_firm_proc9, &agb_firm_p9_exefs);
return 0;
}
-void boot_cfw() {
+void
+boot_cfw()
+{
fprintf(BOTTOM_SCREEN, "Applying patches...\n");
if (patch_firm_all() != 0)
return;
#include <stdint.h>
#include "headers.h"
-enum consoles {
- console_o3ds,
- console_n3ds
+enum consoles
+{
+ console_o3ds,
+ console_n3ds
};
-struct firm_signature {
- uint8_t sig[0x10];
- unsigned int version;
- char version_string[16];
- enum consoles console;
+struct firm_signature
+{
+ uint8_t sig[0x10];
+ unsigned int version;
+ char version_string[16];
+ enum consoles console;
};
-extern firm_h *firm_loc;
-extern struct firm_signature *current_firm;
+extern firm_h* firm_loc;
+extern struct firm_signature* current_firm;
extern firm_section_h firm_proc9;
-extern exefs_h *firm_p9_exefs;
+extern exefs_h* firm_p9_exefs;
-extern firm_h *twl_firm_loc;
-extern struct firm_signature *current_twl_firm;
+extern firm_h* twl_firm_loc;
+extern struct firm_signature* current_twl_firm;
extern firm_section_h twl_firm_proc9;
-extern exefs_h *twl_firm_p9_exefs;
+extern exefs_h* twl_firm_p9_exefs;
-extern firm_h *agb_firm_loc;
-extern struct firm_signature *current_agb_firm;
+extern firm_h* agb_firm_loc;
+extern struct firm_signature* current_agb_firm;
extern firm_section_h agb_firm_proc9;
-extern exefs_h *agb_firm_p9_exefs;
+extern exefs_h* agb_firm_p9_exefs;
-struct firm_signature *get_firm_info(firm_h *firm);
+struct firm_signature* get_firm_info(firm_h* firm);
void slot0x11key96_init();
-int load_firms();
+int load_firms();
void boot_firm();
void boot_cfw();
#include <stdint.h>
-#define FIRM_TYPE_ARM9 0
-#define FIRM_TYPE_ARM11 1
+#define FIRM_TYPE_ARM9 0
+#define FIRM_TYPE_ARM11 1
-#define MEDIA_UNITS 0x200
+#define MEDIA_UNITS 0x200
-#define NCCH_MAGIC (0x4843434E)
-#define NCSD_MAGIC (0x4453434E)
-#define FIRM_MAGIC (0x4D524946)
-#define ARM9BIN_MAGIC (0x47704770)
-#define LGY_ARM9BIN_MAGIC (0xB0862000)
+#define NCCH_MAGIC (0x4843434E)
+#define NCSD_MAGIC (0x4453434E)
+#define FIRM_MAGIC (0x4D524946)
+#define ARM9BIN_MAGIC (0x47704770)
+#define LGY_ARM9BIN_MAGIC (0xB0862000)
-struct memory_header {
+struct memory_header
+{
uint32_t location;
uint32_t size;
} memory_header_t;
-typedef struct firm_section_h {
+typedef struct firm_section_h
+{
uint32_t offset;
uint32_t address;
uint32_t size;
- uint32_t type; // Firmware Type ('0'=ARM9/'1'=ARM11)
- uint8_t hash[0x20]; // SHA-256 Hash of Firmware Section
-} firm_section_h; // 0x30
+ uint32_t type; // Firmware Type ('0'=ARM9/'1'=ARM11)
+ uint8_t hash[0x20]; // SHA-256 Hash of Firmware Section
+} firm_section_h; // 0x30
-typedef struct firm_h {
- uint32_t magic; // FIRM
+typedef struct firm_h
+{
+ uint32_t magic; // FIRM
uint32_t reserved1;
- uint32_t a11Entry; // ARM11 entry
- uint32_t a9Entry; // ARM9 entry
+ uint32_t a11Entry; // ARM11 entry
+ uint32_t a9Entry; // ARM9 entry
uint8_t reserved2[0x30];
firm_section_h section[4];
uint8_t sig[0x100];
} firm_h;
// http://3dbrew.org/wiki/NCCH/Extended_Header
-typedef struct code_set_info {
+typedef struct code_set_info
+{
uint32_t address;
- uint32_t phy_region_size; // Physical region size (in page-multiples)
- uint32_t size; // size in bytes
-} code_set_info; // 0x0C
+ uint32_t phy_region_size; // Physical region size (in page-multiples)
+ uint32_t size; // size in bytes
+} code_set_info; // 0x0C
-typedef struct system_info {
+typedef struct system_info
+{
uint32_t saveDataSize[2];
uint32_t jumpID[2];
uint8_t reserved[0x30];
-} system_info; // 0x40
+} system_info; // 0x40
-typedef struct system_control_info {
+typedef struct system_control_info
+{
uint8_t appTitle[8];
char reserved1[5];
char flag;
char reserved2[4];
code_set_info dataCodeSet;
uint32_t bssSize;
- char depends[0x180]; // Dependency Module (Program ID) List 48*8
+ char depends[0x180]; // Dependency Module (Program ID) List 48*8
system_info systemInfo;
-} system_control_info; // 0x200
+} system_control_info; // 0x200
-typedef struct ncch_ex_h {
+typedef struct ncch_ex_h
+{
system_control_info sci;
uint8_t aci[0x200];
uint8_t accessDescSig[0x100];
uint8_t ncchPubKey[0x100];
uint8_t aciLim[0x200];
-} ncch_ex_h; // 0x800
+} ncch_ex_h; // 0x800
// http://3dbrew.org/wiki/NCCH
-typedef struct ncch_h {
- uint8_t sig[0x100]; // RSA-2048 signature of the NCCH header, using SHA-256.
- uint32_t magic; // NCCH
- uint32_t contentSize; // Content size, in media units (1 media unit = 0x200 bytes)
+typedef struct ncch_h
+{
+ uint8_t sig[0x100]; // RSA-2048 signature of the NCCH header, using SHA-256.
+ uint32_t magic; // NCCH
+ uint32_t contentSize; // Content size, in media units (1 media unit = 0x200
+ // bytes)
uint8_t partitionID[8];
uint8_t makerCode[2];
uint16_t version;
uint8_t reserved1[4];
uint8_t programID[8];
uint8_t reserved2[0x10];
- uint8_t logoHash[0x20]; // Logo Region SHA-256 hash. (For applications built with SDK 5+) (Supported from firmware: 5.0.0-11)
+ uint8_t logoHash[0x20]; // Logo Region SHA-256 hash. (For applications built
+ // with SDK 5+) (Supported from firmware: 5.0.0-11)
uint8_t productCode[0x10];
- uint8_t exHeaderHash[0x20]; // Extended header SHA-256 hash (SHA256 of 2x Alignment Size, beginning at 0x0 of ExHeader)
+ uint8_t exHeaderHash[0x20]; // Extended header SHA-256 hash (SHA256 of 2x
+ // Alignment Size, beginning at 0x0 of ExHeader)
uint32_t exHeaderSize; // Extended header size
uint32_t reserved3;
uint8_t flags[8];
- uint32_t plainOffset; // media unit
- uint32_t plainSize; // media unit
- uint32_t logoOffset; // media unit
- uint32_t logoSize; // media unit
- uint32_t exeFSOffset; // media unit
- uint32_t exeFSSize; // media unit
- uint32_t exeFSHashSize; // media unit ExeFS hash region size
+ uint32_t plainOffset; // media unit
+ uint32_t plainSize; // media unit
+ uint32_t logoOffset; // media unit
+ uint32_t logoSize; // media unit
+ uint32_t exeFSOffset; // media unit
+ uint32_t exeFSSize; // media unit
+ uint32_t exeFSHashSize; // media unit ExeFS hash region size
uint32_t reserved4;
- uint32_t romFSOffset; // media unit
- uint32_t romFSSize; // media unit
- uint32_t romFSHashSize; // media unit RomFS hash region size
+ uint32_t romFSOffset; // media unit
+ uint32_t romFSSize; // media unit
+ uint32_t romFSHashSize; // media unit RomFS hash region size
uint32_t reserved5;
- uint8_t exeFSHash[0x20]; // ExeFS superblock SHA-256 hash - (SHA-256 hash, starting at 0x0 of the ExeFS over the number of media units specified in the ExeFS hash region size)
- uint8_t romFSHash[0x20]; // RomFS superblock SHA-256 hash - (SHA-256 hash, starting at 0x0 of the RomFS over the number of media units specified in the RomFS hash region size)
-} ncch_h; // 0x200
-
-#define NCCH_FLAG_NOCRYPTO 0x4
-#define NCCH_FLAG_7XCRYPTO 0x1
-
-typedef struct cxi_h {
+ uint8_t exeFSHash[0x20]; // ExeFS superblock SHA-256 hash - (SHA-256 hash,
+ // starting at 0x0 of the ExeFS over the number of
+ // media units specified in the ExeFS hash region
+ // size)
+ uint8_t romFSHash[0x20]; // RomFS superblock SHA-256 hash - (SHA-256 hash,
+ // starting at 0x0 of the RomFS over the number of
+ // media units specified in the RomFS hash region
+ // size)
+} ncch_h; // 0x200
+
+#define NCCH_FLAG_NOCRYPTO 0x4
+#define NCCH_FLAG_7XCRYPTO 0x1
+
+typedef struct cxi_h
+{
ncch_h ncch;
ncch_ex_h exheader;
} cxi_h;
-typedef struct exefs_file_h {
+typedef struct exefs_file_h
+{
uint8_t fname[0x8];
- uint32_t offset; // offset starts after exefs_h
+ uint32_t offset; // offset starts after exefs_h
uint32_t size;
-} exefs_file_h; // 0x10
+} exefs_file_h; // 0x10
-typedef struct exefs_file_hash {
+typedef struct exefs_file_hash
+{
uint8_t hash[0x20];
} exefs_file_hash;
-typedef struct exefs_h {
- exefs_file_h fileHeaders[10]; // File headers (10 headers maximum, 16 bytes each)
+typedef struct exefs_h
+{
+ exefs_file_h
+ fileHeaders[10]; // File headers (10 headers maximum, 16 bytes each)
uint8_t reserved[0x20];
- exefs_file_hash fileHashes[10]; // File hashes (10 hashes maximum, 32 bytes each, one for each header), SHA256 over entire file content
+ exefs_file_hash fileHashes[10]; // File hashes (10 hashes maximum, 32 bytes
+ // each, one for each header), SHA256 over
+ // entire file content
} exefs_h; // 0x200
-typedef struct ncsd_partition_table {
+typedef struct ncsd_partition_table
+{
uint32_t offset;
uint32_t size;
} ncsd_partition_table;
// http://3dbrew.org/wiki/NCSD
-typedef struct ncsd_h {
- uint8_t sig[0x100]; // RSA-2048 signature of the NCSD header, using SHA-256.
- uint32_t magic; // NCSD
- uint32_t size; // Size of the NCSD image, in media units (1 media unit = 0x200 bytes)
+typedef struct ncsd_h
+{
+ uint8_t sig[0x100]; // RSA-2048 signature of the NCSD header, using SHA-256.
+ uint32_t magic; // NCSD
+ uint32_t size; // Size of the NCSD image, in media units (1 media unit =
+ // 0x200 bytes)
uint8_t mediaID[8];
- uint8_t fsType[8]; // Partitions FS type (0=None, 1=Normal, 3=FIRM, 4=AGB_FIRM save)
- uint8_t cryptType[8]; // Partitions crypt type
- ncsd_partition_table ptable[8]; // Offset & Length partition table, in media units
+ uint8_t fsType[8]; // Partitions FS type (0=None, 1=Normal, 3=FIRM,
+ // 4=AGB_FIRM save)
+ uint8_t cryptType[8]; // Partitions crypt type
+ ncsd_partition_table
+ ptable[8]; // Offset & Length partition table, in media units
uint8_t spec[0xA0];
} ncsd_h;
-#define NCSD_PARTITION_EXE 0
-#define NCSD_PARTITION_MANUAL 1
-#define NCSD_PARTITION_DLP 2
-#define NCSD_PARTITION_N3DSUPDATE 6
-#define NCSD_PARTITION_O3DSUPDATE 7
+#define NCSD_PARTITION_EXE 0
+#define NCSD_PARTITION_MANUAL 1
+#define NCSD_PARTITION_DLP 2
+#define NCSD_PARTITION_N3DSUPDATE 6
+#define NCSD_PARTITION_O3DSUPDATE 7
-typedef struct arm9bin_h {
+typedef struct arm9bin_h
+{
uint8_t keyx[0x10];
uint8_t keyy[0x10];
uint8_t ctr[0x10];
uint16_t ticketTitleVersion;
uint8_t reserved3[8];
uint8_t licenseType;
- uint8_t ticketCommonKeyYIndex; //Ticket common keyY index, usually 0x1 for retail system titles.
+ uint8_t ticketCommonKeyYIndex; // Ticket common keyY index, usually 0x1 for
+ // retail system titles.
uint8_t reserved4[0x2A];
- uint8_t unk[4]; // eShop Account ID?
+ uint8_t unk[4]; // eShop Account ID?
uint8_t reserved5;
uint8_t audit;
uint8_t reserved6[0x42];
uint8_t contentIndex[0xAC];
} __attribute__((__packed__)) ticket_h; // 0x210
-#define SIG_TYPE_RSA4096_SHA1 0x010000
-#define SIG_TYPE_RSA2048_SHA1 0x010001
-#define SIG_TYPE_ECDSA_SHA1 0x010002
-#define SIG_TYPE_RSA4096_SHA256 0x010003
-#define SIG_TYPE_RSA2048_SHA256 0x010004
-#define SIG_TYPE_ECDSA_SHA256 0x010005
+#define SIG_TYPE_RSA4096_SHA1 0x010000
+#define SIG_TYPE_RSA2048_SHA1 0x010001
+#define SIG_TYPE_ECDSA_SHA1 0x010002
+#define SIG_TYPE_RSA4096_SHA256 0x010003
+#define SIG_TYPE_RSA2048_SHA256 0x010004
+#define SIG_TYPE_ECDSA_SHA256 0x010005
#endif
// We use the firm's section 0's hash to identify the version
struct firm_signature firm_signatures[] = {
- {
- .sig = {0xEE, 0xE2, 0x81, 0x2E, 0xB9, 0x10, 0x0D, 0x03, 0xFE, 0xA2, 0x3F, 0x44, 0xB5, 0x1C, 0xB3, 0x5E},
- .version = 0x1F,
- .version_string = "4.1.0",
- .console = console_o3ds
- }, {
- .sig = {0x8C, 0x29, 0xDA, 0x7B, 0xB5, 0x5F, 0xFE, 0x44, 0x1F, 0x66, 0x79, 0x70, 0x8E, 0xE4, 0x42, 0xE3},
- .version = 0x2A,
- .version_string = "6.1.0",
- .console = console_o3ds
- }, {
- .sig = {0x1D, 0x96, 0x80, 0xD9, 0x0A, 0xA9, 0xDB, 0xE8, 0x29, 0x77, 0xCB, 0x7D, 0x90, 0x55, 0xB7, 0xF9},
- .version = 0x30,
- .version_string = "7.2.0",
- .console = console_o3ds
- }, {
- .sig = {0x3B, 0x61, 0x2E, 0xBA, 0x42, 0xAE, 0x24, 0x46, 0xAD, 0x60, 0x2F, 0x7B, 0x52, 0x16, 0x82, 0x91},
- .version = 0x37,
- .version_string = "8.0.0",
- .console = console_o3ds
- }, {
- .sig = {0x3F, 0xBF, 0x14, 0x06, 0x33, 0x77, 0x82, 0xDE, 0xB2, 0x68, 0x83, 0x01, 0x6B, 0x1A, 0x71, 0x69},
- .version = 0x38,
- .version_string = "9.0.0",
- .console = console_o3ds
- }, {
- .sig = {0x5C, 0x6A, 0x51, 0xF3, 0x79, 0x4D, 0x21, 0x91, 0x0B, 0xBB, 0xFD, 0x17, 0x7B, 0x72, 0x6B, 0x59},
- .version = 0x49,
- .version_string = "9.6.0",
- .console = console_o3ds
- }, {
- .sig = {0xF5, 0x7E, 0xC3, 0x86, 0x1F, 0x8D, 0x8E, 0xFB, 0x44, 0x61, 0xF3, 0x16, 0x51, 0x0A, 0x57, 0x7D},
- .version = 0x50,
- .version_string = "10.4.0",
- .console = console_o3ds
- }, {
- .sig = {0xE9, 0xAD, 0x74, 0x9D, 0x46, 0x9C, 0x9C, 0xF4, 0x96, 0x9E, 0x1A, 0x7A, 0xDF, 0x40, 0x2A, 0x82},
- .version = 0x52,
- .version_string = "11.0.0",
- .console = console_o3ds
- }, {
- .sig = {0x31, 0xCC, 0x46, 0xCD, 0x61, 0x7A, 0xE7, 0x13, 0x7F, 0xE5, 0xFC, 0x20, 0x46, 0x91, 0x6A, 0xBB},
- .version = 0x04,
- .version_string = "9.0.0",
- .console = console_n3ds
- }, {
- .sig = {0x40, 0x35, 0x6C, 0x9A, 0x24, 0x36, 0x93, 0x7B, 0x76, 0xFE, 0x5D, 0xB1, 0x4D, 0x05, 0x06, 0x52},
- .version = 0x0F,
- .version_string = "9.5.0",
- .console = console_n3ds
- }, {
- .sig = {0x07, 0xFE, 0x9A, 0x62, 0x3F, 0xDE, 0x54, 0xC1, 0x9B, 0x06, 0x91, 0xD8, 0x4F, 0x44, 0x9C, 0x21},
- .version = 0x1B,
- .version_string = "10.2.0",
- .console = console_n3ds
- }, {
- .sig = {0x1A, 0x56, 0x5C, 0xFF, 0xC9, 0xCC, 0x62, 0xBB, 0x2B, 0xC2, 0x23, 0xB6, 0x4F, 0x48, 0xD1, 0xCC},
- .version = 0x1F,
- .version_string = "10.4.0",
- .console = console_n3ds
- }, {
- .sig = {0x52, 0x30, 0x0F, 0x55, 0xA2, 0x64, 0x4E, 0xFF, 0x96, 0x90, 0xF0, 0xE5, 0x6E, 0xC8, 0x2E, 0xB3},
- .version = 0x21,
- .version_string = "11.0.0",
- .console = console_n3ds
- },
- {
- .sig = {0xE8, 0xB8, 0x82, 0xF5, 0x8C, 0xC4, 0x1B, 0x24, 0x05, 0x60, 0x6D, 0xB8, 0x74, 0xF5, 0xE5, 0xDD},
- .version = 0x16,
- .version_string = "6.2.0_TWL",
- .console = console_o3ds
- }, {
- .sig = {0x0F, 0x05, 0xC5, 0xF3, 0x60, 0x83, 0x8B, 0x9D, 0xC8, 0x44, 0x3F, 0xB3, 0x06, 0x4D, 0x30, 0xC7},
- .version = 0x00,
- .version_string = "9.0.0_TWL",
- .console = console_n3ds
- },
- {
- .sig = {0x65, 0xB7, 0x55, 0x78, 0x97, 0xE6, 0x5C, 0xD6, 0x11, 0x74, 0x95, 0xDD, 0x61, 0xE8, 0x08, 0x40},
- .version = 0x0B,
- .version_string = "6.0.0_AGB",
- .console = console_o3ds
- }, {
- .sig = {0xAF, 0x81, 0xA1, 0xAB, 0xBA, 0xAC, 0xAC, 0xA7, 0x30, 0xE8, 0xD8, 0x74, 0x7C, 0x47, 0x1C, 0x5D},
- .version = 0x00,
- .version_string = "9.0.0_AGB",
- .console = console_n3ds
- },
- {.version = 0xFF} // Terminate list
+ {.sig = { 0xEE, 0xE2, 0x81, 0x2E, 0xB9, 0x10, 0x0D, 0x03, 0xFE, 0xA2, 0x3F,
+ 0x44, 0xB5, 0x1C, 0xB3, 0x5E },
+ .version = 0x1F,
+ .version_string = "4.1.0",
+ .console = console_o3ds },
+ {.sig = { 0x8C, 0x29, 0xDA, 0x7B, 0xB5, 0x5F, 0xFE, 0x44, 0x1F, 0x66, 0x79,
+ 0x70, 0x8E, 0xE4, 0x42, 0xE3 },
+ .version = 0x2A,
+ .version_string = "6.1.0",
+ .console = console_o3ds },
+ {.sig = { 0x1D, 0x96, 0x80, 0xD9, 0x0A, 0xA9, 0xDB, 0xE8, 0x29, 0x77, 0xCB,
+ 0x7D, 0x90, 0x55, 0xB7, 0xF9 },
+ .version = 0x30,
+ .version_string = "7.2.0",
+ .console = console_o3ds },
+ {.sig = { 0x3B, 0x61, 0x2E, 0xBA, 0x42, 0xAE, 0x24, 0x46, 0xAD, 0x60, 0x2F,
+ 0x7B, 0x52, 0x16, 0x82, 0x91 },
+ .version = 0x37,
+ .version_string = "8.0.0",
+ .console = console_o3ds },
+ {.sig = { 0x3F, 0xBF, 0x14, 0x06, 0x33, 0x77, 0x82, 0xDE, 0xB2, 0x68, 0x83,
+ 0x01, 0x6B, 0x1A, 0x71, 0x69 },
+ .version = 0x38,
+ .version_string = "9.0.0",
+ .console = console_o3ds },
+ {.sig = { 0x5C, 0x6A, 0x51, 0xF3, 0x79, 0x4D, 0x21, 0x91, 0x0B, 0xBB, 0xFD,
+ 0x17, 0x7B, 0x72, 0x6B, 0x59 },
+ .version = 0x49,
+ .version_string = "9.6.0",
+ .console = console_o3ds },
+ {.sig = { 0xF5, 0x7E, 0xC3, 0x86, 0x1F, 0x8D, 0x8E, 0xFB, 0x44, 0x61, 0xF3,
+ 0x16, 0x51, 0x0A, 0x57, 0x7D },
+ .version = 0x50,
+ .version_string = "10.4.0",
+ .console = console_o3ds },
+ {.sig = { 0xE9, 0xAD, 0x74, 0x9D, 0x46, 0x9C, 0x9C, 0xF4, 0x96, 0x9E, 0x1A,
+ 0x7A, 0xDF, 0x40, 0x2A, 0x82 },
+ .version = 0x52,
+ .version_string = "11.0.0",
+ .console = console_o3ds },
+ {.sig = { 0x31, 0xCC, 0x46, 0xCD, 0x61, 0x7A, 0xE7, 0x13, 0x7F, 0xE5, 0xFC,
+ 0x20, 0x46, 0x91, 0x6A, 0xBB },
+ .version = 0x04,
+ .version_string = "9.0.0",
+ .console = console_n3ds },
+ {.sig = { 0x40, 0x35, 0x6C, 0x9A, 0x24, 0x36, 0x93, 0x7B, 0x76, 0xFE, 0x5D,
+ 0xB1, 0x4D, 0x05, 0x06, 0x52 },
+ .version = 0x0F,
+ .version_string = "9.5.0",
+ .console = console_n3ds },
+ {.sig = { 0x07, 0xFE, 0x9A, 0x62, 0x3F, 0xDE, 0x54, 0xC1, 0x9B, 0x06, 0x91,
+ 0xD8, 0x4F, 0x44, 0x9C, 0x21 },
+ .version = 0x1B,
+ .version_string = "10.2.0",
+ .console = console_n3ds },
+ {.sig = { 0x1A, 0x56, 0x5C, 0xFF, 0xC9, 0xCC, 0x62, 0xBB, 0x2B, 0xC2, 0x23,
+ 0xB6, 0x4F, 0x48, 0xD1, 0xCC },
+ .version = 0x1F,
+ .version_string = "10.4.0",
+ .console = console_n3ds },
+ {.sig = { 0x52, 0x30, 0x0F, 0x55, 0xA2, 0x64, 0x4E, 0xFF, 0x96, 0x90, 0xF0,
+ 0xE5, 0x6E, 0xC8, 0x2E, 0xB3 },
+ .version = 0x21,
+ .version_string = "11.0.0",
+ .console = console_n3ds },
+ {.sig = { 0xE8, 0xB8, 0x82, 0xF5, 0x8C, 0xC4, 0x1B, 0x24, 0x05, 0x60, 0x6D,
+ 0xB8, 0x74, 0xF5, 0xE5, 0xDD },
+ .version = 0x16,
+ .version_string = "6.2.0_TWL",
+ .console = console_o3ds },
+ {.sig = { 0x0F, 0x05, 0xC5, 0xF3, 0x60, 0x83, 0x8B, 0x9D, 0xC8, 0x44, 0x3F,
+ 0xB3, 0x06, 0x4D, 0x30, 0xC7 },
+ .version = 0x00,
+ .version_string = "9.0.0_TWL",
+ .console = console_n3ds },
+ {.sig = { 0x65, 0xB7, 0x55, 0x78, 0x97, 0xE6, 0x5C, 0xD6, 0x11, 0x74, 0x95,
+ 0xDD, 0x61, 0xE8, 0x08, 0x40 },
+ .version = 0x0B,
+ .version_string = "6.0.0_AGB",
+ .console = console_o3ds },
+ {.sig = { 0xAF, 0x81, 0xA1, 0xAB, 0xBA, 0xAC, 0xAC, 0xA7, 0x30, 0xE8, 0xD8,
+ 0x74, 0x7C, 0x47, 0x1C, 0x5D },
+ .version = 0x00,
+ .version_string = "9.0.0_AGB",
+ .console = console_n3ds },
+ {.version = 0xFF } // Terminate list
};
-struct firm_signature *get_firm_info(firm_h *firm) {
- for (struct firm_signature *signature = firm_signatures; signature->version != 0xFF; signature++) {
+struct firm_signature*
+get_firm_info(firm_h* firm)
+{
+ for (struct firm_signature* signature = firm_signatures;
+ signature->version != 0xFF; signature++) {
if (memcmp(signature->sig, firm->section[0].hash, 0x10) == 0) {
return signature;
}
//-----------------------------------------------------------------------------
-static const struct { uint8_t bus_id, reg_addr; } dev_data[] = {
- {0, 0x4A}, {0, 0x7A}, {0, 0x78},
- {1, 0x4A}, {1, 0x78}, {1, 0x2C},
- {1, 0x2E}, {1, 0x40}, {1, 0x44},
- {2, 0xD6}, {2, 0xD0}, {2, 0xD2},
- {2, 0xA4}, {2, 0x9A}, {2, 0xA0},
+static const struct
+{
+ uint8_t bus_id, reg_addr;
+} dev_data[] = {
+ { 0, 0x4A }, { 0, 0x7A }, { 0, 0x78 }, { 1, 0x4A }, { 1, 0x78 },
+ { 1, 0x2C }, { 1, 0x2E }, { 1, 0x40 }, { 1, 0x44 }, { 2, 0xD6 },
+ { 2, 0xD0 }, { 2, 0xD2 }, { 2, 0xA4 }, { 2, 0x9A }, { 2, 0xA0 },
};
-uint8_t i2cGetDeviceBusId(uint8_t device_id) {
+uint8_t
+i2cGetDeviceBusId(uint8_t device_id)
+{
return dev_data[device_id].bus_id;
}
-uint8_t i2cGetDeviceRegAddr(uint8_t device_id) {
+uint8_t
+i2cGetDeviceRegAddr(uint8_t device_id)
+{
return dev_data[device_id].reg_addr;
}
(volatile uint8_t*)(I2C3_REG_OFF + I2C_REG_DATA),
};
-volatile uint8_t* i2cGetDataReg(uint8_t bus_id) {
+volatile uint8_t*
+i2cGetDataReg(uint8_t bus_id)
+{
return reg_data_addrs[bus_id];
}
(volatile uint8_t*)(I2C3_REG_OFF + I2C_REG_CNT),
};
-volatile uint8_t* i2cGetCntReg(uint8_t bus_id) {
+volatile uint8_t*
+i2cGetCntReg(uint8_t bus_id)
+{
return reg_cnt_addrs[bus_id];
}
//-----------------------------------------------------------------------------
-void i2cWaitBusy(uint8_t bus_id) {
- while (*i2cGetCntReg(bus_id) & 0x80);
+void
+i2cWaitBusy(uint8_t bus_id)
+{
+ while (*i2cGetCntReg(bus_id) & 0x80)
+ ;
}
-int i2cGetResult(uint8_t bus_id) {
+int
+i2cGetResult(uint8_t bus_id)
+{
i2cWaitBusy(bus_id);
return (*i2cGetCntReg(bus_id) >> 4) & 1;
}
-void i2cStop(uint8_t bus_id, uint8_t arg0) {
+void
+i2cStop(uint8_t bus_id, uint8_t arg0)
+{
*i2cGetCntReg(bus_id) = (arg0 << 5) | 0xC0;
i2cWaitBusy(bus_id);
*i2cGetCntReg(bus_id) = 0xC5;
//-----------------------------------------------------------------------------
-int i2cSelectDevice(uint8_t bus_id, uint8_t dev_reg) {
+int
+i2cSelectDevice(uint8_t bus_id, uint8_t dev_reg)
+{
i2cWaitBusy(bus_id);
*i2cGetDataReg(bus_id) = dev_reg;
*i2cGetCntReg(bus_id) = 0xC2;
return i2cGetResult(bus_id);
}
-int i2cSelectRegister(uint8_t bus_id, uint8_t reg) {
+int
+i2cSelectRegister(uint8_t bus_id, uint8_t reg)
+{
i2cWaitBusy(bus_id);
*i2cGetDataReg(bus_id) = reg;
*i2cGetCntReg(bus_id) = 0xC0;
//-----------------------------------------------------------------------------
-uint8_t i2cReadRegister(uint8_t dev_id, uint8_t reg) {
+uint8_t
+i2cReadRegister(uint8_t dev_id, uint8_t reg)
+{
uint8_t bus_id = i2cGetDeviceBusId(dev_id);
uint8_t dev_addr = i2cGetDeviceRegAddr(dev_id);
for (size_t i = 0; i < 8; i++) {
- if (i2cSelectDevice(bus_id, dev_addr) && i2cSelectRegister(bus_id, reg)) {
+ if (i2cSelectDevice(bus_id, dev_addr) &&
+ i2cSelectRegister(bus_id, reg)) {
if (i2cSelectDevice(bus_id, dev_addr | 1)) {
i2cWaitBusy(bus_id);
i2cStop(bus_id, 1);
return 0xff;
}
-int i2cReadRegisterBuffer(unsigned int dev_id, int reg, uint8_t* buffer, size_t buf_size) {
+int
+i2cReadRegisterBuffer(unsigned int dev_id, int reg, uint8_t* buffer,
+ size_t buf_size)
+{
uint8_t bus_id = i2cGetDeviceBusId(dev_id);
uint8_t dev_addr = i2cGetDeviceRegAddr(dev_id);
size_t j = 0;
- while (!i2cSelectDevice(bus_id, dev_addr)
- || !i2cSelectRegister(bus_id, reg)
- || !i2cSelectDevice(bus_id, dev_addr | 1))
- {
+ while (!i2cSelectDevice(bus_id, dev_addr) ||
+ !i2cSelectRegister(bus_id, reg) ||
+ !i2cSelectDevice(bus_id, dev_addr | 1)) {
i2cWaitBusy(bus_id);
*i2cGetCntReg(bus_id) = 0xC5;
i2cWaitBusy(bus_id);
return 1;
}
-int i2cWriteRegister(uint8_t dev_id, uint8_t reg, uint8_t data) {
+int
+i2cWriteRegister(uint8_t dev_id, uint8_t reg, uint8_t data)
+{
uint8_t bus_id = i2cGetDeviceBusId(dev_id);
uint8_t dev_addr = i2cGetDeviceRegAddr(dev_id);
for (int i = 0; i < 8; i++) {
- if (i2cSelectDevice(bus_id, dev_addr) && i2cSelectRegister(bus_id, reg)) {
+ if (i2cSelectDevice(bus_id, dev_addr) &&
+ i2cSelectRegister(bus_id, reg)) {
i2cWaitBusy(bus_id);
*i2cGetDataReg(bus_id) = data;
*i2cGetCntReg(bus_id) = 0xC1;
#define I2C2_REG_OFF 0x10144000
#define I2C3_REG_OFF 0x10148000
-#define I2C_REG_DATA 0
-#define I2C_REG_CNT 1
+#define I2C_REG_DATA 0
+#define I2C_REG_CNT 1
#define I2C_REG_CNTEX 2
-#define I2C_REG_SCL 4
+#define I2C_REG_SCL 4
-#define I2C_DEV_MCU 3
+#define I2C_DEV_MCU 3
#define I2C_DEV_GYRO 10
-#define I2C_DEV_IR 13
+#define I2C_DEV_IR 13
uint8_t i2cGetDeviceBusId(uint8_t device_id);
uint8_t i2cGetDeviceRegAddr(uint8_t device_id);
uint8_t i2cReadRegister(uint8_t dev_id, uint8_t reg);
int i2cWriteRegister(uint8_t dev_id, uint8_t reg, uint8_t data);
-int i2cReadRegisterBuffer(unsigned int dev_id, int reg, uint8_t* buffer, size_t buf_size);
+int i2cReadRegisterBuffer(unsigned int dev_id, int reg, uint8_t* buffer,
+ size_t buf_size);
-#define BUTTON_A (1 << 0)
-#define BUTTON_B (1 << 1)
-#define BUTTON_SEL (1 << 2)
-#define BUTTON_STA (1 << 3)
-#define BUTTON_RIGHT (1 << 4)
-#define BUTTON_LEFT (1 << 5)
-#define BUTTON_UP (1 << 6)
-#define BUTTON_DOWN (1 << 7)
-#define BUTTON_R (1 << 8)
-#define BUTTON_L (1 << 9)
-#define BUTTON_X (1 << 10)
-#define BUTTON_Y (1 << 11)
+#define BUTTON_A (1 << 0)
+#define BUTTON_B (1 << 1)
+#define BUTTON_SEL (1 << 2)
+#define BUTTON_STA (1 << 3)
+#define BUTTON_RIGHT (1 << 4)
+#define BUTTON_LEFT (1 << 5)
+#define BUTTON_UP (1 << 6)
+#define BUTTON_DOWN (1 << 7)
+#define BUTTON_R (1 << 8)
+#define BUTTON_L (1 << 9)
+#define BUTTON_X (1 << 10)
+#define BUTTON_Y (1 << 11)
/* FIXME - I had ZR and ZL in, but they don't appear to
behave rationally without some initialization. */
-#define BUTTON_ANY 0xFFF
-
-#define HID_PAD ((*(volatile uint32_t *)0x10146000) ^ BUTTON_ANY)
+#define BUTTON_ANY 0xFFF
+#define HID_PAD ((*(volatile uint32_t*)0x10146000) ^ BUTTON_ANY)
// flexibility unlike a 'patch format'.
extern exefs_h* firm_p9_exefs;
-exefs_h* get_firm_proc9_exefs() {
- return firm_p9_exefs;
+exefs_h*
+get_firm_proc9_exefs()
+{
+ return firm_p9_exefs;
}
extern exefs_h* twl_firm_p9_exefs;
-exefs_h* get_twl_proc9_exefs() {
- return twl_firm_p9_exefs;
+exefs_h*
+get_twl_proc9_exefs()
+{
+ return twl_firm_p9_exefs;
}
extern exefs_h* agb_firm_p9_exefs;
-exefs_h* get_agb_proc9_exefs() {
- return agb_firm_p9_exefs;
+exefs_h*
+get_agb_proc9_exefs()
+{
+ return agb_firm_p9_exefs;
}
-int execp(char* path) {
- int basename = 0;
- for(basename=strlen(path); basename > 0; basename--)
- if (path[basename] == '/')
- break;
- basename++;
+int
+execp(char* path)
+{
+ int basename = 0;
+ for (basename = strlen(path); basename > 0; basename--)
+ if (path[basename] == '/')
+ break;
+ basename++;
- fprintf(stderr, "Exec: %s\n", &path[basename]);
+ fprintf(stderr, "Exec: %s\n", &path[basename]);
- struct system_patch patch;
+ struct system_patch patch;
- // Load patch from path.
- FILE* f = fopen(path, "r");
- fread(&patch, 1, sizeof(patch), f);
+ // Load patch from path.
+ FILE* f = fopen(path, "r");
+ fread(&patch, 1, sizeof(patch), f);
- fprintf(stderr, " [h]");
+ fprintf(stderr, " [h]");
- fread((uint8_t*)FCRAM_PATCHBIN_EXEC_LOC, 1, patch.patch_size, f);
+ fread((uint8_t*)FCRAM_PATCHBIN_EXEC_LOC, 1, patch.patch_size, f);
- fprintf(stderr, "[x]");
+ fprintf(stderr, "[x]");
- fclose(f);
+ fclose(f);
- fprintf(stderr, "[s]");
+ fprintf(stderr, "[s]");
- uint32_t* link_table = (uint32_t*)(FCRAM_PATCHBIN_EXEC_LOC+4);
+ uint32_t* link_table = (uint32_t*)(FCRAM_PATCHBIN_EXEC_LOC + 4);
- fprintf(stderr, "[r]");
+ fprintf(stderr, "[r]");
- // 0 - magic
+ // 0 - magic
- // memory.c
- link_table[2] = (uint32_t)strlen;
- link_table[4] = (uint32_t)isprint;
- link_table[6] = (uint32_t)memcpy;
- link_table[8] = (uint32_t)memmove;
- link_table[10] = (uint32_t)memset;
- link_table[12] = (uint32_t)memcmp;
- link_table[14] = (uint32_t)strncpy;
- link_table[16] = (uint32_t)strncmp;
- link_table[18] = (uint32_t)atoi;
- link_table[20] = (uint32_t)memfind;
+ // memory.c
+ link_table[2] = (uint32_t)strlen;
+ link_table[4] = (uint32_t)isprint;
+ link_table[6] = (uint32_t)memcpy;
+ link_table[8] = (uint32_t)memmove;
+ link_table[10] = (uint32_t)memset;
+ link_table[12] = (uint32_t)memcmp;
+ link_table[14] = (uint32_t)strncpy;
+ link_table[16] = (uint32_t)strncmp;
+ link_table[18] = (uint32_t)atoi;
+ link_table[20] = (uint32_t)memfind;
- // draw.c
- link_table[22] = (uint32_t)putc;
- link_table[24] = (uint32_t)puts;
- link_table[26] = (uint32_t)fprintf;
+ // draw.c
+ link_table[22] = (uint32_t)putc;
+ link_table[24] = (uint32_t)puts;
+ link_table[26] = (uint32_t)fprintf;
- // Get functions
- link_table[28] = (uint32_t)get_firm_proc9_exefs;
+ // Get functions
+ link_table[28] = (uint32_t)get_firm_proc9_exefs;
- link_table[30] = (uint32_t)get_agb_proc9_exefs;
+ link_table[30] = (uint32_t)get_agb_proc9_exefs;
- link_table[32] = (uint32_t)get_twl_proc9_exefs;
+ link_table[32] = (uint32_t)get_twl_proc9_exefs;
- fprintf(stderr, "[b]\n");
+ fprintf(stderr, "[b]\n");
- int (*patch_loc)() = (void*)FCRAM_PATCHBIN_EXEC_LOC ;
+ int (*patch_loc)() = (void*)FCRAM_PATCHBIN_EXEC_LOC;
- int ret = (*patch_loc)();
+ int ret = (*patch_loc)();
- fprintf(stderr, " Exit: %d\n", ret);
+ fprintf(stderr, " Exit: %d\n", ret);
- return ret;
+ return ret;
}
int doing_autoboot = 0;
void shut_up();
-int main() {
+int
+main()
+{
if (fmount()) {
// Failed to mount SD. Bomb out.
- fprintf(BOTTOM_SCREEN, "%pFailed to mount SD card.\n", COLOR(RED, BLACK));
+ fprintf(BOTTOM_SCREEN, "%pFailed to mount SD card.\n",
+ COLOR(RED, BLACK));
}
load_config(); // Load configuration.
- // Autoboot. Non-standard code path.
- if (config.options[OPTION_AUTOBOOT] && !(HID_PAD & BUTTON_R)) {
- if (config.options[OPTION_SILENCE])
- shut_up();
- load_firms();
- doing_autoboot = 1;
- boot_cfw(); // Just boot shit.
- }
+ // Autoboot. Non-standard code path.
+ if (config.options[OPTION_AUTOBOOT] && !(HID_PAD & BUTTON_R)) {
+ if (config.options[OPTION_SILENCE])
+ shut_up();
+ load_firms();
+ doing_autoboot = 1;
+ boot_cfw(); // Just boot shit.
+ }
int in_menu = 1;
load_firms();
- while(in_menu) {
+ while (in_menu) {
in_menu = menu_handler();
}
- fprintf(BOTTOM_SCREEN, "Booting CFW\n");
+ fprintf(BOTTOM_SCREEN, "Booting CFW\n");
- save_config(); // Save config file.
+ save_config(); // Save config file.
- boot_cfw();
+ boot_cfw();
// Under ideal conditions, we never get here.
}
#include "common.h"
#include "firm/firm.h"
#include "firm/headers.h"
-#define MENU_MAIN 1
+#define MENU_MAIN 1
-#define MENU_OPTIONS 2
-#define MENU_PATCHES 3
-#define MENU_INFO 4
-#define MENU_HELP 5
-#define MENU_RESET 6
-#define MENU_POWER 7
-#define MENU_BOOTME 8
+#define MENU_OPTIONS 2
+#define MENU_PATCHES 3
+#define MENU_INFO 4
+#define MENU_HELP 5
+#define MENU_RESET 6
+#define MENU_POWER 7
+#define MENU_BOOTME 8
static struct options_s options[] = {
- { 0, "Signature Patch", boolean_val, 0, 0 },
- { 1, "FIRM Protection", boolean_val, 0, 0 },
- { 2, "SysModule Replacement", boolean_val, 0, 0 },
- { 3, "Service Replacement", boolean_val, 0, 0 },
- { 4, "ARM9 Thread", boolean_val, 0, 0 },
+ { 0, "Signature Patch", boolean_val, 0, 0 },
+ { 1, "FIRM Protection", boolean_val, 0, 0 },
+ { 2, "SysModule Replacement", boolean_val, 0, 0 },
+ { 3, "Service Replacement", boolean_val, 0, 0 },
+ { 4, "ARM9 Thread", boolean_val, 0, 0 },
- { 5, "Autoboot", boolean_val, 0, 0 },
- { 6, "Silence w/ Autoboot", boolean_val, 0, 0 },
- { 7, "Step through with button", boolean_val, 0, 0 },
+ { 5, "Autoboot", boolean_val, 0, 0 },
+ { 6, "Silence w/ Autoboot", boolean_val, 0, 0 },
+ { 7, "Step through with button", boolean_val, 0, 0 },
- { 8, "Don't draw background color", boolean_val, 0, 0 },
- { 9, "Preserve framebuffer data", boolean_val, 0, 0 },
+ { 8, "Don't draw background color", boolean_val, 0, 0 },
+ { 9, "Preserve framebuffer data", boolean_val, 0, 0 },
- { 10, "Hide Help from menu", boolean_val, 0, 0 },
+ { 10, "Hide Help from menu", boolean_val, 0, 0 },
- { 11, "Loader: CPU L2 enable", boolean_val, 0, 0 },
- { 12, "Loader: CPU 800Mhz mode", boolean_val, 0, 0 },
- { 13, "Loader: Language Emulation", boolean_val, 0, 0 },
+ { 11, "Loader: CPU L2 enable", boolean_val, 0, 0 },
+ { 12, "Loader: CPU 800Mhz mode", boolean_val, 0, 0 },
+ { 13, "Loader: Language Emulation", boolean_val, 0, 0 },
- { 14, "Svc: Force replace allocated", boolean_val, 0, 0 },
+ { 14, "Svc: Force replace allocated", boolean_val, 0, 0 },
- { 15, "No dependency tracking", boolean_val, 0, 0 },
- { 16, "Allow unsafe options", boolean_val, 0, 0 },
+ { 15, "No dependency tracking", boolean_val, 0, 0 },
+ { 16, "Allow unsafe options", boolean_val, 0, 0 },
- { -1, "", 0, 0, 0},
+ { -1, "", 0, 0, 0 },
};
static int cursor_y = 0;
static int which_menu = 1;
static int need_redraw = 1;
-uint32_t wait_key() {
+uint32_t
+wait_key()
+{
uint32_t get = 0;
- while(get == 0) {
- if(HID_PAD & BUTTON_UP)
+ while (get == 0) {
+ if (HID_PAD & BUTTON_UP)
get = BUTTON_UP;
else if (HID_PAD & BUTTON_DOWN)
get = BUTTON_DOWN;
else if (HID_PAD & BUTTON_B)
get = BUTTON_B;
}
- while(HID_PAD&get);
+ while (HID_PAD & get)
+ ;
return get;
}
-void header(char* append) {
+void
+header(char* append)
+{
fprintf(stdout, "\x1b[33;40m[.corbenik//%s] %s\x1b[0m\n", VERSION, append);
}
-int menu_patches() { return MENU_MAIN; }
+int
+menu_patches()
+{
+ return MENU_MAIN;
+}
-int menu_options() {
+int
+menu_options()
+{
set_cursor(TOP_SCREEN, 0, 0);
header("A:Enter B:Back DPAD:Nav");
- int i = 0;
- while(options[i].index != -1) { // -1 Sentinel.
+ int i = 0;
+ while (options[i].index != -1) { // -1 Sentinel.
if (cursor_y == i)
fprintf(TOP_SCREEN, "\x1b[32m>>\x1b[0m ");
else
fprintf(TOP_SCREEN, " ");
if (need_redraw)
- fprintf(TOP_SCREEN, "[%c] %s\n", (config.options[options[i].index] ? 'X' : ' '), options[i].name);
- else {
- // Yes, this is weird. printf does a large number of extra things we don't
- // want computed at the moment; this is faster.
- putc(TOP_SCREEN, '[');
- putc(TOP_SCREEN, (config.options[options[i].index] ? 'X' : ' '));
- putc(TOP_SCREEN, ']');
- putc(TOP_SCREEN, '\n');
- }
- ++i;
+ fprintf(TOP_SCREEN, "[%c] %s\n",
+ (config.options[options[i].index] ? 'X' : ' '),
+ options[i].name);
+ else {
+ // Yes, this is weird. printf does a large number of extra things we
+ // don't
+ // want computed at the moment; this is faster.
+ putc(TOP_SCREEN, '[');
+ putc(TOP_SCREEN, (config.options[options[i].index] ? 'X' : ' '));
+ putc(TOP_SCREEN, ']');
+ putc(TOP_SCREEN, '\n');
+ }
+ ++i;
}
- need_redraw = 0;
+ need_redraw = 0;
uint32_t key = wait_key();
- switch(key) {
+ switch (key) {
case BUTTON_UP:
cursor_y -= 1;
- if (cursor_y < 0)
- cursor_y = 0;
+ if (cursor_y < 0)
+ cursor_y = 0;
break;
case BUTTON_DOWN:
cursor_y += 1;
- if (options[cursor_y].index == -1)
- cursor_y -= 1;
+ if (options[cursor_y].index == -1)
+ cursor_y -= 1;
break;
case BUTTON_A:
// TODO - Value options
- config.options[options[cursor_y].index] = !config.options[options[cursor_y].index];
+ config.options[options[cursor_y].index] =
+ !config.options[options[cursor_y].index];
break;
case BUTTON_B:
- need_redraw = 1;
- clear_screen(TOP_SCREEN);
- cursor_y = 0;
+ need_redraw = 1;
+ clear_screen(TOP_SCREEN);
+ cursor_y = 0;
return MENU_MAIN;
break;
}
return 0;
}
-int menu_info() {
+int
+menu_info()
+{
clear_screen(TOP_SCREEN);
set_cursor(TOP_SCREEN, 0, 0);
header("Any:Back");
- struct firm_signature *native = get_firm_info(firm_loc);
- struct firm_signature *agb = get_firm_info(agb_firm_loc);
- struct firm_signature *twl = get_firm_info(twl_firm_loc);
-
- fprintf(stdout, "\nNATIVE_FIRM / Firmware:\n"
- " Version: %s (%x)\n"
- "AGB_FIRM / GBA Firmware:\n"
- " Version: %s (%x)\n"
- "TWL_FIRM / DSi Firmware:\n"
- " Version: %s (%x)\n",
- native->version_string, native->version,
- agb->version_string, agb->version,
- twl->version_string, twl->version);
+ struct firm_signature* native = get_firm_info(firm_loc);
+ struct firm_signature* agb = get_firm_info(agb_firm_loc);
+ struct firm_signature* twl = get_firm_info(twl_firm_loc);
+
+ fprintf(stdout, "\nNATIVE_FIRM / Firmware:\n"
+ " Version: %s (%x)\n"
+ "AGB_FIRM / GBA Firmware:\n"
+ " Version: %s (%x)\n"
+ "TWL_FIRM / DSi Firmware:\n"
+ " Version: %s (%x)\n",
+ native->version_string, native->version, agb->version_string,
+ agb->version, twl->version_string, twl->version);
while (1) {
if (wait_key() & BUTTON_ANY)
break;
}
- need_redraw = 1;
+ need_redraw = 1;
clear_screen(TOP_SCREEN);
return MENU_MAIN;
}
-int menu_help() {
+int
+menu_help()
+{
clear_screen(TOP_SCREEN);
set_cursor(TOP_SCREEN, 0, 0);
header("Any:Back");
- fprintf(stdout, "\nCorbenik is a 3DS firmware patching tool;\n"
- " commonly known as a CFW. It seeks to address\n"
- " some faults in other CFWs and is generally\n"
- " just another choice for users - but primarily\n"
- " is intended for developers.\n"
- "\n"
- "Credits to people who've helped me put this\n"
- " together either by code or helpfulness:\n"
- " @mid-kid, @Wolfvak, @Reisyukaku, @AuroraWright\n"
- " @d0k3, @TuxSH, and others\n"
- "\n"
- "[PROTECT BREAK] DATA DRAIN: OK\n"
- "\n"
- " <https://github.com/chaoskagami/corbenik>\n"
- "\n");
+ fprintf(stdout, "\nCorbenik is a 3DS firmware patching tool;\n"
+ " commonly known as a CFW. It seeks to address\n"
+ " some faults in other CFWs and is generally\n"
+ " just another choice for users - but primarily\n"
+ " is intended for developers.\n"
+ "\n"
+ "Credits to people who've helped me put this\n"
+ " together either by code or helpfulness:\n"
+ " @mid-kid, @Wolfvak, @Reisyukaku, @AuroraWright\n"
+ " @d0k3, @TuxSH, and others\n"
+ "\n"
+ "[PROTECT BREAK] DATA DRAIN: OK\n"
+ "\n"
+ " <https://github.com/chaoskagami/corbenik>\n"
+ "\n");
while (1) {
if (wait_key() & BUTTON_ANY)
break;
}
- need_redraw = 1;
+ need_redraw = 1;
clear_screen(TOP_SCREEN);
return MENU_MAIN;
}
-int menu_reset() {
+int
+menu_reset()
+{
fumount(); // Unmount SD.
// Reboot.
fprintf(BOTTOM_SCREEN, "Resetting system.\n");
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2);
- while(1);
+ while (1)
+ ;
}
-int menu_poweroff() {
+int
+menu_poweroff()
+{
fumount(); // Unmount SD.
// Reboot.
fprintf(BOTTOM_SCREEN, "Powering off system.\n");
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 0);
- while(1);
+ while (1)
+ ;
}
-int menu_main() {
+int
+menu_main()
+{
set_cursor(TOP_SCREEN, 0, 0);
- const char *list[] = {
- "Options",
- "Patches",
- "Info",
- "Help/Readme",
- "Reset",
- "Power off",
- "Boot firmware"
- };
+ const char* list[] = { "Options", "Patches", "Info",
+ "Help/Readme", "Reset", "Power off",
+ "Boot firmware" };
int menu_max = 7;
header("A:Enter DPAD:Nav");
- for(int i=0; i < menu_max; i++) {
- if (!(i+2 == MENU_HELP && config.options[OPTION_READ_ME])) {
- if (cursor_y == i)
- fprintf(TOP_SCREEN, "\x1b[32m>>\x1b[0m ");
- else
- fprintf(TOP_SCREEN, " ");
-
- if (need_redraw)
- fprintf(TOP_SCREEN, "%s\n", list[i]);
- else
- putc(TOP_SCREEN, '\n');
- }
+ for (int i = 0; i < menu_max; i++) {
+ if (!(i + 2 == MENU_HELP && config.options[OPTION_READ_ME])) {
+ if (cursor_y == i)
+ fprintf(TOP_SCREEN, "\x1b[32m>>\x1b[0m ");
+ else
+ fprintf(TOP_SCREEN, " ");
+
+ if (need_redraw)
+ fprintf(TOP_SCREEN, "%s\n", list[i]);
+ else
+ putc(TOP_SCREEN, '\n');
+ }
}
- need_redraw = 0;
+ need_redraw = 0;
uint32_t key = wait_key();
- int ret = cursor_y+2;
+ int ret = cursor_y + 2;
- switch(key) {
+ switch (key) {
case BUTTON_UP:
cursor_y -= 1;
- if (config.options[OPTION_READ_ME] && cursor_y+2 == MENU_HELP)
- cursor_y -= 1; // Disable help.
+ if (config.options[OPTION_READ_ME] && cursor_y + 2 == MENU_HELP)
+ cursor_y -= 1; // Disable help.
break;
case BUTTON_DOWN:
cursor_y += 1;
- if (config.options[OPTION_READ_ME] && cursor_y+2 == MENU_HELP)
- cursor_y += 1; // Disable help.
+ if (config.options[OPTION_READ_ME] && cursor_y + 2 == MENU_HELP)
+ cursor_y += 1; // Disable help.
break;
case BUTTON_A:
- need_redraw = 1;
- cursor_y = 0;
+ need_redraw = 1;
+ cursor_y = 0;
if (ret == MENU_BOOTME)
- return MENU_BOOTME; // Boot meh, damnit!
+ return MENU_BOOTME; // Boot meh, damnit!
return ret;
}
// Loop around the cursor.
if (cursor_y < 0)
- cursor_y = menu_max -1;
+ cursor_y = menu_max - 1;
if (cursor_y > menu_max - 1)
cursor_y = 0;
return 0;
}
-int menu_handler() {
+int
+menu_handler()
+{
int to_menu = 0;
- switch(which_menu) {
+ switch (which_menu) {
case MENU_MAIN:
to_menu = menu_main();
break;
menu_reset();
case MENU_POWER:
menu_poweroff();
- default:
- fprintf(stderr, "Attempt to enter wrong menu!\n");
- to_menu = MENU_MAIN;
+ default:
+ fprintf(stderr, "Attempt to enter wrong menu!\n");
+ to_menu = MENU_MAIN;
}
if (to_menu != 0)
return 1;
}
-
// Do you like examples?
-PATCH(example) {
- fprintf(stderr, "Testing, testing, 1, 2, 3, 4..\n");
+PATCH(example)
+{
+ fprintf(stderr, "Testing, testing, 1, 2, 3, 4..\n");
- return 0;
+ return 0;
}
-
#include "patch_file.h"
-PATCH(modules) {
- // TODO - load module cxi here
- FILE* f = fopen(PATH_MODULES "/loader.cxi", "r");
- if (!f) {
- fprintf(stderr, "Module: loader.cxi not found on FS\n");
- return 2;
- }
+PATCH(modules)
+{
+ // TODO - load module cxi here
+ FILE* f = fopen(PATH_MODULES "/loader.cxi", "r");
+ if (!f) {
+ fprintf(stderr, "Module: loader.cxi not found on FS\n");
+ return 2;
+ }
- uint32_t size = fsize(f);
- fread((uint8_t*)FCRAM_JUNK_LOCATION, 1, size, f);
- fclose(f);
+ uint32_t size = fsize(f);
+ fread((uint8_t*)FCRAM_JUNK_LOCATION, 1, size, f);
+ fclose(f);
- // Look for the section that holds all the sysmodules
- firm_section_h *sysmodule_section = NULL;
- for (firm_section_h *section = firm_loc->section; section < firm_loc->section + 4; section++) {
- if (section->address == 0x1FF00000 && section->type == FIRM_TYPE_ARM11) {
- sysmodule_section = section;
- break;
- }
- }
+ // Look for the section that holds all the sysmodules
+ firm_section_h* sysmodule_section = NULL;
+ for (firm_section_h* section = firm_loc->section;
+ section < firm_loc->section + 4; section++) {
+ if (section->address == 0x1FF00000 &&
+ section->type == FIRM_TYPE_ARM11) {
+ sysmodule_section = section;
+ break;
+ }
+ }
- if (!sysmodule_section) {
- fprintf(stderr, "Module: sysmodule section not found\n");
- return 1;
- }
+ if (!sysmodule_section) {
+ fprintf(stderr, "Module: sysmodule section not found\n");
+ return 1;
+ }
- ncch_h *module = (ncch_h*)FCRAM_JUNK_LOCATION;
- ncch_h *sysmodule = (ncch_h *)((uint32_t)firm_loc + sysmodule_section->offset);
+ ncch_h* module = (ncch_h*)FCRAM_JUNK_LOCATION;
+ ncch_h* sysmodule =
+ (ncch_h*)((uint32_t)firm_loc + sysmodule_section->offset);
- // Check if we want to replace an existing sysmodule
- while (sysmodule->magic == NCCH_MAGIC) {
- if (memcmp(sysmodule->programID, module->programID, 8) == 0) {
- // Expand firmware module size if needed to accomodate replacement.
- if (module->contentSize > sysmodule->contentSize) {
- uint32_t need_units = (module->contentSize - sysmodule->contentSize);
- fprintf(stderr, "Module: Would grow %d units but NYI\n", need_units);
- continue;
+ // Check if we want to replace an existing sysmodule
+ while (sysmodule->magic == NCCH_MAGIC) {
+ if (memcmp(sysmodule->programID, module->programID, 8) == 0) {
+ // Expand firmware module size if needed to accomodate replacement.
+ if (module->contentSize > sysmodule->contentSize) {
+ uint32_t need_units =
+ (module->contentSize - sysmodule->contentSize);
+ fprintf(stderr, "Module: Would grow %d units but NYI\n",
+ need_units);
+ continue;
- // TODO - so in a nutshell, the reason Luma works is because it relocates
- // the sysmodule section to its final location while fixing the size.
- // Once stuff is at the right place, it no longer cares about its' size.
+ // TODO - so in a nutshell, the reason Luma works is because it
+ // relocates
+ // the sysmodule section to its final location while fixing the
+ // size.
+ // Once stuff is at the right place, it no longer cares about
+ // its' size.
- // Cakes performs an in-place resize and leaves the copy for later; essentially,
- // this means I need to scale EVERYTHING after the increase, and adjust NCCH sections accordingly.
+ // Cakes performs an in-place resize and leaves the copy for
+ // later; essentially,
+ // this means I need to scale EVERYTHING after the increase, and
+ // adjust NCCH sections accordingly.
- // It would be hella easier to just patch at the final location in memory;
- // and this was actually mentioned on Luma's issues.
- }
+ // It would be hella easier to just patch at the final location
+ // in memory;
+ // and this was actually mentioned on Luma's issues.
+ }
- // Move the remaining modules closer
- if (module->contentSize < sysmodule->contentSize) {
- fprintf(stderr, "Module: Shrink %d units\n", sysmodule->contentSize - module->contentSize);
- int remaining_size =
- sysmodule_section->size -
+ // Move the remaining modules closer
+ if (module->contentSize < sysmodule->contentSize) {
+ fprintf(stderr, "Module: Shrink %d units\n",
+ sysmodule->contentSize - module->contentSize);
+ int remaining_size =
+ sysmodule_section->size -
(((uint32_t)sysmodule + sysmodule->contentSize * 0x200) -
- ((uint32_t)firm_loc + sysmodule_section->offset));
- // Sysmodule section size - (End location of this sysmodule - Sysmodule section) =>
- memmove((uint8_t*)sysmodule + module->contentSize * 0x200, (uint8_t*)sysmodule + sysmodule->contentSize * 0x200, remaining_size);
- // Move end of section to be adjacent
- }
+ ((uint32_t)firm_loc + sysmodule_section->offset));
+ // Sysmodule section size - (End location of this sysmodule -
+ // Sysmodule section) =>
+ memmove((uint8_t*)sysmodule + module->contentSize * 0x200,
+ (uint8_t*)sysmodule + sysmodule->contentSize * 0x200,
+ remaining_size);
+ // Move end of section to be adjacent
+ }
- fprintf(stderr, "Module: Injecting %llu\n", module->programID);
- // Copy the module into the firm
- memcpy(sysmodule, module, module->contentSize * 0x200);
- break;
- }
- sysmodule = (ncch_h *)((uintptr_t)sysmodule + sysmodule->contentSize * 0x200);
- }
+ fprintf(stderr, "Module: Injecting %llu\n", module->programID);
+ // Copy the module into the firm
+ memcpy(sysmodule, module, module->contentSize * 0x200);
+ break;
+ }
+ sysmodule =
+ (ncch_h*)((uintptr_t)sysmodule + sysmodule->contentSize * 0x200);
+ }
- fprintf(stderr, "Module: injected modules.\n");
+ fprintf(stderr, "Module: injected modules.\n");
- return 0;
+ return 0;
}
-
#define BUILTIN 1
#ifdef BUILTIN
- // Build patch into CFW instead of as module.
- #include "../std/unused.h"
- #include "../std/memory.h"
- #include "../firm/firm.h"
- #include "../firm/fcram.h"
- #include "../config.h"
- #include "../common.h"
-
- #define PATCH(name) int patch_##name ()
+// Build patch into CFW instead of as module.
+#include "../std/unused.h"
+#include "../std/memory.h"
+#include "../firm/firm.h"
+#include "../firm/fcram.h"
+#include "../config.h"
+#include "../common.h"
+
+#define PATCH(name) int patch_##name()
#elif MODULE
- // Build patch as loadable executable.
+// Build patch as loadable executable.
- // TODO - Includes.
+// TODO - Includes.
- #define PATCH(name) int main()
+#define PATCH(name) int main()
#else
- #define PATCH(name) (void)
+#define PATCH(name) (void)
- // Don't build patch; Exclude its code.
+// Don't build patch; Exclude its code.
#endif
#endif
// This patch applies the FIRM protection code needed for safe a9lh usage.
-PATCH(firmprot) {
- uint8_t *firm_mem = (uint8_t*)firm_p9_exefs + sizeof(exefs_h) + firm_p9_exefs->fileHeaders[0].offset;
- uint32_t size = firm_p9_exefs->fileHeaders[0].size;
+PATCH(firmprot)
+{
+ uint8_t* firm_mem = (uint8_t*)firm_p9_exefs + sizeof(exefs_h) +
+ firm_p9_exefs->fileHeaders[0].offset;
+ uint32_t size = firm_p9_exefs->fileHeaders[0].size;
// We look for 'exe:' first; this string is close to what we patch
uint8_t* off = memfind(firm_mem, size, (uint8_t*)"exe:", 4);
- if(off == NULL) {
- fprintf(stderr, "Couldn't find 'exe:' string.\n");
- return 1;
- }
+ if (off == NULL) {
+ fprintf(stderr, "Couldn't find 'exe:' string.\n");
+ return 1;
+ }
- fprintf(stderr, "Firmprot: 'exe:' string @ %x\n", (uint32_t)off);
+ fprintf(stderr, "Firmprot: 'exe:' string @ %x\n", (uint32_t)off);
- uint8_t pattern[] = {0x00, 0x28, 0x01, 0xDA};
+ uint8_t pattern[] = { 0x00, 0x28, 0x01, 0xDA };
uint8_t* firmprot = memfind(off - 0x100, 0x100, pattern, 4);
- if(firmprot == NULL) {
- fprintf(stderr, "Couldn't find firmprot code.\n");
- return 2;
- }
+ if (firmprot == NULL) {
+ fprintf(stderr, "Couldn't find firmprot code.\n");
+ return 2;
+ }
- fprintf(stderr, "Firmprot: %x\n", (uint32_t)firmprot);
+ fprintf(stderr, "Firmprot: %x\n", (uint32_t)firmprot);
- uint8_t patch[] = {0x00, 0x20, 0xC0, 0x46};
- memcpy(firmprot, patch, 4);
+ uint8_t patch[] = { 0x00, 0x20, 0xC0, 0x46 };
+ memcpy(firmprot, patch, 4);
- fprintf(stderr, "Applied firmprot patch.\n");
+ fprintf(stderr, "Applied firmprot patch.\n");
- return 0;
+ return 0;
}
-
// This patch is responsible for fixing signature checks for the firmware.
-PATCH(signatures) {
- //Look for signature checks
+PATCH(signatures)
+{
+ // Look for signature checks
- uint8_t pat1[] = {0xC0, 0x1C, 0x76, 0xE7};
- uint8_t pat2[] = {0xB5, 0x22, 0x4D, 0x0C};
+ uint8_t pat1[] = { 0xC0, 0x1C, 0x76, 0xE7 };
+ uint8_t pat2[] = { 0xB5, 0x22, 0x4D, 0x0C };
- // The code segment.
- uint8_t *firm_mem = (uint8_t*)firm_p9_exefs + sizeof(exefs_h) + firm_p9_exefs->fileHeaders[0].offset;
- uint32_t size = firm_p9_exefs->fileHeaders[0].size;
+ // The code segment.
+ uint8_t* firm_mem = (uint8_t*)firm_p9_exefs + sizeof(exefs_h) +
+ firm_p9_exefs->fileHeaders[0].offset;
+ uint32_t size = firm_p9_exefs->fileHeaders[0].size;
- uint8_t *off = memfind(firm_mem, size, pat1, 4);
+ uint8_t* off = memfind(firm_mem, size, pat1, 4);
- // We're subbing one because the code goes back 1.
- // Unique patterns, etc.
- uint8_t *off2 = memfind(firm_mem, size, pat2, 4) - 1;
+ // We're subbing one because the code goes back 1.
+ // Unique patterns, etc.
+ uint8_t* off2 = memfind(firm_mem, size, pat2, 4) - 1;
- if (off == NULL) {
- fprintf(stderr, "Signature patch failed on P0.\n");
- return 1; // Failed to find sigpatch. Ugh.
- }
+ if (off == NULL) {
+ fprintf(stderr, "Signature patch failed on P0.\n");
+ return 1; // Failed to find sigpatch. Ugh.
+ }
- if (off2 == NULL) {
- fprintf(stderr, "Signature patch failed on P1.\n");
- return 2; // Failed to find sigpatch. Ugh.
- }
+ if (off2 == NULL) {
+ fprintf(stderr, "Signature patch failed on P1.\n");
+ return 2; // Failed to find sigpatch. Ugh.
+ }
- fprintf(stderr, "Signatures[0]: 0x%x\n", (uint32_t)off);
- fprintf(stderr, "Signatures[1]: 0x%x\n", (uint32_t)off2);
+ fprintf(stderr, "Signatures[0]: 0x%x\n", (uint32_t)off);
+ fprintf(stderr, "Signatures[1]: 0x%x\n", (uint32_t)off2);
- // See asm/sigpatches.s for the code here
- uint8_t sigpatch[] = {0x00, 0x20, 0x70, 0x47};
+ // See asm/sigpatches.s for the code here
+ uint8_t sigpatch[] = { 0x00, 0x20, 0x70, 0x47 };
- memcpy(off, sigpatch, 2);
- memcpy(off2, sigpatch, 4);
+ memcpy(off, sigpatch, 2);
+ memcpy(off2, sigpatch, 4);
- fprintf(stderr, "Signature patch succeded.\n");
+ fprintf(stderr, "Signature patch succeded.\n");
- return 0;
+ return 0;
}
-
#include "patch_file.h"
-// This patch handles replacement of services. This includes backdoor, but not just backdoor.
-// Any service can be replaced provided there's enough space within the exception page.
+// This patch handles replacement of services. This includes backdoor, but not
+// just backdoor.
+// Any service can be replaced provided there's enough space within the
+// exception page.
// Please note that the actual code for services is in `external/service`.
-uint32_t *getSvcAndExceptions(uint8_t *pos, uint32_t size, uint32_t **exceptionsPage) {
- uint8_t pattern[] = {0x00, 0xB0, 0x9C, 0xE5}; //cpsid aif
+uint32_t*
+getSvcAndExceptions(uint8_t* pos, uint32_t size, uint32_t** exceptionsPage)
+{
+ uint8_t pattern[] = { 0x00, 0xB0, 0x9C, 0xE5 }; // cpsid aif
- *exceptionsPage = (uint32_t *)memfind(pos, size, pattern, 4) - 0xB;
+ *exceptionsPage = (uint32_t*)memfind(pos, size, pattern, 4) - 0xB;
- uint32_t svcOffset = (-(((*exceptionsPage)[2] & 0xFFFFFF) << 2) & (0xFFFFFF << 2)) - 8; //Branch offset + 8 for prefetch
- uint32_t *svcTable = (uint32_t *)(pos + *(uint32_t *)(pos + 0xFFFF0008 - svcOffset - 0xFFF00000 + 8) - 0xFFF00000); //SVC handler address
- while(*svcTable) svcTable++; //Look for SVC0 (NULL)
+ uint32_t svcOffset =
+ (-(((*exceptionsPage)[2] & 0xFFFFFF) << 2) & (0xFFFFFF << 2)) -
+ 8; // Branch offset + 8 for prefetch
+ uint32_t* svcTable = (uint32_t*)(pos +
+ *(uint32_t*)(pos + 0xFFFF0008 - svcOffset -
+ 0xFFF00000 + 8) -
+ 0xFFF00000); // SVC handler address
+ while (*svcTable)
+ svcTable++; // Look for SVC0 (NULL)
return svcTable;
}
-uint32_t *freeSpace = NULL;
+uint32_t* freeSpace = NULL;
-PATCH(services) {
+PATCH(services)
+{
// Make sure svcBackdoor is there.
uint8_t* arm11Section1 = (uint8_t*)firm_loc + firm_loc->section[1].offset;
- uint32_t *exceptionsPage;
- uint32_t *svcTable = getSvcAndExceptions(arm11Section1, firm_loc->section[1].size, &exceptionsPage);
+ uint32_t* exceptionsPage;
+ uint32_t* svcTable = getSvcAndExceptions(
+ arm11Section1, firm_loc->section[1].size, &exceptionsPage);
- fprintf(stderr, "Svc: table at %x\n", (uint32_t)svcTable);
+ fprintf(stderr, "Svc: table at %x\n", (uint32_t)svcTable);
- char str[] = PATH_SERVICES "/00.bin";
- char* at = str + (strlen(str) - 6);
- for(uint32_t i=0; i <= 0xff; i++) {
- // Get string for svc.
- at[0] = ("0123456789abcdef")[((i >> 4) & 0xf)]; // This is just hexdump. Nothing complicated.
- at[1] = ("0123456789abcdef")[(i & 0xf)];
+ char str[] = PATH_SERVICES "/00.bin";
+ char* at = str + (strlen(str) - 6);
+ for (uint32_t i = 0; i <= 0xff; i++) {
+ // Get string for svc.
+ at[0] = ("0123456789abcdef")[(
+ (i >> 4) & 0xf)]; // This is just hexdump. Nothing complicated.
+ at[1] = ("0123456789abcdef")[(i & 0xf)];
- FILE* data = fopen(str, "r");
- if (!data) {
- continue; // No file for svc. Move on.
- }
+ FILE* data = fopen(str, "r");
+ if (!data) {
+ continue; // No file for svc. Move on.
+ }
- // Refuse to replace non-NULL services unless the user says to.
- if (svcTable[i] && !config.options[OPTION_REPLACE_ALLOCATED_SVC]) {
- fclose(data);
- fprintf(stderr, "Svc: %x non-null, moving on\n", i);
- continue;
- }
+ // Refuse to replace non-NULL services unless the user says to.
+ if (svcTable[i] && !config.options[OPTION_REPLACE_ALLOCATED_SVC]) {
+ fclose(data);
+ fprintf(stderr, "Svc: %x non-null, moving on\n", i);
+ continue;
+ }
- uint32_t size = fsize(data);
- uint8_t* read_to = (void*)FCRAM_JUNK_LOCATION;
+ uint32_t size = fsize(data);
+ uint8_t* read_to = (void*)FCRAM_JUNK_LOCATION;
- fprintf(stderr, "Svc: %s, %d bytes\n", at, size);
+ fprintf(stderr, "Svc: %s, %d bytes\n", at, size);
- fread(read_to, 1, size, data);
+ fread(read_to, 1, size, data);
- fclose(data);
+ fclose(data);
- if (!freeSpace) {
- for(freeSpace = exceptionsPage; *freeSpace != 0xFFFFFFFF; freeSpace++);
- }
+ if (!freeSpace) {
+ for (freeSpace = exceptionsPage; *freeSpace != 0xFFFFFFFF;
+ freeSpace++)
+ ;
+ }
- fprintf(stderr, "Svc: Copy code to %x\n", (uint32_t)freeSpace);
+ fprintf(stderr, "Svc: Copy code to %x\n", (uint32_t)freeSpace);
memcpy(freeSpace, read_to, size);
- svcTable[i] = 0xFFFF0000 + ((uint8_t *)freeSpace - (uint8_t *)exceptionsPage);
+ svcTable[i] =
+ 0xFFFF0000 + ((uint8_t*)freeSpace - (uint8_t*)exceptionsPage);
- freeSpace += size; // We keep track of this because there's more than 7B free.
+ freeSpace +=
+ size; // We keep track of this because there's more than 7B free.
- fprintf(stderr, "Svc: entry set as %x\n", svcTable[0x7B]);
- }
+ fprintf(stderr, "Svc: entry set as %x\n", svcTable[0x7B]);
+ }
- return 0;
+ return 0;
}
#ifndef __PATCH_FORMAT_H
#define __PATCH_FORMAT_H
-// The following are titleids which are handled specially for one reason or another.
-// We use titleIDs to be generic; it ensures that patches can share the same format
+// The following are titleids which are handled specially for one reason or
+// another.
+// We use titleIDs to be generic; it ensures that patches can share the same
+// format
// regardless of whether they're intended for loader or not. Simple logistics.
-#define NATIVE_FIRM_TITLEID 0x0004013800000002llu // NATIVE_FIRM
+#define NATIVE_FIRM_TITLEID 0x0004013800000002llu // NATIVE_FIRM
#define NATIVE_FIRM_N3DS_TITLEID 0x0004013820000002llu // NATIVE_FIRM, n3ds
-#define TWL_FIRM_TITLEID 0x0004013000000102llu // TWL_FIRM (DSi Firmware)
-#define TWL_FIRM_N3DS_TITLEID 0x0004013020000102llu // TWL_FIRM, n3ds (DSi Firmware)
+#define TWL_FIRM_TITLEID 0x0004013000000102llu // TWL_FIRM (DSi Firmware)
+#define TWL_FIRM_N3DS_TITLEID \
+ 0x0004013020000102llu // TWL_FIRM, n3ds (DSi Firmware)
-#define AGB_FIRM_TITLEID 0x0004013000000202llu // AGB_FIRM (GBA firmware)
-#define AGB_FIRM_N3DS_TITLEID 0x0004013020000202llu // AGB_FIRM (GBA firmware)
+#define AGB_FIRM_TITLEID 0x0004013000000202llu // AGB_FIRM (GBA firmware)
+#define AGB_FIRM_N3DS_TITLEID 0x0004013020000202llu // AGB_FIRM (GBA firmware)
-#define LOADER_TITLEID 0x0004013000001302llu // Loader is handled specially.
+#define LOADER_TITLEID 0x0004013000001302llu // Loader is handled specially.
-#define PATCH_MANDATORY (1 << 0) // Patch must be applied for successful boot.
-#define PATCH_FAIL_ABORT (1 << 1) // If patch fails to apply, abort and show an error.
-#define PATCH_DISABLED (1 << 2) // Do not allow changing this patch's status. With PATCH_MANDATORY, this prevents disabling it.
+#define PATCH_MANDATORY (1 << 0) // Patch must be applied for successful boot.
+#define PATCH_FAIL_ABORT \
+ (1 << 1) // If patch fails to apply, abort and show an error.
+#define PATCH_DISABLED \
+ (1 << 2) // Do not allow changing this patch's status. With PATCH_MANDATORY,
+ // this prevents disabling it.
// You can redefine this in the Makefile, if you'd like.
// Recommended names for being silly:
// Windows
// system
#ifndef PATH_CFW
- #define PATH_CFW "/corbenik" // CFW root directory.
+#define PATH_CFW "/corbenik" // CFW root directory.
#endif
-#define PATH_CONFIG_DIR PATH_CFW "/etc" // Config file directory.
-#define PATH_CONFIG PATH_CONFIG_DIR "/main.conf" // Config file.
-#define PATH_LOCEMU PATH_CONFIG_DIR "/langemu.conf" // Locale emulation config
-#define PATH_CPU_CFG PATH_CONFIG_DIR "/cpu.conf" // CPU settings config
+#define PATH_CONFIG_DIR PATH_CFW "/etc" // Config file directory.
+#define PATH_CONFIG PATH_CONFIG_DIR "/main.conf" // Config file.
+#define PATH_LOCEMU PATH_CONFIG_DIR "/langemu.conf" // Locale emulation config
+#define PATH_CPU_CFG PATH_CONFIG_DIR "/cpu.conf" // CPU settings config
-#define PATH_PATCHES PATH_CFW "/bin" // Patch binary folder.
-#define PATH_FIRMWARES PATH_CFW "/lib/firmware" // Firmware folder.
-#define PATH_MODULES PATH_CFW "/lib/module" // Sysmodule location
-#define PATH_SERVICES PATH_CFW "/lib/service" // Service code location.
-#define PATH_TEMP PATH_CFW "/tmp" // Files that are transient (user can delete them and they will be regenerated)
-#define PATH_KEYS PATH_CFW "/share/keys" // Keyfiles will be loaded from this dir, and additionally the root if not found.
-#define PATH_EXEFS PATH_CFW "/lib/exe" // ExeFS overrides, named like '<titleid>.exefs'
+#define PATH_PATCHES PATH_CFW "/bin" // Patch binary folder.
+#define PATH_FIRMWARES PATH_CFW "/lib/firmware" // Firmware folder.
+#define PATH_MODULES PATH_CFW "/lib/module" // Sysmodule location
+#define PATH_SERVICES PATH_CFW "/lib/service" // Service code location.
+#define PATH_TEMP \
+ PATH_CFW "/tmp" // Files that are transient (user can delete them and they
+ // will be regenerated)
+#define PATH_KEYS \
+ PATH_CFW "/share/keys" // Keyfiles will be loaded from this dir, and
+ // additionally the root if not found.
+#define PATH_EXEFS \
+ PATH_CFW "/lib/exe" // ExeFS overrides, named like '<titleid>.exefs'
-#define PATH_NATIVE_F PATH_FIRMWARES "/native"
-#define PATH_AGB_F PATH_FIRMWARES "/agb"
-#define PATH_TWL_F PATH_FIRMWARES "/twl"
+#define PATH_NATIVE_F PATH_FIRMWARES "/native"
+#define PATH_AGB_F PATH_FIRMWARES "/agb"
+#define PATH_TWL_F PATH_FIRMWARES "/twl"
-#define PATH_NATIVE_CETK PATH_FIRMWARES "/native.cetk"
+#define PATH_NATIVE_CETK PATH_FIRMWARES "/native.cetk"
-#define PATH_TWL_CETK PATH_FIRMWARES "/twl.cetk"
+#define PATH_TWL_CETK PATH_FIRMWARES "/twl.cetk"
-#define PATH_AGB_CETK PATH_FIRMWARES "/agb.cetk"
+#define PATH_AGB_CETK PATH_FIRMWARES "/agb.cetk"
-#define PATH_NATIVE_FIRMKEY PATH_KEYS "/native.key"
-#define PATH_TWL_FIRMKEY PATH_KEYS "/twl.key"
-#define PATH_AGB_FIRMKEY PATH_KEYS "/agb.key"
+#define PATH_NATIVE_FIRMKEY PATH_KEYS "/native.key"
+#define PATH_TWL_FIRMKEY PATH_KEYS "/twl.key"
+#define PATH_AGB_FIRMKEY PATH_KEYS "/agb.key"
// These are used with O3DS units. Keep in mind I have no way to test this.
-#define PATH_NATIVE_FIRMKEY_2 PATH_KEYS "/native_old.key"
-#define PATH_TWL_FIRMKEY_2 PATH_KEYS "/twl_old.key"
-#define PATH_AGB_FIRMKEY_2 PATH_KEYS "/agb_old.key"
+#define PATH_NATIVE_FIRMKEY_2 PATH_KEYS "/native_old.key"
+#define PATH_TWL_FIRMKEY_2 PATH_KEYS "/twl_old.key"
+#define PATH_AGB_FIRMKEY_2 PATH_KEYS "/agb_old.key"
-#define PATH_SLOT0X11KEY96 PATH_KEYS "/11.key"
+#define PATH_SLOT0X11KEY96 PATH_KEYS "/11.key"
-#define PATH_ALT_SLOT0X11KEY96 "/slot0x11key96.bin" // Hey, your perrogative, buddy. I like cleaned up paths.
+#define PATH_ALT_SLOT0X11KEY96 \
+ "/slot0x11key96.bin" // Hey, your perrogative, buddy. I like cleaned up
+ // paths.
// Structure of a patch file.
-struct system_patch {
- char magic[4]; // "AIDA" for shits and giggles and because we like .hack.
- uint32_t patch_ver; // Version of the patch itself.
- uint32_t load_ver; // Version of the CFW the patch is intended for.
+struct system_patch
+{
+ char magic[4]; // "AIDA" for shits and giggles and because we like .hack.
+ uint32_t patch_ver; // Version of the patch itself.
+ uint32_t load_ver; // Version of the CFW the patch is intended for.
- char name[64]; // User-readable name for patch in menu.
- char desc[256]; // User-readable description for patch in menu.
- uint64_t patch_id; // Unique ID for patch. Each unique patch should provide a unique ID.
+ char name[64]; // User-readable name for patch in menu.
+ char desc[256]; // User-readable description for patch in menu.
+ uint64_t patch_id; // Unique ID for patch. Each unique patch should provide
+ // a unique ID.
- uint64_t tid; // What title this patch is intended for. Certain values are specially handled.
+ uint64_t tid; // What title this patch is intended for. Certain values are
+ // specially handled.
- uint8_t extra_flags; // Extra flags for patch.
+ uint8_t extra_flags; // Extra flags for patch.
- uint64_t depends[16]; // What patches need to be applied for this patch to be applied; as unique IDs
+ uint64_t depends[16]; // What patches need to be applied for this patch to
+ // be applied; as unique IDs
- uint32_t patch_size; // Size of the following patch data.
-// uint8_t patch_data[]; // The data for the patch. This is a compiled binary for ARM9/11.
+ uint32_t patch_size; // Size of the following patch data.
+ // uint8_t patch_data[]; // The data for the patch. This is a
+ // compiled binary for ARM9/11.
} __attribute__((packed));
-struct patch_opcode {
+struct patch_opcode
+{
} __attribute__((packed));
#endif
-
extern int patch_services();
extern int patch_modules();
-// A portion of this file is inherited from Luma3DS.
-/*u32 getLoader(u8 *pos, u32 *loaderSize) {
- u8 *off = pos;
- u32 size;
-
- while(1)
- {
- size = *(u32 *)(off + 0x104) * 0x200;
- if(*(u32 *)(off + 0x200) == 0x64616F6C) break;
- off += size;
- }
-
- *loaderSize = size;
-
- return (u32)(off - pos);
-}
-*/
-
extern int doing_autoboot;
-void wait() {
- if (config.options[OPTION_TRACE] && !doing_autoboot) {
- fprintf(stderr, " [WAIT]");
- wait_key();
- }
- fprintf(stderr, "\r \r");
+void
+wait()
+{
+ if (config.options[OPTION_TRACE] && !doing_autoboot) {
+ fprintf(stderr, " [WAIT]");
+ wait_key();
+ }
+ fprintf(stderr, "\r \r");
}
-int patch_firm_all() {
- // FIXME - Linker is bork at the moment.
-// execp(PATH_PATCHES "/example.vco");
+int
+patch_firm_all()
+{
+ // FIXME - Linker is bork at the moment.
+ // execp(PATH_PATCHES "/example.vco");
-// wait();
+ // wait();
- // Use builtin signature patcher?
+ // Use builtin signature patcher?
- wait();
+ wait();
- if (config.options[OPTION_SIGPATCH]) {
- // TODO - Patch menu. This is okay-ish for now.
-// if(execp(PATH_PATCHES "/signatures.vco")) {
- if(patch_signatures()) {
- abort("Fatal. Sigpatch has failed.");
- }
- }
+ if (config.options[OPTION_SIGPATCH]) {
+ // TODO - Patch menu. This is okay-ish for now.
+ // if(execp(PATH_PATCHES "/signatures.vco")) {
+ if (patch_signatures()) {
+ abort("Fatal. Sigpatch has failed.");
+ }
+ }
- wait();
+ wait();
- if (config.options[OPTION_FIRMPROT]) {
- if(patch_firmprot()) {
- abort("Fatal. Firmprot has failed.");
- }
- }
+ if (config.options[OPTION_FIRMPROT]) {
+ if (patch_firmprot()) {
+ abort("Fatal. Firmprot has failed.");
+ }
+ }
- wait();
+ wait();
- // Replace loader?
- if (config.options[OPTION_LOADER]) {
- if(patch_modules()) {
- abort("Fatal. Service patch has failed.");
- }
- // This requires OPTION_SIGPATCH.
- }
+ // Replace loader?
+ if (config.options[OPTION_LOADER]) {
+ if (patch_modules()) {
+ abort("Fatal. Service patch has failed.");
+ }
+ // This requires OPTION_SIGPATCH.
+ }
- wait();
+ wait();
- // Inject services?
- if (config.options[OPTION_SERVICES]) {
- if(patch_services()) {
- abort("Fatal. Service patch has failed.");
- }
- }
+ // Inject services?
+ if (config.options[OPTION_SERVICES]) {
+ if (patch_services()) {
+ abort("Fatal. Service patch has failed.");
+ }
+ }
- // Use ARM9 hook thread?
- if (config.options[OPTION_ARM9THREAD]) {
- // Yes.
+ // Use ARM9 hook thread?
+ if (config.options[OPTION_ARM9THREAD]) {
+ // Yes.
- // FIXME - NYI
- }
+ // FIXME - NYI
+ }
- wait();
+ wait();
- return 0;
+ return 0;
}
#include "draw.h"
-#define abort(x...) { \
- fprintf(stderr, x); \
- fumount(); \
- while(1); \
-}
+#define abort(x...) \
+ { \
+ fprintf(stderr, x); \
+ fumount(); \
+ while (1) \
+ ; \
+ }
#endif
static unsigned int top_cursor_x = 0, top_cursor_y = 0;
static unsigned int bottom_cursor_x = 0, bottom_cursor_y = 0;
-static char text_buffer_top [TEXT_TOP_HEIGHT*TEXT_TOP_WIDTH+1];
-static char text_buffer_bottom [TEXT_BOTTOM_HEIGHT*TEXT_BOTTOM_WIDTH+1];
+static char text_buffer_top[TEXT_TOP_HEIGHT * TEXT_TOP_WIDTH + 1];
+static char text_buffer_bottom[TEXT_BOTTOM_HEIGHT * TEXT_BOTTOM_WIDTH + 1];
-static char color_buffer_top [TEXT_TOP_HEIGHT*TEXT_TOP_WIDTH+1];
-static char color_buffer_bottom [TEXT_BOTTOM_HEIGHT*TEXT_BOTTOM_WIDTH+1];
+static char color_buffer_top[TEXT_TOP_HEIGHT * TEXT_TOP_WIDTH + 1];
+static char color_buffer_bottom[TEXT_BOTTOM_HEIGHT * TEXT_BOTTOM_WIDTH + 1];
static uint32_t colors[16] = {
- 0x000000, // Black
- 0xaa0000, // Blue
- 0x00aa00, // Green
- 0xaaaa00, // Cyan
- 0x0000aa, // Red
- 0xaa00aa, // Magenta
- 0x0055aa, // Brown
- 0xaaaaaa, // Gray
- 0x555555, // Dark gray
- 0xff5555, // Bright blue
- 0x55ff55, // Bright green
- 0xffff55, // Bright cyan
- 0x5555ff, // Bright red
- 0xff55ff, // Bright megenta
- 0x55ffff, // Yellow
- 0xffffff // White
+ 0x000000, // Black
+ 0xaa0000, // Blue
+ 0x00aa00, // Green
+ 0xaaaa00, // Cyan
+ 0x0000aa, // Red
+ 0xaa00aa, // Magenta
+ 0x0055aa, // Brown
+ 0xaaaaaa, // Gray
+ 0x555555, // Dark gray
+ 0xff5555, // Bright blue
+ 0x55ff55, // Bright green
+ 0xffff55, // Bright cyan
+ 0x5555ff, // Bright red
+ 0xff55ff, // Bright megenta
+ 0x55ffff, // Yellow
+ 0xffffff // White
};
-void clear_disp(uint8_t* screen) {
+void
+clear_disp(uint8_t* screen)
+{
if (screen == TOP_SCREEN)
screen = framebuffers->top_left;
else if (screen == BOTTOM_SCREEN)
screen = framebuffers->bottom;
- if(screen == framebuffers->top_left ||
- screen == framebuffers->top_right) {
- memset(screen, 0, SCREEN_TOP_SIZE);
- } else if(screen == framebuffers->bottom) {
- memset(screen, 0, SCREEN_BOTTOM_SIZE);
- }
+ if (screen == framebuffers->top_left || screen == framebuffers->top_right) {
+ memset(screen, 0, SCREEN_TOP_SIZE);
+ } else if (screen == framebuffers->bottom) {
+ memset(screen, 0, SCREEN_BOTTOM_SIZE);
+ }
}
-void clear_text(uint8_t* screen) {
+void
+clear_text(uint8_t* screen)
+{
if (screen == TOP_SCREEN)
screen = framebuffers->top_left;
else if (screen == BOTTOM_SCREEN)
screen = framebuffers->bottom;
- if(screen == framebuffers->top_left ||
- screen == framebuffers->top_right) {
- for(int i=0; i < TEXT_TOP_HEIGHT; i++) {
- text_buffer_top[i*TEXT_TOP_WIDTH] = 0;
- color_buffer_top[i*TEXT_TOP_WIDTH] = 0;
- }
- } else if(screen == framebuffers->bottom) {
- for(int i=0; i < TEXT_BOTTOM_HEIGHT; i++) {
- text_buffer_bottom[i*TEXT_BOTTOM_WIDTH] = 0;
- color_buffer_bottom[i*TEXT_BOTTOM_WIDTH] = 0;
- }
- }
+ if (screen == framebuffers->top_left || screen == framebuffers->top_right) {
+ for (int i = 0; i < TEXT_TOP_HEIGHT; i++) {
+ text_buffer_top[i * TEXT_TOP_WIDTH] = 0;
+ color_buffer_top[i * TEXT_TOP_WIDTH] = 0;
+ }
+ } else if (screen == framebuffers->bottom) {
+ for (int i = 0; i < TEXT_BOTTOM_HEIGHT; i++) {
+ text_buffer_bottom[i * TEXT_BOTTOM_WIDTH] = 0;
+ color_buffer_bottom[i * TEXT_BOTTOM_WIDTH] = 0;
+ }
+ }
}
-void clear_screen(uint8_t* screen) {
- clear_disp(screen);
- clear_text(screen);
+void
+clear_screen(uint8_t* screen)
+{
+ clear_disp(screen);
+ clear_text(screen);
}
-void set_cursor(void* channel, unsigned int x, unsigned int y) {
- if (channel == TOP_SCREEN) {
+void
+set_cursor(void* channel, unsigned int x, unsigned int y)
+{
+ if (channel == TOP_SCREEN) {
top_cursor_x = x;
top_cursor_y = y;
- } else if (channel == BOTTOM_SCREEN) {
+ } else if (channel == BOTTOM_SCREEN) {
bottom_cursor_x = x;
bottom_cursor_y = y;
- }
+ }
}
-void clear_screens() {
+void
+clear_screens()
+{
clear_screen(framebuffers->top_left);
clear_screen(framebuffers->bottom);
}
-void draw_character(uint8_t* screen, const char character, const unsigned int buf_x, const unsigned int buf_y, const uint32_t color_fg, const uint32_t color_bg) {
+void
+draw_character(uint8_t* screen, const char character, const unsigned int buf_x,
+ const unsigned int buf_y, const uint32_t color_fg,
+ const uint32_t color_bg)
+{
if (!isprint(character))
return; // Don't output non-printables.
- _UNUSED int width = 0;
- int height = 0;
- if(screen == framebuffers->top_left ||
- screen == framebuffers->top_right) {
- width = SCREEN_TOP_WIDTH;
- height = SCREEN_TOP_HEIGHT;
- } else if(screen == framebuffers->bottom) {
- width = SCREEN_BOTTOM_WIDTH;
- height = SCREEN_BOTTOM_HEIGHT;
- } else {
- return; // Invalid buffer.
- }
+ _UNUSED int width = 0;
+ int height = 0;
+ if (screen == framebuffers->top_left || screen == framebuffers->top_right) {
+ width = SCREEN_TOP_WIDTH;
+ height = SCREEN_TOP_HEIGHT;
+ } else if (screen == framebuffers->bottom) {
+ width = SCREEN_BOTTOM_WIDTH;
+ height = SCREEN_BOTTOM_HEIGHT;
+ } else {
+ return; // Invalid buffer.
+ }
unsigned int pos_x = buf_x * 8;
unsigned int pos_y = buf_y * 8;
unsigned char char_pos = font[character * 8 + y];
for (int x = 7; x >= 0; x--) {
- int screen_pos = (pos_x * height * 3 + (height - y - pos_y - 1) * 3) + (7 - x) * 3 * height;
+ int screen_pos =
+ (pos_x * height * 3 + (height - y - pos_y - 1) * 3) +
+ (7 - x) * 3 * height;
- screen[screen_pos] = color_bg >> 16;
+ screen[screen_pos] = color_bg >> 16;
screen[screen_pos + 1] = color_bg >> 8;
screen[screen_pos + 2] = color_bg;
unsigned char color_bottom = 0xf0;
int kill_output = 0;
-void shut_up() {
- kill_output = !kill_output;
+void
+shut_up()
+{
+ kill_output = !kill_output;
}
-void putc(void* buf, const int c) {
+void
+putc(void* buf, const int c)
+{
if (buf == stdout || buf == stderr) {
- if (kill_output)
- return;
-
- unsigned int width = 0;
- _UNUSED unsigned int height = 0;
- unsigned int *cursor_x = NULL;
- unsigned int *cursor_y = NULL;
- char *colorbuf = NULL;
- char *strbuf = NULL;
-
- unsigned char* color = NULL;
-
- if (buf == TOP_SCREEN) {
- width = TEXT_TOP_WIDTH;
- height = TEXT_TOP_HEIGHT;
- colorbuf = color_buffer_top;
- strbuf = text_buffer_top;
- cursor_x = &top_cursor_x;
- cursor_y = &top_cursor_y;
- color = &color_top;
- } else if (buf == BOTTOM_SCREEN) {
- width = TEXT_BOTTOM_WIDTH;
- height = TEXT_BOTTOM_HEIGHT;
- colorbuf = color_buffer_bottom;
- strbuf = text_buffer_bottom;
- cursor_x = &bottom_cursor_x;
- cursor_y = &bottom_cursor_y;
- color = &color_bottom;
- }
-
- if (cursor_x[0] >= width) {
- cursor_x[0] = 0;
- cursor_y[0]++;
- }
-
- while (cursor_y[0] >= height) {
- // Scroll.
- for(unsigned int y=0; y < height-1; y++) {
- memset(&strbuf[y*width], 0, width);
- memset(&colorbuf[y*width], 0, width);
- strncpy(&strbuf[y*width], &strbuf[(y+1)*width], width);
- strncpy(&colorbuf[y*width], &colorbuf[(y+1)*width], width);
- }
- memset(&strbuf[(height-1)*width], 0, width);
- memset(&colorbuf[(height-1)*width], 0, width);
-
- cursor_y[0]--;
-
- clear_disp(buf); // Clear screen.
- }
-
- switch(c) {
- case '\n':
- strbuf[cursor_y[0]*width+cursor_x[0]] = 0;
- colorbuf[cursor_y[0]*width+cursor_x[0]] = 0;
- cursor_y[0]++;
- // Fall through intentional.
- case '\r':
- cursor_x[0] = 0; // Reset to beginning of line.
- break;
- default:
- strbuf[cursor_y[0]*width+cursor_x[0]] = c;
- colorbuf[cursor_y[0]*width+cursor_x[0]] = *color;
-
- if (cursor_x[0] + 1 < width) {
- strbuf[cursor_y[0]*width+cursor_x[0]+1] = 0; // Terminate.
- colorbuf[cursor_y[0]*width+cursor_x[0]+1] = 0;
- }
-
- cursor_x[0]++;
-
- break;
- }
- } else {
- // FILE*, not stdin or stdout.
- fwrite(&c, 1, 1, (FILE*)buf);
- }
+ if (kill_output)
+ return;
+
+ unsigned int width = 0;
+ _UNUSED unsigned int height = 0;
+ unsigned int* cursor_x = NULL;
+ unsigned int* cursor_y = NULL;
+ char* colorbuf = NULL;
+ char* strbuf = NULL;
+
+ unsigned char* color = NULL;
+
+ if (buf == TOP_SCREEN) {
+ width = TEXT_TOP_WIDTH;
+ height = TEXT_TOP_HEIGHT;
+ colorbuf = color_buffer_top;
+ strbuf = text_buffer_top;
+ cursor_x = &top_cursor_x;
+ cursor_y = &top_cursor_y;
+ color = &color_top;
+ } else if (buf == BOTTOM_SCREEN) {
+ width = TEXT_BOTTOM_WIDTH;
+ height = TEXT_BOTTOM_HEIGHT;
+ colorbuf = color_buffer_bottom;
+ strbuf = text_buffer_bottom;
+ cursor_x = &bottom_cursor_x;
+ cursor_y = &bottom_cursor_y;
+ color = &color_bottom;
+ }
+
+ if (cursor_x[0] >= width) {
+ cursor_x[0] = 0;
+ cursor_y[0]++;
+ }
+
+ while (cursor_y[0] >= height) {
+ // Scroll.
+ for (unsigned int y = 0; y < height - 1; y++) {
+ memset(&strbuf[y * width], 0, width);
+ memset(&colorbuf[y * width], 0, width);
+ strncpy(&strbuf[y * width], &strbuf[(y + 1) * width], width);
+ strncpy(&colorbuf[y * width], &colorbuf[(y + 1) * width],
+ width);
+ }
+ memset(&strbuf[(height - 1) * width], 0, width);
+ memset(&colorbuf[(height - 1) * width], 0, width);
+
+ cursor_y[0]--;
+
+ clear_disp(buf); // Clear screen.
+ }
+
+ switch (c) {
+ case '\n':
+ strbuf[cursor_y[0] * width + cursor_x[0]] = 0;
+ colorbuf[cursor_y[0] * width + cursor_x[0]] = 0;
+ cursor_y[0]++;
+ // Fall through intentional.
+ case '\r':
+ cursor_x[0] = 0; // Reset to beginning of line.
+ break;
+ default:
+ strbuf[cursor_y[0] * width + cursor_x[0]] = c;
+ colorbuf[cursor_y[0] * width + cursor_x[0]] = *color;
+
+ if (cursor_x[0] + 1 < width) {
+ strbuf[cursor_y[0] * width + cursor_x[0] + 1] =
+ 0; // Terminate.
+ colorbuf[cursor_y[0] * width + cursor_x[0] + 1] = 0;
+ }
+
+ cursor_x[0]++;
+
+ break;
+ }
+ } else {
+ // FILE*, not stdin or stdout.
+ fwrite(&c, 1, 1, (FILE*)buf);
+ }
}
-void puts(void* buf, const char *string) {
- char *ref = (char*)string;
+void
+puts(void* buf, const char* string)
+{
+ char* ref = (char*)string;
- while(*ref != '\0') {
+ while (*ref != '\0') {
putc(buf, *ref);
ref++;
}
}
-void put_int64(void* channel, int64_t n, int length) {
+void
+put_int64(void* channel, int64_t n, int length)
+{
char conv[32], out[32];
memset(conv, 0, 32);
memset(out, 0, 32);
conv[i] = n % 10;
conv[i] += '0';
++i;
- } while((n /= 10) != 0);
+ } while ((n /= 10) != 0);
if (sign)
conv[i++] = '-';
out[length] = '\0';
int len = strlen(conv);
- for(int i=0; i < len; i++)
- out[i] = conv[(len-1) - i];
+ for (int i = 0; i < len; i++)
+ out[i] = conv[(len - 1) - i];
puts(channel, out);
}
-void put_uint64(void* channel, uint64_t n, int length) {
+void
+put_uint64(void* channel, uint64_t n, int length)
+{
char conv[32], out[32];
memset(conv, 0, 32);
memset(out, 0, 32);
int i = 0;
do {
conv[i++] = (n % 10) + '0';
- } while((n /= 10) != 0);
+ } while ((n /= 10) != 0);
if (length > 0)
out[length] = '\0';
int len = strlen(conv);
- for(int i=0; i < len; i++)
- out[i] = conv[(len-1) - i];
+ for (int i = 0; i < len; i++)
+ out[i] = conv[(len - 1) - i];
puts(channel, out);
}
-void put_hexdump(void* channel, unsigned int num) {
- uint8_t* num_8 = (uint8_t*)#
- for(int i=3; i>=0; i--) {
- uint8_t high = (num_8[i] >> 4) & 0xf;
- uint8_t low = num_8[i] & 0xf;
+void
+put_hexdump(void* channel, unsigned int num)
+{
+ uint8_t* num_8 = (uint8_t*)#
+ for (int i = 3; i >= 0; i--) {
+ uint8_t high = (num_8[i] >> 4) & 0xf;
+ uint8_t low = num_8[i] & 0xf;
- putc(channel, ("0123456789abcdef")[high]);
- putc(channel, ("0123456789abcdef")[low]);
- }
+ putc(channel, ("0123456789abcdef")[high]);
+ putc(channel, ("0123456789abcdef")[low]);
+ }
}
-void put_uint(void* channel, unsigned int n, int length) {
+void
+put_uint(void* channel, unsigned int n, int length)
+{
put_uint64(channel, n, length);
}
-void put_int(void* channel, int n, int length) {
+void
+put_int(void* channel, int n, int length)
+{
put_int64(channel, n, length);
}
-void fflush(void* channel) {
+void
+fflush(void* channel)
+{
if (channel == TOP_SCREEN) {
- for(int y=0; y < TEXT_TOP_HEIGHT; y++) {
- for(int x=0; x < TEXT_TOP_WIDTH; x++) {
- char c = text_buffer_top[y*TEXT_TOP_WIDTH+x];
- if (c == 0)
- break;
- uint32_t color_fg = colors[((color_buffer_top[y*TEXT_TOP_WIDTH+x] >> 4) & 0x0f)];
- uint32_t color_bg = colors[(color_buffer_top[y*TEXT_TOP_WIDTH+x] & 0x0f)];
- draw_character(framebuffers->top_left, c, x, y, color_fg, color_bg);
- }
- }
+ for (int y = 0; y < TEXT_TOP_HEIGHT; y++) {
+ for (int x = 0; x < TEXT_TOP_WIDTH; x++) {
+ char c = text_buffer_top[y * TEXT_TOP_WIDTH + x];
+ if (c == 0)
+ break;
+ uint32_t color_fg = colors[(
+ (color_buffer_top[y * TEXT_TOP_WIDTH + x] >> 4) & 0x0f)];
+ uint32_t color_bg =
+ colors[(color_buffer_top[y * TEXT_TOP_WIDTH + x] & 0x0f)];
+ draw_character(framebuffers->top_left, c, x, y, color_fg,
+ color_bg);
+ }
+ }
} else if (channel == BOTTOM_SCREEN) {
- for(int y=0; y < TEXT_BOTTOM_HEIGHT; y++) {
- for(int x=0; x < TEXT_BOTTOM_WIDTH; x++) {
- char c = text_buffer_bottom[y*TEXT_BOTTOM_WIDTH+x];
- if (c == 0)
- break;
- uint32_t color_fg = colors[((color_buffer_bottom[y*TEXT_BOTTOM_WIDTH+x] >> 4) & 0x0f)];
- uint32_t color_bg = colors[(color_buffer_bottom[y*TEXT_BOTTOM_WIDTH+x] & 0x0f)];
- draw_character(framebuffers->bottom, c, x, y, color_fg, color_bg);
- }
- }
- } else {
- f_sync(&(((FILE*)channel)->handle)); // Sync to disk.
- }
+ for (int y = 0; y < TEXT_BOTTOM_HEIGHT; y++) {
+ for (int x = 0; x < TEXT_BOTTOM_WIDTH; x++) {
+ char c = text_buffer_bottom[y * TEXT_BOTTOM_WIDTH + x];
+ if (c == 0)
+ break;
+ uint32_t color_fg = colors[(
+ (color_buffer_bottom[y * TEXT_BOTTOM_WIDTH + x] >> 4) &
+ 0x0f)];
+ uint32_t color_bg = colors[(
+ color_buffer_bottom[y * TEXT_BOTTOM_WIDTH + x] & 0x0f)];
+ draw_character(framebuffers->bottom, c, x, y, color_fg,
+ color_bg);
+ }
+ }
+ } else {
+ f_sync(&(((FILE*)channel)->handle)); // Sync to disk.
+ }
}
-void vfprintf(void* channel, const char* format, va_list ap ) {
- char *ref = (char*)format;
-
- unsigned char* color;
- if (channel == TOP_SCREEN)
- color = &color_top;
- else if (channel == TOP_SCREEN)
- color = &color_bottom;
-
- while(*ref != '\0') {
- if (*ref == 0x1B && *(++ref) == '[' && ( channel == stdout || channel == stderr) ) {
-ansi_codes:
+void
+vfprintf(void* channel, const char* format, va_list ap)
+{
+ char* ref = (char*)format;
+
+ unsigned char* color;
+ if (channel == TOP_SCREEN)
+ color = &color_top;
+ else if (channel == TOP_SCREEN)
+ color = &color_bottom;
+
+ while (*ref != '\0') {
+ if (*ref == 0x1B && *(++ref) == '[' &&
+ (channel == stdout || channel == stderr)) {
+ ansi_codes:
// Ansi escape code.
++ref;
// [30-37] Set text color
if (*ref == '3') {
++ref;
- if(*ref >= '0' && *ref <= '7') {
+ if (*ref >= '0' && *ref <= '7') {
// Valid FG color.
*color &= 0x0f; // Remove fg color.
*color |= (*ref - '0') << 4;
// [40-47] Set bg color
else if (*ref == '4') {
++ref;
- if(*ref >= '0' && *ref <= '7') {
+ if (*ref >= '0' && *ref <= '7') {
// Valid BG color.
*color &= 0xf0; // Remove bg color.
*color |= *ref - '0';
}
} else if (*ref == '0') {
- // Reset.
- *color = 0xf0;
- }
+ // Reset.
+ *color = 0xf0;
+ }
++ref;
goto ansi_codes; // Another code.
}
- // Loop until the character is somewhere 0x40 - 0x7E, which terminates an ANSI sequence
- while(!(*ref >= 0x40 && *ref <= 0x7E)) ref++;
+ // Loop until the character is somewhere 0x40 - 0x7E, which
+ // terminates an ANSI sequence
+ while (!(*ref >= 0x40 && *ref <= 0x7E))
+ ref++;
} else if (*ref == '%') {
int type_size = 0;
int length = -1;
-check_format:
+ check_format:
// Format string.
++ref;
- switch(*ref) {
+ switch (*ref) {
case 'd':
- switch(type_size) {
+ switch (type_size) {
case 2:
- put_int64(channel, va_arg( ap, int64_t ), length);
+ put_int64(channel, va_arg(ap, int64_t), length);
break;
default:
- put_int(channel, va_arg( ap, int ), length);
+ put_int(channel, va_arg(ap, int), length);
break;
}
break;
case 'u':
- switch(type_size) {
+ switch (type_size) {
case 2:
- put_uint64(channel, va_arg( ap, uint64_t ), length);
+ put_uint64(channel, va_arg(ap, uint64_t), length);
break;
default:
- put_uint(channel, va_arg( ap, unsigned int ), length);
+ put_uint(channel, va_arg(ap, unsigned int), length);
break;
}
break;
case 's':
- puts(channel, va_arg( ap, char* ));
+ puts(channel, va_arg(ap, char*));
break;
case 'c':
- putc(channel, va_arg( ap, int ));
+ putc(channel, va_arg(ap, int));
break;
case 'p':
- puts(channel, va_arg( ap, char* ));
+ puts(channel, va_arg(ap, char*));
break;
case '%':
putc(channel, '%');
case 'l':
++type_size;
goto check_format;
- case 'x':
- put_hexdump(channel, va_arg( ap, unsigned int ));
- break;
+ case 'x':
+ put_hexdump(channel, va_arg(ap, unsigned int));
+ break;
default:
if (*ref >= '0' && *ref <= '9') {
length = *ref - '0';
fflush(channel);
}
-void fprintf(void* channel, const char* format, ...) {
+void
+fprintf(void* channel, const char* format, ...)
+{
va_list ap;
- va_start( ap, format );
+ va_start(ap, format);
- vfprintf( channel, format, ap );
+ vfprintf(channel, format, ap);
- va_end( ap );
+ va_end(ap);
}
#define SCREEN_DEPTH 3
#define SCREEN_TOP_SIZE (SCREEN_TOP_WIDTH * SCREEN_TOP_HEIGHT * SCREEN_DEPTH)
-#define SCREEN_BOTTOM_SIZE (SCREEN_BOTTOM_WIDTH * SCREEN_BOTTOM_HEIGHT * SCREEN_DEPTH)
+#define SCREEN_BOTTOM_SIZE \
+ (SCREEN_BOTTOM_WIDTH * SCREEN_BOTTOM_HEIGHT * SCREEN_DEPTH)
#define CHARA_HEIGHT 8
-#define CHARA_WIDTH 8
+#define CHARA_WIDTH 8
-#define TEXT_TOP_WIDTH (SCREEN_TOP_WIDTH / CHARA_WIDTH)
-#define TEXT_TOP_HEIGHT (SCREEN_TOP_HEIGHT / CHARA_HEIGHT)
+#define TEXT_TOP_WIDTH (SCREEN_TOP_WIDTH / CHARA_WIDTH)
+#define TEXT_TOP_HEIGHT (SCREEN_TOP_HEIGHT / CHARA_HEIGHT)
-#define TEXT_BOTTOM_WIDTH (SCREEN_BOTTOM_WIDTH / CHARA_WIDTH)
+#define TEXT_BOTTOM_WIDTH (SCREEN_BOTTOM_WIDTH / CHARA_WIDTH)
#define TEXT_BOTTOM_HEIGHT (SCREEN_BOTTOM_HEIGHT / CHARA_HEIGHT)
-#define TEXT_TOP_SIZE (TEXT_TOP_WIDTH * TEXT_TOP_HEIGHT)
+#define TEXT_TOP_SIZE (TEXT_TOP_WIDTH * TEXT_TOP_HEIGHT)
#define TEXT_BOTTOM_SIZE (TEXT_BOTTOM_WIDTH * TEXT_BOTTOM_HEIGHT)
-enum screen {
+enum screen
+{
screen_top_left,
screen_top_right,
screen_bottom
#include "unused.h"
-_UNUSED static struct framebuffers {
- uint8_t *top_left;
- uint8_t *top_right;
- uint8_t *bottom;
-} *framebuffers = (struct framebuffers *)0x23FFFE00;
+_UNUSED static struct framebuffers
+{
+ uint8_t* top_left;
+ uint8_t* top_right;
+ uint8_t* bottom;
+}* framebuffers = (struct framebuffers*)0x23FFFE00;
// This is marked unused since it occurs in all files.
-#define TOP_FB framebuffers->top_left
+#define TOP_FB framebuffers->top_left
#define BOTTOM_FB framebuffers->bottom
void clear_screen(uint8_t* screen);
void clear_screens();
-void draw_character(uint8_t* screen, const char character, const unsigned int pos_x, const unsigned int pos_y, const uint32_t color_fg, const uint32_t color_bg);
+void draw_character(uint8_t* screen, const char character,
+ const unsigned int pos_x, const unsigned int pos_y,
+ const uint32_t color_fg, const uint32_t color_bg);
-#define TOP_SCREEN ((void*)0)
+#define TOP_SCREEN ((void*)0)
#define BOTTOM_SCREEN ((void*)2)
#define stdout TOP_SCREEN
#define stderr BOTTOM_SCREEN
void putc(void* buf, const int c);
-void puts(void* buf, const char *string);
+void puts(void* buf, const char* string);
void fflush(void* channel);
void set_cursor(void* channel, unsigned int x, unsigned int y);
// %hh - byte (stub)
// %[0-9][0-9]
// Formats are also supported (but are subject to replacement)
-// %p - unsigned char, changes color of text (will be replaced with ANSI codes eventually)
+// %p - unsigned char, changes color of text (will be replaced with ANSI codes
+// eventually)
void fprintf(void* channel, const char* format, ...);
-#define BLACK 0
-#define BLUE 1
-#define GREEN 2
-#define CYAN 3
-#define RED 4
-#define MAGENTA 5
-#define BROWN 6
-#define GRAY 7
-#define D_GRAY 8
-#define B_BLUE 9
-#define B_GREEN 10
-#define B_CYAN 11
-#define B_RED 12
+#define BLACK 0
+#define BLUE 1
+#define GREEN 2
+#define CYAN 3
+#define RED 4
+#define MAGENTA 5
+#define BROWN 6
+#define GRAY 7
+#define D_GRAY 8
+#define B_BLUE 9
+#define B_GREEN 10
+#define B_CYAN 11
+#define B_RED 12
#define B_MAGENTA 13
-#define YELLOW 14
-#define WHITE 15
+#define YELLOW 14
+#define WHITE 15
#define COLOR(fg, bg) "\x1b[3" #fg ";4" #bg "m"
#define __STD_FONT_H
static const unsigned char font[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e,
- 0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e, 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00,
- 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x3c, 0x3c, 0x18, 0xff, 0xe7, 0x18, 0x3c, 0x00,
- 0x10, 0x38, 0x7c, 0xfe, 0xee, 0x10, 0x38, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00,
- 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00,
- 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0x0f, 0x07, 0x0f, 0x7d, 0xcc, 0xcc, 0xcc, 0x78,
- 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x08, 0x0c, 0x0a, 0x0a, 0x08, 0x78, 0xf0, 0x00,
- 0x18, 0x14, 0x1a, 0x16, 0x72, 0xe2, 0x0e, 0x1c, 0x10, 0x54, 0x38, 0xee, 0x38, 0x54, 0x10, 0x00,
- 0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00, 0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00,
- 0x18, 0x3c, 0x5a, 0x18, 0x5a, 0x3c, 0x18, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00,
- 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x00, 0x1c, 0x22, 0x38, 0x44, 0x44, 0x38, 0x88, 0x70,
- 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x00, 0x18, 0x3c, 0x5a, 0x18, 0x5a, 0x3c, 0x18, 0x7e,
- 0x18, 0x3c, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x5a, 0x3c, 0x18, 0x00,
- 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00,
- 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x24, 0x42, 0xff, 0x42, 0x24, 0x00, 0x00,
- 0x00, 0x10, 0x38, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x18, 0x00, 0x18, 0x00,
- 0x6c, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00,
- 0x10, 0x7c, 0xd0, 0x7c, 0x16, 0xfc, 0x10, 0x00, 0x00, 0x66, 0xac, 0xd8, 0x36, 0x6a, 0xcc, 0x00,
- 0x38, 0x4c, 0x38, 0x78, 0xce, 0xcc, 0x7a, 0x00, 0x30, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00, 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00,
- 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x10, 0x20, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x00,
- 0x7c, 0xce, 0xde, 0xf6, 0xe6, 0xe6, 0x7c, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x7e, 0x00,
- 0x7c, 0xc6, 0x06, 0x1c, 0x70, 0xc6, 0xfe, 0x00, 0x7c, 0xc6, 0x06, 0x3c, 0x06, 0xc6, 0x7c, 0x00,
- 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x1e, 0x00, 0xfe, 0xc0, 0xfc, 0x06, 0x06, 0xc6, 0x7c, 0x00,
- 0x7c, 0xc6, 0xc0, 0xfc, 0xc6, 0xc6, 0x7c, 0x00, 0xfe, 0xc6, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00,
- 0x7c, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0x7e, 0x06, 0xc6, 0x7c, 0x00,
- 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x10, 0x20,
- 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00,
- 0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x78, 0xcc, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00,
- 0x7c, 0x82, 0x9e, 0xa6, 0x9e, 0x80, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00,
- 0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00,
- 0xfc, 0x66, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00,
- 0xfe, 0x62, 0x68, 0x78, 0x68, 0x60, 0xf0, 0x00, 0x7c, 0xc6, 0xc6, 0xc0, 0xce, 0xc6, 0x7e, 0x00,
- 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00,
- 0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, 0xe6, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00,
- 0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x82, 0xc6, 0xee, 0xfe, 0xd6, 0xc6, 0xc6, 0x00,
- 0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00,
- 0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x06,
- 0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xe6, 0x00, 0x7c, 0xc6, 0xc0, 0x7c, 0x06, 0xc6, 0x7c, 0x00,
- 0x7e, 0x5a, 0x5a, 0x18, 0x18, 0x18, 0x3c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00,
- 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x82, 0x00,
- 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x00,
- 0xfe, 0xc6, 0x8c, 0x18, 0x32, 0x66, 0xfe, 0x00, 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00,
- 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00,
- 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
- 0x30, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00,
- 0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc6, 0x7c, 0x00,
- 0x1c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00,
- 0x1c, 0x36, 0x30, 0x78, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0x78,
- 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00,
- 0x00, 0x0c, 0x00, 0x1c, 0x0c, 0x0c, 0xcc, 0x78, 0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00,
- 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0xcc, 0xfe, 0xd6, 0xd6, 0xd6, 0x00,
- 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00,
- 0x00, 0x00, 0xdc, 0x66, 0x66, 0x7c, 0x60, 0xf0, 0x00, 0x00, 0x7c, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e,
- 0x00, 0x00, 0xde, 0x76, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x7c, 0xc0, 0x7c, 0x06, 0x7c, 0x00,
- 0x10, 0x30, 0xfc, 0x30, 0x30, 0x34, 0x18, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00,
- 0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00,
- 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8,
- 0x00, 0x00, 0xfc, 0x98, 0x30, 0x64, 0xfc, 0x00, 0x0e, 0x18, 0x18, 0x30, 0x18, 0x18, 0x0e, 0x00,
- 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, 0xe0, 0x30, 0x30, 0x18, 0x30, 0x30, 0xe0, 0x00,
- 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00,
- 0x7c, 0xc6, 0xc0, 0xc0, 0xc6, 0x7c, 0x18, 0x70, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00,
- 0x0e, 0x10, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00, 0x7c, 0x82, 0x38, 0x0c, 0x7c, 0xcc, 0x76, 0x00,
- 0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, 0xe0, 0x10, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00,
- 0x30, 0x30, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x7c, 0xc0, 0xc0, 0x7c, 0x18, 0x70,
- 0x7c, 0x82, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00,
- 0xe0, 0x10, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00,
- 0x7c, 0x82, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00, 0xe0, 0x10, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00,
- 0xc6, 0x00, 0x7c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x38, 0x38, 0x7c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00,
- 0x0e, 0x10, 0xfe, 0x60, 0x78, 0x60, 0xfe, 0x00, 0x00, 0x00, 0x7c, 0x12, 0x7e, 0xd0, 0x7e, 0x00,
- 0x7e, 0xc8, 0xc8, 0xfe, 0xc8, 0xc8, 0xce, 0x00, 0x7c, 0x82, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00,
- 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0xe0, 0x10, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00,
- 0x7c, 0x82, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0xe0, 0x10, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00,
- 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00,
- 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x18, 0x7c, 0xd6, 0xd0, 0xd6, 0x7c, 0x18, 0x00,
- 0x38, 0x6c, 0x60, 0xf0, 0x60, 0xf2, 0xdc, 0x00, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x00,
- 0xf8, 0xcc, 0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0x06, 0x0e, 0x1b, 0x18, 0x3c, 0x18, 0x18, 0xd8, 0x70,
- 0x0e, 0x10, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, 0x0e, 0x10, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00,
- 0x0e, 0x10, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x0e, 0x10, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00,
- 0x66, 0x98, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x98, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0x00,
- 0x38, 0x0c, 0x3c, 0x34, 0x00, 0x7e, 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00,
- 0x30, 0x00, 0x30, 0x60, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xc0, 0xc0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0c, 0x00, 0x00, 0xc0, 0xc8, 0xd0, 0xfe, 0x46, 0x8c, 0x1e, 0x00,
- 0xc0, 0xc8, 0xd0, 0xec, 0x5c, 0xbe, 0x0c, 0x00, 0x18, 0x00, 0x18, 0x18, 0x3c, 0x3c, 0x18, 0x00,
- 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00,
- 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
- 0xdb, 0x77, 0xdb, 0xee, 0xdb, 0x77, 0xdb, 0xee, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
- 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18,
- 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36,
- 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00,
- 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18,
- 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18,
- 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00,
- 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00,
- 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00,
- 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18,
- 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36,
- 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
- 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x74, 0xcc, 0xc8, 0xdc, 0x76, 0x00, 0x78, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xdc, 0x40,
- 0xfe, 0x62, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x02, 0x7e, 0xec, 0x6c, 0x6c, 0x48, 0x00,
- 0xfe, 0x62, 0x30, 0x18, 0x30, 0x62, 0xfe, 0x00, 0x00, 0x00, 0x7e, 0xd0, 0xc8, 0xc8, 0x70, 0x00,
- 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xf8, 0x80, 0x00, 0x00, 0x7e, 0xd8, 0x18, 0x18, 0x10, 0x00,
- 0x38, 0x10, 0x7c, 0xd6, 0xd6, 0x7c, 0x10, 0x38, 0x7c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x7c, 0x00,
- 0x7c, 0xc6, 0xc6, 0xc6, 0x6c, 0x28, 0xee, 0x00, 0x3c, 0x22, 0x18, 0x7c, 0xcc, 0xcc, 0x78, 0x00,
- 0x00, 0x00, 0x66, 0x99, 0x99, 0x66, 0x00, 0x00, 0x00, 0x06, 0x7c, 0x9e, 0xf2, 0x7c, 0xc0, 0x00,
- 0x00, 0x00, 0x7c, 0xc0, 0xf8, 0xc0, 0x7c, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00,
- 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x7e, 0x00,
- 0x30, 0x18, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0x00, 0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0x7c, 0x00,
- 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70,
- 0x00, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00,
- 0x38, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x00,
- 0xd8, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x30, 0xc0, 0xf0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81,
+ 0xbd, 0x99, 0x81, 0x7e, 0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e,
+ 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x10, 0x38, 0x7c, 0xfe,
+ 0x7c, 0x38, 0x10, 0x00, 0x3c, 0x3c, 0x18, 0xff, 0xe7, 0x18, 0x3c, 0x00,
+ 0x10, 0x38, 0x7c, 0xfe, 0xee, 0x10, 0x38, 0x00, 0x00, 0x00, 0x18, 0x3c,
+ 0x3c, 0x18, 0x00, 0x00, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff,
+ 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0xff, 0xc3, 0x99, 0xbd,
+ 0xbd, 0x99, 0xc3, 0xff, 0x0f, 0x07, 0x0f, 0x7d, 0xcc, 0xcc, 0xcc, 0x78,
+ 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x08, 0x0c, 0x0a, 0x0a,
+ 0x08, 0x78, 0xf0, 0x00, 0x18, 0x14, 0x1a, 0x16, 0x72, 0xe2, 0x0e, 0x1c,
+ 0x10, 0x54, 0x38, 0xee, 0x38, 0x54, 0x10, 0x00, 0x80, 0xe0, 0xf8, 0xfe,
+ 0xf8, 0xe0, 0x80, 0x00, 0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00,
+ 0x18, 0x3c, 0x5a, 0x18, 0x5a, 0x3c, 0x18, 0x00, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x00, 0x66, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x00,
+ 0x1c, 0x22, 0x38, 0x44, 0x44, 0x38, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00,
+ 0x7e, 0x7e, 0x7e, 0x00, 0x18, 0x3c, 0x5a, 0x18, 0x5a, 0x3c, 0x18, 0x7e,
+ 0x18, 0x3c, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18,
+ 0x5a, 0x3c, 0x18, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00,
+ 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
+ 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x24, 0x42, 0xff, 0x42, 0x24, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c,
+ 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x3c, 0x3c, 0x18, 0x18, 0x00, 0x18, 0x00, 0x6c, 0x24, 0x24, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00,
+ 0x10, 0x7c, 0xd0, 0x7c, 0x16, 0xfc, 0x10, 0x00, 0x00, 0x66, 0xac, 0xd8,
+ 0x36, 0x6a, 0xcc, 0x00, 0x38, 0x4c, 0x38, 0x78, 0xce, 0xcc, 0x7a, 0x00,
+ 0x30, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x60,
+ 0x60, 0x30, 0x18, 0x00, 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00,
+ 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x30, 0x30, 0xfc,
+ 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x10, 0x20,
+ 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x30, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x00,
+ 0x7c, 0xce, 0xde, 0xf6, 0xe6, 0xe6, 0x7c, 0x00, 0x18, 0x38, 0x78, 0x18,
+ 0x18, 0x18, 0x7e, 0x00, 0x7c, 0xc6, 0x06, 0x1c, 0x70, 0xc6, 0xfe, 0x00,
+ 0x7c, 0xc6, 0x06, 0x3c, 0x06, 0xc6, 0x7c, 0x00, 0x1c, 0x3c, 0x6c, 0xcc,
+ 0xfe, 0x0c, 0x1e, 0x00, 0xfe, 0xc0, 0xfc, 0x06, 0x06, 0xc6, 0x7c, 0x00,
+ 0x7c, 0xc6, 0xc0, 0xfc, 0xc6, 0xc6, 0x7c, 0x00, 0xfe, 0xc6, 0x0c, 0x18,
+ 0x30, 0x30, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0x7c, 0x00,
+ 0x7c, 0xc6, 0xc6, 0x7e, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x30, 0x00, 0x00,
+ 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x10, 0x20,
+ 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x7e, 0x00,
+ 0x00, 0x7e, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00,
+ 0x78, 0xcc, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00, 0x7c, 0x82, 0x9e, 0xa6,
+ 0x9e, 0x80, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00,
+ 0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x7c, 0xc6, 0xc0, 0xc0,
+ 0xc0, 0xc6, 0x7c, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00,
+ 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, 0xfe, 0x62, 0x68, 0x78,
+ 0x68, 0x60, 0xf0, 0x00, 0x7c, 0xc6, 0xc6, 0xc0, 0xce, 0xc6, 0x7e, 0x00,
+ 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x3c, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x3c, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00,
+ 0xe6, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0xf0, 0x60, 0x60, 0x60,
+ 0x62, 0x66, 0xfe, 0x00, 0x82, 0xc6, 0xee, 0xfe, 0xd6, 0xc6, 0xc6, 0x00,
+ 0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0x7c, 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00,
+ 0x7c, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x06, 0xfc, 0x66, 0x66, 0x7c,
+ 0x66, 0x66, 0xe6, 0x00, 0x7c, 0xc6, 0xc0, 0x7c, 0x06, 0xc6, 0x7c, 0x00,
+ 0x7e, 0x5a, 0x5a, 0x18, 0x18, 0x18, 0x3c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0x7c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00,
+ 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x82, 0x00, 0xc6, 0x6c, 0x38, 0x38,
+ 0x38, 0x6c, 0xc6, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x00,
+ 0xfe, 0xc6, 0x8c, 0x18, 0x32, 0x66, 0xfe, 0x00, 0x78, 0x60, 0x60, 0x60,
+ 0x60, 0x60, 0x78, 0x00, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00,
+ 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00, 0x10, 0x38, 0x6c, 0xc6,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+ 0x30, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c,
+ 0x7c, 0xcc, 0x76, 0x00, 0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x7c, 0x00,
+ 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc6, 0x7c, 0x00, 0x1c, 0x0c, 0x0c, 0x7c,
+ 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00,
+ 0x1c, 0x36, 0x30, 0x78, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x76, 0xcc,
+ 0xcc, 0x7c, 0x0c, 0x78, 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00,
+ 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x0c, 0x00, 0x1c,
+ 0x0c, 0x0c, 0xcc, 0x78, 0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00,
+ 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0xcc, 0xfe,
+ 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x00,
+ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0xdc, 0x66,
+ 0x66, 0x7c, 0x60, 0xf0, 0x00, 0x00, 0x7c, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e,
+ 0x00, 0x00, 0xde, 0x76, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x7c, 0xc0,
+ 0x7c, 0x06, 0x7c, 0x00, 0x10, 0x30, 0xfc, 0x30, 0x30, 0x34, 0x18, 0x00,
+ 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0xc6, 0xc6,
+ 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00,
+ 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0xcc, 0xcc,
+ 0xcc, 0x7c, 0x0c, 0xf8, 0x00, 0x00, 0xfc, 0x98, 0x30, 0x64, 0xfc, 0x00,
+ 0x0e, 0x18, 0x18, 0x30, 0x18, 0x18, 0x0e, 0x00, 0x18, 0x18, 0x18, 0x00,
+ 0x18, 0x18, 0x18, 0x00, 0xe0, 0x30, 0x30, 0x18, 0x30, 0x30, 0xe0, 0x00,
+ 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c,
+ 0xc6, 0xc6, 0xfe, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc6, 0x7c, 0x18, 0x70,
+ 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x0e, 0x10, 0x7c, 0xc6,
+ 0xfe, 0xc0, 0x7c, 0x00, 0x7c, 0x82, 0x38, 0x0c, 0x7c, 0xcc, 0x76, 0x00,
+ 0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, 0xe0, 0x10, 0x78, 0x0c,
+ 0x7c, 0xcc, 0x76, 0x00, 0x30, 0x30, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00,
+ 0x00, 0x00, 0x7c, 0xc0, 0xc0, 0x7c, 0x18, 0x70, 0x7c, 0x82, 0x7c, 0xc6,
+ 0xfe, 0xc0, 0x7c, 0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00,
+ 0xe0, 0x10, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00, 0x66, 0x00, 0x38, 0x18,
+ 0x18, 0x18, 0x3c, 0x00, 0x7c, 0x82, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00,
+ 0xe0, 0x10, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00, 0xc6, 0x00, 0x7c, 0xc6,
+ 0xfe, 0xc6, 0xc6, 0x00, 0x38, 0x38, 0x7c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00,
+ 0x0e, 0x10, 0xfe, 0x60, 0x78, 0x60, 0xfe, 0x00, 0x00, 0x00, 0x7c, 0x12,
+ 0x7e, 0xd0, 0x7e, 0x00, 0x7e, 0xc8, 0xc8, 0xfe, 0xc8, 0xc8, 0xce, 0x00,
+ 0x7c, 0x82, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0xc6, 0x00, 0x7c, 0xc6,
+ 0xc6, 0xc6, 0x7c, 0x00, 0xe0, 0x10, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00,
+ 0x7c, 0x82, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0xe0, 0x10, 0xcc, 0xcc,
+ 0xcc, 0xcc, 0x76, 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8,
+ 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0xc6, 0x00, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0x7c, 0x00, 0x18, 0x7c, 0xd6, 0xd0, 0xd6, 0x7c, 0x18, 0x00,
+ 0x38, 0x6c, 0x60, 0xf0, 0x60, 0xf2, 0xdc, 0x00, 0x66, 0x3c, 0x18, 0x7e,
+ 0x18, 0x7e, 0x18, 0x00, 0xf8, 0xcc, 0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0x06,
+ 0x0e, 0x1b, 0x18, 0x3c, 0x18, 0x18, 0xd8, 0x70, 0x0e, 0x10, 0x78, 0x0c,
+ 0x7c, 0xcc, 0x76, 0x00, 0x0e, 0x10, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00,
+ 0x0e, 0x10, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x0e, 0x10, 0xcc, 0xcc,
+ 0xcc, 0xcc, 0x76, 0x00, 0x66, 0x98, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x00,
+ 0x66, 0x98, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0x00, 0x38, 0x0c, 0x3c, 0x34,
+ 0x00, 0x7e, 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00,
+ 0x30, 0x00, 0x30, 0x60, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0xfc,
+ 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0c, 0x00, 0x00,
+ 0xc0, 0xc8, 0xd0, 0xfe, 0x46, 0x8c, 0x1e, 0x00, 0xc0, 0xc8, 0xd0, 0xec,
+ 0x5c, 0xbe, 0x0c, 0x00, 0x18, 0x00, 0x18, 0x18, 0x3c, 0x3c, 0x18, 0x00,
+ 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36,
+ 0x6c, 0xd8, 0x00, 0x00, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88,
+ 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0xdb, 0x77, 0xdb, 0xee,
+ 0xdb, 0x77, 0xdb, 0xee, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18,
+ 0xf8, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36,
+ 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x00, 0x00, 0xf8, 0x18,
+ 0xf8, 0x18, 0x18, 0x18, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0xfe, 0x06,
+ 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00,
+ 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x18, 0x18, 0xf8, 0x18,
+ 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36,
+ 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x00, 0x00, 0xff, 0x00,
+ 0xff, 0x00, 0x00, 0x00, 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36,
+ 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x3f, 0x00, 0x00, 0x00, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36,
+ 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0xcc, 0xc8, 0xdc, 0x76, 0x00,
+ 0x78, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xdc, 0x40, 0xfe, 0x62, 0x60, 0x60,
+ 0x60, 0x60, 0xf0, 0x00, 0x00, 0x02, 0x7e, 0xec, 0x6c, 0x6c, 0x48, 0x00,
+ 0xfe, 0x62, 0x30, 0x18, 0x30, 0x62, 0xfe, 0x00, 0x00, 0x00, 0x7e, 0xd0,
+ 0xc8, 0xc8, 0x70, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xf8, 0x80,
+ 0x00, 0x00, 0x7e, 0xd8, 0x18, 0x18, 0x10, 0x00, 0x38, 0x10, 0x7c, 0xd6,
+ 0xd6, 0x7c, 0x10, 0x38, 0x7c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x7c, 0x00,
+ 0x7c, 0xc6, 0xc6, 0xc6, 0x6c, 0x28, 0xee, 0x00, 0x3c, 0x22, 0x18, 0x7c,
+ 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x66, 0x99, 0x99, 0x66, 0x00, 0x00,
+ 0x00, 0x06, 0x7c, 0x9e, 0xf2, 0x7c, 0xc0, 0x00, 0x00, 0x00, 0x7c, 0xc0,
+ 0xf8, 0xc0, 0x7c, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00,
+ 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18,
+ 0x18, 0x00, 0x7e, 0x00, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0x00,
+ 0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0x7c, 0x00, 0x0e, 0x1b, 0x1b, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70,
+ 0x00, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00,
+ 0x76, 0xdc, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x00,
+ 0xd8, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x30, 0xc0, 0xf0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static FILE files[MAX_FILES_OPEN];
-int fmount(void) {
+int
+fmount(void)
+{
if (f_mount(&fs, "0:", 1))
return 1;
- for(int i=0; i < MAX_FILES_OPEN; i++)
+ for (int i = 0; i < MAX_FILES_OPEN; i++)
memset(&files[i], 0, sizeof(FILE));
return 0;
}
-int fumount(void) {
- for(int i=0; i < MAX_FILES_OPEN; i++)
+int
+fumount(void)
+{
+ for (int i = 0; i < MAX_FILES_OPEN; i++)
if (files[i].is_open)
fclose(&files[i]);
return 0;
}
-FILE* fopen(const char *filename, const char *mode) {
+FILE*
+fopen(const char* filename, const char* mode)
+{
if (*mode != 'r' && *mode != 'w' && *mode != 'a')
return NULL; // Mode not valid.
FILE* fp;
int i;
- for(i=0; i < MAX_FILES_OPEN; i++) {
- if(!files[i].is_open) {
- fp = &files[i];
- break;
+ for (i = 0; i < MAX_FILES_OPEN; i++) {
+ if (!files[i].is_open) {
+ fp = &files[i];
+ break;
}
}
if (i == MAX_FILES_OPEN)
return NULL; // Out of handles.
- fp->mode = (*mode == 'r' ? FA_READ : (FA_WRITE | FA_OPEN_ALWAYS));
+ fp->mode = (*mode == 'r' ? FA_READ : (FA_WRITE | FA_OPEN_ALWAYS));
if (f_open(&(fp->handle), filename, fp->mode))
return NULL;
return fp;
}
-void fclose(FILE* fp) {
+void
+fclose(FILE* fp)
+{
f_close(&(fp->handle));
memset(fp, 0, sizeof(FILE));
}
-void fseek(FILE* fp, int64_t offset, int whence) {
- uint32_t fixed_offset;
- switch(whence) {
- case SEEK_SET:
- fixed_offset = 0;
- break;
- case SEEK_CUR:
- fixed_offset = ftell(fp);
- break;
- case SEEK_END:
- fixed_offset = fsize(fp);
- break;
- default:
- return;
- }
-
- f_lseek(&(fp->handle), fixed_offset+offset);
+void
+fseek(FILE* fp, int64_t offset, int whence)
+{
+ uint32_t fixed_offset;
+ switch (whence) {
+ case SEEK_SET:
+ fixed_offset = 0;
+ break;
+ case SEEK_CUR:
+ fixed_offset = ftell(fp);
+ break;
+ case SEEK_END:
+ fixed_offset = fsize(fp);
+ break;
+ default:
+ return;
+ }
+
+ f_lseek(&(fp->handle), fixed_offset + offset);
}
-size_t ftell(FILE* fp) {
- return f_tell(&(fp->handle));
+size_t
+ftell(FILE* fp)
+{
+ return f_tell(&(fp->handle));
}
-int feof(FILE* fp) {
+int
+feof(FILE* fp)
+{
return f_eof(&(fp->handle));
}
-size_t fsize(FILE* fp) {
+size_t
+fsize(FILE* fp)
+{
return f_size(&(fp->handle));
}
-size_t fwrite(const void *buffer, size_t elementSize, size_t elementCnt, FILE* fp) {
+size_t
+fwrite(const void* buffer, size_t elementSize, size_t elementCnt, FILE* fp)
+{
UINT br;
- if(f_write(&(fp->handle), buffer, elementSize*elementCnt, &br)) return 0;
- if (br == elementSize*elementCnt) br /= elementSize; else return 0;
+ if (f_write(&(fp->handle), buffer, elementSize * elementCnt, &br))
+ return 0;
+ if (br == elementSize * elementCnt)
+ br /= elementSize;
+ else
+ return 0;
return br;
}
-size_t fread(void *buffer, size_t elementSize, size_t elementCnt, FILE* fp) {
+size_t
+fread(void* buffer, size_t elementSize, size_t elementCnt, FILE* fp)
+{
UINT br;
- if(f_read(&(fp->handle), buffer, elementSize*elementCnt, &br))
+ if (f_read(&(fp->handle), buffer, elementSize * elementCnt, &br))
return 0;
- if (br == elementSize*elementCnt)
+ if (br == elementSize * elementCnt)
br /= elementSize;
else
return 0;
return br;
}
-size_t write_file(void* data, char* path, size_t size) {
+size_t
+write_file(void* data, char* path, size_t size)
+{
FILE* temp = fopen(path, "w");
if (!temp)
return wrote;
}
-size_t read_file(void* data, char* path, size_t size) {
+size_t
+read_file(void* data, char* path, size_t size)
+{
FILE* temp = fopen(path, "r");
if (!temp)
#define MAX_FILES_OPEN 64
-typedef struct {
- FIL handle;
- uint32_t mode;
- size_t size;
- size_t at;
+typedef struct
+{
+ FIL handle;
+ uint32_t mode;
+ size_t size;
+ size_t at;
uint8_t is_open;
} __attribute__((packed)) FILE;
#define SEEK_CUR 1
#define SEEK_END 2
-int fmount (void);
-int fumount (void);
+int fmount(void);
+int fumount(void);
-FILE* fopen (const char *filename, const char *mode);
+FILE* fopen(const char* filename, const char* mode);
-void fclose (FILE* fp);
+void fclose(FILE* fp);
-void fseek (FILE* fp, int64_t offset, int whence);
+void fseek(FILE* fp, int64_t offset, int whence);
-size_t ftell (FILE* fp);
+size_t ftell(FILE* fp);
-int feof (FILE* fp);
+int feof(FILE* fp);
-size_t fsize (FILE* fp);
-
-size_t fwrite (const void *buffer, size_t elementSize, size_t elementCnt, FILE* fp);
-size_t fread (void *buffer, size_t elementSize, size_t elementCnt, FILE* fp);
+size_t fsize(FILE* fp);
+size_t fwrite(const void* buffer, size_t elementSize, size_t elementCnt,
+ FILE* fp);
+size_t fread(void* buffer, size_t elementSize, size_t elementCnt, FILE* fp);
size_t write_file(void* data, char* path, size_t size);
size_t read_file(void* data, char* path, size_t size);
#include <stdint.h>
#include <stddef.h>
-int strlen(const char *string)
+int
+strlen(const char* string)
{
- char *string_end = (char *)string;
- while (*string_end) string_end++;
+ char* string_end = (char*)string;
+ while (*string_end)
+ string_end++;
return string_end - string;
}
-int isprint(char c) {
- if (c >= 32 && c <= 127)
+int
+isprint(char c)
+{
+ if (c >= 32 && c <= 127)
return 1;
return 0;
}
-void memcpy(void *dest, const void *src, size_t size)
+void
+memcpy(void* dest, const void* src, size_t size)
{
- char *destc = (char *)dest;
- const char *srcc = (const char *)src;
+ char* destc = (char*)dest;
+ const char* srcc = (const char*)src;
// If we can align both dest and src together...
if ((uintptr_t)srcc % sizeof(size_t) == (uintptr_t)destc % sizeof(size_t)) {
}
for (; size >= sizeof(size_t); size -= sizeof(size_t),
- destc += sizeof(size_t), srcc += sizeof(size_t)) {
- *(size_t *)destc = *(size_t *)srcc;
+ destc += sizeof(size_t),
+ srcc += sizeof(size_t)) {
+ *(size_t*)destc = *(size_t*)srcc;
}
}
}
}
-void memmove(void *dest, const void *src, size_t size)
+void
+memmove(void* dest, const void* src, size_t size)
{
// memcpy does the job of moving backwards just fine
if (dest < src || src + size <= dest) {
}
// Moving forward is just a reverse memcpy
- char *destc = (char *)dest;
- const char *srcc = (const char *)src;
+ char* destc = (char*)dest;
+ const char* srcc = (const char*)src;
// If we can align both dest and src together...
if ((uintptr_t)srcc % sizeof(size_t) == (uintptr_t)destc % sizeof(size_t)) {
while (size >= sizeof(size_t)) {
size -= sizeof(size_t);
- *(size_t *)(destc + size) = *(size_t *)(srcc + size);
+ *(size_t*)(destc + size) = *(size_t*)(srcc + size);
}
}
}
}
-void memset(void *dest, const int filler, size_t size)
+void
+memset(void* dest, const int filler, size_t size)
{
- char *destc = (char *)dest;
+ char* destc = (char*)dest;
// Align dest to 4 bytes
while ((uintptr_t)destc % sizeof(size_t) && size--) {
}
// Set 32 bytes at a time
- for (; size >= sizeof(size_t); size -= sizeof(size_t), destc += sizeof(size_t)) {
- *(size_t *)destc = filler;
+ for (; size >= sizeof(size_t);
+ size -= sizeof(size_t), destc += sizeof(size_t)) {
+ *(size_t*)destc = filler;
}
// Finish
}
}
-int memcmp(const void *buf1, const void *buf2, const size_t size)
+int
+memcmp(const void* buf1, const void* buf2, const size_t size)
{
- const char *buf1c = (const char *)buf1;
- const char *buf2c = (const char *)buf2;
+ const char* buf1c = (const char*)buf1;
+ const char* buf2c = (const char*)buf2;
for (size_t i = 0; i < size; i++) {
int cmp = buf1c[i] - buf2c[i];
if (cmp) {
return 0;
}
-void strncpy(void *dest, const void *src, const size_t size)
+void
+strncpy(void* dest, const void* src, const size_t size)
{
- char *destc = (char *)dest;
- const char *srcc = (const char *)src;
+ char* destc = (char*)dest;
+ const char* srcc = (const char*)src;
size_t i;
for (i = 0; i < size && srcc[i] != 0; i++) {
destc[i] = 0;
}
-int strncmp(const void *buf1, const void *buf2, const size_t size)
+int
+strncmp(const void* buf1, const void* buf2, const size_t size)
{
- const char *buf1c = (const char *)buf1;
- const char *buf2c = (const char *)buf2;
+ const char* buf1c = (const char*)buf1;
+ const char* buf2c = (const char*)buf2;
size_t i;
for (i = 0; i < size && buf1c[i] != 0 && buf2c[i] != 0; i++) {
return 0;
}
-int atoi(const char *str)
+int
+atoi(const char* str)
{
int res = 0;
while (*str && *str >= '0' && *str <= '9') {
- res = *str - '0' + res * 10;
+ res = *str - '0' + res * 10;
str++;
}
#define NOT_FOUND patlen
#define max(a, b) ((a < b) ? b : a)
-void make_delta1(int *delta1, uint8_t *pat, int32_t patlen) {
+void
+make_delta1(int* delta1, uint8_t* pat, int32_t patlen)
+{
int i;
- for (i=0; i < ALPHABET_LEN; i++) {
+ for (i = 0; i < ALPHABET_LEN; i++) {
delta1[i] = NOT_FOUND;
}
- for (i=0; i < patlen-1; i++) {
- delta1[pat[i]] = patlen-1 - i;
+ for (i = 0; i < patlen - 1; i++) {
+ delta1[pat[i]] = patlen - 1 - i;
}
}
-int is_prefix(uint8_t *word, int wordlen, int pos) {
+int
+is_prefix(uint8_t* word, int wordlen, int pos)
+{
int i;
int suffixlen = wordlen - pos;
// could also use the strncmp() library function here
for (i = 0; i < suffixlen; i++) {
- if (word[i] != word[pos+i]) {
+ if (word[i] != word[pos + i]) {
return 0;
}
}
return 1;
}
-int suffix_length(uint8_t *word, int wordlen, int pos) {
+int
+suffix_length(uint8_t* word, int wordlen, int pos)
+{
int i;
// increment suffix length i to the first mismatch or beginning
// of the word
- for (i = 0; (word[pos-i] == word[wordlen-1-i]) && (i < pos); i++);
+ for (i = 0; (word[pos - i] == word[wordlen - 1 - i]) && (i < pos); i++)
+ ;
return i;
}
-void make_delta2(int *delta2, uint8_t *pat, int32_t patlen) {
+void
+make_delta2(int* delta2, uint8_t* pat, int32_t patlen)
+{
int p;
- int last_prefix_index = patlen-1;
+ int last_prefix_index = patlen - 1;
// first loop
- for (p=patlen-1; p>=0; p--) {
- if (is_prefix(pat, patlen, p+1)) {
- last_prefix_index = p+1;
+ for (p = patlen - 1; p >= 0; p--) {
+ if (is_prefix(pat, patlen, p + 1)) {
+ last_prefix_index = p + 1;
}
- delta2[p] = last_prefix_index + (patlen-1 - p);
+ delta2[p] = last_prefix_index + (patlen - 1 - p);
}
// second loop
- for (p=0; p < patlen-1; p++) {
+ for (p = 0; p < patlen - 1; p++) {
int slen = suffix_length(pat, patlen, p);
- if (pat[p - slen] != pat[patlen-1 - slen]) {
- delta2[patlen-1 - slen] = patlen-1 - p + slen;
+ if (pat[p - slen] != pat[patlen - 1 - slen]) {
+ delta2[patlen - 1 - slen] = patlen - 1 - p + slen;
}
}
}
-uint8_t* memfind (uint8_t *string, uint32_t stringlen, uint8_t *pat, uint32_t patlen) {
+uint8_t*
+memfind(uint8_t* string, uint32_t stringlen, uint8_t* pat, uint32_t patlen)
+{
uint32_t i;
int delta1[ALPHABET_LEN];
int delta2[ALPHABET_LEN]; // Max search length is 256.
make_delta2(delta2, pat, patlen);
// The empty pattern must be considered specially
- if (patlen == 0) return string;
+ if (patlen == 0)
+ return string;
- i = patlen-1;
+ i = patlen - 1;
while (i < stringlen) {
- int j = patlen-1;
+ int j = patlen - 1;
while (j >= 0 && (string[i] == pat[j])) {
--i;
--j;
}
if (j < 0) {
- return (string + i+1);
+ return (string + i + 1);
}
i += max(delta1[string[i]], delta2[j]);
#include <stdint.h>
#include <stddef.h>
-int strlen(const char *string);
-void memcpy(void *dest, const void *src, size_t size);
-void memmove(void *dest, const void *src, size_t size);
-void memset(void *dest, const int filler, size_t size);
-int memcmp(const void *buf1, const void *buf2, const size_t size);
-void strncpy(void *dest, const void *src, const size_t size);
-int strncmp(const void *buf1, const void *buf2, const size_t size);
-int atoi(const char *str);
-uint8_t* memfind (uint8_t *string, uint32_t stringlen, uint8_t *pat, uint32_t patlen);
+int strlen(const char* string);
+void memcpy(void* dest, const void* src, size_t size);
+void memmove(void* dest, const void* src, size_t size);
+void memset(void* dest, const int filler, size_t size);
+int memcmp(const void* buf1, const void* buf2, const size_t size);
+void strncpy(void* dest, const void* src, const size_t size);
+int strncmp(const void* buf1, const void* buf2, const size_t size);
+int atoi(const char* str);
+uint8_t* memfind(uint8_t* string, uint32_t stringlen, uint8_t* pat,
+ uint32_t patlen);
int isprint(char c);
#endif
#include <stdint.h>
#include <stdlib.h>
-#define CFG_BOOTENV *(volatile uint32_t *)0x10010000
-#define HID ~*(volatile uint32_t *)0x10146000
+#define CFG_BOOTENV *(volatile uint32_t*)0x10010000
+#define HID ~*(volatile uint32_t*)0x10146000
#define PDN_MPCORE_CFG *(uint8_t*)0x10140FFC
#endif