First commit of the AuReiNand rewrite!
- Gotten rid of the patched FIRMs, AuReiNand now finds and loads all the FIRMs from CTRNAND by default. If you are booting an emuNAND, the FIRMs will be loaded from its CTRNAND. This also applies to AGB and TWL FIRM, and allows for a very fast boot with no firmware files on the SD card. - If for some reason (like using NTR) you do not want to use the CTRNAND FIRM, you can place a firmware.bin in the aurei folder and it will be loaded just for the default NAND. - The way AuReiNand works has changed. Now you can specify to autoboot SysNAND or not, and a NAND is no more tied to a FIRM (since 9.0 FIRM is autodetected). If you press nothing the default NAND is booted with its own FIRM, L boots the non-default NAND with its own FIRM, R boots EmuNAND with the SysNAND FIRM if you picked "Updated SysNAND", and vice-versa. - In order for AuReiNand to handle FIRM reboots, the .bin path needs to be hardcoded in the program. The default is /arm9loaderhax.bin (the AuReiNand.dat is also supported for 9.0 people). A PC tool was written to make changing the path easier. - Bug fixes and stuff I forgot. - Gelex is a saint.
This commit is contained in:
parent
4180261f1f
commit
7dbded99a2
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,6 +1,7 @@
|
|||||||
out
|
out
|
||||||
build
|
build
|
||||||
loader/build
|
loader/build
|
||||||
|
screeninit/build
|
||||||
injector/build
|
injector/build
|
||||||
*.bin
|
*.bin
|
||||||
*.3dsx
|
*.3dsx
|
||||||
|
10
Makefile
10
Makefile
@ -42,6 +42,9 @@ ninjhax: $(dir_out)/3ds/$(name)
|
|||||||
.PHONY: release
|
.PHONY: release
|
||||||
release: $(dir_out)/$(name).zip
|
release: $(dir_out)/$(name).zip
|
||||||
|
|
||||||
|
.PHONY: pathchanger
|
||||||
|
pathchanger: $(dir_out)/pathchanger
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
@$(MAKE) $(FLAGS) -C $(dir_mset) clean
|
@$(MAKE) $(FLAGS) -C $(dir_mset) clean
|
||||||
@ -54,6 +57,9 @@ clean:
|
|||||||
$(dir_out):
|
$(dir_out):
|
||||||
@mkdir -p "$(dir_out)/aurei/payloads"
|
@mkdir -p "$(dir_out)/aurei/payloads"
|
||||||
|
|
||||||
|
$(dir_out)/pathchanger: $(dir_out)
|
||||||
|
@cc pathchanger/pathchanger.c -o out/pathchanger
|
||||||
|
|
||||||
$(dir_out)/$(name).dat: $(dir_build)/main.bin $(dir_out)
|
$(dir_out)/$(name).dat: $(dir_build)/main.bin $(dir_out)
|
||||||
@$(MAKE) $(FLAGS) -C $(dir_mset) launcher
|
@$(MAKE) $(FLAGS) -C $(dir_mset) launcher
|
||||||
@dd if=$(dir_build)/main.bin of=$@ bs=512 seek=144
|
@dd if=$(dir_build)/main.bin of=$@ bs=512 seek=144
|
||||||
@ -108,9 +114,9 @@ $(dir_build)/%.o: $(dir_source)/%.s
|
|||||||
|
|
||||||
$(dir_build)/fatfs/%.o: $(dir_source)/fatfs/%.c
|
$(dir_build)/fatfs/%.o: $(dir_source)/fatfs/%.c
|
||||||
@mkdir -p "$(@D)"
|
@mkdir -p "$(@D)"
|
||||||
$(COMPILE.c) -mthumb -mthumb-interwork -Wno-unused-function $(OUTPUT_OPTION) $<
|
$(COMPILE.c) -Wno-unused-function $(OUTPUT_OPTION) $<
|
||||||
|
|
||||||
$(dir_build)/fatfs/%.o: $(dir_source)/fatfs/%.s
|
$(dir_build)/fatfs/%.o: $(dir_source)/fatfs/%.s
|
||||||
@mkdir -p "$(@D)"
|
@mkdir -p "$(@D)"
|
||||||
$(COMPILE.s) -mthumb -mthumb-interwork $(OUTPUT_OPTION) $<
|
$(COMPILE.s) $(OUTPUT_OPTION) $<
|
||||||
include $(call rwildcard, $(dir_build), *.d)
|
include $(call rwildcard, $(dir_build), *.d)
|
||||||
|
@ -187,18 +187,18 @@ void patchCode(u64 progId, u8 *code, u32 size)
|
|||||||
case 0x0004001000027000LL: // KOR MSET
|
case 0x0004001000027000LL: // KOR MSET
|
||||||
case 0x0004001000028000LL: // TWN MSET
|
case 0x0004001000028000LL: // TWN MSET
|
||||||
{
|
{
|
||||||
if(R_SUCCEEDED(loadConfig()) && ((config >> 5) & 1))
|
if(R_SUCCEEDED(loadConfig()) && ((config >> 4) & 1))
|
||||||
{
|
{
|
||||||
static const u16 verPattern[] = u"Ver.";
|
static const u16 verPattern[] = u"Ver.";
|
||||||
const u32 currentFirm = ((config >> 12) & 1);
|
const u32 currentNand = ((config >> 16) & 3);
|
||||||
const u32 currentNand = ((config >> 13) & 3);
|
const u32 matchingFirm = ((config >> 18) & 1) == (currentNand != 0);
|
||||||
|
|
||||||
//Patch Ver. string
|
//Patch Ver. string
|
||||||
patchMemory(code, size,
|
patchMemory(code, size,
|
||||||
verPattern,
|
verPattern,
|
||||||
sizeof(verPattern) - sizeof(u16), 0,
|
sizeof(verPattern) - sizeof(u16), 0,
|
||||||
currentNand ? ((currentNand == 1) ? ((currentFirm == 1) ? u" Emu" : u"Emu9") : u"Emu2") :
|
!currentNand ? ((matchingFirm) ? u" Sys" : u"SysA") :
|
||||||
((currentFirm == 1) ? u" Sys" : u"Sys9"),
|
((currentNand == 1) ? (matchingFirm ? u" Emu" : u"EmuA") : ((matchingFirm) ? u"Emu2" : u"Em2A")),
|
||||||
sizeof(verPattern) - sizeof(u16), 1
|
sizeof(verPattern) - sizeof(u16), 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
128
patches/reboot.s
128
patches/reboot.s
@ -1,7 +1,7 @@
|
|||||||
.arm.little
|
.arm.little
|
||||||
|
|
||||||
firm_addr equ 0x24000000 ; Temporary location where we'll load the FIRM to
|
payload_addr equ 0x23F00000 ; Brahma payload address.
|
||||||
firm_maxsize equ 0x200000 ; Random value that's bigger than any of the currently known firm's sizes.
|
payload_maxsize equ 0x20000 ; Maximum size for the payload (200 KB will do).
|
||||||
|
|
||||||
.create "reboot.bin", 0
|
.create "reboot.bin", 0
|
||||||
.arm
|
.arm
|
||||||
@ -21,80 +21,43 @@ firm_maxsize equ 0x200000 ; Random value that's bigger than any of the currentl
|
|||||||
cmp r0, r2
|
cmp r0, r2
|
||||||
bne pxi_wait_recv
|
bne pxi_wait_recv
|
||||||
|
|
||||||
; Convert 2 bytes of the path string
|
mov r4, #0
|
||||||
; This will be the method of getting the lower 2 bytes of the title ID
|
adr r1, bin_fname
|
||||||
; until someone bothers figuring out where the value is derived from.
|
b open_payload
|
||||||
mov r0, #0 ; Result
|
|
||||||
add r1, sp, #0x3A8 - 0x70
|
|
||||||
add r1, #0x22 ; The significant bytes
|
|
||||||
mov r2, #4 ; Maximum loops (amount of bytes * 2)
|
|
||||||
|
|
||||||
hex_string_to_int_loop:
|
|
||||||
ldr r3, [r1], #2 ; 2 because it's a utf-16 string.
|
|
||||||
and r3, #0xFF
|
|
||||||
|
|
||||||
; Check if it"s a number
|
|
||||||
cmp r3, #'0'
|
|
||||||
blo hex_string_to_int_end
|
|
||||||
sub r3, #'0'
|
|
||||||
cmp r3, #9
|
|
||||||
bls hex_string_to_int_calc
|
|
||||||
|
|
||||||
; Check if it"s a capital letter
|
|
||||||
cmp r3, #'A' - '0'
|
|
||||||
blo hex_string_to_int_end
|
|
||||||
sub r3, #'A' - '0' - 0xA ; Make the correct value: 0xF >= al >= 0xA
|
|
||||||
cmp r3, #0xF
|
|
||||||
bls hex_string_to_int_calc
|
|
||||||
|
|
||||||
; Incorrect value: x > "A"
|
|
||||||
bhi hex_string_to_int_end
|
|
||||||
|
|
||||||
hex_string_to_int_calc:
|
|
||||||
orr r0, r3, r0, lsl #4
|
|
||||||
subs r2, #1
|
|
||||||
bne hex_string_to_int_loop
|
|
||||||
hex_string_to_int_end:
|
|
||||||
|
|
||||||
; Get the FIRM path
|
|
||||||
cmp r0, #0x0002 ; NATIVE_FIRM
|
|
||||||
adreq r1, firm_fname
|
|
||||||
beq load_firm
|
|
||||||
ldr r5, =0x0102 ; TWL_FIRM
|
|
||||||
cmp r0, r5
|
|
||||||
adreq r1, twlfirm_fname
|
|
||||||
beq load_firm
|
|
||||||
ldr r5, =0x0202 ; AGB_FIRM
|
|
||||||
cmp r0, r5
|
|
||||||
adreq r1, agbfirm_fname
|
|
||||||
beq load_firm
|
|
||||||
bne fallback ; TODO: Stubbed
|
|
||||||
|
|
||||||
fallback:
|
fallback:
|
||||||
; Fallback: Load specified FIRM from exefs
|
mov r4, #1
|
||||||
add r1, sp, #0x3A8-0x70 ; Location of exefs string.
|
adr r1, dat_fname
|
||||||
b load_firm
|
|
||||||
|
|
||||||
load_firm:
|
open_payload:
|
||||||
; Open file
|
; Open file
|
||||||
add r0, r7, #8
|
add r0, r7, #8
|
||||||
mov r2, #1
|
mov r2, #1
|
||||||
ldr r6, [fopen]
|
ldr r6, [fopen]
|
||||||
orr r6, 1
|
orr r6, 1
|
||||||
blx r6
|
blx r6
|
||||||
|
cmp r0, #0
|
||||||
|
bne fallback ; If the .bin is not found, try the .dat.
|
||||||
|
|
||||||
cmp r0, #0 ; Check if we were able to load the FIRM
|
read_payload:
|
||||||
bne fallback ; Otherwise, try again with the FIRM from exefs.
|
|
||||||
; This will loop indefinitely if the exefs FIRM fails to load, but whatever.
|
|
||||||
|
|
||||||
; Read file
|
; Read file
|
||||||
mov r0, r7
|
mov r0, r7
|
||||||
adr r1, bytes_read
|
adr r1, bytes_read
|
||||||
mov r2, firm_addr
|
ldr r2, =payload_addr
|
||||||
mov r3, firm_maxsize
|
cmp r4, #0
|
||||||
|
movne r3, #0x12000 ; Skip the first 0x12000 bytes.
|
||||||
|
moveq r3, payload_maxsize
|
||||||
ldr r6, [sp, #0x3A8-0x198]
|
ldr r6, [sp, #0x3A8-0x198]
|
||||||
ldr r6, [r6, #0x28]
|
ldr r6, [r6, #0x28]
|
||||||
blx r6
|
blx r6
|
||||||
|
cmp r4, #0
|
||||||
|
movne r4, #0
|
||||||
|
bne read_payload ; Go read the real payload.
|
||||||
|
|
||||||
|
add r0, sp, #0x3A8 - 0x70
|
||||||
|
ldr r0, [r0, #0x27]
|
||||||
|
ldr r1, =payload_addr + 4
|
||||||
|
str r0, [r1] ; Copy the last digits of the wanted firm to the 5th byte of the payload.
|
||||||
|
|
||||||
; Set kernel state
|
; Set kernel state
|
||||||
mov r0, #0
|
mov r0, #0
|
||||||
@ -115,13 +78,9 @@ firm_maxsize equ 0x200000 ; Random value that's bigger than any of the currentl
|
|||||||
bytes_read: .word 0
|
bytes_read: .word 0
|
||||||
fopen: .ascii "OPEN"
|
fopen: .ascii "OPEN"
|
||||||
.pool
|
.pool
|
||||||
firm_fname: .dcw "sdmc:/aurei/patched_firmware_sys.bin"
|
bin_fname: .dcw "sdmc:/arm9loaderhax.bin"
|
||||||
.word 0
|
.word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
.pool
|
dat_fname: .dcw "sdmc:/AuReiNand.dat"
|
||||||
twlfirm_fname: .dcw "sdmc:/aurei/patched_firmware_twl.bin"
|
|
||||||
.word 0
|
|
||||||
.pool
|
|
||||||
agbfirm_fname: .dcw "sdmc:/aurei/patched_firmware_agb.bin"
|
|
||||||
.word 0
|
.word 0
|
||||||
|
|
||||||
.align 4
|
.align 4
|
||||||
@ -157,23 +116,6 @@ agbfirm_fname: .dcw "sdmc:/aurei/patched_firmware_agb.bin"
|
|||||||
mcr p15, 0, r1, c2, c0, 1 ; icacheable
|
mcr p15, 0, r1, c2, c0, 1 ; icacheable
|
||||||
mcr p15, 0, r2, c3, c0, 0 ; write bufferable
|
mcr p15, 0, r2, c3, c0, 0 ; write bufferable
|
||||||
|
|
||||||
; Copy the firmware
|
|
||||||
mov r4, firm_addr
|
|
||||||
add r5, r4, #0x40 ; Start of loop
|
|
||||||
add r6, r5, #0x30 * 3 ; End of loop (scan 4 entries)
|
|
||||||
|
|
||||||
copy_firm_loop:
|
|
||||||
ldr r0, [r5]
|
|
||||||
cmp r0, #0
|
|
||||||
addne r0, r4 ; src
|
|
||||||
ldrne r1, [r5, #4] ; dest
|
|
||||||
ldrne r2, [r5, #8] ; size
|
|
||||||
blne memcpy32
|
|
||||||
|
|
||||||
cmp r5, r6
|
|
||||||
addlo r5, #0x30
|
|
||||||
blo copy_firm_loop
|
|
||||||
|
|
||||||
; Flush cache
|
; Flush cache
|
||||||
mov r2, #0
|
mov r2, #0
|
||||||
mov r1, r2
|
mov r1, r2
|
||||||
@ -197,22 +139,10 @@ agbfirm_fname: .dcw "sdmc:/aurei/patched_firmware_agb.bin"
|
|||||||
mcr p15, 0, r1, c7, c5, 0 ; flush dcache
|
mcr p15, 0, r1, c7, c5, 0 ; flush dcache
|
||||||
mcr p15, 0, r1, c7, c6, 0 ; flush icache
|
mcr p15, 0, r1, c7, c6, 0 ; flush icache
|
||||||
mcr p15, 0, r1, c7, c10, 4 ; drain write buffer
|
mcr p15, 0, r1, c7, c10, 4 ; drain write buffer
|
||||||
mov r0, firm_addr
|
|
||||||
|
|
||||||
; Boot FIRM
|
; Jump to payload
|
||||||
mov r1, #0x1FFFFFFC
|
ldr r0, =payload_addr
|
||||||
ldr r2, [r0, #8] ; arm11 entry
|
|
||||||
str r2, [r1]
|
|
||||||
ldr r0, [r0, #0xC] ; arm9 entry
|
|
||||||
bx r0
|
bx r0
|
||||||
.pool
|
|
||||||
|
|
||||||
memcpy32: ; memcpy32(void *src, void *dst, unsigned int size)
|
.pool
|
||||||
add r2, r0
|
|
||||||
memcpy32_loop:
|
|
||||||
ldmia r0!, {r3}
|
|
||||||
stmia r1!, {r3}
|
|
||||||
cmp r0, r2
|
|
||||||
blo memcpy32_loop
|
|
||||||
bx lr
|
|
||||||
.close
|
.close
|
||||||
|
98
pathchanger/pathchanger.c
Normal file
98
pathchanger/pathchanger.c
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
typedef uint8_t u8;
|
||||||
|
|
||||||
|
static u8 *memsearch(u8 *startPos, const void *pattern, int size, int patternSize)
|
||||||
|
{
|
||||||
|
const u8 *patternc = (const u8 *)pattern;
|
||||||
|
|
||||||
|
//Preprocessing
|
||||||
|
int table[256];
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < 256; ++i)
|
||||||
|
table[i] = patternSize + 1;
|
||||||
|
for(i = 0; i < patternSize; ++i)
|
||||||
|
table[patternc[i]] = patternSize - i;
|
||||||
|
|
||||||
|
//Searching
|
||||||
|
int j = 0;
|
||||||
|
|
||||||
|
while(j <= size - patternSize)
|
||||||
|
{
|
||||||
|
if(memcmp(patternc, startPos + j, patternSize) == 0)
|
||||||
|
return startPos + j;
|
||||||
|
j += table[startPos[j + patternSize]];
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fsize(FILE *fp)
|
||||||
|
{
|
||||||
|
fseek(fp, 0, SEEK_END);
|
||||||
|
int size = ftell(fp);
|
||||||
|
rewind(fp);
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void error(FILE *payload, const char *message)
|
||||||
|
{
|
||||||
|
fclose(payload);
|
||||||
|
printf("%s, are you sure you're using an AuReiNand payload?\n", message);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
if(argc == 1)
|
||||||
|
{
|
||||||
|
printf("Usage: %s <AuReiNand payload path>\n", argv[0]);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *payload;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
payload = fopen(argv[1], "rb+");
|
||||||
|
size = fsize(payload);
|
||||||
|
if(size > 0x20000)
|
||||||
|
error(payload, "The input file is too large");
|
||||||
|
|
||||||
|
u8 *buffer = (u8 *)malloc(size);
|
||||||
|
fread(buffer, 1, size, payload);
|
||||||
|
|
||||||
|
u8 pattern[] = {'s', 0, 'd', 0, 'm', 0, 'c', 0, ':', 0, '/', 0};
|
||||||
|
|
||||||
|
u8 *found = memsearch(buffer, pattern, size, sizeof(pattern));
|
||||||
|
|
||||||
|
if(found == NULL)
|
||||||
|
{
|
||||||
|
free(buffer);
|
||||||
|
error(payload, "Pattern not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 input[37] = {0};
|
||||||
|
u8 payloadname[2 * sizeof(input)] = {0};
|
||||||
|
|
||||||
|
printf("Enter the payload's path (37 characters max): ");
|
||||||
|
scanf("%37s", input);
|
||||||
|
|
||||||
|
unsigned int i;
|
||||||
|
for (i = 0; i < sizeof(input); i++)
|
||||||
|
payloadname[2 * i] = input[i];
|
||||||
|
|
||||||
|
memcpy(found + 12, payloadname, sizeof(payloadname));
|
||||||
|
|
||||||
|
rewind(payload);
|
||||||
|
fwrite(buffer, 1, size, payload);
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
|
fclose(payload);
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
@ -12,7 +12,7 @@
|
|||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
#include "buttons.h"
|
#include "buttons.h"
|
||||||
|
|
||||||
void configureCFW(const char *configPath, const char *patchedFirms[])
|
void configureCFW(const char *configPath)
|
||||||
{
|
{
|
||||||
initScreens();
|
initScreens();
|
||||||
|
|
||||||
@ -20,10 +20,9 @@ void configureCFW(const char *configPath, const char *patchedFirms[])
|
|||||||
drawString("Press A to select, START to save and reboot", 10, 30, COLOR_WHITE);
|
drawString("Press A to select, START to save and reboot", 10, 30, COLOR_WHITE);
|
||||||
|
|
||||||
const char *optionsText[] = { "Screen-init brightness: 4( ) 3( ) 2( ) 1( )",
|
const char *optionsText[] = { "Screen-init brightness: 4( ) 3( ) 2( ) 1( )",
|
||||||
|
"( ) Autoboot SysNAND",
|
||||||
"( ) Updated SysNAND mode (A9LH-only)",
|
"( ) Updated SysNAND mode (A9LH-only)",
|
||||||
"( ) Use pre-patched FIRMs",
|
|
||||||
"( ) Force A9LH detection",
|
"( ) Force A9LH detection",
|
||||||
"( ) Use 9.0 FIRM as default",
|
|
||||||
"( ) Use second EmuNAND as default",
|
"( ) Use second EmuNAND as default",
|
||||||
"( ) Show current NAND in System Settings",
|
"( ) Show current NAND in System Settings",
|
||||||
"( ) Show GBA boot screen in patched AGB_FIRM",
|
"( ) Show GBA boot screen in patched AGB_FIRM",
|
||||||
@ -37,8 +36,8 @@ void configureCFW(const char *configPath, const char *patchedFirms[])
|
|||||||
} options[optionsAmount];
|
} options[optionsAmount];
|
||||||
|
|
||||||
//Parse the existing configuration
|
//Parse the existing configuration
|
||||||
options[0].enabled = CONFIG(10, 3);
|
options[0].enabled = CONFIG(14, 3);
|
||||||
for(u32 i = optionsAmount; i; i--)
|
for(u32 i = optionsAmount - 1; i; i--)
|
||||||
options[i].enabled = CONFIG((i - 1), 1);
|
options[i].enabled = CONFIG((i - 1), 1);
|
||||||
|
|
||||||
//Pre-select the first configuration option
|
//Pre-select the first configuration option
|
||||||
@ -55,7 +54,9 @@ void configureCFW(const char *configPath, const char *patchedFirms[])
|
|||||||
//Display all the normal options in white, brightness will be displayed later
|
//Display all the normal options in white, brightness will be displayed later
|
||||||
for(u32 i = 1; i < optionsAmount; i++)
|
for(u32 i = 1; i < optionsAmount; i++)
|
||||||
{
|
{
|
||||||
options[i].posY = drawString(optionsText[i], 10, options[i - 1].posY + SPACING_Y + (!(1 - i) * 7), COLOR_WHITE);
|
static int endPos = 59;
|
||||||
|
options[i].posY = endPos + SPACING_Y;
|
||||||
|
endPos = drawString(optionsText[i], 10, options[i].posY, COLOR_WHITE);
|
||||||
if(options[i].enabled) drawCharacter(selected, 10 + SPACING_X, options[i].posY, COLOR_WHITE);
|
if(options[i].enabled) drawCharacter(selected, 10 + SPACING_X, options[i].posY, COLOR_WHITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,18 +130,12 @@ void configureCFW(const char *configPath, const char *patchedFirms[])
|
|||||||
if(pressed == BUTTON_START) break;
|
if(pressed == BUTTON_START) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//If the user has been using A9LH and the "Updated SysNAND" setting changed, delete the patched 9.0 FIRM
|
|
||||||
if(CONFIG(16, 1) && (CONFIG(0, 1) != options[1].enabled)) fileDelete(patchedFirms[3]);
|
|
||||||
|
|
||||||
//If the "Show GBA boot screen in patched AGB_FIRM" setting changed, delete the patched AGB_FIRM
|
|
||||||
if(CONFIG(6, 1) != options[7].enabled) fileDelete(patchedFirms[5]);
|
|
||||||
|
|
||||||
//Preserve the last-used boot options (last 12 bits)
|
//Preserve the last-used boot options (last 12 bits)
|
||||||
config &= 0xFFF000;
|
config &= 0xFF0000;
|
||||||
|
|
||||||
//Parse and write the new configuration
|
//Parse and write the new configuration
|
||||||
config |= options[0].enabled << 10;
|
config |= options[0].enabled << 14;
|
||||||
for(u32 i = optionsAmount; i; i--)
|
for(u32 i = optionsAmount - 1; i; i--)
|
||||||
config |= options[i].enabled << (i - 1);
|
config |= options[i].enabled << (i - 1);
|
||||||
|
|
||||||
fileWrite(&config, configPath, 3);
|
fileWrite(&config, configPath, 3);
|
||||||
|
@ -11,6 +11,6 @@
|
|||||||
#define CFG_BOOTENV (*(vu32 *)0x10010000)
|
#define CFG_BOOTENV (*(vu32 *)0x10010000)
|
||||||
#define CONFIG(a, b) ((config >> a) & b)
|
#define CONFIG(a, b) ((config >> a) & b)
|
||||||
|
|
||||||
u32 config;
|
extern u32 config;
|
||||||
|
|
||||||
void configureCFW(const char *configPath, const char *patchedFirms[]);
|
void configureCFW(const char *configPath);
|
171
source/crypto.c
171
source/crypto.c
@ -229,47 +229,154 @@ static void aes(void *dst, const void *src, u32 blockCount, void *iv, u32 mode,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void sha_wait_idle()
|
||||||
|
{
|
||||||
|
while(*REG_SHA_CNT & 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sha(void *res, const void *src, u32 size, u32 mode)
|
||||||
|
{
|
||||||
|
sha_wait_idle();
|
||||||
|
*REG_SHA_CNT = mode | SHA_CNT_OUTPUT_ENDIAN | SHA_NORMAL_ROUND;
|
||||||
|
|
||||||
|
const u32 *src32 = (const u32 *)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();
|
||||||
|
|
||||||
|
u32 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);
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************
|
/****************************************************************
|
||||||
* Nand/FIRM Crypto stuff
|
* Nand/FIRM Crypto stuff
|
||||||
****************************************************************/
|
****************************************************************/
|
||||||
|
|
||||||
//Nand key#2 (0x12C10)
|
static u8 nandCTR[0x10],
|
||||||
static const u8 key2[0x10] = {
|
nandSlot;
|
||||||
0x42, 0x3F, 0x81, 0x7A, 0x23, 0x52, 0x58, 0x31, 0x6E, 0x75, 0x8E, 0x3A, 0x39, 0x43, 0x2E, 0xD0
|
|
||||||
};
|
|
||||||
|
|
||||||
//Get Nand CTR key
|
static u32 fatStart;
|
||||||
static void getNandCTR(u8 *buf, u32 console)
|
|
||||||
|
//Initialize the CTRNAND crypto
|
||||||
|
void ctrNandInit(void)
|
||||||
{
|
{
|
||||||
u8 *addr = (console ? (u8 *)0x080D8BBC : (u8 *)0x080D797C) + 0x0F;
|
u8 nandCid[0x10];
|
||||||
for(u8 keyLen = 0x10; keyLen; keyLen--)
|
u8 shaSum[0x20];
|
||||||
*(buf++) = *(addr--);
|
|
||||||
|
sdmmc_get_cid(1, (u32 *)nandCid);
|
||||||
|
sha(shaSum, nandCid, 0x10, SHA_256_MODE);
|
||||||
|
memcpy(nandCTR, shaSum, 0x10);
|
||||||
|
|
||||||
|
if(console)
|
||||||
|
{
|
||||||
|
u8 keyY0x5[0x10] = {0x4D, 0x80, 0x4F, 0x4E, 0x99, 0x90, 0x19, 0x46, 0x13, 0xA2, 0x04, 0xAC, 0x58, 0x44, 0x60, 0xBE};
|
||||||
|
aes_setkey(0x05, keyY0x5, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
|
nandSlot = 0x05;
|
||||||
|
fatStart = 0x5CAD7;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nandSlot = 0x04;
|
||||||
|
fatStart = 0x5CAE5;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Read firm0 from NAND and write to buffer
|
//Read and decrypt from the selected CTRNAND
|
||||||
void nandFirm0(u8 *outbuf, u32 size, u32 console)
|
u32 ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf)
|
||||||
{
|
{
|
||||||
u8 CTR[0x10];
|
u8 tmpCTR[0x10];
|
||||||
getNandCTR(CTR, console);
|
memcpy(tmpCTR, nandCTR, 0x10);
|
||||||
|
aes_advctr(tmpCTR, ((sector + fatStart) * 0x200) / AES_BLOCK_SIZE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
|
|
||||||
sdmmc_nand_readsectors(0x0B130000 / 0x200, size / 0x200, outbuf);
|
//Read
|
||||||
|
u32 result;
|
||||||
aes_advctr(CTR, 0x0B130000/0x10, AES_INPUT_BE | AES_INPUT_NORMAL);
|
if(!firmSource)
|
||||||
aes_use_keyslot(0x06);
|
result = sdmmc_nand_readsectors(sector + fatStart, sectorCount, outbuf);
|
||||||
aes(outbuf, outbuf, size / AES_BLOCK_SIZE, CTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
else
|
||||||
|
{
|
||||||
|
sector += emuOffset;
|
||||||
|
result = sdmmc_sdcard_readsectors(sector + fatStart, sectorCount, outbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Decrypts the N3DS arm9bin
|
//Decrypt
|
||||||
void decryptArm9Bin(u8 *arm9Section, u32 mode)
|
aes_use_keyslot(nandSlot);
|
||||||
|
aes(outbuf, outbuf, (sectorCount * 0x200) / AES_BLOCK_SIZE, tmpCTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Encrypt and write to the selected CTRNAND
|
||||||
|
u32 ctrNandWrite(u32 sector, u32 sectorCount, u8 *inbuf)
|
||||||
|
{
|
||||||
|
u8 tmpCTR[0x10];
|
||||||
|
memcpy(tmpCTR, nandCTR, 0x10);
|
||||||
|
aes_advctr(tmpCTR, ((sector + fatStart) * 0x200) / AES_BLOCK_SIZE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
|
|
||||||
|
//Encrypt
|
||||||
|
aes_use_keyslot(nandSlot);
|
||||||
|
aes(inbuf, inbuf, (sectorCount * 0x200) / AES_BLOCK_SIZE, tmpCTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
|
|
||||||
|
//Write
|
||||||
|
if(!firmSource)
|
||||||
|
return sdmmc_nand_writesectors(sector + fatStart, sectorCount, inbuf);
|
||||||
|
|
||||||
|
sector += emuOffset;
|
||||||
|
return sdmmc_sdcard_writesectors(sector + fatStart, sectorCount, inbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Decrypt a FIRM ExeFS
|
||||||
|
void decryptExeFs(u8 *inbuf)
|
||||||
|
{
|
||||||
|
u32 exeFsOffset = (u32)inbuf + *(u32 *)(inbuf + 0x1A0) * 0x200;
|
||||||
|
u32 exeFsSize = *(u32 *)(inbuf + 0x1A4) * 0x200;
|
||||||
|
u8 ncchCTR[0x10];
|
||||||
|
|
||||||
|
memset(ncchCTR, 0, 0x10);
|
||||||
|
for(u32 i=0; i<8; i++)
|
||||||
|
ncchCTR[7-i] = *(inbuf + 0x108 + i);
|
||||||
|
ncchCTR[8] = 2;
|
||||||
|
|
||||||
|
aes_setkey(0x2C, inbuf, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
|
aes_setiv(ncchCTR, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
|
aes_use_keyslot(0x2C);
|
||||||
|
aes(inbuf - 0x200, (void *)exeFsOffset, exeFsSize/AES_BLOCK_SIZE, ncchCTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
//ARM9Loader replacement
|
||||||
|
void arm9Loader(u8 *arm9Section, u32 mode)
|
||||||
{
|
{
|
||||||
//Firm keys
|
//Firm keys
|
||||||
u8 keyY[0x10];
|
u8 keyY[0x10];
|
||||||
u8 CTR[0x10];
|
u8 arm9BinCTR[0x10];
|
||||||
u8 slot = mode ? 0x16 : 0x15;
|
u8 arm9BinSlot = mode ? 0x16 : 0x15;
|
||||||
|
|
||||||
//Setup keys needed for arm9bin decryption
|
//Setup keys needed for arm9bin decryption
|
||||||
memcpy(keyY, arm9Section + 0x10, 0x10);
|
memcpy(keyY, arm9Section + 0x10, 0x10);
|
||||||
memcpy(CTR, arm9Section + 0x20, 0x10);
|
memcpy(arm9BinCTR, arm9Section + 0x20, 0x10);
|
||||||
|
|
||||||
//Calculate the size of the ARM9 binary
|
//Calculate the size of the ARM9 binary
|
||||||
u32 size = 0;
|
u32 size = 0;
|
||||||
@ -279,31 +386,30 @@ void decryptArm9Bin(u8 *arm9Section, u32 mode)
|
|||||||
|
|
||||||
if(mode)
|
if(mode)
|
||||||
{
|
{
|
||||||
|
const u8 key2[0x10] = {0x42, 0x3F, 0x81, 0x7A, 0x23, 0x52, 0x58, 0x31, 0x6E, 0x75, 0x8E, 0x3A, 0x39, 0x43, 0x2E, 0xD0};
|
||||||
u8 keyX[0x10];
|
u8 keyX[0x10];
|
||||||
|
|
||||||
//Set 0x11 to key2 for the arm9bin and misc keys
|
//Set 0x11 to key2 for the arm9bin and misc keys
|
||||||
aes_setkey(0x11, key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
|
aes_setkey(0x11, key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
aes_use_keyslot(0x11);
|
aes_use_keyslot(0x11);
|
||||||
aes(keyX, arm9Section + 0x60, 1, NULL, AES_ECB_DECRYPT_MODE, 0);
|
aes(keyX, arm9Section + 0x60, 1, NULL, AES_ECB_DECRYPT_MODE, 0);
|
||||||
aes_setkey(slot, keyX, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
aes_setkey(arm9BinSlot, keyX, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
aes_setkey(slot, keyY, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
|
aes_setkey(arm9BinSlot, keyY, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
aes_setiv(CTR, AES_INPUT_BE | AES_INPUT_NORMAL);
|
aes_setiv(arm9BinCTR, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
aes_use_keyslot(slot);
|
aes_use_keyslot(arm9BinSlot);
|
||||||
|
|
||||||
//Decrypt arm9bin
|
//Decrypt arm9bin
|
||||||
aes(arm9Section + 0x800, arm9Section + 0x800, size/AES_BLOCK_SIZE, CTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
aes(arm9Section + 0x800, arm9Section + 0x800, size/AES_BLOCK_SIZE, arm9BinCTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
}
|
|
||||||
|
|
||||||
//Sets the N3DS 9.6 KeyXs
|
//Set >=9.6 KeyXs
|
||||||
void setKeyXs(u8 *arm9Section)
|
if(mode)
|
||||||
{
|
{
|
||||||
u8 *keyData = arm9Section + 0x89814;
|
u8 *keyData = arm9Section + 0x89814;
|
||||||
u8 *decKey = keyData + 0x10;
|
u8 *decKey = keyData + 0x10;
|
||||||
|
|
||||||
//Set keys 0x19..0x1F keyXs
|
//Set keys 0x19..0x1F keyXs
|
||||||
aes_setkey(0x11, key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
|
|
||||||
aes_use_keyslot(0x11);
|
aes_use_keyslot(0x11);
|
||||||
for(u8 slot = 0x19; slot < 0x20; slot++)
|
for(u8 slot = 0x19; slot < 0x20; slot++)
|
||||||
{
|
{
|
||||||
@ -312,3 +418,4 @@ void setKeyXs(u8 *arm9Section)
|
|||||||
*(keyData + 0xF) += 1;
|
*(keyData + 0xF) += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
@ -53,7 +53,38 @@
|
|||||||
#define AES_KEYX 1
|
#define AES_KEYX 1
|
||||||
#define AES_KEYY 2
|
#define AES_KEYY 2
|
||||||
|
|
||||||
//NAND/FIRM stuff
|
/**************************SHA****************************/
|
||||||
void nandFirm0(u8 *outbuf, u32 size, u32 console);
|
#define REG_SHA_CNT ((vu32 *)0x1000A000)
|
||||||
void decryptArm9Bin(u8 *arm9Section, u32 mode);
|
#define REG_SHA_BLKCNT ((vu32 *)0x1000A004)
|
||||||
void setKeyXs(u8 *arm9Section);
|
#define REG_SHA_HASH ((vu32 *)0x1000A040)
|
||||||
|
#define REG_SHA_INFIFO ((vu32 *)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_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_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)
|
||||||
|
|
||||||
|
extern u32 emuOffset, console, firmSource;
|
||||||
|
|
||||||
|
void ctrNandInit(void);
|
||||||
|
u32 ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf);
|
||||||
|
u32 ctrNandWrite(u32 sector, u32 sectorCount, u8 *inbuf);
|
||||||
|
void decryptExeFs(u8 *inbuf);
|
||||||
|
void arm9Loader(u8 *arm9Section, u32 mode);
|
@ -8,7 +8,7 @@
|
|||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "fatfs/sdmmc/sdmmc.h"
|
#include "fatfs/sdmmc/sdmmc.h"
|
||||||
|
|
||||||
u32 getEmunandSect(u32 *off, u32 *head, u32 *emuNAND)
|
void getEmunandSect(u32 *off, u32 *head, u32 *emuNAND)
|
||||||
{
|
{
|
||||||
u8 *const temp = (u8 *)0x24300000;
|
u8 *const temp = (u8 *)0x24300000;
|
||||||
|
|
||||||
@ -40,13 +40,9 @@ u32 getEmunandSect(u32 *off, u32 *head, u32 *emuNAND)
|
|||||||
{
|
{
|
||||||
(*emuNAND)--;
|
(*emuNAND)--;
|
||||||
if(*emuNAND) getEmunandSect(off, head, emuNAND);
|
if(*emuNAND) getEmunandSect(off, head, emuNAND);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 getSDMMC(u8 *pos, u32 size)
|
u32 getSDMMC(u8 *pos, u32 size)
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
#define NCSD_MAGIC (0x4453434E)
|
#define NCSD_MAGIC (0x4453434E)
|
||||||
|
|
||||||
u32 getEmunandSect(u32 *off, u32 *head, u32 *emuNAND);
|
void getEmunandSect(u32 *off, u32 *head, u32 *emuNAND);
|
||||||
u32 getSDMMC(u8 *pos, u32 size);
|
u32 getSDMMC(u8 *pos, u32 size);
|
||||||
void getEmuRW(u8 *pos, u32 size, u32 *readOff, u32 *writeOff);
|
void getEmuRW(u8 *pos, u32 size, u32 *readOff, u32 *writeOff);
|
||||||
u32 *getMPU(u8 *pos, u32 size);
|
u32 *getMPU(u8 *pos, u32 size);
|
||||||
|
@ -10,6 +10,9 @@
|
|||||||
#include "diskio.h" /* FatFs lower layer API */
|
#include "diskio.h" /* FatFs lower layer API */
|
||||||
#include "sdmmc/sdmmc.h"
|
#include "sdmmc/sdmmc.h"
|
||||||
|
|
||||||
|
/* Definitions of physical drive number for each media */
|
||||||
|
#define SDCARD 0
|
||||||
|
#define CTRNAND 1
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* Get Drive Status */
|
/* Get Drive Status */
|
||||||
@ -34,7 +37,16 @@ DSTATUS disk_initialize (
|
|||||||
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
switch(pdrv)
|
||||||
|
{
|
||||||
|
case SDCARD:
|
||||||
sdmmc_sdcard_init();
|
sdmmc_sdcard_init();
|
||||||
|
break;
|
||||||
|
case CTRNAND:
|
||||||
|
ctrNandInit();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return RES_OK;
|
return RES_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,8 +64,16 @@ DRESULT disk_read (
|
|||||||
UINT count /* Number of sectors to read */
|
UINT count /* Number of sectors to read */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (sdmmc_sdcard_readsectors(sector, count, buff)) {
|
switch(pdrv)
|
||||||
|
{
|
||||||
|
case SDCARD:
|
||||||
|
if(sdmmc_sdcard_readsectors(sector, count, (BYTE *)buff))
|
||||||
return RES_PARERR;
|
return RES_PARERR;
|
||||||
|
break;
|
||||||
|
case CTRNAND:
|
||||||
|
if(ctrNandRead(sector, count, (BYTE *)buff))
|
||||||
|
return RES_PARERR;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return RES_OK;
|
return RES_OK;
|
||||||
@ -74,8 +94,16 @@ DRESULT disk_write (
|
|||||||
UINT count /* Number of sectors to write */
|
UINT count /* Number of sectors to write */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (sdmmc_sdcard_writesectors(sector, count, (BYTE *)buff)) {
|
switch(pdrv)
|
||||||
|
{
|
||||||
|
case SDCARD:
|
||||||
|
if(sdmmc_sdcard_writesectors(sector, count, (BYTE *)buff))
|
||||||
return RES_PARERR;
|
return RES_PARERR;
|
||||||
|
break;
|
||||||
|
case CTRNAND:
|
||||||
|
if(ctrNandWrite(sector, count, (BYTE *)buff))
|
||||||
|
return RES_PARERR;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return RES_OK;
|
return RES_OK;
|
||||||
|
550
source/fatfs/ff.c
Normal file → Executable file
550
source/fatfs/ff.c
Normal file → Executable file
@ -1,5 +1,5 @@
|
|||||||
/*----------------------------------------------------------------------------/
|
/*----------------------------------------------------------------------------/
|
||||||
/ FatFs - FAT file system module R0.11 (C)ChaN, 2015
|
/ FatFs - FAT file system module R0.11a (C)ChaN, 2015 /
|
||||||
/-----------------------------------------------------------------------------/
|
/-----------------------------------------------------------------------------/
|
||||||
/ FatFs module is a free software that opened under license policy of
|
/ FatFs module is a free software that opened under license policy of
|
||||||
/ following conditions.
|
/ following conditions.
|
||||||
@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
---------------------------------------------------------------------------*/
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#if _FATFS != 32020 /* Revision ID */
|
#if _FATFS != 64180 /* Revision ID */
|
||||||
#error Wrong include file (ff.h).
|
#error Wrong include file (ff.h).
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ typedef struct {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* DBCS code ranges and SBCS extend character conversion table */
|
/* DBCS code ranges and SBCS upper conversion tables */
|
||||||
|
|
||||||
#if _CODE_PAGE == 932 /* Japanese Shift-JIS */
|
#if _CODE_PAGE == 932 /* Japanese Shift-JIS */
|
||||||
#define _DF1S 0x81 /* DBC 1st byte range 1 start */
|
#define _DF1S 0x81 /* DBC 1st byte range 1 start */
|
||||||
@ -121,211 +121,192 @@ typedef struct {
|
|||||||
#define _DS2S 0xA1
|
#define _DS2S 0xA1
|
||||||
#define _DS2E 0xFE
|
#define _DS2E 0xFE
|
||||||
|
|
||||||
#elif _CODE_PAGE == 437 /* U.S. (OEM) */
|
#elif _CODE_PAGE == 437 /* U.S. */
|
||||||
#define _DF1S 0
|
#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, \
|
#define _EXCVT {0x80,0x9A,0x45,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \
|
||||||
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, \
|
0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
|
||||||
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,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
|
||||||
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}*/
|
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
|
#elif _CODE_PAGE == 720 /* Arabic */
|
||||||
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 ff_wtoupper(WCHAR chr)
|
|
||||||
{
|
|
||||||
if(chr >= 'a' && chr <= 'z')
|
|
||||||
return (chr - 32);
|
|
||||||
else
|
|
||||||
return chr;
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif _CODE_PAGE == 720 /* Arabic (OEM) */
|
|
||||||
#define _DF1S 0
|
#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, \
|
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \
|
||||||
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, \
|
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
|
||||||
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, \
|
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
|
||||||
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}
|
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) */
|
#elif _CODE_PAGE == 737 /* Greek */
|
||||||
#define _DF1S 0
|
#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, \
|
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \
|
||||||
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, \
|
0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \
|
||||||
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, \
|
0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96, \
|
||||||
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}
|
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,0xEF,0xF5,0xF0,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) */
|
#elif _CODE_PAGE == 771 /* KBL */
|
||||||
#define _DF1S 0
|
#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, \
|
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \
|
||||||
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, \
|
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
|
||||||
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, \
|
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \
|
||||||
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}
|
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,0xDC,0xDE,0xDE, \
|
||||||
|
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
|
||||||
|
0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFE,0xFF}
|
||||||
|
|
||||||
#elif _CODE_PAGE == 850 /* Multilingual Latin 1 (OEM) */
|
#elif _CODE_PAGE == 775 /* Baltic */
|
||||||
#define _DF1S 0
|
#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, \
|
#define _EXCVT {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F, \
|
||||||
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, \
|
0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
|
||||||
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, \
|
0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
|
||||||
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}
|
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 == 852 /* Latin 2 (OEM) */
|
#elif _CODE_PAGE == 850 /* Latin 1 */
|
||||||
#define _DF1S 0
|
#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, \
|
#define _EXCVT {0x43,0x55,0x45,0x41,0x41,0x41,0x41,0x43,0x45,0x45,0x45,0x49,0x49,0x49,0x41,0x41, \
|
||||||
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, \
|
0x45,0x92,0x92,0x4F,0x4F,0x4F,0x55,0x55,0x59,0x4F,0x55,0x4F,0x9C,0x4F,0x9E,0x9F, \
|
||||||
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, \
|
0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
|
||||||
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}
|
0xB0,0xB1,0xB2,0xB3,0xB4,0x41,0x41,0x41,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||||
|
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0x41,0x41,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
|
||||||
|
0xD1,0xD1,0x45,0x45,0x45,0x49,0x49,0x49,0x49,0xD9,0xDA,0xDB,0xDC,0xDD,0x49,0xDF, \
|
||||||
|
0x4F,0xE1,0x4F,0x4F,0x4F,0x4F,0xE6,0xE8,0xE8,0x55,0x55,0x55,0x59,0x59,0xEE,0xEF, \
|
||||||
|
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
|
||||||
|
|
||||||
#elif _CODE_PAGE == 855 /* Cyrillic (OEM) */
|
#elif _CODE_PAGE == 852 /* Latin 2 */
|
||||||
#define _DF1S 0
|
#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, \
|
#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F, \
|
||||||
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, \
|
0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0xAC, \
|
||||||
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, \
|
0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF, \
|
||||||
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}
|
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 == 857 /* Turkish (OEM) */
|
#elif _CODE_PAGE == 855 /* Cyrillic */
|
||||||
#define _DF1S 0
|
#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, \
|
#define _EXCVT {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F, \
|
||||||
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, \
|
0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \
|
||||||
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, \
|
0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF, \
|
||||||
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}
|
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 == 858 /* Multilingual Latin 1 + Euro (OEM) */
|
#elif _CODE_PAGE == 857 /* Turkish */
|
||||||
#define _DF1S 0
|
#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, \
|
#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x49,0x8E,0x8F, \
|
||||||
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, \
|
0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \
|
||||||
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, \
|
0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
|
||||||
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}
|
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,0x49,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||||
|
0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,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) */
|
#elif _CODE_PAGE == 860 /* Portuguese */
|
||||||
#define _DF1S 0
|
#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, \
|
#define _EXCVT {0x80,0x9A,0x90,0x8F,0x8E,0x91,0x86,0x80,0x89,0x89,0x92,0x8B,0x8C,0x98,0x8E,0x8F, \
|
||||||
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, \
|
0x90,0x91,0x92,0x8C,0x99,0xA9,0x96,0x9D,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
|
||||||
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, \
|
0x86,0x8B,0x9F,0x96,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
|
||||||
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}
|
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) */
|
#elif _CODE_PAGE == 861 /* Icelandic */
|
||||||
#define _DF1S 0
|
#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, \
|
#define _EXCVT {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x8B,0x8B,0x8D,0x8E,0x8F, \
|
||||||
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, \
|
0x90,0x92,0x92,0x4F,0x99,0x8D,0x55,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
|
||||||
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, \
|
0xA4,0xA5,0xA6,0xA7,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
|
||||||
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}
|
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 == 874 /* Thai (OEM, Windows) */
|
#elif _CODE_PAGE == 862 /* Hebrew */
|
||||||
#define _DF1S 0
|
#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, \
|
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \
|
||||||
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, \
|
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
|
||||||
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,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
|
||||||
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}
|
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) */
|
#elif _CODE_PAGE == 863 /* Canadian-French */
|
||||||
#define _DF1S 0
|
#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, \
|
#define _EXCVT {0x43,0x55,0x45,0x41,0x41,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x41,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, \
|
0x45,0x45,0x45,0x4F,0x45,0x49,0x55,0x55,0x98,0x4F,0x55,0x9B,0x9C,0x55,0x55,0x9F, \
|
||||||
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, \
|
0xA0,0xA1,0x4F,0x55,0xA4,0xA5,0xA6,0xA7,0x49,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
|
||||||
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}
|
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 == 1251 /* Cyrillic (Windows) */
|
#elif _CODE_PAGE == 864 /* Arabic */
|
||||||
#define _DF1S 0
|
#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, \
|
#define _EXCVT {0x80,0x9A,0x45,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,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, \
|
0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
|
||||||
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,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,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}
|
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 == 1252 /* Latin 1 (Windows) */
|
#elif _CODE_PAGE == 865 /* Nordic */
|
||||||
#define _DF1S 0
|
#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, \
|
#define _EXCVT {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \
|
||||||
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, \
|
0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
|
||||||
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,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
|
||||||
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}
|
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 == 1253 /* Greek (Windows) */
|
#elif _CODE_PAGE == 866 /* Russian */
|
||||||
#define _DF1S 0
|
#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, \
|
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \
|
||||||
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, \
|
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
|
||||||
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, \
|
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \
|
||||||
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}
|
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 == 1254 /* Turkish (Windows) */
|
#elif _CODE_PAGE == 869 /* Greek 2 */
|
||||||
#define _DF1S 0
|
#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, \
|
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \
|
||||||
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, \
|
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x86,0x9C,0x8D,0x8F,0x90, \
|
||||||
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, \
|
0x91,0x90,0x92,0x95,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
|
||||||
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}
|
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, \
|
||||||
#elif _CODE_PAGE == 1255 /* Hebrew (Windows) */
|
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xA4,0xA5,0xA6,0xD9,0xDA,0xDB,0xDC,0xA7,0xA8,0xDF, \
|
||||||
#define _DF1S 0
|
0xA9,0xAA,0xAC,0xAD,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xCF,0xCF,0xD0,0xEF, \
|
||||||
#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, \
|
0xF0,0xF1,0xD1,0xD2,0xD3,0xF5,0xD4,0xF7,0xF8,0xF9,0xD5,0x96,0x95,0x98,0xFE,0xFF}
|
||||||
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}
|
|
||||||
|
|
||||||
#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}
|
|
||||||
|
|
||||||
#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) */
|
#elif _CODE_PAGE == 1 /* ASCII (for only non-LFN cfg) */
|
||||||
#if _USE_LFN
|
#if _USE_LFN
|
||||||
@ -377,12 +358,12 @@ WCHAR ff_wtoupper(WCHAR chr)
|
|||||||
|
|
||||||
|
|
||||||
/* FAT sub-type boundaries (Differ from specs but correct for real DOS/Windows) */
|
/* 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_FAT16 4086U /* Minimum number of clusters of FAT16 */
|
||||||
#define MIN_FAT32 65526U /* Minimum number of clusters as FAT32 */
|
#define MIN_FAT32 65526U /* Minimum number of clusters of FAT32 */
|
||||||
|
|
||||||
|
|
||||||
/* FatFs refers the members in the FAT structures as byte array instead of
|
/* FatFs refers the members in the FAT structures as byte array instead of
|
||||||
/ structure member because the structure is not binary compatible between
|
/ structure members because the structure is not binary compatible between
|
||||||
/ different platforms */
|
/ different platforms */
|
||||||
|
|
||||||
#define BS_jmpBoot 0 /* x86 jump instruction (3) */
|
#define BS_jmpBoot 0 /* x86 jump instruction (3) */
|
||||||
@ -399,7 +380,8 @@ WCHAR ff_wtoupper(WCHAR chr)
|
|||||||
#define BPB_NumHeads 26 /* Number of heads (2) */
|
#define BPB_NumHeads 26 /* Number of heads (2) */
|
||||||
#define BPB_HiddSec 28 /* Number of special hidden sectors (4) */
|
#define BPB_HiddSec 28 /* Number of special hidden sectors (4) */
|
||||||
#define BPB_TotSec32 32 /* Volume size [sector] (4) */
|
#define BPB_TotSec32 32 /* Volume size [sector] (4) */
|
||||||
#define BS_DrvNum 36 /* Physical drive number (2) */
|
#define BS_DrvNum 36 /* Physical drive number (1) */
|
||||||
|
#define BS_NTres 37 /* Error flag (1) */
|
||||||
#define BS_BootSig 38 /* Extended boot signature (1) */
|
#define BS_BootSig 38 /* Extended boot signature (1) */
|
||||||
#define BS_VolID 39 /* Volume serial number (4) */
|
#define BS_VolID 39 /* Volume serial number (4) */
|
||||||
#define BS_VolLab 43 /* Volume label (8) */
|
#define BS_VolLab 43 /* Volume label (8) */
|
||||||
@ -410,7 +392,8 @@ WCHAR ff_wtoupper(WCHAR chr)
|
|||||||
#define BPB_RootClus 44 /* Root directory first cluster (4) */
|
#define BPB_RootClus 44 /* Root directory first cluster (4) */
|
||||||
#define BPB_FSInfo 48 /* Offset of FSINFO sector (2) */
|
#define BPB_FSInfo 48 /* Offset of FSINFO sector (2) */
|
||||||
#define BPB_BkBootSec 50 /* Offset of backup boot sector (2) */
|
#define BPB_BkBootSec 50 /* Offset of backup boot sector (2) */
|
||||||
#define BS_DrvNum32 64 /* Physical drive number (2) */
|
#define BS_DrvNum32 64 /* Physical drive number (1) */
|
||||||
|
#define BS_NTres32 65 /* Error flag (1) */
|
||||||
#define BS_BootSig32 66 /* Extended boot signature (1) */
|
#define BS_BootSig32 66 /* Extended boot signature (1) */
|
||||||
#define BS_VolID32 67 /* Volume serial number (4) */
|
#define BS_VolID32 67 /* Volume serial number (4) */
|
||||||
#define BS_VolLab32 71 /* Volume label (8) */
|
#define BS_VolLab32 71 /* Volume label (8) */
|
||||||
@ -438,7 +421,7 @@ WCHAR ff_wtoupper(WCHAR chr)
|
|||||||
#define LDIR_Ord 0 /* LFN entry order and LLE flag (1) */
|
#define LDIR_Ord 0 /* LFN entry order and LLE flag (1) */
|
||||||
#define LDIR_Attr 11 /* LFN attribute (1) */
|
#define LDIR_Attr 11 /* LFN attribute (1) */
|
||||||
#define LDIR_Type 12 /* LFN type (1) */
|
#define LDIR_Type 12 /* LFN type (1) */
|
||||||
#define LDIR_Chksum 13 /* Sum of corresponding SFN entry */
|
#define LDIR_Chksum 13 /* Checksum of corresponding SFN entry */
|
||||||
#define LDIR_FstClusLO 26 /* Must be zero (0) */
|
#define LDIR_FstClusLO 26 /* Must be zero (0) */
|
||||||
#define SZ_DIRE 32 /* Size of a directory entry */
|
#define SZ_DIRE 32 /* Size of a directory entry */
|
||||||
#define LLEF 0x40 /* Last long entry flag in LDIR_Ord */
|
#define LLEF 0x40 /* Last long entry flag in LDIR_Ord */
|
||||||
@ -448,12 +431,15 @@ WCHAR ff_wtoupper(WCHAR chr)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------
|
||||||
/* Module private work area */
|
|
||||||
/*------------------------------------------------------------*/
|
Module Private Work Area
|
||||||
/* Remark: Uninitialized variables with static duration are
|
|
||||||
/ guaranteed zero/null at start-up. If not, either the linker
|
---------------------------------------------------------------------------*/
|
||||||
/ or start-up routine being used is out of ANSI-C standard.
|
|
||||||
|
/* Remark: Uninitialized variables with static duration are guaranteed
|
||||||
|
/ zero/null at start-up. If not, either the linker or start-up routine
|
||||||
|
/ being used is not compliance with ANSI-C standard.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if _VOLUMES < 1 || _VOLUMES > 9
|
#if _VOLUMES < 1 || _VOLUMES > 9
|
||||||
@ -497,7 +483,7 @@ static WCHAR LfnBuf[_MAX_LFN + 1];
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _EXCVT
|
#ifdef _EXCVT
|
||||||
static const BYTE ExCvt[] = _EXCVT; /* Upper conversion table for extended characters */
|
static const BYTE ExCvt[] = _EXCVT; /* Upper conversion table for SBCS extended characters */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -711,7 +697,7 @@ void clear_lock ( /* Clear lock entries of the volume */
|
|||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
#if !_FS_READONLY
|
#if !_FS_READONLY
|
||||||
static
|
static
|
||||||
FRESULT sync_window (
|
FRESULT sync_window ( /* FR_OK:succeeded, !=0:error */
|
||||||
FATFS* fs /* File system object */
|
FATFS* fs /* File system object */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -740,7 +726,7 @@ FRESULT sync_window (
|
|||||||
|
|
||||||
|
|
||||||
static
|
static
|
||||||
FRESULT move_window (
|
FRESULT move_window ( /* FR_OK(0):succeeded, !=0:error */
|
||||||
FATFS* fs, /* File system object */
|
FATFS* fs, /* File system object */
|
||||||
DWORD sector /* Sector number to make appearance in the fs->win[] */
|
DWORD sector /* Sector number to make appearance in the fs->win[] */
|
||||||
)
|
)
|
||||||
@ -771,7 +757,7 @@ FRESULT move_window (
|
|||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
#if !_FS_READONLY
|
#if !_FS_READONLY
|
||||||
static
|
static
|
||||||
FRESULT sync_fs ( /* FR_OK: successful, FR_DISK_ERR: failed */
|
FRESULT sync_fs ( /* FR_OK:succeeded, !=0:error */
|
||||||
FATFS* fs /* File system object */
|
FATFS* fs /* File system object */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -780,16 +766,16 @@ FRESULT sync_fs ( /* FR_OK: successful, FR_DISK_ERR: failed */
|
|||||||
|
|
||||||
res = sync_window(fs);
|
res = sync_window(fs);
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
/* Update FSINFO sector if needed */
|
/* Update FSInfo sector if needed */
|
||||||
if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) {
|
if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) {
|
||||||
/* Create FSINFO structure */
|
/* Create FSInfo structure */
|
||||||
mem_set(fs->win, 0, SS(fs));
|
mem_set(fs->win, 0, SS(fs));
|
||||||
ST_WORD(fs->win + BS_55AA, 0xAA55);
|
ST_WORD(fs->win + BS_55AA, 0xAA55);
|
||||||
ST_DWORD(fs->win + FSI_LeadSig, 0x41615252);
|
ST_DWORD(fs->win + FSI_LeadSig, 0x41615252);
|
||||||
ST_DWORD(fs->win + FSI_StrucSig, 0x61417272);
|
ST_DWORD(fs->win + FSI_StrucSig, 0x61417272);
|
||||||
ST_DWORD(fs->win + FSI_Free_Count, fs->free_clust);
|
ST_DWORD(fs->win + FSI_Free_Count, fs->free_clust);
|
||||||
ST_DWORD(fs->win + FSI_Nxt_Free, fs->last_clust);
|
ST_DWORD(fs->win + FSI_Nxt_Free, fs->last_clust);
|
||||||
/* Write it into the FSINFO sector */
|
/* Write it into the FSInfo sector */
|
||||||
fs->winsect = fs->volbase + 1;
|
fs->winsect = fs->volbase + 1;
|
||||||
disk_write(fs->drv, fs->win, fs->winsect, 1);
|
disk_write(fs->drv, fs->win, fs->winsect, 1);
|
||||||
fs->fsi_flag = 0;
|
fs->fsi_flag = 0;
|
||||||
@ -811,7 +797,7 @@ FRESULT sync_fs ( /* FR_OK: successful, FR_DISK_ERR: failed */
|
|||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* Hidden API for hacks and disk tools */
|
/* Hidden API for hacks and disk tools */
|
||||||
|
|
||||||
static DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */
|
DWORD clust2sect ( /* !=0:Sector number, 0:Failed (invalid cluster#) */
|
||||||
FATFS* fs, /* File system object */
|
FATFS* fs, /* File system object */
|
||||||
DWORD clst /* Cluster# to be converted */
|
DWORD clst /* Cluster# to be converted */
|
||||||
)
|
)
|
||||||
@ -829,7 +815,7 @@ static DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */
|
|||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* Hidden API for hacks and disk tools */
|
/* Hidden API for hacks and disk tools */
|
||||||
|
|
||||||
static DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x0FFFFFFF:Cluster status */
|
DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x0FFFFFFF:Cluster status */
|
||||||
FATFS* fs, /* File system object */
|
FATFS* fs, /* File system object */
|
||||||
DWORD clst /* FAT index number (cluster number) to get the value */
|
DWORD clst /* FAT index number (cluster number) to get the value */
|
||||||
)
|
)
|
||||||
@ -839,7 +825,7 @@ static DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x0FFFFFFF
|
|||||||
DWORD val;
|
DWORD val;
|
||||||
|
|
||||||
|
|
||||||
if (clst < 2 || clst >= fs->n_fatent) { /* Check range */
|
if (clst < 2 || clst >= fs->n_fatent) { /* Check if in valid range */
|
||||||
val = 1; /* Internal error */
|
val = 1; /* Internal error */
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -884,7 +870,7 @@ static DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x0FFFFFFF
|
|||||||
/* Hidden API for hacks and disk tools */
|
/* Hidden API for hacks and disk tools */
|
||||||
|
|
||||||
#if !_FS_READONLY
|
#if !_FS_READONLY
|
||||||
static FRESULT put_fat (
|
FRESULT put_fat ( /* FR_OK(0):succeeded, !=0:error */
|
||||||
FATFS* fs, /* File system object */
|
FATFS* fs, /* File system object */
|
||||||
DWORD clst, /* FAT index number (cluster number) to be changed */
|
DWORD clst, /* FAT index number (cluster number) to be changed */
|
||||||
DWORD val /* New value to be set to the entry */
|
DWORD val /* New value to be set to the entry */
|
||||||
@ -895,7 +881,7 @@ static FRESULT put_fat (
|
|||||||
FRESULT res;
|
FRESULT res;
|
||||||
|
|
||||||
|
|
||||||
if (clst < 2 || clst >= fs->n_fatent) { /* Check range */
|
if (clst < 2 || clst >= fs->n_fatent) { /* Check if in valid range */
|
||||||
res = FR_INT_ERR;
|
res = FR_INT_ERR;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -948,7 +934,7 @@ static FRESULT put_fat (
|
|||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
#if !_FS_READONLY
|
#if !_FS_READONLY
|
||||||
static
|
static
|
||||||
FRESULT remove_chain (
|
FRESULT remove_chain ( /* FR_OK(0):succeeded, !=0:error */
|
||||||
FATFS* fs, /* File system object */
|
FATFS* fs, /* File system object */
|
||||||
DWORD clst /* Cluster# to remove a chain from */
|
DWORD clst /* Cluster# to remove a chain from */
|
||||||
)
|
)
|
||||||
@ -959,7 +945,7 @@ FRESULT remove_chain (
|
|||||||
DWORD scl = clst, ecl = clst, rt[2];
|
DWORD scl = clst, ecl = clst, rt[2];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (clst < 2 || clst >= fs->n_fatent) { /* Check range */
|
if (clst < 2 || clst >= fs->n_fatent) { /* Check if in valid range */
|
||||||
res = FR_INT_ERR;
|
res = FR_INT_ERR;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -1003,7 +989,7 @@ FRESULT remove_chain (
|
|||||||
static
|
static
|
||||||
DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */
|
DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */
|
||||||
FATFS* fs, /* File system object */
|
FATFS* fs, /* File system object */
|
||||||
DWORD clst /* Cluster# to stretch. 0 means create a new chain. */
|
DWORD clst /* Cluster# to stretch, 0:Create a new chain */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
DWORD cs, ncl, scl;
|
DWORD cs, ncl, scl;
|
||||||
@ -1091,7 +1077,7 @@ DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */
|
|||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
static
|
static
|
||||||
FRESULT dir_sdi (
|
FRESULT dir_sdi ( /* FR_OK(0):succeeded, !=0:error */
|
||||||
DIR* dp, /* Pointer to directory object */
|
DIR* dp, /* Pointer to directory object */
|
||||||
UINT idx /* Index of directory table */
|
UINT idx /* Index of directory table */
|
||||||
)
|
)
|
||||||
@ -1139,7 +1125,7 @@ FRESULT dir_sdi (
|
|||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
static
|
static
|
||||||
FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:Could not stretch */
|
FRESULT dir_next ( /* FR_OK(0):succeeded, FR_NO_FILE:End of table, FR_DENIED:Could not stretch */
|
||||||
DIR* dp, /* Pointer to the directory object */
|
DIR* dp, /* Pointer to the directory object */
|
||||||
int stretch /* 0: Do not stretch table, 1: Stretch table if needed */
|
int stretch /* 0: Do not stretch table, 1: Stretch table if needed */
|
||||||
)
|
)
|
||||||
@ -1210,7 +1196,7 @@ FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:Could
|
|||||||
|
|
||||||
#if !_FS_READONLY
|
#if !_FS_READONLY
|
||||||
static
|
static
|
||||||
FRESULT dir_alloc (
|
FRESULT dir_alloc ( /* FR_OK(0):succeeded, !=0:error */
|
||||||
DIR* dp, /* Pointer to the directory object */
|
DIR* dp, /* Pointer to the directory object */
|
||||||
UINT nent /* Number of contiguous entries to allocate (1-21) */
|
UINT nent /* Number of contiguous entries to allocate (1-21) */
|
||||||
)
|
)
|
||||||
@ -1246,9 +1232,9 @@ FRESULT dir_alloc (
|
|||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
static
|
static
|
||||||
DWORD ld_clust (
|
DWORD ld_clust ( /* Returns the top cluster value of the SFN entry */
|
||||||
FATFS* fs, /* Pointer to the fs object */
|
FATFS* fs, /* Pointer to the fs object */
|
||||||
BYTE* dir /* Pointer to the directory entry */
|
const BYTE* dir /* Pointer to the SFN entry */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
DWORD cl;
|
DWORD cl;
|
||||||
@ -1264,7 +1250,7 @@ DWORD ld_clust (
|
|||||||
#if !_FS_READONLY
|
#if !_FS_READONLY
|
||||||
static
|
static
|
||||||
void st_clust (
|
void st_clust (
|
||||||
BYTE* dir, /* Pointer to the directory entry */
|
BYTE* dir, /* Pointer to the SFN entry */
|
||||||
DWORD cl /* Value to be set */
|
DWORD cl /* Value to be set */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -1285,27 +1271,29 @@ const BYTE LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30}; /* Offset of LFN char
|
|||||||
|
|
||||||
|
|
||||||
static
|
static
|
||||||
int cmp_lfn ( /* 1:Matched, 0:Not matched */
|
int cmp_lfn ( /* 1:matched, 0:not matched */
|
||||||
WCHAR* lfnbuf, /* Pointer to the LFN to be compared */
|
WCHAR* lfnbuf, /* Pointer to the LFN working buffer to be compared */
|
||||||
BYTE* dir /* Pointer to the directory entry containing a part of LFN */
|
BYTE* dir /* Pointer to the directory entry containing the part of LFN */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
UINT i, s;
|
UINT i, s;
|
||||||
WCHAR wc, uc;
|
WCHAR wc, uc;
|
||||||
|
|
||||||
|
|
||||||
i = ((dir[LDIR_Ord] & ~LLEF) - 1) * 13; /* Get offset in the LFN buffer */
|
if (LD_WORD(dir + LDIR_FstClusLO) != 0) return 0; /* Check LDIR_FstClusLO */
|
||||||
s = 0; wc = 1;
|
|
||||||
do {
|
i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; /* Offset in the LFN buffer */
|
||||||
uc = LD_WORD(dir + LfnOfs[s]); /* Pick an LFN character from the entry */
|
|
||||||
if (wc) { /* Last character has not been processed */
|
for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */
|
||||||
wc = ff_wtoupper(uc); /* Convert it to upper case */
|
uc = LD_WORD(dir + LfnOfs[s]); /* Pick an LFN character */
|
||||||
if (i >= _MAX_LFN || wc != ff_wtoupper(lfnbuf[i++])) /* Compare it */
|
if (wc) {
|
||||||
|
if (i >= _MAX_LFN || ff_wtoupper(uc) != ff_wtoupper(lfnbuf[i++])) /* Compare it */
|
||||||
return 0; /* Not matched */
|
return 0; /* Not matched */
|
||||||
|
wc = uc;
|
||||||
} else {
|
} else {
|
||||||
if (uc != 0xFFFF) return 0; /* Check filler */
|
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 */
|
if ((dir[LDIR_Ord] & LLEF) && wc && lfnbuf[i]) /* Last segment matched but different length */
|
||||||
return 0;
|
return 0;
|
||||||
@ -1314,47 +1302,47 @@ int cmp_lfn ( /* 1:Matched, 0:Not matched */
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if _FS_MINIMIZE <= 1 || _USE_LABEL || _FS_RPATH >= 2
|
|
||||||
static
|
static
|
||||||
int pick_lfn ( /* 1:Succeeded, 0:Buffer overflow */
|
int pick_lfn ( /* 1:succeeded, 0:buffer overflow or invalid LFN entry */
|
||||||
WCHAR* lfnbuf, /* Pointer to the Unicode-LFN buffer */
|
WCHAR* lfnbuf, /* Pointer to the LFN working buffer */
|
||||||
BYTE* dir /* Pointer to the directory entry */
|
BYTE* dir /* Pointer to the LFN entry */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
UINT i, s;
|
UINT i, s;
|
||||||
WCHAR wc, uc;
|
WCHAR wc, uc;
|
||||||
|
|
||||||
|
|
||||||
|
if (LD_WORD(dir + LDIR_FstClusLO) != 0) return 0; /* Check LDIR_FstClusLO */
|
||||||
|
|
||||||
i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; /* Offset in the LFN buffer */
|
i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; /* Offset in the LFN buffer */
|
||||||
|
|
||||||
s = 0; wc = 1;
|
for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */
|
||||||
do {
|
uc = LD_WORD(dir + LfnOfs[s]); /* Pick an LFN character */
|
||||||
uc = LD_WORD(dir + LfnOfs[s]); /* Pick an LFN character from the entry */
|
if (wc) {
|
||||||
if (wc) { /* Last character has not been processed */
|
|
||||||
if (i >= _MAX_LFN) return 0; /* Buffer overflow? */
|
if (i >= _MAX_LFN) return 0; /* Buffer overflow? */
|
||||||
lfnbuf[i++] = wc = uc; /* Store it */
|
lfnbuf[i++] = wc = uc; /* Store it */
|
||||||
} else {
|
} else {
|
||||||
if (uc != 0xFFFF) return 0; /* Check filler */
|
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 (dir[LDIR_Ord] & LLEF) { /* Put terminator if it is the last LFN part */
|
||||||
if (i >= _MAX_LFN) return 0; /* Buffer overflow? */
|
if (i >= _MAX_LFN) return 0; /* Buffer overflow? */
|
||||||
lfnbuf[i] = 0;
|
lfnbuf[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1; /* The part of LFN is valid */
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if !_FS_READONLY
|
#if !_FS_READONLY
|
||||||
static
|
static
|
||||||
void fit_lfn (
|
void fit_lfn (
|
||||||
const WCHAR* lfnbuf, /* Pointer to the LFN buffer */
|
const WCHAR* lfnbuf, /* Pointer to the LFN working buffer */
|
||||||
BYTE* dir, /* Pointer to the directory entry */
|
BYTE* dir, /* Pointer to the LFN entry to be processed */
|
||||||
BYTE ord, /* LFN order (1-20) */
|
BYTE ord, /* LFN order (1-20) */
|
||||||
BYTE sum /* SFN sum */
|
BYTE sum /* Checksum of the corresponding SFN */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
UINT i, s;
|
UINT i, s;
|
||||||
@ -1366,7 +1354,7 @@ void fit_lfn (
|
|||||||
dir[LDIR_Type] = 0;
|
dir[LDIR_Type] = 0;
|
||||||
ST_WORD(dir + LDIR_FstClusLO, 0);
|
ST_WORD(dir + LDIR_FstClusLO, 0);
|
||||||
|
|
||||||
i = (ord - 1) * 13; /* Get offset in the LFN buffer */
|
i = (ord - 1) * 13; /* Get offset in the LFN working buffer */
|
||||||
s = wc = 0;
|
s = wc = 0;
|
||||||
do {
|
do {
|
||||||
if (wc != 0xFFFF) wc = lfnbuf[i++]; /* Get an effective character */
|
if (wc != 0xFFFF) wc = lfnbuf[i++]; /* Get an effective character */
|
||||||
@ -1386,7 +1374,7 @@ void fit_lfn (
|
|||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* Create numbered name */
|
/* Create numbered name */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
#if _USE_LFN && !_FS_READONLY
|
#if _USE_LFN
|
||||||
static
|
static
|
||||||
void gen_numname (
|
void gen_numname (
|
||||||
BYTE* dst, /* Pointer to the buffer to store numbered SFN */
|
BYTE* dst, /* Pointer to the buffer to store numbered SFN */
|
||||||
@ -1443,7 +1431,7 @@ void gen_numname (
|
|||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* Calculate sum of an SFN */
|
/* Calculate checksum of an SFN entry */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
#if _USE_LFN
|
#if _USE_LFN
|
||||||
static
|
static
|
||||||
@ -1467,7 +1455,7 @@ BYTE sum_sfn (
|
|||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
static
|
static
|
||||||
FRESULT dir_find (
|
FRESULT dir_find ( /* FR_OK(0):succeeded, !=0:error */
|
||||||
DIR* dp /* Pointer to the directory object linked to the file name */
|
DIR* dp /* Pointer to the directory object linked to the file name */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -1587,7 +1575,7 @@ FRESULT dir_read (
|
|||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
#if !_FS_READONLY
|
#if !_FS_READONLY
|
||||||
static
|
static
|
||||||
FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many SFN collision, FR_DISK_ERR:Disk error */
|
FRESULT dir_register ( /* FR_OK:succeeded, 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 */
|
DIR* dp /* Target directory with object name to be created */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -1627,7 +1615,7 @@ FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many
|
|||||||
if (res == FR_OK && --nent) { /* Set LFN entry if needed */
|
if (res == FR_OK && --nent) { /* Set LFN entry if needed */
|
||||||
res = dir_sdi(dp, dp->index - nent);
|
res = dir_sdi(dp, dp->index - nent);
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
sum = sum_sfn(dp->fn); /* Sum value of the SFN tied to the LFN */
|
sum = sum_sfn(dp->fn); /* Checksum value of the SFN tied to the LFN */
|
||||||
do { /* Store LFN entries in bottom first */
|
do { /* Store LFN entries in bottom first */
|
||||||
res = move_window(dp->fs, dp->sect);
|
res = move_window(dp->fs, dp->sect);
|
||||||
if (res != FR_OK) break;
|
if (res != FR_OK) break;
|
||||||
@ -1665,7 +1653,7 @@ FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many
|
|||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
#if !_FS_READONLY && !_FS_MINIMIZE
|
#if !_FS_READONLY && !_FS_MINIMIZE
|
||||||
static
|
static
|
||||||
FRESULT dir_remove ( /* FR_OK: Successful, FR_DISK_ERR: A disk error */
|
FRESULT dir_remove ( /* FR_OK:Succeeded, FR_DISK_ERR:A disk error */
|
||||||
DIR* dp /* Directory object pointing the entry to be removed */
|
DIR* dp /* Directory object pointing the entry to be removed */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -1804,7 +1792,7 @@ WCHAR get_achar ( /* Get a character and advances ptr 1 or 2 */
|
|||||||
|
|
||||||
|
|
||||||
static
|
static
|
||||||
int pattern_matching ( /* Return value: 0:mismatched, 1:matched */
|
int pattern_matching ( /* 0:mismatched, 1:matched */
|
||||||
const TCHAR* pat, /* Matching pattern */
|
const TCHAR* pat, /* Matching pattern */
|
||||||
const TCHAR* nam, /* String to be tested */
|
const TCHAR* nam, /* String to be tested */
|
||||||
int skip, /* Number of pre-skip chars (number of ?s) */
|
int skip, /* Number of pre-skip chars (number of ?s) */
|
||||||
@ -1848,11 +1836,11 @@ int pattern_matching ( /* Return value: 0:mismatched, 1:matched */
|
|||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* Pick a segment and create the object name in directory form */
|
/* Pick a top segment and create the object name in directory form */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
static
|
static
|
||||||
FRESULT create_name (
|
FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not create */
|
||||||
DIR* dp, /* Pointer to the directory object */
|
DIR* dp, /* Pointer to the directory object */
|
||||||
const TCHAR** path /* Pointer to pointer to the segment in the path string */
|
const TCHAR** path /* Pointer to pointer to the segment in the path string */
|
||||||
)
|
)
|
||||||
@ -1890,22 +1878,21 @@ FRESULT create_name (
|
|||||||
*path = &p[si]; /* Return pointer to the next segment */
|
*path = &p[si]; /* Return pointer to the next segment */
|
||||||
cf = (w < ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */
|
cf = (w < ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */
|
||||||
#if _FS_RPATH
|
#if _FS_RPATH
|
||||||
if ((di == 1 && lfn[di - 1] == '.') || /* Is this a dot entry? */
|
if ((di == 1 && lfn[di - 1] == '.') ||
|
||||||
(di == 2 && lfn[di - 1] == '.' && lfn[di - 2] == '.')) {
|
(di == 2 && lfn[di - 1] == '.' && lfn[di - 2] == '.')) { /* Is this segment a dot entry? */
|
||||||
lfn[di] = 0;
|
lfn[di] = 0;
|
||||||
for (i = 0; i < 11; i++)
|
for (i = 0; i < 11; i++) /* Create dot name for SFN entry */
|
||||||
dp->fn[i] = (i < di) ? '.' : ' ';
|
dp->fn[i] = (i < di) ? '.' : ' ';
|
||||||
dp->fn[i] = cf | NS_DOT; /* This is a dot entry */
|
dp->fn[i] = cf | NS_DOT; /* This is a dot entry */
|
||||||
return FR_OK;
|
return FR_OK;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
while (di) { /* Strip trailing spaces and dots */
|
while (di) { /* Snip off trailing spaces and dots if exist */
|
||||||
w = lfn[di - 1];
|
w = lfn[di - 1];
|
||||||
if (w != ' ' && w != '.') break;
|
if (w != ' ' && w != '.') break;
|
||||||
di--;
|
di--;
|
||||||
}
|
}
|
||||||
if (!di) return FR_INVALID_NAME; /* Reject nul string */
|
if (!di) return FR_INVALID_NAME; /* Reject nul string */
|
||||||
|
|
||||||
lfn[di] = 0; /* LFN is created */
|
lfn[di] = 0; /* LFN is created */
|
||||||
|
|
||||||
/* Create SFN in directory form */
|
/* Create SFN in directory form */
|
||||||
@ -1942,7 +1929,7 @@ FRESULT create_name (
|
|||||||
cf |= NS_LFN; /* Force create LFN entry */
|
cf |= NS_LFN; /* Force create LFN entry */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_DF1S && w >= 0x100) { /* DBC (always false at SBCS cfg) */
|
if (_DF1S && w >= 0x100) { /* Is this DBC? (always false at SBCS cfg) */
|
||||||
if (i >= ni - 1) {
|
if (i >= ni - 1) {
|
||||||
cf |= NS_LOSS | NS_LFN; i = ni; continue;
|
cf |= NS_LOSS | NS_LFN; i = ni; continue;
|
||||||
}
|
}
|
||||||
@ -1963,7 +1950,7 @@ FRESULT create_name (
|
|||||||
dp->fn[i++] = (BYTE)w;
|
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 (dp->fn[0] == DDEM) dp->fn[0] = RDDEM; /* If the first character collides with DDEM, replace it with RDDEM */
|
||||||
|
|
||||||
if (ni == 8) b <<= 2;
|
if (ni == 8) b <<= 2;
|
||||||
if ((b & 0x0C) == 0x0C || (b & 0x03) == 0x03) /* Create LFN entry when there are composite capitals */
|
if ((b & 0x0C) == 0x0C || (b & 0x03) == 0x03) /* Create LFN entry when there are composite capitals */
|
||||||
@ -1984,7 +1971,7 @@ FRESULT create_name (
|
|||||||
const char *p;
|
const char *p;
|
||||||
|
|
||||||
/* Create file name in directory form */
|
/* Create file name in directory form */
|
||||||
for (p = *path; *p == '/' || *p == '\\'; p++) ; /* Strip duplicated separator */
|
for (p = *path; *p == '/' || *p == '\\'; p++) ; /* Skip duplicated separator */
|
||||||
sfn = dp->fn;
|
sfn = dp->fn;
|
||||||
mem_set(sfn, ' ', 11);
|
mem_set(sfn, ' ', 11);
|
||||||
si = i = b = 0; ni = 8;
|
si = i = b = 0; ni = 8;
|
||||||
@ -2019,7 +2006,7 @@ FRESULT create_name (
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (IsDBCS1(c)) { /* Check if it is a DBC 1st byte (always false on SBCS cfg) */
|
if (IsDBCS1(c)) { /* Check if it is a DBC 1st byte (always false at SBCS cfg.) */
|
||||||
d = (BYTE)p[si++]; /* Get 2nd byte */
|
d = (BYTE)p[si++]; /* Get 2nd byte */
|
||||||
if (!IsDBCS2(d) || i >= ni - 1) /* Reject invalid DBC */
|
if (!IsDBCS2(d) || i >= ni - 1) /* Reject invalid DBC */
|
||||||
return FR_INVALID_NAME;
|
return FR_INVALID_NAME;
|
||||||
@ -2185,7 +2172,7 @@ int get_ldnumber ( /* Returns logical drive number (-1:invalid drive) */
|
|||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
static
|
static
|
||||||
BYTE check_fs ( /* 0:FAT boor sector, 1:Valid boor sector but not FAT, 2:Not a boot sector, 3:Disk error */
|
BYTE check_fs ( /* 0:Valid FAT-BS, 1:Valid BS but not FAT, 2:Not a BS, 3:Disk error */
|
||||||
FATFS* fs, /* File system object */
|
FATFS* fs, /* File system object */
|
||||||
DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */
|
DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */
|
||||||
)
|
)
|
||||||
@ -2343,7 +2330,7 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */
|
|||||||
/* Get fsinfo if available */
|
/* Get fsinfo if available */
|
||||||
fs->fsi_flag = 0x80;
|
fs->fsi_flag = 0x80;
|
||||||
#if (_FS_NOFSINFO & 3) != 3
|
#if (_FS_NOFSINFO & 3) != 3
|
||||||
if (fmt == FS_FAT32 /* Enable FSINFO only if FAT32 and BPB_FSInfo is 1 */
|
if (fmt == FS_FAT32 /* Enable FSINFO only if FAT32 and BPB_FSInfo == 1 */
|
||||||
&& LD_WORD(fs->win + BPB_FSInfo) == 1
|
&& LD_WORD(fs->win + BPB_FSInfo) == 1
|
||||||
&& move_window(fs, bsect + 1) == FR_OK)
|
&& move_window(fs, bsect + 1) == FR_OK)
|
||||||
{
|
{
|
||||||
@ -2389,14 +2376,11 @@ FRESULT validate ( /* FR_OK(0): The object is valid, !=0: Invalid */
|
|||||||
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)
|
if (!fil || !fil->fs || !fil->fs->fs_type || fil->fs->id != fil->id || (disk_status(fil->fs->drv) & STA_NOINIT))
|
||||||
return FR_INVALID_OBJECT;
|
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;
|
|
||||||
|
|
||||||
return FR_OK;
|
return FR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2407,7 +2391,7 @@ FRESULT validate ( /* FR_OK(0): The object is valid, !=0: Invalid */
|
|||||||
|
|
||||||
Public Functions
|
Public Functions
|
||||||
|
|
||||||
--------------------------------------------------------------------------*/
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -2522,12 +2506,13 @@ FRESULT f_open (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate it if overwrite mode */
|
if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate it if overwrite mode */
|
||||||
dw = GET_FATTIME(); /* Created time */
|
dw = GET_FATTIME();
|
||||||
ST_DWORD(dir + DIR_CrtTime, dw);
|
ST_DWORD(dir + DIR_CrtTime, dw);/* Set created time */
|
||||||
|
ST_DWORD(dir + DIR_WrtTime, dw);/* Set modified time */
|
||||||
dir[DIR_Attr] = 0; /* Reset attribute */
|
dir[DIR_Attr] = 0; /* Reset attribute */
|
||||||
ST_DWORD(dir + DIR_FileSize, 0);/* size = 0 */
|
ST_DWORD(dir + DIR_FileSize, 0);/* Reset file size */
|
||||||
cl = ld_clust(dj.fs, dir); /* Get start cluster */
|
cl = ld_clust(dj.fs, dir); /* Get cluster chain */
|
||||||
st_clust(dir, 0); /* cluster = 0 */
|
st_clust(dir, 0); /* Reset cluster */
|
||||||
dj.fs->wflag = 1;
|
dj.fs->wflag = 1;
|
||||||
if (cl) { /* Remove the cluster chain if exist */
|
if (cl) { /* Remove the cluster chain if exist */
|
||||||
dw = dj.fs->winsect;
|
dw = dj.fs->winsect;
|
||||||
@ -2540,7 +2525,7 @@ FRESULT f_open (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { /* Open an existing file */
|
else { /* Open an existing file */
|
||||||
if (res == FR_OK) { /* Follow succeeded */
|
if (res == FR_OK) { /* Following succeeded */
|
||||||
if (dir[DIR_Attr] & AM_DIR) { /* It is a directory */
|
if (dir[DIR_Attr] & AM_DIR) { /* It is a directory */
|
||||||
res = FR_NO_FILE;
|
res = FR_NO_FILE;
|
||||||
} else {
|
} else {
|
||||||
@ -2832,10 +2817,9 @@ FRESULT f_sync (
|
|||||||
|
|
||||||
res = validate(fp); /* Check validity of the object */
|
res = validate(fp); /* Check validity of the object */
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
if (fp->flag & FA__WRITTEN) { /* Has the file been written? */
|
if (fp->flag & FA__WRITTEN) { /* Is there any change to the file? */
|
||||||
/* Write-back dirty buffer */
|
|
||||||
#if !_FS_TINY
|
#if !_FS_TINY
|
||||||
if (fp->flag & FA__DIRTY) {
|
if (fp->flag & FA__DIRTY) { /* Write-back cached data if needed */
|
||||||
if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
|
if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
|
||||||
LEAVE_FF(fp->fs, FR_DISK_ERR);
|
LEAVE_FF(fp->fs, FR_DISK_ERR);
|
||||||
fp->flag &= ~FA__DIRTY;
|
fp->flag &= ~FA__DIRTY;
|
||||||
@ -2848,7 +2832,7 @@ FRESULT f_sync (
|
|||||||
dir[DIR_Attr] |= AM_ARC; /* Set archive bit */
|
dir[DIR_Attr] |= AM_ARC; /* Set archive bit */
|
||||||
ST_DWORD(dir + DIR_FileSize, fp->fsize); /* Update file size */
|
ST_DWORD(dir + DIR_FileSize, fp->fsize); /* Update file size */
|
||||||
st_clust(dir, fp->sclust); /* Update start cluster */
|
st_clust(dir, fp->sclust); /* Update start cluster */
|
||||||
tm = GET_FATTIME(); /* Update updated time */
|
tm = GET_FATTIME(); /* Update modified time */
|
||||||
ST_DWORD(dir + DIR_WrtTime, tm);
|
ST_DWORD(dir + DIR_WrtTime, tm);
|
||||||
ST_WORD(dir + DIR_LstAccDate, 0);
|
ST_WORD(dir + DIR_LstAccDate, 0);
|
||||||
fp->flag &= ~FA__WRITTEN;
|
fp->flag &= ~FA__WRITTEN;
|
||||||
@ -3425,7 +3409,7 @@ FRESULT f_getfree (
|
|||||||
{
|
{
|
||||||
FRESULT res;
|
FRESULT res;
|
||||||
FATFS *fs;
|
FATFS *fs;
|
||||||
DWORD n, clst, sect, stat;
|
DWORD nfree, clst, sect, stat;
|
||||||
UINT i;
|
UINT i;
|
||||||
BYTE fat, *p;
|
BYTE fat, *p;
|
||||||
|
|
||||||
@ -3440,18 +3424,17 @@ FRESULT f_getfree (
|
|||||||
} else {
|
} else {
|
||||||
/* Get number of free clusters */
|
/* Get number of free clusters */
|
||||||
fat = fs->fs_type;
|
fat = fs->fs_type;
|
||||||
n = 0;
|
nfree = 0;
|
||||||
if (fat == FS_FAT12) {
|
if (fat == FS_FAT12) { /* Sector unalighed entries: Search FAT via regular routine. */
|
||||||
clst = 2;
|
clst = 2;
|
||||||
do {
|
do {
|
||||||
stat = get_fat(fs, clst);
|
stat = get_fat(fs, clst);
|
||||||
if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; }
|
if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; }
|
||||||
if (stat == 1) { res = FR_INT_ERR; break; }
|
if (stat == 1) { res = FR_INT_ERR; break; }
|
||||||
if (stat == 0) n++;
|
if (stat == 0) nfree++;
|
||||||
} while (++clst < fs->n_fatent);
|
} while (++clst < fs->n_fatent);
|
||||||
} else {
|
} else { /* Sector alighed entries: Accelerate the FAT search. */
|
||||||
clst = fs->n_fatent;
|
clst = fs->n_fatent; sect = fs->fatbase;
|
||||||
sect = fs->fatbase;
|
|
||||||
i = 0; p = 0;
|
i = 0; p = 0;
|
||||||
do {
|
do {
|
||||||
if (!i) {
|
if (!i) {
|
||||||
@ -3461,17 +3444,17 @@ FRESULT f_getfree (
|
|||||||
i = SS(fs);
|
i = SS(fs);
|
||||||
}
|
}
|
||||||
if (fat == FS_FAT16) {
|
if (fat == FS_FAT16) {
|
||||||
if (LD_WORD(p) == 0) n++;
|
if (LD_WORD(p) == 0) nfree++;
|
||||||
p += 2; i -= 2;
|
p += 2; i -= 2;
|
||||||
} else {
|
} else {
|
||||||
if ((LD_DWORD(p) & 0x0FFFFFFF) == 0) n++;
|
if ((LD_DWORD(p) & 0x0FFFFFFF) == 0) nfree++;
|
||||||
p += 4; i -= 4;
|
p += 4; i -= 4;
|
||||||
}
|
}
|
||||||
} while (--clst);
|
} while (--clst);
|
||||||
}
|
}
|
||||||
fs->free_clust = n;
|
fs->free_clust = nfree; /* free_clust is valid */
|
||||||
fs->fsi_flag |= 1;
|
fs->fsi_flag |= 1; /* FSInfo is to be updated */
|
||||||
*nclst = n;
|
*nclst = nfree; /* Return the free clusters */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LEAVE_FF(fs, res);
|
LEAVE_FF(fs, res);
|
||||||
@ -3695,8 +3678,7 @@ FRESULT f_chmod (
|
|||||||
DEFINE_NAMEBUF;
|
DEFINE_NAMEBUF;
|
||||||
|
|
||||||
|
|
||||||
/* Get logical drive number */
|
res = find_volume(&dj.fs, &path, 1); /* Get logical drive number */
|
||||||
res = find_volume(&dj.fs, &path, 1);
|
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
INIT_BUF(dj);
|
INIT_BUF(dj);
|
||||||
res = follow_path(&dj, path); /* Follow the file path */
|
res = follow_path(&dj, path); /* Follow the file path */
|
||||||
@ -4263,7 +4245,7 @@ FRESULT f_mkfs (
|
|||||||
ST_WORD(tbl + BS_55AA, 0xAA55); /* Signature (Offset is fixed here regardless of sector size) */
|
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 */
|
if (disk_write(pdrv, tbl, b_vol, 1) != RES_OK) /* Write it to the VBR sector */
|
||||||
return FR_DISK_ERR;
|
return FR_DISK_ERR;
|
||||||
if (fmt == FS_FAT32) /* Write backup VBR if needed (VBR + 6) */
|
if (fmt == FS_FAT32) /* Write it to the backup VBR if needed (VBR + 6) */
|
||||||
disk_write(pdrv, tbl, b_vol + 6, 1);
|
disk_write(pdrv, tbl, b_vol + 6, 1);
|
||||||
|
|
||||||
/* Initialize FAT area */
|
/* Initialize FAT area */
|
||||||
|
6
source/fatfs/ff.h
Normal file → Executable file
6
source/fatfs/ff.h
Normal file → Executable file
@ -1,5 +1,5 @@
|
|||||||
/*---------------------------------------------------------------------------/
|
/*---------------------------------------------------------------------------/
|
||||||
/ FatFs - FAT file system module include R0.11 (C)ChaN, 2015
|
/ FatFs - FAT file system module include R0.11a (C)ChaN, 2015
|
||||||
/----------------------------------------------------------------------------/
|
/----------------------------------------------------------------------------/
|
||||||
/ FatFs module is a free software that opened under license policy of
|
/ FatFs module is a free software that opened under license policy of
|
||||||
/ following conditions.
|
/ following conditions.
|
||||||
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#ifndef _FATFS
|
#ifndef _FATFS
|
||||||
#define _FATFS 32020 /* Revision ID */
|
#define _FATFS 64180 /* Revision ID */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -200,7 +200,7 @@ typedef enum {
|
|||||||
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
|
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_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_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
|
||||||
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_SHARE */
|
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_LOCK */
|
||||||
FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
|
FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
|
||||||
} FRESULT;
|
} FRESULT;
|
||||||
|
|
||||||
|
49
source/fatfs/ffconf.h
Normal file → Executable file
49
source/fatfs/ffconf.h
Normal file → Executable file
@ -1,21 +1,13 @@
|
|||||||
/*---------------------------------------------------------------------------/
|
/*---------------------------------------------------------------------------/
|
||||||
/ FatFs - FAT file system module configuration file R0.11 (C)ChaN, 2015
|
/ FatFs - FAT file system module configuration file R0.11a (C)ChaN, 2015
|
||||||
/---------------------------------------------------------------------------*/
|
/---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#define _FFCONF 32020 /* Revision ID */
|
#define _FFCONF 64180 /* Revision ID */
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------/
|
/*---------------------------------------------------------------------------/
|
||||||
/ Functions and Buffer Configurations
|
/ Function Configurations
|
||||||
/---------------------------------------------------------------------------*/
|
/---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#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)
|
/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
|
||||||
/ Read-only configuration removes writing API functions, f_write(), f_sync(),
|
/ Read-only configuration removes writing API functions, f_write(), f_sync(),
|
||||||
@ -23,7 +15,7 @@
|
|||||||
/ and optional writing functions as well. */
|
/ and optional writing functions as well. */
|
||||||
|
|
||||||
|
|
||||||
#define _FS_MINIMIZE 0
|
#define _FS_MINIMIZE 1
|
||||||
/* This option defines minimization level to remove some basic API functions.
|
/* This option defines minimization level to remove some basic API functions.
|
||||||
/
|
/
|
||||||
/ 0: All basic functions are enabled.
|
/ 0: All basic functions are enabled.
|
||||||
@ -77,19 +69,24 @@
|
|||||||
/ 437 - U.S.
|
/ 437 - U.S.
|
||||||
/ 720 - Arabic
|
/ 720 - Arabic
|
||||||
/ 737 - Greek
|
/ 737 - Greek
|
||||||
|
/ 771 - KBL
|
||||||
/ 775 - Baltic
|
/ 775 - Baltic
|
||||||
/ 850 - Multilingual Latin 1
|
/ 850 - Latin 1
|
||||||
/ 852 - Latin 2
|
/ 852 - Latin 2
|
||||||
/ 855 - Cyrillic
|
/ 855 - Cyrillic
|
||||||
/ 857 - Turkish
|
/ 857 - Turkish
|
||||||
/ 858 - Multilingual Latin 1 + Euro
|
/ 860 - Portuguese
|
||||||
|
/ 861 - Icelandic
|
||||||
/ 862 - Hebrew
|
/ 862 - Hebrew
|
||||||
|
/ 863 - Canadian French
|
||||||
|
/ 864 - Arabic
|
||||||
|
/ 865 - Nordic
|
||||||
/ 866 - Russian
|
/ 866 - Russian
|
||||||
/ 874 - Thai
|
/ 869 - Greek 2
|
||||||
/ 932 - Japanese Shift_JIS (DBCS)
|
/ 932 - Japanese (DBCS)
|
||||||
/ 936 - Simplified Chinese GBK (DBCS)
|
/ 936 - Simplified Chinese (DBCS)
|
||||||
/ 949 - Korean (DBCS)
|
/ 949 - Korean (DBCS)
|
||||||
/ 950 - Traditional Chinese Big5 (DBCS)
|
/ 950 - Traditional Chinese (DBCS)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@ -115,7 +112,7 @@
|
|||||||
/ to 1. This option also affects behavior of string I/O functions. */
|
/ to 1. This option also affects behavior of string I/O functions. */
|
||||||
|
|
||||||
|
|
||||||
#define _STRF_ENCODE 0
|
#define _STRF_ENCODE 3
|
||||||
/* When _LFN_UNICODE is 1, this option selects the character encoding on the file to
|
/* 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().
|
/ be read/written via string I/O functions, f_gets(), f_putc(), f_puts and f_printf().
|
||||||
/
|
/
|
||||||
@ -141,7 +138,7 @@
|
|||||||
/ Drive/Volume Configurations
|
/ Drive/Volume Configurations
|
||||||
/---------------------------------------------------------------------------*/
|
/---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#define _VOLUMES 1
|
#define _VOLUMES 2
|
||||||
/* Number of volumes (logical drives) to be used. */
|
/* Number of volumes (logical drives) to be used. */
|
||||||
|
|
||||||
|
|
||||||
@ -195,8 +192,16 @@
|
|||||||
/ System Configurations
|
/ System Configurations
|
||||||
/---------------------------------------------------------------------------*/
|
/---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#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_NORTC 1
|
#define _FS_NORTC 1
|
||||||
#define _NORTC_MON 2
|
#define _NORTC_MON 1
|
||||||
#define _NORTC_MDAY 1
|
#define _NORTC_MDAY 1
|
||||||
#define _NORTC_YEAR 2015
|
#define _NORTC_YEAR 2015
|
||||||
/* The _FS_NORTC option switches timestamp feature. If the system does not have
|
/* The _FS_NORTC option switches timestamp feature. If the system does not have
|
||||||
@ -253,7 +258,7 @@
|
|||||||
/ * Byte order on the memory is little-endian.
|
/ * Byte order on the memory is little-endian.
|
||||||
/
|
/
|
||||||
/ If it is the case, _WORD_ACCESS can also be set to 1 to reduce code size.
|
/ If it is the case, _WORD_ACCESS can also be set to 1 to reduce code size.
|
||||||
/ Following table shows allowable settings of some processor types.
|
/ Following table shows allowable settings of some type of processors.
|
||||||
/
|
/
|
||||||
/ ARM7TDMI 0 *2 ColdFire 0 *1 V850E 0 *2
|
/ ARM7TDMI 0 *2 ColdFire 0 *1 V850E 0 *2
|
||||||
/ Cortex-M3 0 *3 Z80 0/1 V850ES 0/1
|
/ Cortex-M3 0 *3 Z80 0/1 V850ES 0/1
|
||||||
|
10
source/fatfs/integer.h
Normal file → Executable file
10
source/fatfs/integer.h
Normal file → Executable file
@ -5,26 +5,26 @@
|
|||||||
#ifndef _FF_INTEGER
|
#ifndef _FF_INTEGER
|
||||||
#define _FF_INTEGER
|
#define _FF_INTEGER
|
||||||
|
|
||||||
#ifdef _WIN32 /* FatFs development platform */
|
#ifdef _WIN32 /* Development platform */
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
|
|
||||||
#else /* Embedded platform */
|
#else /* Embedded platform */
|
||||||
|
|
||||||
/* This type MUST be 8 bit */
|
/* This type MUST be 8-bit */
|
||||||
typedef unsigned char BYTE;
|
typedef unsigned char BYTE;
|
||||||
|
|
||||||
/* These types MUST be 16 bit */
|
/* These types MUST be 16-bit */
|
||||||
typedef short SHORT;
|
typedef short SHORT;
|
||||||
typedef unsigned short WORD;
|
typedef unsigned short WORD;
|
||||||
typedef unsigned short WCHAR;
|
typedef unsigned short WCHAR;
|
||||||
|
|
||||||
/* These types MUST be 16 bit or 32 bit */
|
/* These types MUST be 16-bit or 32-bit */
|
||||||
typedef int INT;
|
typedef int INT;
|
||||||
typedef unsigned int UINT;
|
typedef unsigned int UINT;
|
||||||
|
|
||||||
/* These types MUST be 32 bit */
|
/* These types MUST be 32-bit */
|
||||||
typedef long LONG;
|
typedef long LONG;
|
||||||
typedef unsigned long DWORD;
|
typedef unsigned long DWORD;
|
||||||
|
|
||||||
|
348
source/fatfs/option/ccsbcs.c
Executable file
348
source/fatfs/option/ccsbcs.c
Executable file
@ -0,0 +1,348 @@
|
|||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* Unicode - Local code bidirectional converter (C)ChaN, 2015 */
|
||||||
|
/* (SBCS code pages) */
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* 437 U.S.
|
||||||
|
/ 720 Arabic
|
||||||
|
/ 737 Greek
|
||||||
|
/ 771 KBL
|
||||||
|
/ 775 Baltic
|
||||||
|
/ 850 Latin 1
|
||||||
|
/ 852 Latin 2
|
||||||
|
/ 855 Cyrillic
|
||||||
|
/ 857 Turkish
|
||||||
|
/ 860 Portuguese
|
||||||
|
/ 861 Icelandic
|
||||||
|
/ 862 Hebrew
|
||||||
|
/ 863 Canadian French
|
||||||
|
/ 864 Arabic
|
||||||
|
/ 865 Nordic
|
||||||
|
/ 866 Russian
|
||||||
|
/ 869 Greek 2
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../ff.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if _CODE_PAGE == 437
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR 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
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 720
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP720(0x80-0xFF) to Unicode conversion table */
|
||||||
|
0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000,
|
||||||
|
0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9, 0x0621, 0x0622, 0x0623, 0x0624, 0x00A3, 0x0625, 0x0626, 0x0627,
|
||||||
|
0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 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,
|
||||||
|
0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0641, 0x00B5, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A,
|
||||||
|
0x2261, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, 0x0650, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 737
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP737(0x80-0xFF) to Unicode conversion table */
|
||||||
|
0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0,
|
||||||
|
0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8,
|
||||||
|
0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8,
|
||||||
|
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,
|
||||||
|
0x03C9, 0x03AC, 0x03AD, 0x03AE, 0x03CA, 0x03AF, 0x03CC, 0x03CD, 0x03CB, 0x03CE, 0x0386, 0x0388, 0x0389, 0x038A, 0x038C, 0x038E,
|
||||||
|
0x038F, 0x00B1, 0x2265, 0x2264, 0x03AA, 0x03AB, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 771
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP771(0x80-0xFF) to Unicode conversion table */
|
||||||
|
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
|
||||||
|
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
|
||||||
|
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
|
||||||
|
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 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, 0x0104, 0x0105, 0x010C, 0x010D,
|
||||||
|
0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
|
||||||
|
0x0118, 0x0119, 0x0116, 0x0117, 0x012E, 0x012F, 0x0160, 0x0161, 0x0172, 0x0173, 0x016A, 0x016B, 0x017D, 0x017E, 0x25A0, 0x00A0
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 775
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP775(0x80-0xFF) to Unicode conversion table */
|
||||||
|
0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107, 0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5,
|
||||||
|
0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x00A4,
|
||||||
|
0x0100, 0x012A, 0x00F3, 0x017B, 0x017C, 0x017A, 0x201D, 0x00A6, 0x00A9, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x0141, 0x00AB, 0x00BB,
|
||||||
|
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0104, 0x010C, 0x0118, 0x0116, 0x2563, 0x2551, 0x2557, 0x255D, 0x012E, 0x0160, 0x2510,
|
||||||
|
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0172, 0x016A, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x017D,
|
||||||
|
0x0105, 0x010D, 0x0119, 0x0117, 0x012F, 0x0161, 0x0173, 0x016B, 0x017E, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
|
||||||
|
0x00D3, 0x00DF, 0x014C, 0x0143, 0x00F5, 0x00D5, 0x00B5, 0x0144, 0x0136, 0x0137, 0x013B, 0x013C, 0x0146, 0x0112, 0x0145, 0x2019,
|
||||||
|
0x00AD, 0x00B1, 0x201C, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x201E, 0x00B0, 0x2219, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 850
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP850(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, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192,
|
||||||
|
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
|
||||||
|
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510,
|
||||||
|
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
|
||||||
|
0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE, 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580,
|
||||||
|
0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4,
|
||||||
|
0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 852
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP852(0x80-0xFF) to Unicode conversion table */
|
||||||
|
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7, 0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106,
|
||||||
|
0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x0164, 0x0165, 0x0141, 0x00D7, 0x010D,
|
||||||
|
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x0104, 0x0105, 0x017D, 0x017E, 0x0118, 0x0119, 0x00AC, 0x017A, 0x010C, 0x015F, 0x00AB, 0x00BB,
|
||||||
|
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x011A, 0x015E, 0x2563, 0x2551, 0x2557, 0x255D, 0x017B, 0x017C, 0x2510,
|
||||||
|
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0102, 0x0103, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
|
||||||
|
0x0111, 0x0110, 0x010E, 0x00CB, 0x010F, 0x0147, 0x00CD, 0x00CE, 0x011B, 0x2518, 0x250C, 0x2588, 0x2584, 0x0162, 0x016E, 0x2580,
|
||||||
|
0x00D3, 0x00DF, 0x00D4, 0x0143, 0x0144, 0x0148, 0x0160, 0x0161, 0x0154, 0x00DA, 0x0155, 0x0170, 0x00FD, 0x00DD, 0x0163, 0x00B4,
|
||||||
|
0x00AD, 0x02DD, 0x02DB, 0x02C7, 0x02D8, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x02D9, 0x0171, 0x0158, 0x0159, 0x25A0, 0x00A0
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 855
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP855(0x80-0xFF) to Unicode conversion table */
|
||||||
|
0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404, 0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408,
|
||||||
|
0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C, 0x045E, 0x040E, 0x045F, 0x040F, 0x044E, 0x042E, 0x044A, 0x042A,
|
||||||
|
0x0430, 0x0410, 0x0431, 0x0411, 0x0446, 0x0426, 0x0434, 0x0414, 0x0435, 0x0415, 0x0444, 0x0424, 0x0433, 0x0413, 0x00AB, 0x00BB,
|
||||||
|
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0445, 0x0425, 0x0438, 0x0418, 0x2563, 0x2551, 0x2557, 0x255D, 0x0439, 0x0419, 0x2510,
|
||||||
|
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x043A, 0x041A, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
|
||||||
|
0x043B, 0x041B, 0x043C, 0x041C, 0x043D, 0x041D, 0x043E, 0x041E, 0x043F, 0x2518, 0x250C, 0x2588, 0x2584, 0x041F, 0x044F, 0x2580,
|
||||||
|
0x042F, 0x0440, 0x0420, 0x0441, 0x0421, 0x0442, 0x0422, 0x0443, 0x0423, 0x0436, 0x0416, 0x0432, 0x0412, 0x044C, 0x042C, 0x2116,
|
||||||
|
0x00AD, 0x044B, 0x042B, 0x0437, 0x0417, 0x0448, 0x0428, 0x044D, 0x042D, 0x0449, 0x0429, 0x0447, 0x0427, 0x00A7, 0x25A0, 0x00A0
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 857
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP857(0x80-0xFF) to Unicode conversion table */
|
||||||
|
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5,
|
||||||
|
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x0130, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x015E, 0x015F,
|
||||||
|
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x011E, 0x011F, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
|
||||||
|
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510,
|
||||||
|
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
|
||||||
|
0x00BA, 0x00AA, 0x00CA, 0x00CB, 0x00C8, 0x0000, 0x00CD, 0x00CE, 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580,
|
||||||
|
0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x0000, 0x00D7, 0x00DA, 0x00DB, 0x00D9, 0x00EC, 0x00FF, 0x00AF, 0x00B4,
|
||||||
|
0x00AD, 0x00B1, 0x0000, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 860
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP860(0x80-0xFF) to Unicode conversion table */
|
||||||
|
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E3, 0x00E0, 0x00C1, 0x00E7, 0x00EA, 0x00CA, 0x00E8, 0x00CD, 0x00D4, 0x00EC, 0x00C3, 0x00C2,
|
||||||
|
0x00C9, 0x00C0, 0x00C8, 0x00F4, 0x00F5, 0x00F2, 0x00DA, 0x00F9, 0x00CC, 0x00D5, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x20A7, 0x00D3,
|
||||||
|
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00D2, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
|
||||||
|
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 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
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 861
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP861(0x80-0xFF) to Unicode conversion table */
|
||||||
|
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00D0, 0x00F0, 0x00DE, 0x00C4, 0x00C5,
|
||||||
|
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00FE, 0x00FB, 0x00DD, 0x00FD, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192,
|
||||||
|
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00C1, 0x00CD, 0x00D3, 0x00DA, 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
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 862
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP862(0x80-0xFF) to Unicode conversion table */
|
||||||
|
0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
|
||||||
|
0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 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
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 863
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP863(0x80-0xFF) to Unicode conversion table */
|
||||||
|
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00C2, 0x00E0, 0x00B6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x2017, 0x00C0,
|
||||||
|
0x00C9, 0x00C8, 0x00CA, 0x00F4, 0x00CB, 0x00CF, 0x00FB, 0x00F9, 0x00A4, 0x00D4, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x00DB, 0x0192,
|
||||||
|
0x00A6, 0x00B4, 0x00F3, 0x00FA, 0x00A8, 0x00BB, 0x00B3, 0x00AF, 0x00CE, 0x3210, 0x00AC, 0x00BD, 0x00BC, 0x00BE, 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, 0x2219,
|
||||||
|
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 864
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP864(0x80-0xFF) to Unicode conversion table */
|
||||||
|
0x00B0, 0x00B7, 0x2219, 0x221A, 0x2592, 0x2500, 0x2502, 0x253C, 0x2524, 0x252C, 0x251C, 0x2534, 0x2510, 0x250C, 0x2514, 0x2518,
|
||||||
|
0x03B2, 0x221E, 0x03C6, 0x00B1, 0x00BD, 0x00BC, 0x2248, 0x00AB, 0x00BB, 0xFEF7, 0xFEF8, 0x0000, 0x0000, 0xFEFB, 0xFEFC, 0x0000,
|
||||||
|
0x00A0, 0x00AD, 0xFE82, 0x00A3, 0x00A4, 0xFE84, 0x0000, 0x20AC, 0xFE8E, 0xFE8F, 0xFE95, 0xFE99, 0x060C, 0xFE9D, 0xFEA1, 0xFEA5,
|
||||||
|
0x0660, 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667, 0x0668, 0x0669, 0xFED1, 0x061B, 0xFEB1, 0xFEB5, 0xFEB9, 0x061F,
|
||||||
|
0x00A2, 0xFE80, 0xFE81, 0xFE83, 0xFE85, 0xFECA, 0xFE8B, 0xFE8D, 0xFE91, 0xFE93, 0xFE97, 0xFE9B, 0xFE9F, 0xFEA3, 0xFEA7, 0xFEA9,
|
||||||
|
0xFEAB, 0xFEAD, 0xFEAF, 0xFEB3, 0xFEB7, 0xFEBB, 0xFEBF, 0xFEC1, 0xFEC5, 0xFECB, 0xFECF, 0x00A6, 0x00AC, 0x00F7, 0x00D7, 0xFEC9,
|
||||||
|
0x0640, 0xFED3, 0xFED7, 0xFEDB, 0xFEDF, 0xFEE3, 0xFEE7, 0xFEEB, 0xFEED, 0xFEEF, 0xFEF3, 0xFEBD, 0xFECC, 0xFECE, 0xFECD, 0xFEE1,
|
||||||
|
0xFE7D, 0x0651, 0xFEE5, 0xFEE9, 0xFEEC, 0xFEF0, 0xFEF2, 0xFED0, 0xFED5, 0xFEF5, 0xFEF6, 0xFEDD, 0xFED9, 0xFEF1, 0x25A0, 0x0000
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 865
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP865(0x80-0xFF) to Unicode conversion table */
|
||||||
|
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
|
||||||
|
0x00C5, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192,
|
||||||
|
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00A4,
|
||||||
|
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 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
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 866
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP866(0x80-0xFF) to Unicode conversion table */
|
||||||
|
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
|
||||||
|
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
|
||||||
|
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
|
||||||
|
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,
|
||||||
|
0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
|
||||||
|
0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040E, 0x045E, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x2116, 0x00A4, 0x25A0, 0x00A0
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 869
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP869(0x80-0xFF) to Unicode conversion table */
|
||||||
|
0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x0386, 0x00B7, 0x00B7, 0x00AC, 0x00A6, 0x2018, 0x2019, 0x0388, 0x2015, 0x0389,
|
||||||
|
0x038A, 0x03AA, 0x038C, 0x00B7, 0x00B7, 0x038E, 0x03AB, 0x00A9, 0x038F, 0x00B2, 0x00B3, 0x03AC, 0x00A3, 0x03AD, 0x03AE, 0x03AF,
|
||||||
|
0x03CA, 0x0390, 0x03CC, 0x03CD, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x00BD, 0x0398, 0x0399, 0x00AB, 0x00BB,
|
||||||
|
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x039A, 0x039B, 0x039C, 0x039D, 0x2563, 0x2551, 0x2557, 0x255D, 0x039E, 0x039F, 0x2510,
|
||||||
|
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0A30, 0x03A1, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x03A3,
|
||||||
|
0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x2518, 0x250C, 0x2588, 0x2584, 0x03B4, 0x03B5, 0x2580,
|
||||||
|
0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x0384,
|
||||||
|
0x00AD, 0x00B1, 0x03C5, 0x03C6, 0x03C7, 0x00A7, 0x03C8, 0x0385, 0x00B0, 0x00A8, 0x03C9, 0x03CB, 0x03B0, 0x03CE, 0x25A0, 0x00A0
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if !_TBLDEF || !_USE_LFN
|
||||||
|
#error This file is not needed at current configuration. Remove from the project.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
WCHAR ff_convert ( /* Converted character, Returns zero on error */
|
||||||
|
WCHAR chr, /* Character code to be converted */
|
||||||
|
UINT dir /* 0: Unicode to OEM code, 1: OEM code to Unicode */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
WCHAR c;
|
||||||
|
|
||||||
|
|
||||||
|
if (chr < 0x80) { /* ASCII */
|
||||||
|
c = chr;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (dir) { /* OEM code to Unicode */
|
||||||
|
c = (chr >= 0x100) ? 0 : Tbl[chr - 0x80];
|
||||||
|
|
||||||
|
} else { /* Unicode to OEM code */
|
||||||
|
for (c = 0; c < 0x80; c++) {
|
||||||
|
if (chr == Tbl[c]) break;
|
||||||
|
}
|
||||||
|
c = (c + 0x80) & 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
WCHAR ff_wtoupper ( /* Returns upper converted character */
|
||||||
|
WCHAR chr /* Unicode character to be upper converted */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
static const WCHAR lower[] = { /* Lower case characters to be converted */
|
||||||
|
/* Latin Supplement */ 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,
|
||||||
|
/* Latin Extended-A */ 0x101,0x103,0x105,0x107,0x109,0x10B,0x10D,0x10F,0x111,0x113,0x115,0x117,0x119,0x11B,0x11D,0x11F,0x121,0x123,0x125,0x127,0x129,0x12B,0x12D,0x12F,0x131,0x133,0x135,0x137,0x13A,0x13C,0x13E,0x140,0x142,0x144,0x146,0x148,0x14B,0x14D,0x14F,0x151,0x153,0x155,0x157,0x159,0x15B,0x15D,0x15F,0x161,0x163,0x165,0x167,0x169,0x16B,0x16D,0x16F,0x171,0x173,0x175,0x177,0x17A,0x17C,0x17E,
|
||||||
|
/* Latin Extended-B */ 0x183,0x185,0x188,0x18C,0x192,0x199,0x1A1,0x1A3,0x1A8,0x1AD,0x1B0,0x1B4,0x1B6,0x1B9,0x1BD,0x1C6,0x1C9,0x1CC,0x1CE,0x1D0,0x1D2,0x1D4,0x1D6,0x1D8,0x1DA,0x1DC,0x1DD,0x1DF,0x1E1,0x1E3,0x1E5,0x1E7,0x1E9,0x1EB,0x1ED,0x1EF,0x1F3,0x1F5,0x1FB,0x1FD,0x1FF,0x201,0x203,0x205,0x207,0x209,0x20B,0x20D,0x20F,0x211,0x213,0x215,0x217,
|
||||||
|
/* Greek, Coptic */ 0x3B1,0x3B2,0x3B3,0x3B4,0x3B5,0x3B6,0x3B7,0x3B8,0x3B9,0x3BA,0x3BB,0x3BC,0x3BD,0x3BE,0x3BF,0x3C0,0x3C1,0x3C3,0x3C4,0x3C5,0x3C6,0x3C7,0x3C8,0x3C9,0x3CA,0x3CB,0x3CC,0x3CD,0x3CE,0x3E3,0x3E5,0x3E7,0x3E9,0x3EB,
|
||||||
|
/* Cyrillic */ 0x430,0x431,0x432,0x433,0x434,0x435,0x436,0x437,0x438,0x439,0x43A,0x43B,0x43C,0x43D,0x43E,0x43F,0x440,0x441,0x442,0x443,0x444,0x445,0x446,0x447,0x448,0x449,0x44A,0x44B,0x44C,0x44D,0x44E,0x44F,0x452,0x453,0x454,0x455,0x456,0x457,0x458,0x459,0x45A,0x45B,0x45C,0x45E,0x45F,0x461,0x463,0x465,0x467,0x469,0x46B,0x46D,0x46F,0x471,0x473,0x475,0x477,0x479,0x47B,0x47D,0x47F,0x481,0x491,0x493,0x495,0x497,0x499,0x49B,0x49D,0x49F,0x4A1,0x4A3,0x4A5,0x4A7,0x4A9,0x4AB,0x4AD,0x4AF,0x4B1,0x4B3,0x4B5,0x4B7,0x4B9,0x4BB,0x4BD,0x4BF,0x4C2,0x4C4,0x4C8,0x4D1,0x4D3,0x4D5,0x4D7,0x4D9,0x4DB,0x4DD,0x4DF,0x4E1,0x4E3,0x4E5,0x4E7,0x4E9,0x4EB,0x4ED,0x4EF,0x4F1,0x4F3,0x4F5,0x4F9,
|
||||||
|
/* Armenian */ 0x561,0x562,0x563,0x564,0x565,0x566,0x567,0x568,0x569,0x56A,0x56B,0x56C,0x56D,0x56E,0x56F,0x570,0x571,0x572,0x573,0x574,0x575,0x576,0x577,0x578,0x579,0x57A,0x57B,0x57C,0x57D,0x57E,0x57F,0x580,0x581,0x582,0x583,0x584,0x585,0x586,
|
||||||
|
/* Latin Extended Additional */ 0x1E01,0x1E03,0x1E05,0x1E07,0x1E09,0x1E0B,0x1E0D,0x1E0F,0x1E11,0x1E13,0x1E15,0x1E17,0x1E19,0x1E1B,0x1E1D,0x1E1F,0x1E21,0x1E23,0x1E25,0x1E27,0x1E29,0x1E2B,0x1E2D,0x1E2F,0x1E31,0x1E33,0x1E35,0x1E37,0x1E39,0x1E3B,0x1E3D,0x1E3F,0x1E41,0x1E43,0x1E45,0x1E47,0x1E49,0x1E4B,0x1E4D,0x1E4F,0x1E51,0x1E53,0x1E55,0x1E57,0x1E59,0x1E5B,0x1E5D,0x1E5F,0x1E61,0x1E63,0x1E65,0x1E67,0x1E69,0x1E6B,0x1E6D,0x1E6F,0x1E71,0x1E73,0x1E75,0x1E77,0x1E79,0x1E7B,0x1E7D,0x1E7F,0x1E81,0x1E83,0x1E85,0x1E87,0x1E89,0x1E8B,0x1E8D,0x1E8F,0x1E91,0x1E93,0x1E95,0x1E97,0x1E99,0x1E9B,0x1E9D,0x1E9F,0x1EA1,0x1EA3,0x1EA5,0x1EA7,0x1EA9,0x1EAB,0x1EAD,0x1EAF,0x1EB1,0x1EB3,0x1EB5,0x1EB7,0x1EB9,0x1EBB,0x1EBD,0x1EBF,0x1EC1,0x1EC3,0x1EC5,0x1EC7,0x1EC9,0x1ECB,0x1ECD,0x1ECF,0x1ED1,0x1ED3,0x1ED5,0x1ED7,0x1ED9,0x1EDB,0x1EDD,0x1EDF,0x1EE1,0x1EE3,0x1EE5,0x1EE7,0x1EE9,0x1EEB,0x1EED,0x1EEF,0x1EF1,0x1EF3,0x1EF5,0x1EF7,0x1EF9,
|
||||||
|
/* Number forms */ 0x2170,0x2171,0x2172,0x2173,0x2174,0x2175,0x2176,0x2177,0x2178,0x2179,0x217A,0x217B,0x217C,0x217D,0x217E,0x217F,
|
||||||
|
/* Full-width */ 0xFF41,0xFF42,0xFF43,0xFF44,0xFF45,0xFF46,0xFF47,0xFF48,0xFF49,0xFF4A,0xFF4B,0xFF4C,0xFF4D,0xFF4E,0xFF4F,0xFF50,0xFF51,0xFF52,0xFF53,0xFF54,0xFF55,0xFF56,0xFF57,0xFF58,0xFF59,0xFF5A
|
||||||
|
};
|
||||||
|
static const WCHAR upper[] = { /* Upper case characters correspond to lower[] */
|
||||||
|
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x178,
|
||||||
|
0x100,0x102,0x104,0x106,0x108,0x10A,0x10C,0x10E,0x110,0x112,0x114,0x116,0x118,0x11A,0x11C,0x11E,0x120,0x122,0x124,0x126,0x128,0x12A,0x12C,0x12E,0x130,0x132,0x134,0x136,0x139,0x13B,0x13D,0x13F,0x141,0x143,0x145,0x147,0x14A,0x14C,0x14E,0x150,0x152,0x154,0x156,0x158,0x15A,0x15C,0x15E,0x160,0x162,0x164,0x166,0x168,0x16A,0x16C,0x16E,0x170,0x172,0x174,0x176,0x179,0x17B,0x17D,
|
||||||
|
0x182,0x184,0x187,0x18B,0x191,0x198,0x1A0,0x1A2,0x1A7,0x1AC,0x1AF,0x1B3,0x1B5,0x1B8,0x1BC,0x1C4,0x1C7,0x1CA,0x1CD,0x1CF,0x1D1,0x1D3,0x1D5,0x1D7,0x1D9,0x1DB,0x18E,0x1DE,0x1E0,0x1E2,0x1E4,0x1E6,0x1E8,0x1EA,0x1EC,0x1EE,0x1F1,0x1F4,0x1FA,0x1FC,0x1FE,0x200,0x202,0x204,0x206,0x208,0x20A,0x20C,0x20E,0x210,0x212,0x214,0x216,
|
||||||
|
0x391,0x392,0x393,0x394,0x395,0x396,0x397,0x398,0x399,0x39A,0x39B,0x39C,0x39D,0x39E,0x39F,0x3A0,0x3A1,0x3A3,0x3A4,0x3A5,0x3A6,0x3A7,0x3A8,0x3A9,0x3AA,0x3AB,0x38C,0x38E,0x38F,0x3E2,0x3E4,0x3E6,0x3E8,0x3EA,
|
||||||
|
0x410,0x411,0x412,0x413,0x414,0x415,0x416,0x417,0x418,0x419,0x41A,0x41B,0x41C,0x41D,0x41E,0x41F,0x420,0x421,0x422,0x423,0x424,0x425,0x426,0x427,0x428,0x429,0x42A,0x42B,0x42C,0x42D,0x42E,0x42F,0x402,0x403,0x404,0x405,0x406,0x407,0x408,0x409,0x40A,0x40B,0x40C,0x40E,0x40F,0x460,0x462,0x464,0x466,0x468,0x46A,0x46C,0x46E,0x470,0x472,0x474,0x476,0x478,0x47A,0x47C,0x47E,0x480,0x490,0x492,0x494,0x496,0x498,0x49A,0x49C,0x49E,0x4A0,0x4A2,0x4A4,0x4A6,0x4A8,0x4AA,0x4AC,0x4AE,0x4B0,0x4B2,0x4B4,0x4B6,0x4B8,0x4BA,0x4BC,0x4BE,0x4C1,0x4C3,0x5C7,0x4D0,0x4D2,0x4D4,0x4D6,0x4D8,0x4DA,0x4DC,0x4DE,0x4E0,0x4E2,0x4E4,0x4E6,0x4E8,0x4EA,0x4EC,0x4EE,0x4F0,0x4F2,0x4F4,0x4F8,
|
||||||
|
0x531,0x532,0x533,0x534,0x535,0x536,0x537,0x538,0x539,0x53A,0x53B,0x53C,0x53D,0x53E,0x53F,0x540,0x541,0x542,0x543,0x544,0x545,0x546,0x547,0x548,0x549,0x54A,0x54B,0x54C,0x54D,0x54E,0x54F,0x550,0x551,0x552,0x553,0x554,0x555,0x556,
|
||||||
|
0x1E00,0x1E02,0x1E04,0x1E06,0x1E08,0x1E0A,0x1E0C,0x1E0E,0x1E10,0x1E12,0x1E14,0x1E16,0x1E18,0x1E1A,0x1E1C,0x1E1E,0x1E20,0x1E22,0x1E24,0x1E26,0x1E28,0x1E2A,0x1E2C,0x1E2E,0x1E30,0x1E32,0x1E34,0x1E36,0x1E38,0x1E3A,0x1E3C,0x1E3E,0x1E40,0x1E42,0x1E44,0x1E46,0x1E48,0x1E4A,0x1E4C,0x1E4E,0x1E50,0x1E52,0x1E54,0x1E56,0x1E58,0x1E5A,0x1E5C,0x1E5E,0x1E60,0x1E62,0x1E64,0x1E66,0x1E68,0x1E6A,0x1E6C,0x1E6E,0x1E70,0x1E72,0x1E74,0x1E76,0x1E78,0x1E7A,0x1E7C,0x1E7E,0x1E80,0x1E82,0x1E84,0x1E86,0x1E88,0x1E8A,0x1E8C,0x1E8E,0x1E90,0x1E92,0x1E94,0x1E96,0x1E98,0x1E9A,0x1E9C,0x1E9E,0x1EA0,0x1EA2,0x1EA4,0x1EA6,0x1EA8,0x1EAA,0x1EAC,0x1EAE,0x1EB0,0x1EB2,0x1EB4,0x1EB6,0x1EB8,0x1EBA,0x1EBC,0x1EBE,0x1EC0,0x1EC2,0x1EC4,0x1EC6,0x1EC8,0x1ECA,0x1ECC,0x1ECE,0x1ED0,0x1ED2,0x1ED4,0x1ED6,0x1ED8,0x1EDA,0x1EDC,0x1EDE,0x1EE0,0x1EE2,0x1EE4,0x1EE6,0x1EE8,0x1EEA,0x1EEC,0x1EEE,0x1EF0,0x1EF2,0x1EF4,0x1EF6,0x1EF8,
|
||||||
|
0x2160,0x2161,0x2162,0x2163,0x2164,0x2165,0x2166,0x2167,0x2168,0x2169,0x216A,0x216B,0x216C,0x216D,0x216E,0x216F,
|
||||||
|
0xFF21,0xFF22,0xFF23,0xFF24,0xFF25,0xFF26,0xFF27,0xFF28,0xFF29,0xFF2A,0xFF2B,0xFF2C,0xFF2D,0xFF2E,0xFF2F,0xFF30,0xFF31,0xFF32,0xFF33,0xFF34,0xFF35,0xFF36,0xFF37,0xFF38,0xFF39,0xFF3A
|
||||||
|
};
|
||||||
|
UINT i, n, hi, li;
|
||||||
|
|
||||||
|
|
||||||
|
if (chr < 0x80) { /* ASCII characters (acceleration) */
|
||||||
|
if (chr >= 0x61 && chr <= 0x7A) chr -= 0x20;
|
||||||
|
|
||||||
|
} else { /* Non ASCII characters (table search) */
|
||||||
|
n = 12; li = 0; hi = sizeof lower / sizeof lower[0];
|
||||||
|
do {
|
||||||
|
i = li + (hi - li) / 2;
|
||||||
|
if (chr == lower[i]) break;
|
||||||
|
if (chr > lower[i]) li = i; else hi = i;
|
||||||
|
} while (--n);
|
||||||
|
if (n) chr = upper[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return chr;
|
||||||
|
}
|
||||||
|
|
@ -2,3 +2,4 @@
|
|||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "../../types.h"
|
#include "../../types.h"
|
||||||
|
#include "../../crypto.h"
|
@ -402,3 +402,44 @@ int sdmmc_sdcard_init()
|
|||||||
return result | SD_Init();
|
return result | SD_Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sdmmc_get_cid( int isNand, uint32_t *info)
|
||||||
|
{
|
||||||
|
struct mmcdevice *device;
|
||||||
|
if(isNand)
|
||||||
|
device = &handleNAND;
|
||||||
|
else
|
||||||
|
device = &handleSD;
|
||||||
|
|
||||||
|
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(&handleSD);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -122,6 +122,7 @@ int sdmmc_sdcard_init();
|
|||||||
u32 sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, vu8 *out);
|
u32 sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, vu8 *out);
|
||||||
u32 sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, vu8 *in);
|
u32 sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, vu8 *in);
|
||||||
mmcdevice *getMMCDevice(int drive);
|
mmcdevice *getMMCDevice(int drive);
|
||||||
|
int sdmmc_get_cid( int isNand, uint32_t *info);
|
||||||
|
|
||||||
u32 sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, vu8 *out);
|
u32 sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, vu8 *out);
|
||||||
u32 sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, vu8 *in);
|
u32 sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, vu8 *in);
|
442
source/firm.c
442
source/firm.c
@ -18,46 +18,36 @@
|
|||||||
#include "buttons.h"
|
#include "buttons.h"
|
||||||
#include "../build/patches.h"
|
#include "../build/patches.h"
|
||||||
|
|
||||||
//FIRM patches version
|
|
||||||
#define PATCH_VER 4
|
|
||||||
|
|
||||||
static firmHeader *const firm = (firmHeader *)0x24000000;
|
static firmHeader *const firm = (firmHeader *)0x24000000;
|
||||||
static const firmSectionHeader *section;
|
static const firmSectionHeader *section;
|
||||||
static u8 *arm9Section;
|
|
||||||
static const char *patchedFirms[] = { "/aurei/patched_firmware_sys.bin",
|
static const char *firmFolders[3][2] = {{ "00000002", "20000002" },
|
||||||
"/aurei/patched_firmware_emu.bin",
|
{ "00000102", "20000102" },
|
||||||
"/aurei/patched_firmware_em2.bin",
|
{ "00000202", "20000202" }};
|
||||||
"/aurei/patched_firmware90.bin",
|
u32 config,
|
||||||
"/aurei/patched_firmware_twl.bin",
|
|
||||||
"/aurei/patched_firmware_agb.bin" };
|
|
||||||
u32 config;
|
|
||||||
static u32 firmSize,
|
|
||||||
console,
|
console,
|
||||||
mode,
|
|
||||||
emuNAND,
|
|
||||||
a9lhSetup,
|
|
||||||
selectedFirm,
|
|
||||||
usePatchedFirm,
|
|
||||||
emuOffset,
|
emuOffset,
|
||||||
emuHeader;
|
firmSource;
|
||||||
|
|
||||||
void setupCFW(void)
|
void main(void)
|
||||||
{
|
{
|
||||||
//Determine if booting with A9LH
|
u32 bootType,
|
||||||
u32 a9lhBoot = !PDN_SPI_CNT ? 1 : 0;
|
firmType,
|
||||||
|
nandType,
|
||||||
//Retrieve the last booted FIRM
|
a9lhInstalled,
|
||||||
u32 previousFirm = CFG_BOOTENV;
|
updatedSys,
|
||||||
|
needConfig,
|
||||||
|
newConfig,
|
||||||
|
emuHeader;
|
||||||
|
|
||||||
//Detect the console being used
|
//Detect the console being used
|
||||||
console = (PDN_MPCORE_CFG == 1) ? 0 : 1;
|
console = (PDN_MPCORE_CFG == 1) ? 0 : 1;
|
||||||
|
|
||||||
//Get pressed buttons
|
//Mount filesystems. CTRNAND will be mounted only if/when needed
|
||||||
u32 pressed = HID_PAD;
|
mountFs();
|
||||||
|
|
||||||
//Attempt to read the configuration file
|
//Attempt to read the configuration file
|
||||||
const char configPath[] = "/aurei/config.bin";
|
const char configPath[] = "/aurei/config.bin";
|
||||||
u32 needConfig;
|
|
||||||
if(fileRead(&config, configPath, 3)) needConfig = 1;
|
if(fileRead(&config, configPath, 3)) needConfig = 1;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -65,26 +55,54 @@ void setupCFW(void)
|
|||||||
needConfig = 2;
|
needConfig = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Determine if A9LH is installed and the user has an updated sysNAND
|
//Determine if this is a firmlaunch boot
|
||||||
u32 updatedSys;
|
if(*(vu8 *)0x23F00005)
|
||||||
|
{
|
||||||
|
bootType = 1;
|
||||||
|
|
||||||
|
//'0' = NATIVE_FIRM, '1' = TWL_FIRM, '2' = AGB_FIRM
|
||||||
|
firmType = *(vu8 *)0x23F00005 - 0x2F;
|
||||||
|
|
||||||
|
nandType = CONFIG(16, 3);
|
||||||
|
firmSource = CONFIG(18, 1);
|
||||||
|
a9lhInstalled = CONFIG(19, 1);
|
||||||
|
updatedSys = (a9lhInstalled && CONFIG(1, 1)) ? 1 : 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bootType = 0;
|
||||||
|
firmType = 1;
|
||||||
|
|
||||||
|
//Determine if booting with A9LH
|
||||||
|
u32 a9lhBoot = !PDN_SPI_CNT ? 1 : 0;
|
||||||
|
|
||||||
|
//Retrieve the last booted FIRM
|
||||||
|
u32 previousFirm = CFG_BOOTENV;
|
||||||
|
|
||||||
|
//Get pressed buttons
|
||||||
|
u32 pressed = HID_PAD;
|
||||||
|
|
||||||
|
//Determine if we need to autoboot sysNAND
|
||||||
|
u32 autoBootSys = CONFIG(0, 1);
|
||||||
|
|
||||||
|
//Determine if A9LH is installed and the user has an updated sysNAND
|
||||||
if(a9lhBoot || CONFIG(2, 1))
|
if(a9lhBoot || CONFIG(2, 1))
|
||||||
{
|
{
|
||||||
if(pressed == SAFE_MODE)
|
if(pressed == SAFE_MODE)
|
||||||
error("Using Safe Mode would brick you, or remove A9LH!");
|
error("Using Safe Mode would brick you, or remove A9LH!");
|
||||||
|
|
||||||
a9lhSetup = 1;
|
a9lhInstalled = 1;
|
||||||
|
|
||||||
//Check setting for > 9.2 sysNAND
|
//Check setting for > 9.2 sysNAND
|
||||||
updatedSys = CONFIG(0, 1);
|
updatedSys = CONFIG(1, 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
a9lhSetup = 0;
|
a9lhInstalled = 0;
|
||||||
updatedSys = 0;
|
updatedSys = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 tempConfig = (PATCH_VER << 17) | (a9lhSetup << 16);
|
newConfig = a9lhInstalled << 19;
|
||||||
|
|
||||||
/* If booting with A9LH, it's a MCU reboot and a previous configuration exists,
|
/* If booting with A9LH, it's a MCU reboot and a previous configuration exists,
|
||||||
try to force boot options */
|
try to force boot options */
|
||||||
@ -93,19 +111,19 @@ void setupCFW(void)
|
|||||||
//Always force a sysNAND boot when quitting AGB_FIRM
|
//Always force a sysNAND boot when quitting AGB_FIRM
|
||||||
if(previousFirm == 7)
|
if(previousFirm == 7)
|
||||||
{
|
{
|
||||||
mode = updatedSys ? 1 : CONFIG(12, 1);
|
nandType = 0;
|
||||||
emuNAND = 0;
|
firmSource = updatedSys ? 0 : CONFIG(18, 1);
|
||||||
needConfig = 0;
|
needConfig = 0;
|
||||||
|
|
||||||
//Flag to prevent multiple boot options-forcing
|
//Flag to prevent multiple boot options-forcing
|
||||||
tempConfig |= 1 << 15;
|
newConfig |= 1 << 20;
|
||||||
}
|
}
|
||||||
/* Else, force the last used boot options unless a payload button or A/L/R are pressed
|
/* Else, force the last used boot options unless a payload button or A/L/R are pressed
|
||||||
or the no-forcing flag is set */
|
or the no-forcing flag is set */
|
||||||
else if(!(pressed & OVERRIDE_BUTTONS) && !CONFIG(15, 1))
|
else if(!(pressed & OVERRIDE_BUTTONS) && !CONFIG(20, 1))
|
||||||
{
|
{
|
||||||
mode = CONFIG(12, 1);
|
nandType = CONFIG(16, 3);
|
||||||
emuNAND = CONFIG(13, 3);
|
firmSource = CONFIG(18, 1);
|
||||||
needConfig = 0;
|
needConfig = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -121,187 +139,147 @@ void setupCFW(void)
|
|||||||
|
|
||||||
//If no configuration file exists or SELECT is held, load configuration menu
|
//If no configuration file exists or SELECT is held, load configuration menu
|
||||||
if(needConfig == 2 || (pressed & BUTTON_SELECT))
|
if(needConfig == 2 || (pressed & BUTTON_SELECT))
|
||||||
configureCFW(configPath, patchedFirms);
|
configureCFW(configPath);
|
||||||
|
|
||||||
//If screens are inited or the corresponding option is set, load splash screen
|
//If screens are inited or the corresponding option is set, load splash screen
|
||||||
if(PDN_GPU_CNT != 1 || CONFIG(7, 1)) loadSplash();
|
if(PDN_GPU_CNT != 1 || CONFIG(6, 1)) loadSplash();
|
||||||
|
|
||||||
/* If L is pressed, or L or R are not pressed when it is the default FIRM,
|
//Determine if we need to boot an emuNAND or sysNAND
|
||||||
boot 9.0 FIRM */
|
nandType = (pressed & BUTTON_L1) ? autoBootSys : ((pressed & BUTTON_R1) ? updatedSys : !autoBootSys);
|
||||||
mode = CONFIG(3, 1) ? ((!(pressed & BUTTON_L1R1)) ? 0 : 1) :
|
|
||||||
((pressed & BUTTON_L1) ? 0 : 1);
|
|
||||||
|
|
||||||
/* If L or R aren't pressed on a 9.0/9.2 sysNAND, or the 9.0 FIRM is selected
|
/* If we're booting emuNAND the second emuNAND is set as default and B isn't pressed,
|
||||||
or R is pressed on a > 9.2 sysNAND, boot emuNAND */
|
or vice-versa, boot the second emuNAND */
|
||||||
if((updatedSys && (!mode || (pressed & BUTTON_R1))) || (!updatedSys && mode && !(pressed & BUTTON_R1)))
|
if(nandType && ((!(pressed & BUTTON_B)) == CONFIG(3, 1))) nandType++;
|
||||||
|
|
||||||
|
//Determine the NAND we should take the FIRM from
|
||||||
|
firmSource = (pressed & BUTTON_R1) ? !nandType : (nandType != 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//If we need to boot emuNAND, make sure it exists
|
||||||
|
if(nandType)
|
||||||
{
|
{
|
||||||
/* If not 9.0 FIRM and the second emuNAND is set as default and B isn't pressed, or vice-versa,
|
getEmunandSect(&emuOffset, &emuHeader, &nandType);
|
||||||
attempt to boot it */
|
if(!nandType) firmSource = 0;
|
||||||
emuNAND = (mode && ((!(pressed & BUTTON_B)) == CONFIG(4, 1))) ? 2 : 1;
|
|
||||||
}
|
|
||||||
else emuNAND = 0;
|
|
||||||
|
|
||||||
/* If tha FIRM patches version is different or user switched to/from A9LH,
|
|
||||||
delete all patched FIRMs */
|
|
||||||
if((tempConfig & 0xFF0000) != (config & 0xFF0000))
|
|
||||||
deleteFirms(patchedFirms, sizeof(patchedFirms) / sizeof(char *));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 usePatchedFirmSet = CONFIG(1, 1);
|
//Same if we're using emuNAND as the FIRM source
|
||||||
|
else if(firmSource)
|
||||||
|
getEmunandSect(&emuOffset, &emuHeader, &firmSource);
|
||||||
|
|
||||||
while(1)
|
if(!bootType)
|
||||||
{
|
{
|
||||||
/* Determine which patched FIRM we need to write or attempt to use (if any).
|
newConfig |= (nandType << 16) | (firmSource << 18);
|
||||||
Patched 9.0 FIRM is only needed if "Use pre-patched FIRMs" is set */
|
|
||||||
selectedFirm = mode ? (emuNAND ? (emuNAND == 1 ? 2 : 3) : 1) :
|
|
||||||
(usePatchedFirmSet ? 4 : 0);
|
|
||||||
|
|
||||||
//If "Use pre-patched FIRMs" is set and the appropriate FIRM exists, use it
|
|
||||||
if(usePatchedFirmSet && fileExists(patchedFirms[selectedFirm - 1]))
|
|
||||||
usePatchedFirm = 1;
|
|
||||||
|
|
||||||
/* If the user is booting EmuNAND but the chosen one is not found,
|
|
||||||
force 9.6/10.x FIRM and re-detect the patched FIRMs */
|
|
||||||
else if(emuNAND && !getEmunandSect(&emuOffset, &emuHeader, &emuNAND))
|
|
||||||
{
|
|
||||||
mode = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
tempConfig |= (emuNAND << 13) | (mode << 12);
|
|
||||||
|
|
||||||
/* If the boot configuration is different from previously, overwrite it.
|
/* If the boot configuration is different from previously, overwrite it.
|
||||||
Just the no-forcing flag being set is not enough */
|
Just the no-forcing flag being set is not enough */
|
||||||
if((tempConfig & 0xFF7000) != (config & 0xFFF000))
|
if((newConfig & 0xEF0000) != (config & 0xFF0000))
|
||||||
{
|
{
|
||||||
//Preserve user settings (first 12 bits)
|
//Preserve user settings (first 2 bytes)
|
||||||
tempConfig |= config & 0xFFF;
|
newConfig |= config & 0xFFFF;
|
||||||
|
|
||||||
fileWrite(&tempConfig, configPath, 3);
|
fileWrite(&newConfig, configPath, 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadFirm(firmType, firmType == 1 && (nandType == 2 || updatedSys == !nandType));
|
||||||
|
|
||||||
|
if(firmType == 1) patchNativeFirm(firmType, nandType, emuHeader, a9lhInstalled);
|
||||||
|
else patchTwlAgbFirm(firmType);
|
||||||
|
|
||||||
|
launchFirm(bootType);
|
||||||
|
}
|
||||||
|
|
||||||
//Load FIRM into FCRAM
|
//Load FIRM into FCRAM
|
||||||
void loadFirm(void)
|
static inline void loadFirm(u32 firmType, u32 externalFirm)
|
||||||
{
|
{
|
||||||
//If not using an A9LH setup or the patched FIRM, load 9.0 FIRM from NAND
|
u32 firmSize;
|
||||||
if(!usePatchedFirm && !a9lhSetup && !mode)
|
|
||||||
{
|
|
||||||
//Read FIRM from NAND and write to FCRAM
|
|
||||||
firmSize = console ? 0xF2000 : 0xE9000;
|
|
||||||
nandFirm0((u8 *)firm, firmSize, console);
|
|
||||||
|
|
||||||
//Check for correct decryption
|
|
||||||
if(memcmp(firm, "FIRM", 4) != 0)
|
|
||||||
error("Couldn't decrypt NAND FIRM0 (O3DS not on 9.x?)");
|
|
||||||
}
|
|
||||||
|
|
||||||
//Load FIRM from SD
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const char *path = usePatchedFirm ? patchedFirms[selectedFirm - 1] :
|
|
||||||
(mode ? "/aurei/firmware.bin" : "/aurei/firmware90.bin");
|
|
||||||
firmSize = fileSize(path);
|
|
||||||
if(!firmSize) error(mode ? "aurei/firmware.bin doesn't exist" :
|
|
||||||
"aurei/firmware90.bin doesn't exist");
|
|
||||||
fileRead(firm, path, firmSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
section = firm->section;
|
section = firm->section;
|
||||||
|
|
||||||
|
if(externalFirm)
|
||||||
|
{
|
||||||
|
const char *path = "/aurei/firmware.bin";
|
||||||
|
firmSize = fileSize(path);
|
||||||
|
|
||||||
|
if(firmSize)
|
||||||
|
{
|
||||||
|
fileRead(firm, path, firmSize);
|
||||||
|
|
||||||
//Check that the loaded FIRM matches the console
|
//Check that the loaded FIRM matches the console
|
||||||
if((((u32)section[2].address >> 8) & 0xFF) != (console ? 0x60 : 0x68))
|
if((((u32)section[2].address >> 8) & 0xFF) != (console ? 0x60 : 0x68))
|
||||||
error(mode ? "aurei/firmware.bin doesn't match this console,\nor it's encrypted" :
|
error("aurei/firmware.bin doesn't match this console,\nor it's encrypted");
|
||||||
"aurei/firmware90.bin doesn't match this console,\nor it's encrypted");
|
}
|
||||||
|
}
|
||||||
|
else firmSize = 0;
|
||||||
|
|
||||||
arm9Section = (u8 *)firm + section[2].offset;
|
if(!firmSize)
|
||||||
|
|
||||||
//On N3DS, decrypt ARM9Bin and patch ARM9 entrypoint to skip arm9loader
|
|
||||||
if(console && !usePatchedFirm)
|
|
||||||
{
|
{
|
||||||
decryptArm9Bin(arm9Section, mode);
|
firmRead((u8 *)firm, firmFolders[firmType - 1][console]);
|
||||||
firm->arm9Entry = (u8 *)0x801B01C;
|
decryptExeFs((u8 *)firm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void patchTwlAgb(u32 whichFirm)
|
static inline void patchNativeFirm(u32 firmType, u32 nandType, u32 emuHeader, u32 a9lhInstalled)
|
||||||
{
|
{
|
||||||
static firmHeader *const twlAgbFirm = (firmHeader *)0x25000000;
|
u8 *arm9Section = (u8 *)firm + section[2].offset;
|
||||||
|
|
||||||
const char *path = whichFirm ? "/aurei/firmware_agb.bin" : "/aurei/firmware_twl.bin";
|
|
||||||
u32 size = fileSize(path);
|
|
||||||
|
|
||||||
//Skip patching if the file doesn't exist
|
|
||||||
if(!size) return;
|
|
||||||
|
|
||||||
fileRead(twlAgbFirm, path, size);
|
|
||||||
|
|
||||||
static const firmSectionHeader *twlAgbSection = twlAgbFirm->section;
|
|
||||||
|
|
||||||
//Check that the loaded FIRM matches the console
|
|
||||||
if((((u32)twlAgbSection[3].address >> 8) & 0xFF) != (console ? 0x60 : 0x68))
|
|
||||||
error(whichFirm ? "aurei/firmware_agb.bin doesn't match this\nconsole, or it's encrypted" :
|
|
||||||
"aurei/firmware_twl.bin doesn't match this\nconsole, or it's encrypted");
|
|
||||||
|
|
||||||
//On N3DS, decrypt ARM9Bin and patch ARM9 entrypoint to skip arm9loader
|
|
||||||
if(console)
|
if(console)
|
||||||
{
|
{
|
||||||
decryptArm9Bin((u8 *)twlAgbFirm + twlAgbSection[3].offset, 0);
|
//Determine if we're booting the 9.0 FIRM
|
||||||
twlAgbFirm->arm9Entry = (u8 *)0x801301C;
|
if(arm9Section[0x51] == 0xFF) firmType--;
|
||||||
|
|
||||||
|
//Decrypt ARM9Bin and patch ARM9 entrypoint to skip arm9loader
|
||||||
|
arm9Loader((u8 *)firm + section[2].offset, firmType);
|
||||||
|
firm->arm9Entry = (u8 *)0x801B01C;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
static const patchData twlPatches[] = {
|
|
||||||
{{0x1650C0, 0x165D64}, {{ 6, 0x00, 0x20, 0x4E, 0xB0, 0x70, 0xBD }}, 0},
|
|
||||||
{{0x173A0E, 0x17474A}, { .type1 = 0x2001 }, 1},
|
|
||||||
{{0x174802, 0x17553E}, { .type1 = 0x2000 }, 2},
|
|
||||||
{{0x174964, 0x1756A0}, { .type1 = 0x2000 }, 2},
|
|
||||||
{{0x174D52, 0x175A8E}, { .type1 = 0x2001 }, 2},
|
|
||||||
{{0x174D5E, 0x175A9A}, { .type1 = 0x2001 }, 2},
|
|
||||||
{{0x174D6A, 0x175AA6}, { .type1 = 0x2001 }, 2},
|
|
||||||
{{0x174E56, 0x175B92}, { .type1 = 0x2001 }, 1},
|
|
||||||
{{0x174E58, 0x175B94}, { .type1 = 0x4770 }, 1}
|
|
||||||
},
|
|
||||||
agbPatches[] = {
|
|
||||||
{{0x9D2A8, 0x9DF64}, {{ 6, 0x00, 0x20, 0x4E, 0xB0, 0x70, 0xBD }}, 0},
|
|
||||||
{{0xD7A12, 0xD8B8A}, { .type1 = 0xEF26 }, 1}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Calculate the amount of patches to apply. Only count the boot screen patch for AGB_FIRM
|
|
||||||
if the matching option was enabled (keep it as last) */
|
|
||||||
u32 numPatches = whichFirm ? (sizeof(agbPatches) / sizeof(patchData) - !CONFIG(6, 1)) :
|
|
||||||
(sizeof(twlPatches) / sizeof(patchData));
|
|
||||||
const patchData *patches = whichFirm ? agbPatches : twlPatches;
|
|
||||||
|
|
||||||
//Patch
|
|
||||||
for(u32 i = 0; i < numPatches; i++)
|
|
||||||
{
|
{
|
||||||
switch(patches[i].type)
|
//Determine if we're booting the 9.0 FIRM
|
||||||
{
|
u8 firm90Hash[0x10] = {0x27, 0x2D, 0xFE, 0xEB, 0xAF, 0x3F, 0x6B, 0x3B, 0xF5, 0xDE, 0x4C, 0x41, 0xDE, 0x95, 0x27, 0x6A};
|
||||||
case 0:
|
if(memcmp(section[2].hash, firm90Hash, 0x10) == 0) firmType--;
|
||||||
memcpy((u8 *)twlAgbFirm + patches[i].offset[console], patches[i].patch.type0 + 1, patches[i].patch.type0[0]);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
*(u16 *)((u8 *)twlAgbFirm + patches[i].offset[console] + 2) = 0;
|
|
||||||
case 1:
|
|
||||||
*(u16 *)((u8 *)twlAgbFirm + patches[i].offset[console]) = patches[i].patch.type1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fileWrite(twlAgbFirm, whichFirm ? patchedFirms[5] : patchedFirms[4], size);
|
if(firmType == 1 || nandType)
|
||||||
|
{
|
||||||
|
//Find the Process9 NCCH location
|
||||||
|
u8 *proc9Offset = getProc9(arm9Section, section[2].size);
|
||||||
|
|
||||||
|
//Apply emuNAND patches
|
||||||
|
if(nandType) patchEmuNAND(arm9Section, proc9Offset, emuHeader);
|
||||||
|
|
||||||
|
//Apply FIRM reboot patches, not on 9.0 FIRM as it breaks firmlaunchhax
|
||||||
|
if(firmType == 1) patchReboots(arm9Section, proc9Offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
//NAND redirection
|
//Apply FIRM0/1 writes patches on sysNAND to protect A9LH
|
||||||
static inline void patchEmuNAND(u8 *proc9Offset)
|
if(a9lhInstalled && !nandType)
|
||||||
{
|
{
|
||||||
//Copy emuNAND code
|
u16 *writeOffset = getFirmWrite(arm9Section, section[2].size);
|
||||||
|
*writeOffset = writeBlock[0];
|
||||||
|
*(writeOffset + 1) = writeBlock[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
//Apply signature checks patches
|
||||||
|
u32 sigOffset,
|
||||||
|
sigOffset2;
|
||||||
|
|
||||||
|
getSigChecks(arm9Section, section[2].size, &sigOffset, &sigOffset2);
|
||||||
|
*(u16 *)sigOffset = sigPatch[0];
|
||||||
|
*(u16 *)sigOffset2 = sigPatch[0];
|
||||||
|
*((u16 *)sigOffset2 + 1) = sigPatch[1];
|
||||||
|
|
||||||
|
//Replace the FIRM loader with the injector
|
||||||
|
injectLoader();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void patchEmuNAND(u8 *arm9Section, u8 *proc9Offset, u32 emuHeader)
|
||||||
|
{
|
||||||
|
//Copy nandType code
|
||||||
void *emuCodeOffset = getEmuCode(proc9Offset);
|
void *emuCodeOffset = getEmuCode(proc9Offset);
|
||||||
memcpy(emuCodeOffset, emunand, emunand_size);
|
memcpy(emuCodeOffset, emunand, emunand_size);
|
||||||
|
|
||||||
//Add the data of the found emuNAND
|
//Add the data of the found nandType
|
||||||
u32 *pos_offset = (u32 *)memsearch(emuCodeOffset, "NAND", emunand_size, 4);
|
u32 *pos_offset = (u32 *)memsearch(emuCodeOffset, "NAND", emunand_size, 4);
|
||||||
u32 *pos_header = (u32 *)memsearch(emuCodeOffset, "NCSD", emunand_size, 4);
|
u32 *pos_header = (u32 *)memsearch(emuCodeOffset, "NCSD", emunand_size, 4);
|
||||||
*pos_offset = emuOffset;
|
*pos_offset = emuOffset;
|
||||||
@ -334,7 +312,7 @@ static inline void patchEmuNAND(u8 *proc9Offset)
|
|||||||
*(mpuOffset + 9) = mpuPatch[2];
|
*(mpuOffset + 9) = mpuPatch[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void patchReboots(u8 *proc9Offset)
|
static inline void patchReboots(u8 *arm9Section, u8 *proc9Offset)
|
||||||
{
|
{
|
||||||
//Calculate offset for the firmlaunch code
|
//Calculate offset for the firmlaunch code
|
||||||
void *rebootOffset = getReboot(arm9Section, section[2].size);
|
void *rebootOffset = getReboot(arm9Section, section[2].size);
|
||||||
@ -348,13 +326,6 @@ static inline void patchReboots(u8 *proc9Offset)
|
|||||||
//Put the fOpen offset in the right location
|
//Put the fOpen offset in the right location
|
||||||
u32 *pos_fopen = (u32 *)memsearch(rebootOffset, "OPEN", reboot_size, 4);
|
u32 *pos_fopen = (u32 *)memsearch(rebootOffset, "OPEN", reboot_size, 4);
|
||||||
*pos_fopen = fOpenOffset;
|
*pos_fopen = fOpenOffset;
|
||||||
|
|
||||||
//Patch path for emuNAND-patched FIRM
|
|
||||||
if(emuNAND)
|
|
||||||
{
|
|
||||||
void *pos_path = memsearch(rebootOffset, L"sy", reboot_size, 4);
|
|
||||||
memcpy(pos_path, emuNAND == 1 ? L"emu" : L"em2", 5);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void injectLoader(void)
|
static inline void injectLoader(void)
|
||||||
@ -376,71 +347,70 @@ static inline void injectLoader(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Patches
|
static inline void patchTwlAgbFirm(u32 firmType)
|
||||||
void patchFirm(void)
|
|
||||||
{
|
{
|
||||||
if(mode)
|
//On N3DS, decrypt ARM9Bin and patch ARM9 entrypoint to skip arm9loader
|
||||||
|
if(console)
|
||||||
{
|
{
|
||||||
//Only patch AGB_FIRM/TWL_FIRM if the patched ones don't already exist
|
arm9Loader((u8 *)firm + section[3].offset, 0);
|
||||||
if(!fileExists(patchedFirms[4])) patchTwlAgb(0);
|
firm->arm9Entry = (u8 *)0x801301C;
|
||||||
if(!fileExists(patchedFirms[5])) patchTwlAgb(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Skip patching
|
static const patchData twlPatches[] = {
|
||||||
if(usePatchedFirm) return;
|
{{0x1650C0, 0x165D64}, {{ 6, 0x00, 0x20, 0x4E, 0xB0, 0x70, 0xBD }}, 0},
|
||||||
|
{{0x173A0E, 0x17474A}, { .type1 = 0x2001 }, 1},
|
||||||
|
{{0x174802, 0x17553E}, { .type1 = 0x2000 }, 2},
|
||||||
|
{{0x174964, 0x1756A0}, { .type1 = 0x2000 }, 2},
|
||||||
|
{{0x174D52, 0x175A8E}, { .type1 = 0x2001 }, 2},
|
||||||
|
{{0x174D5E, 0x175A9A}, { .type1 = 0x2001 }, 2},
|
||||||
|
{{0x174D6A, 0x175AA6}, { .type1 = 0x2001 }, 2},
|
||||||
|
{{0x174E56, 0x175B92}, { .type1 = 0x2001 }, 1},
|
||||||
|
{{0x174E58, 0x175B94}, { .type1 = 0x4770 }, 1}
|
||||||
|
},
|
||||||
|
agbPatches[] = {
|
||||||
|
{{0x9D2A8, 0x9DF64}, {{ 6, 0x00, 0x20, 0x4E, 0xB0, 0x70, 0xBD }}, 0},
|
||||||
|
{{0xD7A12, 0xD8B8A}, { .type1 = 0xEF26 }, 1}
|
||||||
|
};
|
||||||
|
|
||||||
if(mode || emuNAND)
|
/* Calculate the amount of patches to apply. Only count the boot screen patch for AGB_FIRM
|
||||||
|
if the matching option was enabled (keep it as last) */
|
||||||
|
u32 numPatches = firmType == 2 ? (sizeof(twlPatches) / sizeof(patchData)) : (sizeof(agbPatches) / sizeof(patchData) - !CONFIG(5, 1));
|
||||||
|
const patchData *patches = firmType == 2 ? twlPatches : agbPatches;
|
||||||
|
|
||||||
|
//Patch
|
||||||
|
for(u32 i = 0; i < numPatches; i++)
|
||||||
{
|
{
|
||||||
//Find the Process9 NCCH location
|
switch(patches[i].type)
|
||||||
u8 *proc9Offset = getProc9(arm9Section, section[2].size);
|
{
|
||||||
|
case 0:
|
||||||
//Apply emuNAND patches
|
memcpy((u8 *)firm + patches[i].offset[console], patches[i].patch.type0 + 1, patches[i].patch.type0[0]);
|
||||||
if(emuNAND) patchEmuNAND(proc9Offset);
|
break;
|
||||||
|
case 2:
|
||||||
//Apply FIRM reboot patches, not on 9.0 FIRM as it breaks firmlaunchhax
|
*(u16 *)((u8 *)firm + patches[i].offset[console] + 2) = 0;
|
||||||
if(mode) patchReboots(proc9Offset);
|
case 1:
|
||||||
|
*(u16 *)((u8 *)firm + patches[i].offset[console]) = patches[i].patch.type1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Apply FIRM0/1 writes patches on sysNAND to protect A9LH
|
static inline void launchFirm(u32 bootType)
|
||||||
if(a9lhSetup && !emuNAND)
|
|
||||||
{
|
{
|
||||||
u16 *writeOffset = getFirmWrite(arm9Section, section[2].size);
|
|
||||||
*writeOffset = writeBlock[0];
|
|
||||||
*(writeOffset + 1) = writeBlock[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
//Apply signature checks patches
|
|
||||||
u32 sigOffset,
|
|
||||||
sigOffset2;
|
|
||||||
|
|
||||||
getSigChecks(arm9Section, section[2].size, &sigOffset, &sigOffset2);
|
|
||||||
*(u16 *)sigOffset = sigPatch[0];
|
|
||||||
*(u16 *)sigOffset2 = sigPatch[0];
|
|
||||||
*((u16 *)sigOffset2 + 1) = sigPatch[1];
|
|
||||||
|
|
||||||
//Replace the FIRM loader with the injector
|
|
||||||
injectLoader();
|
|
||||||
|
|
||||||
//Write patched FIRM to SD if needed
|
|
||||||
if(selectedFirm)
|
|
||||||
if(!fileWrite(firm, patchedFirms[selectedFirm - 1], firmSize))
|
|
||||||
error("Couldn't write the patched FIRM (no free space?)");
|
|
||||||
}
|
|
||||||
|
|
||||||
void launchFirm(void)
|
|
||||||
{
|
|
||||||
if(console && mode) setKeyXs(arm9Section);
|
|
||||||
|
|
||||||
//Copy firm partitions to respective memory locations
|
//Copy firm partitions to respective memory locations
|
||||||
memcpy(section[0].address, (u8 *)firm + section[0].offset, section[0].size);
|
for(u32 i = 0; i < 4 && section[i].size; i++)
|
||||||
memcpy(section[1].address, (u8 *)firm + section[1].offset, section[1].size);
|
memcpy(section[i].address, (u8 *)firm + section[i].offset, section[i].size);
|
||||||
memcpy(section[2].address, arm9Section, section[2].size);
|
|
||||||
|
|
||||||
//Fixes N3DS 3D
|
//Determine the ARM11 entry to use
|
||||||
|
vu32 *arm11;
|
||||||
|
if(bootType) arm11 = (u32 *)0x1FFFFFFC;
|
||||||
|
else
|
||||||
|
{
|
||||||
deinitScreens();
|
deinitScreens();
|
||||||
|
arm11 = (u32 *)0x1FFFFFF8;
|
||||||
|
}
|
||||||
|
|
||||||
//Set ARM11 kernel entrypoint
|
//Set ARM11 kernel entrypoint
|
||||||
*(vu32 *)0x1FFFFFF8 = (u32)firm->arm11Entry;
|
*arm11 = (u32)firm->arm11Entry;
|
||||||
|
|
||||||
//Final jump to arm9 kernel
|
//Final jump to arm9 kernel
|
||||||
((void (*)())firm->arm9Entry)();
|
((void (*)())firm->arm9Entry)();
|
||||||
|
@ -38,7 +38,10 @@ typedef struct patchData {
|
|||||||
u32 type;
|
u32 type;
|
||||||
} patchData;
|
} patchData;
|
||||||
|
|
||||||
void setupCFW(void);
|
static inline void loadFirm(u32 firmType, u32 externalFirm);
|
||||||
void loadFirm(void);
|
static inline void patchNativeFirm(u32 firmType, u32 emuNAND, u32 emuHeader, u32 a9lhSetup);
|
||||||
void patchFirm(void);
|
static inline void patchEmuNAND(u8 *arm9Section, u8 *proc9Offset, u32 emuHeader);
|
||||||
void launchFirm(void);
|
static inline void patchReboots(u8 *arm9Section, u8 *proc9Offset);
|
||||||
|
static inline void injectLoader(void);
|
||||||
|
static inline void patchTwlAgbFirm(u32 firmType);
|
||||||
|
static inline void launchFirm(u32 bootType);
|
64
source/fs.c
64
source/fs.c
@ -5,13 +5,16 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
|
#include "memory.h"
|
||||||
#include "fatfs/ff.h"
|
#include "fatfs/ff.h"
|
||||||
|
|
||||||
static FATFS fs;
|
static FATFS sdFs,
|
||||||
|
nandFs;
|
||||||
|
|
||||||
u32 mountSD(void)
|
u32 mountFs(void)
|
||||||
{
|
{
|
||||||
if(f_mount(&fs, "0:", 1) != FR_OK) return 0;
|
if(f_mount(&sdFs, "0:", 1) != FR_OK) return 0;
|
||||||
|
f_mount(&nandFs, "1:", 0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,7 +71,58 @@ u32 fileExists(const char *path)
|
|||||||
return exists;
|
return exists;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fileDelete(const char *path)
|
void firmRead(u8 *dest, const char *firmFolder)
|
||||||
{
|
{
|
||||||
f_unlink(path);
|
char path[48] = "1:/title/00040138/00000000/content";
|
||||||
|
memcpy(&path[18], firmFolder, 8);
|
||||||
|
|
||||||
|
DIR dir;
|
||||||
|
FILINFO info = { .lfname = NULL };
|
||||||
|
|
||||||
|
f_opendir(&dir, path);
|
||||||
|
|
||||||
|
u32 id = 0;
|
||||||
|
|
||||||
|
//Parse the target directory
|
||||||
|
while(f_readdir(&dir, &info) == FR_OK)
|
||||||
|
{
|
||||||
|
//We've parsed the whole folder
|
||||||
|
if(!info.fname[0]) break;
|
||||||
|
|
||||||
|
//Not a cxi
|
||||||
|
if(info.fname[9] != 'a' && info.fname[9] != 'A') continue;
|
||||||
|
|
||||||
|
//Convert the .app name to an integer
|
||||||
|
u32 tempId = 0;
|
||||||
|
for(char *tmp = info.fname; (*tmp) != '.'; tmp++)
|
||||||
|
{
|
||||||
|
if((*tmp) > '9') tempId = (tempId << 4) + ((*tmp) - 'A') + 9;
|
||||||
|
else tempId = (tempId << 4) + (*tmp) - '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
//Found a newer cxi
|
||||||
|
if(tempId > id) id = tempId;
|
||||||
|
}
|
||||||
|
|
||||||
|
f_closedir(&dir);
|
||||||
|
|
||||||
|
//Complete the string with the .app name
|
||||||
|
memcpy(&path[34], "/00000000.app", 14);
|
||||||
|
|
||||||
|
//Last digit of the .app
|
||||||
|
u32 i = 42;
|
||||||
|
|
||||||
|
//Convert back the .app name from integer to array
|
||||||
|
while(id > 15)
|
||||||
|
{
|
||||||
|
u32 remainder = (id % 16);
|
||||||
|
if(remainder > 9) path[i] = remainder - 9 + 'A';
|
||||||
|
else path[i] = remainder + '0';
|
||||||
|
id /= 16;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
if(id > 9) path[i] = id - 9 + 'A';
|
||||||
|
else path[i] = id + '0';
|
||||||
|
|
||||||
|
fileRead(dest, path, 0);
|
||||||
}
|
}
|
@ -8,9 +8,9 @@
|
|||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
u32 mountSD(void);
|
u32 mountFs(void);
|
||||||
u32 fileRead(void *dest, const char *path, u32 size);
|
u32 fileRead(void *dest, const char *path, u32 size);
|
||||||
u32 fileWrite(const void *buffer, const char *path, u32 size);
|
u32 fileWrite(const void *buffer, const char *path, u32 size);
|
||||||
u32 fileSize(const char *path);
|
u32 fileSize(const char *path);
|
||||||
u32 fileExists(const char *path);
|
u32 fileExists(const char *path);
|
||||||
void fileDelete(const char *path);
|
void firmRead(u8 *dest, const char *firmFolder);
|
@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
* main.c
|
|
||||||
* by Reisyukaku / Aurora Wright
|
|
||||||
* Copyright (c) 2016 All Rights Reserved
|
|
||||||
*
|
|
||||||
* Minimalist CFW for (N)3DS
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "fs.h"
|
|
||||||
#include "firm.h"
|
|
||||||
|
|
||||||
void main(void)
|
|
||||||
{
|
|
||||||
mountSD();
|
|
||||||
setupCFW();
|
|
||||||
loadFirm();
|
|
||||||
patchFirm();
|
|
||||||
launchFirm();
|
|
||||||
}
|
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
#define SCREENINIT_ADDRESS 0x24F03000
|
#define SCREENINIT_ADDRESS 0x24F03000
|
||||||
|
|
||||||
static vu32 *const arm11 = (u32 *)0x1FFFFFF8;
|
vu32 *arm11Entry = (u32 *)0x1FFFFFF8;
|
||||||
|
|
||||||
void deinitScreens(void)
|
void deinitScreens(void)
|
||||||
{
|
{
|
||||||
@ -26,7 +26,7 @@ void deinitScreens(void)
|
|||||||
__asm(".word 0xF10C01C0");
|
__asm(".word 0xF10C01C0");
|
||||||
|
|
||||||
//Clear ARM11 entry offset
|
//Clear ARM11 entry offset
|
||||||
*arm11 = 0;
|
*arm11Entry = 0;
|
||||||
|
|
||||||
//Shutdown LCDs
|
//Shutdown LCDs
|
||||||
*(vu32 *)0x10202A44 = 0;
|
*(vu32 *)0x10202A44 = 0;
|
||||||
@ -34,16 +34,16 @@ void deinitScreens(void)
|
|||||||
*(vu32 *)0x10202014 = 0;
|
*(vu32 *)0x10202014 = 0;
|
||||||
|
|
||||||
//Wait for the entry to be set
|
//Wait for the entry to be set
|
||||||
while(!*arm11);
|
while(!*arm11Entry);
|
||||||
|
|
||||||
//Jump to it
|
//Jump to it
|
||||||
((void (*)())*arm11)();
|
((void (*)())*arm11Entry)();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(PDN_GPU_CNT != 1)
|
if(PDN_GPU_CNT != 1)
|
||||||
{
|
{
|
||||||
*arm11 = (u32)ARM11;
|
*arm11Entry = (u32)ARM11;
|
||||||
while(*arm11);
|
while(*arm11Entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,10 +54,10 @@ void initScreens(void)
|
|||||||
memcpy((void *)SCREENINIT_ADDRESS, screeninit, screeninit_size);
|
memcpy((void *)SCREENINIT_ADDRESS, screeninit, screeninit_size);
|
||||||
|
|
||||||
//Write brightness level for the stub to pick up
|
//Write brightness level for the stub to pick up
|
||||||
*(vu32 *)(SCREENINIT_ADDRESS + 8) = CONFIG(10, 3);
|
*(vu32 *)(SCREENINIT_ADDRESS + 8) = CONFIG(14, 3);
|
||||||
|
|
||||||
*arm11 = SCREENINIT_ADDRESS;
|
*arm11Entry = SCREENINIT_ADDRESS;
|
||||||
while(*arm11);
|
while(*arm11Entry);
|
||||||
|
|
||||||
//Turn on backlight
|
//Turn on backlight
|
||||||
i2cWriteRegister(I2C_DEV_MCU, 0x22, 0x2A);
|
i2cWriteRegister(I2C_DEV_MCU, 0x22, 0x2A);
|
||||||
|
@ -2,15 +2,20 @@
|
|||||||
.align 4
|
.align 4
|
||||||
.global _start
|
.global _start
|
||||||
_start:
|
_start:
|
||||||
|
b start
|
||||||
|
|
||||||
|
.word 0
|
||||||
|
|
||||||
|
start:
|
||||||
@ Change the stack pointer
|
@ Change the stack pointer
|
||||||
mov sp, #0x27000000
|
mov sp, #0x27000000
|
||||||
|
|
||||||
@ Give read/write access to all the memory regions
|
@ Give read/write access to all the memory regions
|
||||||
ldr r0, =0x33333333
|
ldr r5, =0x33333333
|
||||||
mcr p15, 0, r0, c5, c0, 2 @ write data access
|
mcr p15, 0, r5, c5, c0, 2 @ write data access
|
||||||
mcr p15, 0, r0, c5, c0, 3 @ write instruction access
|
mcr p15, 0, r5, c5, c0, 3 @ write instruction access
|
||||||
|
|
||||||
@ Set MPU permissions and cache settings
|
@ Sets MPU permissions and cache settings
|
||||||
ldr r0, =0xFFFF001D @ ffff0000 32k
|
ldr r0, =0xFFFF001D @ ffff0000 32k
|
||||||
ldr r1, =0x01FF801D @ 01ff8000 32k
|
ldr r1, =0x01FF801D @ 01ff8000 32k
|
||||||
ldr r2, =0x08000027 @ 08000000 1M
|
ldr r2, =0x08000027 @ 08000000 1M
|
||||||
@ -28,16 +33,16 @@ _start:
|
|||||||
mcr p15, 0, r6, c6, c6, 0
|
mcr p15, 0, r6, c6, c6, 0
|
||||||
mcr p15, 0, r7, c6, c7, 0
|
mcr p15, 0, r7, c6, c7, 0
|
||||||
mov r0, #0x25
|
mov r0, #0x25
|
||||||
mcr p15, 0, r0, c2, c0, 0 @ data cacheable
|
mcr p15, 0, r0, c3, c0, 0 @ Write bufferable 0, 2, 5
|
||||||
mcr p15, 0, r0, c2, c0, 1 @ instruction cacheable
|
mcr p15, 0, r0, c2, c0, 0 @ Data cacheable 0, 2, 5
|
||||||
mcr p15, 0, r0, c3, c0, 0 @ data bufferable
|
mcr p15, 0, r0, c2, c0, 1 @ Inst cacheable 0, 2, 5
|
||||||
|
|
||||||
@ Enable caches
|
@ Enable caches
|
||||||
mrc p15, 0, r0, c1, c0, 0 @ read control register
|
mrc p15, 0, r4, c1, c0, 0 @ read control register
|
||||||
orr r0, r0, #(1<<12) @ - instruction cache enable
|
orr r4, r4, #(1<<12) @ - instruction cache enable
|
||||||
orr r0, r0, #(1<<2) @ - data cache enable
|
orr r4, r4, #(1<<2) @ - data cache enable
|
||||||
orr r0, r0, #(1<<0) @ - mpu enable
|
orr r4, r4, #(1<<0) @ - mpu enable
|
||||||
mcr p15, 0, r0, c1, c0, 0 @ write control register
|
mcr p15, 0, r4, c1, c0, 0 @ write control register
|
||||||
|
|
||||||
@ Flush caches
|
@ Flush caches
|
||||||
mov r0, #0
|
mov r0, #0
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "screeninit.h"
|
#include "screeninit.h"
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
#include "fs.h"
|
|
||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
#include "buttons.h"
|
#include "buttons.h"
|
||||||
|
|
||||||
@ -37,15 +36,6 @@ u32 waitInput(void)
|
|||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
void deleteFirms(const char *firmPaths[], u32 firms)
|
|
||||||
{
|
|
||||||
while(firms)
|
|
||||||
{
|
|
||||||
fileDelete(firmPaths[firms - 1]);
|
|
||||||
firms--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void error(const char *message)
|
void error(const char *message)
|
||||||
{
|
{
|
||||||
initScreens();
|
initScreens();
|
||||||
|
@ -9,5 +9,4 @@
|
|||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
u32 waitInput(void);
|
u32 waitInput(void);
|
||||||
void deleteFirms(const char *firmPaths[], u32 firms);
|
|
||||||
void error(const char *message);
|
void error(const char *message);
|
Reference in New Issue
Block a user