Code restructuring, added A9LH updater with the new "perfect" key2 from @gemarcano and 8.1 instead of 9.0 FIRM for FIRM0, which together net 1312 bytes for stage1, added uninstalling feature (only works if SysNAND is not 11.0 or later to prevent resulting in an unhackable console, NOT YET TESTED ON N3DS), merged PR from @d0k3 (https://github.com/AuroraWright/SafeA9LHInstaller/pull/10) which adds support for installing A9LH and dumping OTP directly from 2.1
This commit is contained in:
parent
9833b29c78
commit
4ec05a33bc
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -4,3 +4,6 @@
|
|||||||
[submodule "CakeHax"]
|
[submodule "CakeHax"]
|
||||||
path = CakeHax
|
path = CakeHax
|
||||||
url = https://github.com/mid-kid/CakeHax.git
|
url = https://github.com/mid-kid/CakeHax.git
|
||||||
|
[submodule "2xrsa"]
|
||||||
|
path = 2xrsa
|
||||||
|
url = https://github.com/b1l1s/2xrsa.git
|
||||||
|
1
2xrsa
Submodule
1
2xrsa
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit c3f93cb492d61978fd0620d715510932837495dd
|
47
Makefile
47
Makefile
@ -6,26 +6,26 @@ LD := arm-none-eabi-ld
|
|||||||
OC := arm-none-eabi-objcopy
|
OC := arm-none-eabi-objcopy
|
||||||
|
|
||||||
name := SafeA9LHInstaller
|
name := SafeA9LHInstaller
|
||||||
version := $(shell git describe --abbrev=0 --tags)
|
revision := $(shell git describe --tags --match v[0-9]* --abbrev=8 | sed 's/-[0-9]*-g/-/i')
|
||||||
|
|
||||||
dir_source := source
|
dir_source := source
|
||||||
dir_mset := CakeHax
|
dir_mset := CakeHax
|
||||||
dir_ninjhax := CakeBrah
|
dir_ninjhax := CakeBrah
|
||||||
|
dir_2xrsa := 2xrsa
|
||||||
dir_build := build
|
dir_build := build
|
||||||
dir_out := out
|
dir_out := out
|
||||||
|
|
||||||
ASFLAGS := -mlittle-endian -mcpu=arm946e-s -march=armv5te
|
ASFLAGS := -mcpu=arm946e-s
|
||||||
CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -fno-builtin -fshort-wchar -std=c11 -Wno-main -O2 -ffast-math
|
CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -fno-builtin -fshort-wchar -std=c11 -Wno-main -O2 -flto -ffast-math
|
||||||
CFLAGS += -DTITLE="\"$(name) $(version)\""
|
LDFLAGS := -nostartfiles
|
||||||
FLAGS := name=$(name).dat dir_out=$(abspath $(dir_out)) ICON=$(abspath icon.png) APP_DESCRIPTION="Noob-proof ARM9LoaderHax installer/updater." APP_AUTHOR="Aurora Wright" --no-print-directory
|
FLAGS := name=$(name).dat dir_out=$(abspath $(dir_out)) ICON=$(abspath icon.png) APP_DESCRIPTION="Noob-proof ARM9LoaderHax installer/updater." APP_AUTHOR="Aurora Wright" --no-print-directory
|
||||||
|
|
||||||
objects= $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
objects= $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
||||||
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
||||||
$(call rwildcard, $(dir_source), *.s *.c)))
|
$(call rwildcard, $(dir_source), *.s *.c)))
|
||||||
|
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
all: launcher a9lh ninjhax
|
all: launcher a9lh ninjhax 2xrsa
|
||||||
|
|
||||||
.PHONY: launcher
|
.PHONY: launcher
|
||||||
launcher: $(dir_out)/$(name).dat
|
launcher: $(dir_out)/$(name).dat
|
||||||
@ -33,16 +33,20 @@ launcher: $(dir_out)/$(name).dat
|
|||||||
.PHONY: a9lh
|
.PHONY: a9lh
|
||||||
a9lh: $(dir_out)/arm9loaderhax.bin
|
a9lh: $(dir_out)/arm9loaderhax.bin
|
||||||
|
|
||||||
|
.PHONY: 2xrsa
|
||||||
|
2xrsa: $(dir_out)/arm9.bin $(dir_out)/arm11.bin
|
||||||
|
|
||||||
.PHONY: ninjhax
|
.PHONY: ninjhax
|
||||||
ninjhax: $(dir_out)/3ds/$(name)
|
ninjhax: $(dir_out)/3ds/$(name)
|
||||||
|
|
||||||
.PHONY: release
|
.PHONY: release
|
||||||
release: $(dir_out)/$(name).zip
|
release: $(dir_out)/$(name)$(revision).7z
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
@$(MAKE) $(FLAGS) -C $(dir_mset) clean
|
@$(MAKE) $(FLAGS) -C $(dir_mset) clean
|
||||||
@$(MAKE) $(FLAGS) -C $(dir_ninjhax) clean
|
@$(MAKE) $(FLAGS) -C $(dir_ninjhax) clean
|
||||||
|
@$(MAKE) -C $(dir_2xrsa) clean
|
||||||
@rm -rf $(dir_out) $(dir_build)
|
@rm -rf $(dir_out) $(dir_build)
|
||||||
|
|
||||||
$(dir_out):
|
$(dir_out):
|
||||||
@ -56,21 +60,30 @@ $(dir_out)/$(name).dat: $(dir_build)/main.bin $(dir_out)
|
|||||||
$(dir_out)/arm9loaderhax.bin: $(dir_build)/main.bin $(dir_out)
|
$(dir_out)/arm9loaderhax.bin: $(dir_build)/main.bin $(dir_out)
|
||||||
@cp -av $(dir_build)/main.bin $@
|
@cp -av $(dir_build)/main.bin $@
|
||||||
|
|
||||||
|
$(dir_out)/arm9.bin: $(dir_build)/main.bin $(dir_out)
|
||||||
|
@cp -av $(dir_build)/main.bin $@
|
||||||
|
|
||||||
|
$(dir_out)/arm11.bin:
|
||||||
|
@$(MAKE) -C $(dir_2xrsa)
|
||||||
|
@cp -av $(dir_2xrsa)/bin/arm11.bin $@
|
||||||
|
|
||||||
$(dir_out)/3ds/$(name): $(dir_out)
|
$(dir_out)/3ds/$(name): $(dir_out)
|
||||||
@mkdir -p $(dir_out)/3ds/$(name)
|
@mkdir -p $(dir_out)/3ds/$(name)
|
||||||
@$(MAKE) $(FLAGS) -C $(dir_ninjhax)
|
@$(MAKE) $(FLAGS) -C $(dir_ninjhax)
|
||||||
@mv $(dir_out)/$(name).3dsx $@
|
@mv $(dir_out)/$(name).3dsx $@
|
||||||
@mv $(dir_out)/$(name).smdh $@
|
@mv $(dir_out)/$(name).smdh $@
|
||||||
|
|
||||||
$(dir_out)/$(name).zip: launcher a9lh ninjhax
|
$(dir_out)/$(name)$(revision).7z: launcher a9lh ninjhax 2xrsa
|
||||||
@cd $(dir_out) && zip -9 -r $(name) *
|
@7z a -mx $@ ./$(@D)/*
|
||||||
|
|
||||||
$(dir_build)/main.bin: $(dir_build)/main.elf
|
$(dir_build)/main.bin: $(dir_build)/main.elf
|
||||||
$(OC) -S -O binary $< $@
|
$(OC) -S -O binary $< $@
|
||||||
|
|
||||||
$(dir_build)/main.elf: $(objects)
|
$(dir_build)/main.elf: $(objects)
|
||||||
# FatFs requires libgcc for __aeabi_uidiv
|
$(LINK.o) -T linker.ld $(OUTPUT_OPTION) $^
|
||||||
$(CC) -nostartfiles $(LDFLAGS) -T linker.ld $(OUTPUT_OPTION) $^
|
|
||||||
|
$(dir_build)/memory.o: CFLAGS += -O3
|
||||||
|
$(dir_build)/installer.o: CFLAGS += -DTITLE="\"$(name) $(revision)\""
|
||||||
|
|
||||||
$(dir_build)/%.o: $(dir_source)/%.c
|
$(dir_build)/%.o: $(dir_source)/%.c
|
||||||
@mkdir -p "$(@D)"
|
@mkdir -p "$(@D)"
|
||||||
@ -79,12 +92,4 @@ $(dir_build)/%.o: $(dir_source)/%.c
|
|||||||
$(dir_build)/%.o: $(dir_source)/%.s
|
$(dir_build)/%.o: $(dir_source)/%.s
|
||||||
@mkdir -p "$(@D)"
|
@mkdir -p "$(@D)"
|
||||||
$(COMPILE.s) $(OUTPUT_OPTION) $<
|
$(COMPILE.s) $(OUTPUT_OPTION) $<
|
||||||
|
|
||||||
$(dir_build)/fatfs/%.o: $(dir_source)/fatfs/%.c
|
|
||||||
@mkdir -p "$(@D)"
|
|
||||||
$(COMPILE.c) -mthumb -mthumb-interwork -Wno-unused-function $(OUTPUT_OPTION) $<
|
|
||||||
|
|
||||||
$(dir_build)/fatfs/%.o: $(dir_source)/fatfs/%.s
|
|
||||||
@mkdir -p "$(@D)"
|
|
||||||
$(COMPILE.s) -mthumb -mthumb-interwork $(OUTPUT_OPTION) $<
|
|
||||||
include $(call rwildcard, $(dir_build), *.d)
|
include $(call rwildcard, $(dir_build), *.d)
|
||||||
|
118
source/crypto.c
118
source/crypto.c
@ -1,4 +1,8 @@
|
|||||||
// From http://github.com/b1l1s/ctr
|
/*
|
||||||
|
* crypto.c
|
||||||
|
*
|
||||||
|
* Crypto libs from http://github.com/b1l1s/ctr
|
||||||
|
*/
|
||||||
|
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
@ -270,26 +274,68 @@ void sha(void *res, const void *src, u32 size, u32 mode)
|
|||||||
* Nand/FIRM Crypto stuff
|
* Nand/FIRM Crypto stuff
|
||||||
****************************************************************/
|
****************************************************************/
|
||||||
|
|
||||||
static u8 CTR[0x10];
|
static u8 nandSlot, nandCTR[0x10];
|
||||||
|
|
||||||
static const u8 a9lhKey2[0x10] = {
|
static u32 fatStart;
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, 0xF5, 0xF6
|
|
||||||
|
const u8 key2s[3][0x10] = {
|
||||||
|
{0x42, 0x3F, 0x81, 0x7A, 0x23, 0x52, 0x58, 0x31, 0x6E, 0x75, 0x8E, 0x3A, 0x39, 0x43, 0x2E, 0xD0},
|
||||||
|
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, 0xF5, 0xF6},
|
||||||
|
{0x65, 0x29, 0x3E, 0x12, 0x56, 0x0C, 0x0B, 0xD1, 0xDD, 0xB5, 0x63, 0x1C, 0xB6, 0xD9, 0x52, 0x75}
|
||||||
};
|
};
|
||||||
|
|
||||||
//Get Nand CTR key
|
//Get Nand CTR key
|
||||||
void getNandCTR(void){
|
void getNandCTR(void)
|
||||||
u8 NandCid[0x10];
|
{
|
||||||
u8 shasum[0x20];
|
u8 cid[0x10];
|
||||||
|
u8 shaSum[0x20];
|
||||||
|
|
||||||
sdmmc_get_cid(1, (u32 *)NandCid);
|
sdmmc_get_cid(1, (u32 *)cid);
|
||||||
sha(shasum, NandCid, 0x10, SHA_256_MODE);
|
sha(shaSum, cid, 0x10, SHA_256_MODE);
|
||||||
memcpy(CTR, shasum, 0x10);
|
memcpy(nandCTR, shaSum, 0x10);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Initialize the CTRNAND crypto
|
||||||
|
void ctrNandInit(void)
|
||||||
|
{
|
||||||
|
getNandCTR();
|
||||||
|
|
||||||
|
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 and decrypt from CTRNAND
|
||||||
|
u32 ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf)
|
||||||
|
{
|
||||||
|
u8 tmpCTR[0x10];
|
||||||
|
memcpy(tmpCTR, nandCTR, 0x10);
|
||||||
|
aes_advctr(tmpCTR, ((sector + fatStart) * 0x200) / AES_BLOCK_SIZE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
|
|
||||||
|
//Read
|
||||||
|
u32 result = sdmmc_nand_readsectors(sector + fatStart, sectorCount, outbuf);
|
||||||
|
|
||||||
|
//Decrypt
|
||||||
|
aes_use_keyslot(nandSlot);
|
||||||
|
aes(outbuf, outbuf, sectorCount * 0x200 / AES_BLOCK_SIZE, tmpCTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Read and decrypt from the FIRM0 partition on NAND
|
//Read and decrypt from the FIRM0 partition on NAND
|
||||||
void readFirm0(u8 *outbuf, u32 size){
|
void readFirm0(u8 *outbuf, u32 size)
|
||||||
u8 CTRtmp[sizeof(CTR)];
|
{
|
||||||
memcpy(CTRtmp, CTR, sizeof(CTR));
|
u8 CTRtmp[0x10];
|
||||||
|
memcpy(CTRtmp, nandCTR, 0x10);
|
||||||
|
|
||||||
//Read FIRM0 data
|
//Read FIRM0 data
|
||||||
sdmmc_nand_readsectors(0x0B130000 / 0x200, size / 0x200, outbuf);
|
sdmmc_nand_readsectors(0x0B130000 / 0x200, size / 0x200, outbuf);
|
||||||
@ -301,10 +347,11 @@ void readFirm0(u8 *outbuf, u32 size){
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Encrypt and write a FIRM partition to NAND
|
//Encrypt and write a FIRM partition to NAND
|
||||||
void writeFirm(u8 *inbuf, u32 firm, u32 size){
|
void writeFirm(u8 *inbuf, u32 firm, u32 size)
|
||||||
|
{
|
||||||
u32 offset = firm ? 0x0B530000 : 0x0B130000;
|
u32 offset = firm ? 0x0B530000 : 0x0B130000;
|
||||||
u8 CTRtmp[sizeof(CTR)];
|
u8 CTRtmp[0x10];
|
||||||
memcpy(CTRtmp, CTR, sizeof(CTR));
|
memcpy(CTRtmp, nandCTR, 0x10);
|
||||||
|
|
||||||
//Encrypt FIRM data
|
//Encrypt FIRM data
|
||||||
aes_advctr(CTRtmp, offset / 0x10, AES_INPUT_BE | AES_INPUT_NORMAL);
|
aes_advctr(CTRtmp, offset / 0x10, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
@ -316,7 +363,8 @@ void writeFirm(u8 *inbuf, u32 firm, u32 size){
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Setup keyslot 0x11 for key sector de/encryption
|
//Setup keyslot 0x11 for key sector de/encryption
|
||||||
void setupKeyslot0x11(u32 a9lhBoot, const void *otp){
|
void setupKeyslot0x11(u32 a9lhBoot, const void *otp)
|
||||||
|
{
|
||||||
u8 shasum[0x20];
|
u8 shasum[0x20];
|
||||||
u8 keyX[0x10];
|
u8 keyX[0x10];
|
||||||
u8 keyY[0x10];
|
u8 keyY[0x10];
|
||||||
@ -334,9 +382,10 @@ void setupKeyslot0x11(u32 a9lhBoot, const void *otp){
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Generate and encrypt an A9LH key sector
|
//Generate and encrypt an A9LH key sector
|
||||||
void generateSector(u8 *keySector){
|
void generateSector(u8 *keySector, u32 mode)
|
||||||
//Inject A9LH key2
|
{
|
||||||
memcpy(keySector + 0x10, a9lhKey2, 0x10);
|
//Inject key2
|
||||||
|
memcpy(keySector + 0x10, mode ? key2s[0] : key2s[2], 0x10);
|
||||||
|
|
||||||
//Encrypt key sector
|
//Encrypt key sector
|
||||||
aes_use_keyslot(0x11);
|
aes_use_keyslot(0x11);
|
||||||
@ -345,7 +394,8 @@ void generateSector(u8 *keySector){
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Read and decrypt the NAND key sector
|
//Read and decrypt the NAND key sector
|
||||||
void getSector(u8 *keySector){
|
void getSector(u8 *keySector)
|
||||||
|
{
|
||||||
//Read keysector from NAND
|
//Read keysector from NAND
|
||||||
sdmmc_nand_readsectors(0x96, 1, keySector);
|
sdmmc_nand_readsectors(0x96, 1, keySector);
|
||||||
|
|
||||||
@ -356,9 +406,29 @@ void getSector(u8 *keySector){
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Check SHA256 hash
|
//Check SHA256 hash
|
||||||
u32 verifyHash(const void *data, u32 size, const u8 *hash){
|
u32 verifyHash(const void *data, u32 size, const u8 *hash)
|
||||||
|
{
|
||||||
u8 shasum[0x20];
|
u8 shasum[0x20];
|
||||||
sha(shasum, data, size, SHA_256_MODE);
|
sha(shasum, data, size, SHA_256_MODE);
|
||||||
if(memcmp(shasum, hash, 0x20) != 0) return 0;
|
|
||||||
return 1;
|
return memcmp(shasum, hash, 0x20) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Decrypt a FIRM ExeFS
|
||||||
|
u32 decryptExeFs(u8 *inbuf)
|
||||||
|
{
|
||||||
|
u8 *exeFsOffset = inbuf + *(u32 *)(inbuf + 0x1A0) * 0x200;
|
||||||
|
u32 exeFsSize = *(u32 *)(inbuf + 0x1A4) * 0x200;
|
||||||
|
u8 ncchCTR[0x10] = {0};
|
||||||
|
|
||||||
|
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, exeFsOffset, exeFsSize / AES_BLOCK_SIZE, ncchCTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
|
|
||||||
|
return exeFsSize - 0x200;
|
||||||
}
|
}
|
@ -1,4 +1,8 @@
|
|||||||
// From http://github.com/b1l1s/ctr
|
/*
|
||||||
|
* crypto.h
|
||||||
|
*
|
||||||
|
* Crypto libs from http://github.com/b1l1s/ctr
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -76,10 +80,16 @@
|
|||||||
#define SHA_1_HASH_SIZE (160 / 8)
|
#define SHA_1_HASH_SIZE (160 / 8)
|
||||||
|
|
||||||
//NAND/FIRM stuff
|
//NAND/FIRM stuff
|
||||||
|
extern u32 console;
|
||||||
|
const u8 key2s[3][0x10];
|
||||||
|
|
||||||
void getNandCTR(void);
|
void getNandCTR(void);
|
||||||
|
void ctrNandInit(void);
|
||||||
|
u32 ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf);
|
||||||
void readFirm0(u8 *outbuf, u32 size);
|
void readFirm0(u8 *outbuf, u32 size);
|
||||||
void writeFirm(u8 *inbuf, u32 offset, u32 size);
|
void writeFirm(u8 *inbuf, u32 offset, u32 size);
|
||||||
void setupKeyslot0x11(u32 a9lhBoot, const void *otp);
|
void setupKeyslot0x11(u32 a9lhBoot, const void *otp);
|
||||||
void generateSector(u8 *keySector);
|
void generateSector(u8 *keySector, u32 mode);
|
||||||
void getSector(u8 *keySector);
|
void getSector(u8 *keySector);
|
||||||
u32 verifyHash(const void *data, u32 size, const u8 *hash);
|
u32 verifyHash(const void *data, u32 size, const u8 *hash);
|
||||||
|
u32 decryptExeFs(u8 *inbuf);
|
@ -1,63 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* draw.c
|
||||||
|
*
|
||||||
|
* Code to print to the screen by mid-kid @CakesFW
|
||||||
|
*/
|
||||||
|
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "font.h"
|
#include "font.h"
|
||||||
|
|
||||||
#define SCREEN_TOP_WIDTH 400
|
|
||||||
#define SCREEN_TOP_HEIGHT 240
|
|
||||||
|
|
||||||
static const struct fb {
|
static const struct fb {
|
||||||
u8 *top_left;
|
u8 *top_left;
|
||||||
u8 *top_right;
|
u8 *top_right;
|
||||||
u8 *bottom;
|
u8 *bottom;
|
||||||
} *const fb = (struct fb *)0x23FFFE00;
|
} *const fb = (struct fb *)0x23FFFE00;
|
||||||
|
|
||||||
static int strlen(const char *string){
|
static inline int strlen(const char *string)
|
||||||
|
{
|
||||||
char *stringEnd = (char *)string;
|
char *stringEnd = (char *)string;
|
||||||
|
|
||||||
while(*stringEnd) stringEnd++;
|
while(*stringEnd) stringEnd++;
|
||||||
|
|
||||||
return stringEnd - string;
|
return stringEnd - string;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearScreens(void){
|
void clearScreens(void)
|
||||||
|
{
|
||||||
memset32(fb->top_left, 0, 0x46500);
|
memset32(fb->top_left, 0, 0x46500);
|
||||||
memset32(fb->top_right, 0, 0x46500);
|
memset32(fb->top_right, 0, 0x46500);
|
||||||
memset32(fb->bottom, 0, 0x38400);
|
memset32(fb->bottom, 0, 0x38400);
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawCharacter(char character, int pos_x, int pos_y, u32 color){
|
void drawCharacter(char character, int posX, int posY, u32 color)
|
||||||
|
{
|
||||||
u8 *const select = fb->top_left;
|
u8 *const select = fb->top_left;
|
||||||
|
|
||||||
for(int y = 0; y < 8; y++){
|
for(int y = 0; y < 8; y++)
|
||||||
unsigned char char_pos = font[character * 8 + y];
|
{
|
||||||
|
char charPos = font[character * 8 + y];
|
||||||
|
|
||||||
for(int x = 7; x >= 0; x--){
|
for(int x = 7; x >= 0; x--)
|
||||||
int screen_pos = (pos_x * SCREEN_TOP_HEIGHT * 3 + (SCREEN_TOP_HEIGHT - y - pos_y - 1) * 3) + (7 - x) * 3 * SCREEN_TOP_HEIGHT;
|
if ((charPos >> x) & 1)
|
||||||
|
{
|
||||||
|
int screenPos = (posX * SCREEN_TOP_HEIGHT * 3 + (SCREEN_TOP_HEIGHT - y - posY - 1) * 3) + (7 - x) * 3 * SCREEN_TOP_HEIGHT;
|
||||||
|
|
||||||
if ((char_pos >> x) & 1) {
|
select[screenPos] = color >> 16;
|
||||||
select[screen_pos] = color >> 16;
|
select[screenPos + 1] = color >> 8;
|
||||||
select[screen_pos + 1] = color >> 8;
|
select[screenPos + 2] = color;
|
||||||
select[screen_pos + 2] = color;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int drawString(const char *string, int pos_x, int pos_y, u32 color){
|
int drawString(const char *string, int posX, int posY, u32 color)
|
||||||
int length = strlen(string);
|
{
|
||||||
|
for(int i = 0, line_i = 0; i < strlen(string); i++, line_i++)
|
||||||
for(int i = 0, line_i = 0; i < length; i++, line_i++){
|
{
|
||||||
if(string[i] == '\n'){
|
if(string[i] == '\n')
|
||||||
pos_y += SPACING_VERT;
|
{
|
||||||
|
posY += SPACING_Y;
|
||||||
line_i = 0;
|
line_i = 0;
|
||||||
i++;
|
i++;
|
||||||
} else if(line_i >= (SCREEN_TOP_WIDTH - pos_x) / SPACING_HORIZ){
|
}
|
||||||
|
else if(line_i >= (SCREEN_TOP_WIDTH - posX) / SPACING_X)
|
||||||
|
{
|
||||||
// Make sure we never get out of the screen.
|
// Make sure we never get out of the screen.
|
||||||
pos_y += SPACING_VERT;
|
posY += SPACING_Y;
|
||||||
line_i = 2; // Little offset so we know the same string continues.
|
line_i = 2; //Little offset so we know the same string continues.
|
||||||
if(string[i] == ' ') i++; // Spaces at the start look weird
|
if(string[i] == ' ') i++; //Spaces at the start look weird
|
||||||
}
|
}
|
||||||
|
|
||||||
drawCharacter(string[i], pos_x + line_i * SPACING_HORIZ, pos_y, color);
|
drawCharacter(string[i], posX + line_i * SPACING_X, posY, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
return pos_y + SPACING_VERT;
|
return posY + SPACING_Y;
|
||||||
}
|
}
|
@ -1,9 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* draw.h
|
||||||
|
*
|
||||||
|
* Code to print to the screen by mid-kid @CakesFW
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
#define SPACING_VERT 10
|
#define SCREEN_TOP_WIDTH 400
|
||||||
#define SPACING_HORIZ 8
|
#define SCREEN_TOP_HEIGHT 240
|
||||||
|
|
||||||
|
#define SPACING_Y 10
|
||||||
|
#define SPACING_X 8
|
||||||
|
|
||||||
void clearScreens(void);
|
void clearScreens(void);
|
||||||
void drawCharacter(char character, int pos_x, int pos_y, u32 color);
|
void drawCharacter(char character, int pos_x, int pos_y, u32 color);
|
||||||
|
@ -1,180 +1,254 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
Revision history of FatFs module
|
Revision history of FatFs module
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
|
|
||||||
R0.00 (February 26, 2006)
|
R0.00 (February 26, 2006)
|
||||||
Prototype.
|
|
||||||
|
Prototype.
|
||||||
|
|
||||||
R0.01 (April 29, 2006)
|
|
||||||
First stable version.
|
|
||||||
|
R0.01 (April 29, 2006)
|
||||||
|
|
||||||
R0.02 (June 01, 2006)
|
First stable version.
|
||||||
Added FAT12 support.
|
|
||||||
Removed unbuffered mode.
|
|
||||||
Fixed a problem on small (<32M) partition.
|
|
||||||
|
R0.02 (June 01, 2006)
|
||||||
|
|
||||||
R0.02a (June 10, 2006)
|
Added FAT12 support.
|
||||||
Added a configuration option (_FS_MINIMUM).
|
Removed unbuffered mode.
|
||||||
|
Fixed a problem on small (<32M) partition.
|
||||||
|
|
||||||
R0.03 (September 22, 2006)
|
|
||||||
Added f_rename().
|
|
||||||
Changed option _FS_MINIMUM to _FS_MINIMIZE.
|
R0.02a (June 10, 2006)
|
||||||
|
|
||||||
|
Added a configuration option (_FS_MINIMUM).
|
||||||
R0.03a (December 11, 2006)
|
|
||||||
Improved cluster scan algorithm to write files fast.
|
|
||||||
Fixed f_mkdir() creates incorrect directory on FAT32.
|
|
||||||
|
R0.03 (September 22, 2006)
|
||||||
|
|
||||||
R0.04 (February 04, 2007)
|
Added f_rename().
|
||||||
Added f_mkfs().
|
Changed option _FS_MINIMUM to _FS_MINIMIZE.
|
||||||
Supported multiple drive system.
|
|
||||||
Changed some interfaces for multiple drive system.
|
|
||||||
Changed f_mountdrv() to f_mount().
|
|
||||||
|
R0.03a (December 11, 2006)
|
||||||
|
|
||||||
R0.04a (April 01, 2007)
|
Improved cluster scan algorithm to write files fast.
|
||||||
Supported multiple partitions on a physical drive.
|
Fixed f_mkdir() creates incorrect directory on FAT32.
|
||||||
Added a capability of extending file size to f_lseek().
|
|
||||||
Added minimization level 3.
|
|
||||||
Fixed an endian sensitive code in f_mkfs().
|
|
||||||
|
R0.04 (February 04, 2007)
|
||||||
|
|
||||||
R0.04b (May 05, 2007)
|
Added f_mkfs().
|
||||||
Added a configuration option _USE_NTFLAG.
|
Supported multiple drive system.
|
||||||
Added FSINFO support.
|
Changed some interfaces for multiple drive system.
|
||||||
Fixed DBCS name can result FR_INVALID_NAME.
|
Changed f_mountdrv() to f_mount().
|
||||||
Fixed short seek (<= csize) collapses the file object.
|
|
||||||
|
|
||||||
|
|
||||||
R0.05 (August 25, 2007)
|
R0.04a (April 01, 2007)
|
||||||
Changed arguments of f_read(), f_write() and f_mkfs().
|
|
||||||
Fixed f_mkfs() on FAT32 creates incorrect FSINFO.
|
Supported multiple partitions on a physical drive.
|
||||||
Fixed f_mkdir() on FAT32 creates incorrect directory.
|
Added a capability of extending file size to f_lseek().
|
||||||
|
Added minimization level 3.
|
||||||
|
Fixed an endian sensitive code in f_mkfs().
|
||||||
R0.05a (February 03, 2008)
|
|
||||||
Added f_truncate() and f_utime().
|
|
||||||
Fixed off by one error at FAT sub-type determination.
|
|
||||||
Fixed btr in f_read() can be mistruncated.
|
R0.04b (May 05, 2007)
|
||||||
Fixed cached sector is not flushed when create and close without write.
|
|
||||||
|
Added a configuration option _USE_NTFLAG.
|
||||||
|
Added FSINFO support.
|
||||||
R0.06 (April 01, 2008)
|
Fixed DBCS name can result FR_INVALID_NAME.
|
||||||
Added fputc(), fputs(), fprintf() and fgets().
|
Fixed short seek (<= csize) collapses the file object.
|
||||||
Improved performance of f_lseek() on moving to the same or following cluster.
|
|
||||||
|
|
||||||
|
|
||||||
R0.07 (April 01, 2009)
|
R0.05 (August 25, 2007)
|
||||||
Merged Tiny-FatFs as a configuration option. (_FS_TINY)
|
|
||||||
Added long file name feature. (_USE_LFN)
|
Changed arguments of f_read(), f_write() and f_mkfs().
|
||||||
Added multiple code page feature. (_CODE_PAGE)
|
Fixed f_mkfs() on FAT32 creates incorrect FSINFO.
|
||||||
Added re-entrancy for multitask operation. (_FS_REENTRANT)
|
Fixed f_mkdir() on FAT32 creates incorrect directory.
|
||||||
Added auto cluster size selection to f_mkfs().
|
|
||||||
Added rewind option to f_readdir().
|
|
||||||
Changed result code of critical errors.
|
|
||||||
Renamed string functions to avoid name collision.
|
R0.05a (February 03, 2008)
|
||||||
|
|
||||||
|
Added f_truncate() and f_utime().
|
||||||
R0.07a (April 14, 2009)
|
Fixed off by one error at FAT sub-type determination.
|
||||||
Septemberarated out OS dependent code on reentrant cfg.
|
Fixed btr in f_read() can be mistruncated.
|
||||||
Added multiple sector size feature.
|
Fixed cached sector is not flushed when create and close without write.
|
||||||
|
|
||||||
|
|
||||||
R0.07c (June 21, 2009)
|
|
||||||
Fixed f_unlink() can return FR_OK on error.
|
R0.06 (April 01, 2008)
|
||||||
Fixed wrong cache control in f_lseek().
|
|
||||||
Added relative path feature.
|
Added fputc(), fputs(), fprintf() and fgets().
|
||||||
Added f_chdir() and f_chdrive().
|
Improved performance of f_lseek() on moving to the same or following cluster.
|
||||||
Added proper case conversion to extended character.
|
|
||||||
|
|
||||||
|
|
||||||
R0.07e (November 03, 2009)
|
R0.07 (April 01, 2009)
|
||||||
Septemberarated out configuration options from ff.h to ffconf.h.
|
|
||||||
Fixed f_unlink() fails to remove a sub-directory on _FS_RPATH.
|
Merged Tiny-FatFs as a configuration option. (_FS_TINY)
|
||||||
Fixed name matching error on the 13 character boundary.
|
Added long file name feature. (_USE_LFN)
|
||||||
Added a configuration option, _LFN_UNICODE.
|
Added multiple code page feature. (_CODE_PAGE)
|
||||||
Changed f_readdir() to return the SFN with always upper case on non-LFN cfg.
|
Added re-entrancy for multitask operation. (_FS_REENTRANT)
|
||||||
|
Added auto cluster size selection to f_mkfs().
|
||||||
|
Added rewind option to f_readdir().
|
||||||
R0.08 (May 15, 2010)
|
Changed result code of critical errors.
|
||||||
Added a memory configuration option. (_USE_LFN = 3)
|
Renamed string functions to avoid name collision.
|
||||||
Added file lock feature. (_FS_SHARE)
|
|
||||||
Added fast seek feature. (_USE_FASTSEEK)
|
|
||||||
Changed some types on the API, XCHAR->TCHAR.
|
|
||||||
Changed .fname in the FILINFO structure on Unicode cfg.
|
R0.07a (April 14, 2009)
|
||||||
String functions support UTF-8 encoding files on Unicode cfg.
|
|
||||||
|
Septemberarated out OS dependent code on reentrant cfg.
|
||||||
|
Added multiple sector size feature.
|
||||||
R0.08a (August 16, 2010)
|
|
||||||
Added f_getcwd(). (_FS_RPATH = 2)
|
|
||||||
Added sector erase feature. (_USE_ERASE)
|
|
||||||
Moved file lock semaphore table from fs object to the bss.
|
R0.07c (June 21, 2009)
|
||||||
Fixed f_mkfs() creates wrong FAT32 volume.
|
|
||||||
|
Fixed f_unlink() can return FR_OK on error.
|
||||||
|
Fixed wrong cache control in f_lseek().
|
||||||
R0.08b (January 15, 2011)
|
Added relative path feature.
|
||||||
Fast seek feature is also applied to f_read() and f_write().
|
Added f_chdir() and f_chdrive().
|
||||||
f_lseek() reports required table size on creating CLMP.
|
Added proper case conversion to extended character.
|
||||||
Extended format syntax of f_printf().
|
|
||||||
Ignores duplicated directory separators in given path name.
|
|
||||||
|
|
||||||
|
R0.07e (November 03, 2009)
|
||||||
R0.09 (September 06, 2011)
|
|
||||||
f_mkfs() supports multiple partition to complete the multiple partition feature.
|
Septemberarated out configuration options from ff.h to ffconf.h.
|
||||||
Added f_fdisk().
|
Fixed f_unlink() fails to remove a sub-directory on _FS_RPATH.
|
||||||
|
Fixed name matching error on the 13 character boundary.
|
||||||
|
Added a configuration option, _LFN_UNICODE.
|
||||||
R0.09a (August 27, 2012)
|
Changed f_readdir() to return the SFN with always upper case on non-LFN cfg.
|
||||||
Changed f_open() and f_opendir() reject null object pointer to avoid crash.
|
|
||||||
Changed option name _FS_SHARE to _FS_LOCK.
|
|
||||||
Fixed assertion failure due to OS/2 EA on FAT12/16 volume.
|
|
||||||
|
R0.08 (May 15, 2010)
|
||||||
|
|
||||||
R0.09b (January 24, 2013)
|
Added a memory configuration option. (_USE_LFN = 3)
|
||||||
Added f_setlabel() and f_getlabel().
|
Added file lock feature. (_FS_SHARE)
|
||||||
|
Added fast seek feature. (_USE_FASTSEEK)
|
||||||
|
Changed some types on the API, XCHAR->TCHAR.
|
||||||
R0.10 (October 02, 2013)
|
Changed .fname in the FILINFO structure on Unicode cfg.
|
||||||
Added selection of character encoding on the file. (_STRF_ENCODE)
|
String functions support UTF-8 encoding files on Unicode cfg.
|
||||||
Added f_closedir().
|
|
||||||
Added forced full FAT scan for f_getfree(). (_FS_NOFSINFO)
|
|
||||||
Added forced mount feature with changes of f_mount().
|
|
||||||
Improved behavior of volume auto detection.
|
R0.08a (August 16, 2010)
|
||||||
Improved write throughput of f_puts() and f_printf().
|
|
||||||
Changed argument of f_chdrive(), f_mkfs(), disk_read() and disk_write().
|
Added f_getcwd(). (_FS_RPATH = 2)
|
||||||
Fixed f_write() can be truncated when the file size is close to 4GB.
|
Added sector erase feature. (_USE_ERASE)
|
||||||
Fixed f_open(), f_mkdir() and f_setlabel() can return incorrect error code.
|
Moved file lock semaphore table from fs object to the bss.
|
||||||
|
Fixed f_mkfs() creates wrong FAT32 volume.
|
||||||
|
|
||||||
R0.10a (January 15, 2014)
|
|
||||||
Added arbitrary strings as drive number in the path name. (_STR_VOLUME_ID)
|
|
||||||
Added a configuration option of minimum sector size. (_MIN_SS)
|
R0.08b (January 15, 2011)
|
||||||
2nd argument of f_rename() can have a drive number and it will be ignored.
|
|
||||||
Fixed f_mount() with forced mount fails when drive number is >= 1. (appeared at R0.10)
|
Fast seek feature is also applied to f_read() and f_write().
|
||||||
Fixed f_close() invalidates the file object without volume lock.
|
f_lseek() reports required table size on creating CLMP.
|
||||||
Fixed f_closedir() returns but the volume lock is left acquired. (appeared at R0.10)
|
Extended format syntax of f_printf().
|
||||||
Fixed creation of an entry with LFN fails on too many SFN collisions. (appeared at R0.07)
|
Ignores duplicated directory separators in given path name.
|
||||||
|
|
||||||
|
|
||||||
R0.10b (May 19, 2014)
|
|
||||||
Fixed a hard error in the disk I/O layer can collapse the directory entry.
|
R0.09 (September 06, 2011)
|
||||||
Fixed LFN entry is not deleted on delete/rename an object with lossy converted SFN. (appeared at R0.07)
|
|
||||||
|
f_mkfs() supports multiple partition to complete the multiple partition feature.
|
||||||
|
Added f_fdisk().
|
||||||
R0.10c (November 09, 2014)
|
|
||||||
Added a configuration option for the platforms without RTC. (_FS_NORTC)
|
|
||||||
Changed option name _USE_ERASE to _USE_TRIM.
|
|
||||||
Fixed volume label created by Mac OS X cannot be retrieved with f_getlabel(). (appeared at R0.09b)
|
R0.09a (August 27, 2012)
|
||||||
Fixed a potential problem of FAT access that can appear on disk error.
|
|
||||||
Fixed null pointer dereference on attempting to delete the root direcotry. (appeared at R0.08)
|
Changed f_open() and f_opendir() reject null object pointer to avoid crash.
|
||||||
|
Changed option name _FS_SHARE to _FS_LOCK.
|
||||||
|
Fixed assertion failure due to OS/2 EA on FAT12/16 volume.
|
||||||
R0.11 (February 09, 2015)
|
|
||||||
Added f_findfirst(), f_findnext() and f_findclose(). (_USE_FIND)
|
|
||||||
Fixed f_unlink() does not remove cluster chain of the file. (appeared at R0.10c)
|
|
||||||
Fixed _FS_NORTC option does not work properly. (appeared at R0.10c)
|
R0.09b (January 24, 2013)
|
||||||
|
|
||||||
|
Added f_setlabel() and f_getlabel().
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
R0.10 (October 02, 2013)
|
||||||
|
|
||||||
|
Added selection of character encoding on the file. (_STRF_ENCODE)
|
||||||
|
Added f_closedir().
|
||||||
|
Added forced full FAT scan for f_getfree(). (_FS_NOFSINFO)
|
||||||
|
Added forced mount feature with changes of f_mount().
|
||||||
|
Improved behavior of volume auto detection.
|
||||||
|
Improved write throughput of f_puts() and f_printf().
|
||||||
|
Changed argument of f_chdrive(), f_mkfs(), disk_read() and disk_write().
|
||||||
|
Fixed f_write() can be truncated when the file size is close to 4GB.
|
||||||
|
Fixed f_open(), f_mkdir() and f_setlabel() can return incorrect value on error.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
R0.10a (January 15, 2014)
|
||||||
|
|
||||||
|
Added arbitrary strings as drive number in the path name. (_STR_VOLUME_ID)
|
||||||
|
Added a configuration option of minimum sector size. (_MIN_SS)
|
||||||
|
2nd argument of f_rename() can have a drive number and it will be ignored.
|
||||||
|
Fixed f_mount() with forced mount fails when drive number is >= 1. (appeared at R0.10)
|
||||||
|
Fixed f_close() invalidates the file object without volume lock.
|
||||||
|
Fixed f_closedir() returns but the volume lock is left acquired. (appeared at R0.10)
|
||||||
|
Fixed creation of an entry with LFN fails on too many SFN collisions. (appeared at R0.07)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
R0.10b (May 19, 2014)
|
||||||
|
|
||||||
|
Fixed a hard error in the disk I/O layer can collapse the directory entry.
|
||||||
|
Fixed LFN entry is not deleted on delete/rename an object with lossy converted SFN. (appeared at R0.07)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
R0.10c (November 09, 2014)
|
||||||
|
|
||||||
|
Added a configuration option for the platforms without RTC. (_FS_NORTC)
|
||||||
|
Changed option name _USE_ERASE to _USE_TRIM.
|
||||||
|
Fixed volume label created by Mac OS X cannot be retrieved with f_getlabel(). (appeared at R0.09b)
|
||||||
|
Fixed a potential problem of FAT access that can appear on disk error.
|
||||||
|
Fixed null pointer dereference on attempting to delete the root direcotry. (appeared at R0.08)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
R0.11 (February 09, 2015)
|
||||||
|
|
||||||
|
Added f_findfirst(), f_findnext() and f_findclose(). (_USE_FIND)
|
||||||
|
Fixed f_unlink() does not remove cluster chain of the file. (appeared at R0.10c)
|
||||||
|
Fixed _FS_NORTC option does not work properly. (appeared at R0.10c)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
R0.11a (September 05, 2015)
|
||||||
|
|
||||||
|
Fixed wrong media change can lead a deadlock at thread-safe configuration.
|
||||||
|
Added code page 771, 860, 861, 863, 864, 865 and 869. (_CODE_PAGE)
|
||||||
|
Removed some code pages actually not exist on the standard systems. (_CODE_PAGE)
|
||||||
|
Fixed errors in the case conversion teble of code page 437 and 850 (ff.c).
|
||||||
|
Fixed errors in the case conversion teble of Unicode (cc*.c).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
R0.12 (April 12, 2016)
|
||||||
|
|
||||||
|
Added support of exFAT file system. (_FS_EXFAT)
|
||||||
|
Added f_expand(). (_USE_EXPAND)
|
||||||
|
Changed some members in FINFO structure and behavior of f_readdir().
|
||||||
|
Added an option _USE_CHMOD and removed an option _WORD_ACCESS.
|
||||||
|
Fixed errors in the case conversion teble of Unicode (cc*.c).
|
||||||
|
|
@ -1,21 +1,21 @@
|
|||||||
FatFs Module Source Files R0.11
|
FatFs Module Source Files R0.12
|
||||||
|
|
||||||
|
|
||||||
FILES
|
FILES
|
||||||
|
|
||||||
00readme.txt This file.
|
00readme.txt This file.
|
||||||
history.txt Revision history.
|
history.txt Revision history.
|
||||||
ffconf.h Configuration file for FatFs module.
|
ffconf.h Configuration file for FatFs module.
|
||||||
ff.h Common include file for FatFs and application module.
|
ff.h Common include file for FatFs and application module.
|
||||||
ff.c FatFs module.
|
ff.c FatFs module.
|
||||||
diskio.h Common include file for FatFs and disk I/O module.
|
diskio.h Common include file for FatFs and disk I/O module.
|
||||||
diskio.c An example of glue function to attach existing disk I/O module to FatFs.
|
diskio.c An example of glue function to attach existing disk I/O module to FatFs.
|
||||||
integer.h Integer type definitions for FatFs.
|
integer.h Integer type definitions for FatFs.
|
||||||
option Optional external functions.
|
option Optional external functions.
|
||||||
|
|
||||||
|
|
||||||
Low level disk I/O module is not included in this archive because the FatFs
|
Low level disk I/O module is not included in this archive because the FatFs
|
||||||
module is only a generic file system layer and not depend on any specific
|
module is only a generic file system layer and not depend on any specific
|
||||||
storage device. You have to provide a low level disk I/O module that written
|
storage device. You have to provide a low level disk I/O module that written
|
||||||
to control the target storage device.
|
to control the target storage device.
|
||||||
|
|
||||||
|
@ -9,7 +9,11 @@
|
|||||||
|
|
||||||
#include "diskio.h" /* FatFs lower layer API */
|
#include "diskio.h" /* FatFs lower layer API */
|
||||||
#include "sdmmc/sdmmc.h"
|
#include "sdmmc/sdmmc.h"
|
||||||
|
#include "../crypto.h"
|
||||||
|
|
||||||
|
/* Definitions of physical drive number for each media */
|
||||||
|
#define SDCARD 0
|
||||||
|
#define CTRNAND 1
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* Get Drive Status */
|
/* Get Drive Status */
|
||||||
@ -30,11 +34,17 @@ DSTATUS disk_status (
|
|||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
DSTATUS disk_initialize (
|
DSTATUS disk_initialize (
|
||||||
__attribute__((unused))
|
|
||||||
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
sdmmc_sdcard_init();
|
static u32 sdmmcInited = 0;
|
||||||
|
|
||||||
|
if(!sdmmcInited)
|
||||||
|
sdmmc_sdcard_init();
|
||||||
|
|
||||||
|
if(pdrv == CTRNAND)
|
||||||
|
ctrNandInit();
|
||||||
|
|
||||||
return RES_OK;
|
return RES_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,18 +55,25 @@ DSTATUS disk_initialize (
|
|||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
DRESULT disk_read (
|
DRESULT disk_read (
|
||||||
__attribute__((unused))
|
|
||||||
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
||||||
BYTE *buff, /* Data buffer to store read data */
|
BYTE *buff, /* Data buffer to store read data */
|
||||||
DWORD sector, /* Sector address in LBA */
|
DWORD sector, /* Sector address in LBA */
|
||||||
UINT count /* Number of sectors to read */
|
UINT count /* Number of sectors to read */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (sdmmc_sdcard_readsectors(sector, count, buff)) {
|
switch(pdrv)
|
||||||
return RES_PARERR;
|
{
|
||||||
}
|
case SDCARD:
|
||||||
|
if(sdmmc_sdcard_readsectors(sector, count, (BYTE *)buff))
|
||||||
|
return RES_PARERR;
|
||||||
|
break;
|
||||||
|
case CTRNAND:
|
||||||
|
if(ctrNandRead(sector, count, (BYTE *)buff))
|
||||||
|
return RES_PARERR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return RES_OK;
|
return RES_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -67,18 +84,16 @@ DRESULT disk_read (
|
|||||||
|
|
||||||
#if _USE_WRITE
|
#if _USE_WRITE
|
||||||
DRESULT disk_write (
|
DRESULT disk_write (
|
||||||
__attribute__((unused))
|
|
||||||
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
||||||
const BYTE *buff, /* Data to be written */
|
const BYTE *buff, /* Data to be written */
|
||||||
DWORD sector, /* Sector address in LBA */
|
DWORD sector, /* Sector address in LBA */
|
||||||
UINT count /* Number of sectors to write */
|
UINT count /* Number of sectors to write */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (sdmmc_sdcard_writesectors(sector, count, (BYTE *)buff)) {
|
if(pdrv == SDCARD && sdmmc_sdcard_writesectors(sector, count, (BYTE *)buff))
|
||||||
return RES_PARERR;
|
return RES_PARERR;
|
||||||
}
|
|
||||||
|
|
||||||
return RES_OK;
|
return RES_OK;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
10482
source/fatfs/ff.c
10482
source/fatfs/ff.c
File diff suppressed because it is too large
Load Diff
@ -1,350 +1,366 @@
|
|||||||
/*---------------------------------------------------------------------------/
|
/*---------------------------------------------------------------------------/
|
||||||
/ FatFs - FAT file system module include R0.11 (C)ChaN, 2015
|
/ FatFs - FAT file system module include R0.12 (C)ChaN, 2016
|
||||||
/----------------------------------------------------------------------------/
|
/----------------------------------------------------------------------------/
|
||||||
/ 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.
|
||||||
/
|
/
|
||||||
/ Copyright (C) 2015, ChaN, all right reserved.
|
/ Copyright (C) 2016, ChaN, all right reserved.
|
||||||
/
|
/
|
||||||
/ 1. Redistributions of source code must retain the above copyright notice,
|
/ 1. Redistributions of source code must retain the above copyright notice,
|
||||||
/ this condition and the following disclaimer.
|
/ this condition and the following disclaimer.
|
||||||
/
|
/
|
||||||
/ This software is provided by the copyright holder and contributors "AS IS"
|
/ This software is provided by the copyright holder and contributors "AS IS"
|
||||||
/ and any warranties related to this software are DISCLAIMED.
|
/ and any warranties related to this software are DISCLAIMED.
|
||||||
/ The copyright owner or contributors be NOT LIABLE for any damages caused
|
/ The copyright owner or contributors be NOT LIABLE for any damages caused
|
||||||
/ by use of this software.
|
/ by use of this software.
|
||||||
/---------------------------------------------------------------------------*/
|
/---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef _FATFS
|
#ifndef _FATFS
|
||||||
#define _FATFS 32020 /* Revision ID */
|
#define _FATFS 88100 /* Revision ID */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "integer.h" /* Basic integer types */
|
#include "integer.h" /* Basic integer types */
|
||||||
#include "ffconf.h" /* FatFs configuration options */
|
#include "ffconf.h" /* FatFs configuration options */
|
||||||
#if _FATFS != _FFCONF
|
#if _FATFS != _FFCONF
|
||||||
#error Wrong configuration file (ffconf.h).
|
#error Wrong configuration file (ffconf.h).
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Definitions of volume management */
|
/* Definitions of volume management */
|
||||||
|
|
||||||
#if _MULTI_PARTITION /* Multiple partition configuration */
|
#if _MULTI_PARTITION /* Multiple partition configuration */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
BYTE pd; /* Physical drive number */
|
BYTE pd; /* Physical drive number */
|
||||||
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
|
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
|
||||||
} PARTITION;
|
} PARTITION;
|
||||||
extern PARTITION VolToPart[]; /* Volume - Partition resolution table */
|
extern PARTITION VolToPart[]; /* Volume - Partition resolution table */
|
||||||
#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive number */
|
#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive number */
|
||||||
#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition index */
|
#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition index */
|
||||||
|
|
||||||
#else /* Single partition configuration */
|
#else /* Single partition configuration */
|
||||||
#define LD2PD(vol) (BYTE)(vol) /* Each logical drive is bound to the same physical drive number */
|
#define LD2PD(vol) (BYTE)(vol) /* Each logical drive is bound to the same physical drive number */
|
||||||
#define LD2PT(vol) 0 /* Find first valid partition or in SFD */
|
#define LD2PT(vol) 0 /* Find first valid partition or in SFD */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Type of path name strings on FatFs API */
|
/* Type of path name strings on FatFs API */
|
||||||
|
|
||||||
#if _LFN_UNICODE /* Unicode string */
|
#if _LFN_UNICODE /* Unicode string */
|
||||||
#if !_USE_LFN
|
#if _USE_LFN == 0
|
||||||
#error _LFN_UNICODE must be 0 at non-LFN cfg.
|
#error _LFN_UNICODE must be 0 at non-LFN cfg.
|
||||||
#endif
|
#endif
|
||||||
#ifndef _INC_TCHAR
|
#ifndef _INC_TCHAR
|
||||||
typedef WCHAR TCHAR;
|
typedef WCHAR TCHAR;
|
||||||
#define _T(x) L ## x
|
#define _T(x) L ## x
|
||||||
#define _TEXT(x) L ## x
|
#define _TEXT(x) L ## x
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else /* ANSI/OEM string */
|
#else /* ANSI/OEM string */
|
||||||
#ifndef _INC_TCHAR
|
#ifndef _INC_TCHAR
|
||||||
typedef char TCHAR;
|
typedef char TCHAR;
|
||||||
#define _T(x) x
|
#define _T(x) x
|
||||||
#define _TEXT(x) x
|
#define _TEXT(x) x
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* File system object structure (FATFS) */
|
/* File system object structure (FATFS) */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
BYTE fs_type; /* FAT sub-type (0:Not mounted) */
|
BYTE fs_type; /* File system type (0:N/A) */
|
||||||
BYTE drv; /* Physical drive number */
|
BYTE drv; /* Physical drive number */
|
||||||
BYTE csize; /* Sectors per cluster (1,2,4...128) */
|
BYTE n_fats; /* Number of FATs (1 or 2) */
|
||||||
BYTE n_fats; /* Number of FAT copies (1 or 2) */
|
BYTE wflag; /* win[] flag (b0:dirty) */
|
||||||
BYTE wflag; /* win[] flag (b0:dirty) */
|
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
|
||||||
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
|
WORD id; /* File system mount ID */
|
||||||
WORD id; /* File system mount ID */
|
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
|
||||||
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
|
WORD csize; /* Cluster size [sectors] */
|
||||||
#if _MAX_SS != _MIN_SS
|
#if _MAX_SS != _MIN_SS
|
||||||
WORD ssize; /* Bytes per sector (512, 1024, 2048 or 4096) */
|
WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */
|
||||||
#endif
|
#endif
|
||||||
#if _FS_REENTRANT
|
#if _FS_EXFAT
|
||||||
_SYNC_t sobj; /* Identifier of sync object */
|
BYTE* dirbuf; /* Directory entry block scratchpad buffer */
|
||||||
#endif
|
#endif
|
||||||
#if !_FS_READONLY
|
#if _FS_REENTRANT
|
||||||
DWORD last_clust; /* Last allocated cluster */
|
_SYNC_t sobj; /* Identifier of sync object */
|
||||||
DWORD free_clust; /* Number of free clusters */
|
#endif
|
||||||
#endif
|
#if !_FS_READONLY
|
||||||
#if _FS_RPATH
|
DWORD last_clst; /* Last allocated cluster */
|
||||||
DWORD cdir; /* Current directory start cluster (0:root) */
|
DWORD free_clst; /* Number of free clusters */
|
||||||
#endif
|
#endif
|
||||||
DWORD n_fatent; /* Number of FAT entries, = number of clusters + 2 */
|
#if _FS_RPATH != 0
|
||||||
DWORD fsize; /* Sectors per FAT */
|
DWORD cdir; /* Current directory start cluster (0:root) */
|
||||||
DWORD volbase; /* Volume start sector */
|
#if _FS_EXFAT
|
||||||
DWORD fatbase; /* FAT start sector */
|
DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is 0) */
|
||||||
DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */
|
DWORD cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */
|
||||||
DWORD database; /* Data start sector */
|
DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is 0) */
|
||||||
DWORD winsect; /* Current sector appearing in the win[] */
|
#endif
|
||||||
BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
|
#endif
|
||||||
} FATFS;
|
DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */
|
||||||
|
DWORD fsize; /* Size of an FAT [sectors] */
|
||||||
|
DWORD volbase; /* Volume base sector */
|
||||||
|
DWORD fatbase; /* FAT base sector */
|
||||||
/* File object structure (FIL) */
|
DWORD dirbase; /* Root directory base sector/cluster */
|
||||||
|
DWORD database; /* Data base sector */
|
||||||
typedef struct {
|
DWORD winsect; /* Current sector appearing in the win[] */
|
||||||
FATFS* fs; /* Pointer to the related file system object (**do not change order**) */
|
BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
|
||||||
WORD id; /* Owner file system mount ID (**do not change order**) */
|
} FATFS;
|
||||||
BYTE flag; /* Status flags */
|
|
||||||
BYTE err; /* Abort flag (error code) */
|
|
||||||
DWORD fptr; /* File read/write pointer (Zeroed on file open) */
|
|
||||||
DWORD fsize; /* File size */
|
/* Type of file size variables and object identifier */
|
||||||
DWORD sclust; /* File start cluster (0:no cluster chain, always 0 when fsize is 0) */
|
|
||||||
DWORD clust; /* Current cluster of fpter (not valid when fprt is 0) */
|
#if _FS_EXFAT
|
||||||
DWORD dsect; /* Sector number appearing in buf[] (0:invalid) */
|
#if _USE_LFN == 0
|
||||||
#if !_FS_READONLY
|
#error LFN must be enabled when enable exFAT
|
||||||
DWORD dir_sect; /* Sector number containing the directory entry */
|
#endif
|
||||||
BYTE* dir_ptr; /* Pointer to the directory entry in the win[] */
|
typedef QWORD FSIZE_t;
|
||||||
#endif
|
#else
|
||||||
#if _USE_FASTSEEK
|
typedef DWORD FSIZE_t;
|
||||||
DWORD* cltbl; /* Pointer to the cluster link map table (Nulled on file open) */
|
#endif
|
||||||
#endif
|
|
||||||
#if _FS_LOCK
|
|
||||||
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */
|
|
||||||
#endif
|
/* Object ID and allocation information (_FDID) */
|
||||||
#if !_FS_TINY
|
|
||||||
BYTE buf[_MAX_SS]; /* File private data read/write window */
|
typedef struct {
|
||||||
#endif
|
FATFS* fs; /* Pointer to the owner file system object */
|
||||||
} FIL;
|
WORD id; /* Owner file system mount ID */
|
||||||
|
BYTE attr; /* Object attribute */
|
||||||
|
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous (no data on FAT), =3:got flagmented, b2:sub-directory stretched) */
|
||||||
|
DWORD sclust; /* Object start cluster (0:no cluster or root directory) */
|
||||||
/* Directory object structure (DIR) */
|
FSIZE_t objsize; /* Object size (valid when sclust != 0) */
|
||||||
|
#if _FS_EXFAT
|
||||||
typedef struct {
|
DWORD n_cont; /* Size of coutiguous part, clusters - 1 (valid when stat == 3) */
|
||||||
FATFS* fs; /* Pointer to the owner file system object (**do not change order**) */
|
DWORD c_scl; /* Containing directory start cluster (valid when sclust != 0) */
|
||||||
WORD id; /* Owner file system mount ID (**do not change order**) */
|
DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */
|
||||||
WORD index; /* Current read/write index number */
|
DWORD c_ofs; /* Offset in the containing directory (valid when sclust != 0) */
|
||||||
DWORD sclust; /* Table start cluster (0:Root dir) */
|
#endif
|
||||||
DWORD clust; /* Current cluster */
|
#if _FS_LOCK != 0
|
||||||
DWORD sect; /* Current sector */
|
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */
|
||||||
BYTE* dir; /* Pointer to the current SFN entry in the win[] */
|
#endif
|
||||||
BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
|
} _FDID;
|
||||||
#if _FS_LOCK
|
|
||||||
UINT lockid; /* File lock ID (index of file semaphore table Files[]) */
|
|
||||||
#endif
|
|
||||||
#if _USE_LFN
|
/* File object structure (FIL) */
|
||||||
WCHAR* lfn; /* Pointer to the LFN working buffer */
|
|
||||||
WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */
|
typedef struct {
|
||||||
#endif
|
_FDID obj; /* Object identifier */
|
||||||
#if _USE_FIND
|
BYTE flag; /* File status flags */
|
||||||
const TCHAR* pat; /* Pointer to the name matching pattern */
|
BYTE err; /* Abort flag (error code) */
|
||||||
#endif
|
FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */
|
||||||
} DIR;
|
DWORD clust; /* Current cluster of fpter (not valid when fprt is 0) */
|
||||||
|
DWORD sect; /* Sector number appearing in buf[] (0:invalid) */
|
||||||
|
#if !_FS_READONLY
|
||||||
|
DWORD dir_sect; /* Sector number containing the directory entry */
|
||||||
/* File information structure (FILINFO) */
|
BYTE* dir_ptr; /* Pointer to the directory entry in the win[] */
|
||||||
|
#endif
|
||||||
typedef struct {
|
#if _USE_FASTSEEK
|
||||||
DWORD fsize; /* File size */
|
DWORD* cltbl; /* Pointer to the cluster link map table (Nulled on file open) */
|
||||||
WORD fdate; /* Last modified date */
|
#endif
|
||||||
WORD ftime; /* Last modified time */
|
#if !_FS_TINY
|
||||||
BYTE fattrib; /* Attribute */
|
BYTE buf[_MAX_SS]; /* File private data read/write window */
|
||||||
TCHAR fname[13]; /* Short file name (8.3 format) */
|
#endif
|
||||||
#if _USE_LFN
|
} FIL;
|
||||||
TCHAR* lfname; /* Pointer to the LFN buffer */
|
|
||||||
UINT lfsize; /* Size of LFN buffer in TCHAR */
|
|
||||||
#endif
|
|
||||||
} FILINFO;
|
/* Directory object structure (DIR) */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
_FDID obj; /* Object identifier */
|
||||||
/* File function return code (FRESULT) */
|
DWORD dptr; /* Current read/write offset */
|
||||||
|
DWORD clust; /* Current cluster */
|
||||||
typedef enum {
|
DWORD sect; /* Current sector */
|
||||||
FR_OK = 0, /* (0) Succeeded */
|
BYTE* dir; /* Pointer to the directory item in the win[] */
|
||||||
FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
|
BYTE* fn; /* Pointer to the SFN (in/out) {body[8],ext[3],status[1]} */
|
||||||
FR_INT_ERR, /* (2) Assertion failed */
|
#if _USE_LFN != 0
|
||||||
FR_NOT_READY, /* (3) The physical drive cannot work */
|
DWORD blk_ofs; /* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */
|
||||||
FR_NO_FILE, /* (4) Could not find the file */
|
WCHAR* lfn; /* Pointer to the LFN working buffer */
|
||||||
FR_NO_PATH, /* (5) Could not find the path */
|
#endif
|
||||||
FR_INVALID_NAME, /* (6) The path name format is invalid */
|
#if _USE_FIND
|
||||||
FR_DENIED, /* (7) Access denied due to prohibited access or directory full */
|
const TCHAR* pat; /* Pointer to the name matching pattern */
|
||||||
FR_EXIST, /* (8) Access denied due to prohibited access */
|
#endif
|
||||||
FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
|
} DIR;
|
||||||
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
|
|
||||||
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
|
|
||||||
FR_NOT_ENABLED, /* (12) The volume has no work area */
|
|
||||||
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
|
/* File information structure (FILINFO) */
|
||||||
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */
|
|
||||||
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
|
typedef struct {
|
||||||
FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
|
FSIZE_t fsize; /* File size */
|
||||||
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
|
WORD fdate; /* Modified date */
|
||||||
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_SHARE */
|
WORD ftime; /* Modified time */
|
||||||
FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
|
BYTE fattrib; /* File attribute */
|
||||||
} FRESULT;
|
#if _USE_LFN != 0
|
||||||
|
TCHAR altname[13]; /* Altenative file name */
|
||||||
|
TCHAR fname[_MAX_LFN + 1]; /* Primary file name */
|
||||||
|
#else
|
||||||
/*--------------------------------------------------------------*/
|
TCHAR fname[13]; /* File name */
|
||||||
/* FatFs module application interface */
|
#endif
|
||||||
|
} FILINFO;
|
||||||
FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */
|
|
||||||
FRESULT f_close (FIL* fp); /* Close an open file object */
|
|
||||||
FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from a file */
|
|
||||||
FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to a file */
|
/* File function return code (FRESULT) */
|
||||||
FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */
|
|
||||||
FRESULT f_lseek (FIL* fp, DWORD ofs); /* Move file pointer of a file object */
|
typedef enum {
|
||||||
FRESULT f_truncate (FIL* fp); /* Truncate file */
|
FR_OK = 0, /* (0) Succeeded */
|
||||||
FRESULT f_sync (FIL* fp); /* Flush cached data of a writing file */
|
FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
|
||||||
FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */
|
FR_INT_ERR, /* (2) Assertion failed */
|
||||||
FRESULT f_closedir (DIR* dp); /* Close an open directory */
|
FR_NOT_READY, /* (3) The physical drive cannot work */
|
||||||
FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */
|
FR_NO_FILE, /* (4) Could not find the file */
|
||||||
FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern); /* Find first file */
|
FR_NO_PATH, /* (5) Could not find the path */
|
||||||
FRESULT f_findnext (DIR* dp, FILINFO* fno); /* Find next file */
|
FR_INVALID_NAME, /* (6) The path name format is invalid */
|
||||||
FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */
|
FR_DENIED, /* (7) Access denied due to prohibited access or directory full */
|
||||||
FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */
|
FR_EXIST, /* (8) Access denied due to prohibited access */
|
||||||
FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */
|
FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
|
||||||
FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */
|
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
|
||||||
FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of the file/dir */
|
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
|
||||||
FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change times-tamp of the file/dir */
|
FR_NOT_ENABLED, /* (12) The volume has no work area */
|
||||||
FRESULT f_chdir (const TCHAR* path); /* Change current directory */
|
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
|
||||||
FRESULT f_chdrive (const TCHAR* path); /* Change current drive */
|
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */
|
||||||
FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */
|
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
|
||||||
FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */
|
FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
|
||||||
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */
|
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
|
||||||
FRESULT f_setlabel (const TCHAR* label); /* Set volume label */
|
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_LOCK */
|
||||||
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */
|
FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
|
||||||
FRESULT f_mkfs (const TCHAR* path, BYTE sfd, UINT au); /* Create a file system on the volume */
|
} FRESULT;
|
||||||
FRESULT f_fdisk (BYTE pdrv, const DWORD szt[], void* work); /* Divide a physical drive into some partitions */
|
|
||||||
int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */
|
|
||||||
int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */
|
|
||||||
int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */
|
/*--------------------------------------------------------------*/
|
||||||
TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */
|
/* FatFs module application interface */
|
||||||
|
|
||||||
#define f_eof(fp) ((int)((fp)->fptr == (fp)->fsize))
|
FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */
|
||||||
#define f_error(fp) ((fp)->err)
|
FRESULT f_close (FIL* fp); /* Close an open file object */
|
||||||
#define f_tell(fp) ((fp)->fptr)
|
FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from a file */
|
||||||
#define f_size(fp) ((fp)->fsize)
|
FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to a file */
|
||||||
#define f_rewind(fp) f_lseek((fp), 0)
|
FRESULT f_lseek (FIL* fp, FSIZE_t ofs); /* Move file pointer of a file object */
|
||||||
#define f_rewinddir(dp) f_readdir((dp), 0)
|
FRESULT f_truncate (FIL* fp); /* Truncate file */
|
||||||
|
FRESULT f_sync (FIL* fp); /* Flush cached data of a writing file */
|
||||||
#ifndef EOF
|
FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */
|
||||||
#define EOF (-1)
|
FRESULT f_closedir (DIR* dp); /* Close an open directory */
|
||||||
#endif
|
FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */
|
||||||
|
FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern); /* Find first file */
|
||||||
|
FRESULT f_findnext (DIR* dp, FILINFO* fno); /* Find next file */
|
||||||
|
FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */
|
||||||
|
FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */
|
||||||
/*--------------------------------------------------------------*/
|
FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */
|
||||||
/* Additional user defined functions */
|
FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */
|
||||||
|
FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of the file/dir */
|
||||||
/* RTC function */
|
FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change timestamp of the file/dir */
|
||||||
#if !_FS_READONLY && !_FS_NORTC
|
FRESULT f_chdir (const TCHAR* path); /* Change current directory */
|
||||||
DWORD get_fattime (void);
|
FRESULT f_chdrive (const TCHAR* path); /* Change current drive */
|
||||||
#endif
|
FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */
|
||||||
|
FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */
|
||||||
/* Unicode support functions */
|
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */
|
||||||
#if _USE_LFN /* Unicode - OEM code conversion */
|
FRESULT f_setlabel (const TCHAR* label); /* Set volume label */
|
||||||
WCHAR ff_convert (WCHAR chr, UINT dir); /* OEM-Unicode bidirectional conversion */
|
FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */
|
||||||
WCHAR ff_wtoupper (WCHAR chr); /* Unicode upper-case conversion */
|
FRESULT f_expand (FIL* fp, FSIZE_t szf, BYTE opt); /* Allocate a contiguous block to the file */
|
||||||
#if _USE_LFN == 3 /* Memory functions */
|
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */
|
||||||
void* ff_memalloc (UINT msize); /* Allocate memory block */
|
FRESULT f_mkfs (const TCHAR* path, BYTE sfd, UINT au); /* Create a file system on the volume */
|
||||||
void ff_memfree (void* mblock); /* Free memory block */
|
FRESULT f_fdisk (BYTE pdrv, const DWORD szt[], void* work); /* Divide a physical drive into some partitions */
|
||||||
#endif
|
int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */
|
||||||
#endif
|
int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */
|
||||||
|
int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */
|
||||||
/* Sync functions */
|
TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */
|
||||||
#if _FS_REENTRANT
|
|
||||||
int ff_cre_syncobj (BYTE vol, _SYNC_t* sobj); /* Create a sync object */
|
#define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize))
|
||||||
int ff_req_grant (_SYNC_t sobj); /* Lock sync object */
|
#define f_error(fp) ((fp)->err)
|
||||||
void ff_rel_grant (_SYNC_t sobj); /* Unlock sync object */
|
#define f_tell(fp) ((fp)->fptr)
|
||||||
int ff_del_syncobj (_SYNC_t sobj); /* Delete a sync object */
|
#define f_size(fp) ((fp)->obj.objsize)
|
||||||
#endif
|
#define f_rewind(fp) f_lseek((fp), 0)
|
||||||
|
#define f_rewinddir(dp) f_readdir((dp), 0)
|
||||||
|
|
||||||
|
#ifndef EOF
|
||||||
|
#define EOF (-1)
|
||||||
/*--------------------------------------------------------------*/
|
#endif
|
||||||
/* Flags and offset address */
|
|
||||||
|
|
||||||
|
|
||||||
/* File access control and file status flags (FIL.flag) */
|
|
||||||
|
/*--------------------------------------------------------------*/
|
||||||
#define FA_READ 0x01
|
/* Additional user defined functions */
|
||||||
#define FA_OPEN_EXISTING 0x00
|
|
||||||
|
/* RTC function */
|
||||||
#if !_FS_READONLY
|
#if !_FS_READONLY && !_FS_NORTC
|
||||||
#define FA_WRITE 0x02
|
DWORD get_fattime (void);
|
||||||
#define FA_CREATE_NEW 0x04
|
#endif
|
||||||
#define FA_CREATE_ALWAYS 0x08
|
|
||||||
#define FA_OPEN_ALWAYS 0x10
|
/* Unicode support functions */
|
||||||
#define FA__WRITTEN 0x20
|
#if _USE_LFN != 0 /* Unicode - OEM code conversion */
|
||||||
#define FA__DIRTY 0x40
|
WCHAR ff_convert (WCHAR chr, UINT dir); /* OEM-Unicode bidirectional conversion */
|
||||||
#endif
|
WCHAR ff_wtoupper (WCHAR chr); /* Unicode upper-case conversion */
|
||||||
|
#if _USE_LFN == 3 /* Memory functions */
|
||||||
|
void* ff_memalloc (UINT msize); /* Allocate memory block */
|
||||||
/* FAT sub type (FATFS.fs_type) */
|
void ff_memfree (void* mblock); /* Free memory block */
|
||||||
|
#endif
|
||||||
#define FS_FAT12 1
|
#endif
|
||||||
#define FS_FAT16 2
|
|
||||||
#define FS_FAT32 3
|
/* Sync functions */
|
||||||
|
#if _FS_REENTRANT
|
||||||
|
int ff_cre_syncobj (BYTE vol, _SYNC_t* sobj); /* Create a sync object */
|
||||||
/* File attribute bits for directory entry */
|
int ff_req_grant (_SYNC_t sobj); /* Lock sync object */
|
||||||
|
void ff_rel_grant (_SYNC_t sobj); /* Unlock sync object */
|
||||||
#define AM_RDO 0x01 /* Read only */
|
int ff_del_syncobj (_SYNC_t sobj); /* Delete a sync object */
|
||||||
#define AM_HID 0x02 /* Hidden */
|
#endif
|
||||||
#define AM_SYS 0x04 /* System */
|
|
||||||
#define AM_VOL 0x08 /* Volume label */
|
|
||||||
#define AM_LFN 0x0F /* LFN entry */
|
|
||||||
#define AM_DIR 0x10 /* Directory */
|
|
||||||
#define AM_ARC 0x20 /* Archive */
|
/*--------------------------------------------------------------*/
|
||||||
#define AM_MASK 0x3F /* Mask of defined bits */
|
/* Flags and offset address */
|
||||||
|
|
||||||
|
|
||||||
/* Fast seek feature */
|
/* File access control and file status flags (FIL.flag) */
|
||||||
#define CREATE_LINKMAP 0xFFFFFFFF
|
|
||||||
|
#define FA_READ 0x01
|
||||||
|
#define FA_WRITE 0x02
|
||||||
|
#define FA_OPEN_EXISTING 0x00
|
||||||
/*--------------------------------*/
|
#define FA_CREATE_NEW 0x04
|
||||||
/* Multi-byte word access macros */
|
#define FA_CREATE_ALWAYS 0x08
|
||||||
|
#define FA_OPEN_ALWAYS 0x10
|
||||||
#if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */
|
#define _FA_MODIFIED 0x20
|
||||||
#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr))
|
#define _FA_DIRTY 0x40
|
||||||
#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr))
|
|
||||||
#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val)
|
|
||||||
#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val)
|
/* FAT sub type (FATFS.fs_type) */
|
||||||
#else /* Use byte-by-byte access to the FAT structure */
|
|
||||||
#define LD_WORD(ptr) (WORD)(((WORD)*((BYTE*)(ptr)+1)<<8)|(WORD)*(BYTE*)(ptr))
|
#define FS_FAT12 1
|
||||||
#define LD_DWORD(ptr) (DWORD)(((DWORD)*((BYTE*)(ptr)+3)<<24)|((DWORD)*((BYTE*)(ptr)+2)<<16)|((WORD)*((BYTE*)(ptr)+1)<<8)|*(BYTE*)(ptr))
|
#define FS_FAT16 2
|
||||||
#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8)
|
#define FS_FAT32 3
|
||||||
#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8); *((BYTE*)(ptr)+2)=(BYTE)((DWORD)(val)>>16); *((BYTE*)(ptr)+3)=(BYTE)((DWORD)(val)>>24)
|
#define FS_EXFAT 4
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
/* File attribute bits for directory entry */
|
||||||
}
|
|
||||||
#endif
|
#define AM_RDO 0x01 /* Read only */
|
||||||
|
#define AM_HID 0x02 /* Hidden */
|
||||||
#endif /* _FATFS */
|
#define AM_SYS 0x04 /* System */
|
||||||
|
#define AM_VOL 0x08 /* Volume label */
|
||||||
|
#define AM_LFN 0x0F /* LFN entry */
|
||||||
|
#define AM_DIR 0x10 /* Directory */
|
||||||
|
#define AM_ARC 0x20 /* Archive */
|
||||||
|
#define AM_MASK 0x3F /* Mask of defined bits */
|
||||||
|
|
||||||
|
|
||||||
|
/* Fast seek controls */
|
||||||
|
#define CREATE_LINKMAP ((FSIZE_t)0 - 1)
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _FATFS */
|
||||||
|
@ -1,271 +1,266 @@
|
|||||||
/*---------------------------------------------------------------------------/
|
/*---------------------------------------------------------------------------/
|
||||||
/ FatFs - FAT file system module configuration file R0.11 (C)ChaN, 2015
|
/ FatFs - FAT file system module configuration file R0.12 (C)ChaN, 2016
|
||||||
/---------------------------------------------------------------------------*/
|
/---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#define _FFCONF 32020 /* Revision ID */
|
#define _FFCONF 88100 /* Revision ID */
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------/
|
/*---------------------------------------------------------------------------/
|
||||||
/ Functions and Buffer Configurations
|
/ Function Configurations
|
||||||
/---------------------------------------------------------------------------*/
|
/---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#define _FS_TINY 0
|
#define _FS_READONLY 0
|
||||||
/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
|
/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
|
||||||
/ At the tiny configuration, size of the file object (FIL) is reduced _MAX_SS
|
/ Read-only configuration removes writing API functions, f_write(), f_sync(),
|
||||||
/ bytes. Instead of private sector buffer eliminated from the file object,
|
/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
|
||||||
/ common sector buffer in the file system object (FATFS) is used for the file
|
/ and optional writing functions as well. */
|
||||||
/ data transfer. */
|
|
||||||
|
|
||||||
|
#define _FS_MINIMIZE 1
|
||||||
#define _FS_READONLY 1
|
/* This option defines minimization level to remove some basic API functions.
|
||||||
/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
|
/
|
||||||
/ Read-only configuration removes writing API functions, f_write(), f_sync(),
|
/ 0: All basic functions are enabled.
|
||||||
/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
|
/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename()
|
||||||
/ and optional writing functions as well. */
|
/ are removed.
|
||||||
|
/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
|
||||||
|
/ 3: f_lseek() function is removed in addition to 2. */
|
||||||
#define _FS_MINIMIZE 3
|
|
||||||
/* This option defines minimization level to remove some basic API functions.
|
|
||||||
/
|
#define _USE_STRFUNC 0
|
||||||
/ 0: All basic functions are enabled.
|
/* This option switches string functions, f_gets(), f_putc(), f_puts() and
|
||||||
/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_chmod(), f_utime(),
|
/ f_printf().
|
||||||
/ f_truncate() and f_rename() function are removed.
|
/
|
||||||
/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
|
/ 0: Disable string functions.
|
||||||
/ 3: f_lseek() function is removed in addition to 2. */
|
/ 1: Enable without LF-CRLF conversion.
|
||||||
|
/ 2: Enable with LF-CRLF conversion. */
|
||||||
|
|
||||||
#define _USE_STRFUNC 0
|
|
||||||
/* This option switches string functions, f_gets(), f_putc(), f_puts() and
|
#define _USE_FIND 0
|
||||||
/ f_printf().
|
/* This option switches filtered directory read functions, f_findfirst() and
|
||||||
/
|
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
|
||||||
/ 0: Disable string functions.
|
|
||||||
/ 1: Enable without LF-CRLF conversion.
|
|
||||||
/ 2: Enable with LF-CRLF conversion. */
|
#define _USE_MKFS 0
|
||||||
|
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
|
||||||
|
|
||||||
#define _USE_FIND 0
|
|
||||||
/* This option switches filtered directory read feature and related functions,
|
#define _USE_FASTSEEK 0
|
||||||
/ f_findfirst() and f_findnext(). (0:Disable or 1:Enable) */
|
/* This option switches fast seek function. (0:Disable or 1:Enable) */
|
||||||
|
|
||||||
|
|
||||||
#define _USE_MKFS 0
|
#define _USE_EXPAND 0
|
||||||
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
|
/* This option switches f_expand function. (0:Disable or 1:Enable) */
|
||||||
|
|
||||||
|
|
||||||
#define _USE_FASTSEEK 0
|
#define _USE_CHMOD 0
|
||||||
/* This option switches fast seek feature. (0:Disable or 1:Enable) */
|
/* This option switches attribute manipulation functions, f_chmod() and f_utime().
|
||||||
|
/ (0:Disable or 1:Enable) Also _FS_READONLY needs to be 0 to enable this option. */
|
||||||
|
|
||||||
#define _USE_LABEL 0
|
|
||||||
/* This option switches volume label functions, f_getlabel() and f_setlabel().
|
#define _USE_LABEL 0
|
||||||
/ (0:Disable or 1:Enable) */
|
/* This option switches volume label functions, f_getlabel() and f_setlabel().
|
||||||
|
/ (0:Disable or 1:Enable) */
|
||||||
|
|
||||||
#define _USE_FORWARD 0
|
|
||||||
/* This option switches f_forward() function. (0:Disable or 1:Enable)
|
#define _USE_FORWARD 0
|
||||||
/ To enable it, also _FS_TINY need to be set to 1. */
|
/* This option switches f_forward() function. (0:Disable or 1:Enable)
|
||||||
|
/ To enable it, also _FS_TINY need to be 1. */
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------/
|
|
||||||
/ Locale and Namespace Configurations
|
/*---------------------------------------------------------------------------/
|
||||||
/---------------------------------------------------------------------------*/
|
/ Locale and Namespace Configurations
|
||||||
|
/---------------------------------------------------------------------------*/
|
||||||
#define _CODE_PAGE 437
|
|
||||||
/* This option specifies the OEM code page to be used on the target system.
|
#define _CODE_PAGE 437
|
||||||
/ Incorrect setting of the code page can cause a file open failure.
|
/* This option specifies the OEM code page to be used on the target system.
|
||||||
/
|
/ Incorrect setting of the code page can cause a file open failure.
|
||||||
/ 1 - ASCII (No extended character. Non-LFN cfg. only)
|
/
|
||||||
/ 437 - U.S.
|
/ 1 - ASCII (No extended character. Non-LFN cfg. only)
|
||||||
/ 720 - Arabic
|
/ 437 - U.S.
|
||||||
/ 737 - Greek
|
/ 720 - Arabic
|
||||||
/ 775 - Baltic
|
/ 737 - Greek
|
||||||
/ 850 - Multilingual Latin 1
|
/ 771 - KBL
|
||||||
/ 852 - Latin 2
|
/ 775 - Baltic
|
||||||
/ 855 - Cyrillic
|
/ 850 - Latin 1
|
||||||
/ 857 - Turkish
|
/ 852 - Latin 2
|
||||||
/ 858 - Multilingual Latin 1 + Euro
|
/ 855 - Cyrillic
|
||||||
/ 862 - Hebrew
|
/ 857 - Turkish
|
||||||
/ 866 - Russian
|
/ 860 - Portuguese
|
||||||
/ 874 - Thai
|
/ 861 - Icelandic
|
||||||
/ 932 - Japanese Shift_JIS (DBCS)
|
/ 862 - Hebrew
|
||||||
/ 936 - Simplified Chinese GBK (DBCS)
|
/ 863 - Canadian French
|
||||||
/ 949 - Korean (DBCS)
|
/ 864 - Arabic
|
||||||
/ 950 - Traditional Chinese Big5 (DBCS)
|
/ 865 - Nordic
|
||||||
*/
|
/ 866 - Russian
|
||||||
|
/ 869 - Greek 2
|
||||||
|
/ 932 - Japanese (DBCS)
|
||||||
#define _USE_LFN 2
|
/ 936 - Simplified Chinese (DBCS)
|
||||||
#define _MAX_LFN 255
|
/ 949 - Korean (DBCS)
|
||||||
/* The _USE_LFN option switches the LFN feature.
|
/ 950 - Traditional Chinese (DBCS)
|
||||||
/
|
*/
|
||||||
/ 0: Disable LFN feature. _MAX_LFN has no effect.
|
|
||||||
/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
|
|
||||||
/ 2: Enable LFN with dynamic working buffer on the STACK.
|
#define _USE_LFN 2
|
||||||
/ 3: Enable LFN with dynamic working buffer on the HEAP.
|
#define _MAX_LFN 255
|
||||||
/
|
/* The _USE_LFN switches the support of long file name (LFN).
|
||||||
/ When enable the LFN feature, Unicode handling functions (option/unicode.c) must
|
/
|
||||||
/ be added to the project. The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes.
|
/ 0: Disable support of LFN. _MAX_LFN has no effect.
|
||||||
/ When use stack for the working buffer, take care on stack overflow. When use heap
|
/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
|
||||||
/ memory for the working buffer, memory management functions, ff_memalloc() and
|
/ 2: Enable LFN with dynamic working buffer on the STACK.
|
||||||
/ ff_memfree(), must be added to the project. */
|
/ 3: Enable LFN with dynamic working buffer on the HEAP.
|
||||||
|
/
|
||||||
|
/ To enable the LFN, Unicode handling functions (option/unicode.c) must be added
|
||||||
#define _LFN_UNICODE 0
|
/ to the project. The working buffer occupies (_MAX_LFN + 1) * 2 bytes and
|
||||||
/* This option switches character encoding on the API. (0:ANSI/OEM or 1:Unicode)
|
/ additional 608 bytes at exFAT enabled. _MAX_LFN can be in range from 12 to 255.
|
||||||
/ To use Unicode string for the path name, enable LFN feature and set _LFN_UNICODE
|
/ It should be set 255 to support full featured LFN operations.
|
||||||
/ to 1. This option also affects behavior of string I/O functions. */
|
/ When use stack for the working buffer, take care on stack overflow. When use heap
|
||||||
|
/ memory for the working buffer, memory management functions, ff_memalloc() and
|
||||||
|
/ ff_memfree(), must be added to the project. */
|
||||||
#define _STRF_ENCODE 0
|
|
||||||
/* When _LFN_UNICODE is 1, this option selects the character encoding on the file to
|
|
||||||
/ be read/written via string I/O functions, f_gets(), f_putc(), f_puts and f_printf().
|
#define _LFN_UNICODE 0
|
||||||
/
|
/* This option switches character encoding on the API. (0:ANSI/OEM or 1:Unicode)
|
||||||
/ 0: ANSI/OEM
|
/ To use Unicode string for the path name, enable LFN and set _LFN_UNICODE = 1.
|
||||||
/ 1: UTF-16LE
|
/ This option also affects behavior of string I/O functions. */
|
||||||
/ 2: UTF-16BE
|
|
||||||
/ 3: UTF-8
|
|
||||||
/
|
#define _STRF_ENCODE 3
|
||||||
/ When _LFN_UNICODE is 0, this option has no effect. */
|
/* When _LFN_UNICODE == 1, this option selects the character encoding on the file to
|
||||||
|
/ be read/written via string I/O functions, f_gets(), f_putc(), f_puts and f_printf().
|
||||||
|
/
|
||||||
#define _FS_RPATH 0
|
/ 0: ANSI/OEM
|
||||||
/* This option configures relative path feature.
|
/ 1: UTF-16LE
|
||||||
/
|
/ 2: UTF-16BE
|
||||||
/ 0: Disable relative path feature and remove related functions.
|
/ 3: UTF-8
|
||||||
/ 1: Enable relative path feature. f_chdir() and f_chdrive() are available.
|
/
|
||||||
/ 2: f_getcwd() function is available in addition to 1.
|
/ This option has no effect when _LFN_UNICODE == 0. */
|
||||||
/
|
|
||||||
/ Note that directory items read via f_readdir() are affected by this option. */
|
|
||||||
|
#define _FS_RPATH 0
|
||||||
|
/* This option configures support of relative path.
|
||||||
/*---------------------------------------------------------------------------/
|
/
|
||||||
/ Drive/Volume Configurations
|
/ 0: Disable relative path and remove related functions.
|
||||||
/---------------------------------------------------------------------------*/
|
/ 1: Enable relative path. f_chdir() and f_chdrive() are available.
|
||||||
|
/ 2: f_getcwd() function is available in addition to 1.
|
||||||
#define _VOLUMES 1
|
*/
|
||||||
/* Number of volumes (logical drives) to be used. */
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------/
|
||||||
#define _STR_VOLUME_ID 0
|
/ Drive/Volume Configurations
|
||||||
#define _VOLUME_STRS "RAM","NAND","CF","SD1","SD2","USB1","USB2","USB3"
|
/---------------------------------------------------------------------------*/
|
||||||
/* _STR_VOLUME_ID option switches string volume ID feature.
|
|
||||||
/ When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
|
#define _VOLUMES 2
|
||||||
/ number in the path name. _VOLUME_STRS defines the drive ID strings for each
|
/* Number of volumes (logical drives) to be used. */
|
||||||
/ logical drives. Number of items must be equal to _VOLUMES. Valid characters for
|
|
||||||
/ the drive ID strings are: A-Z and 0-9. */
|
|
||||||
|
#define _STR_VOLUME_ID 0
|
||||||
|
#define _VOLUME_STRS "RAM","NAND","CF","SD1","SD2","USB1","USB2","USB3"
|
||||||
#define _MULTI_PARTITION 0
|
/* _STR_VOLUME_ID switches string support of volume ID.
|
||||||
/* This option switches multi-partition feature. By default (0), each logical drive
|
/ When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
|
||||||
/ number is bound to the same physical drive number and only an FAT volume found on
|
/ number in the path name. _VOLUME_STRS defines the drive ID strings for each
|
||||||
/ the physical drive will be mounted. When multi-partition feature is enabled (1),
|
/ logical drives. Number of items must be equal to _VOLUMES. Valid characters for
|
||||||
/ each logical drive number is bound to arbitrary physical drive and partition
|
/ the drive ID strings are: A-Z and 0-9. */
|
||||||
/ listed in the VolToPart[]. Also f_fdisk() funciton will be available. */
|
|
||||||
|
|
||||||
|
#define _MULTI_PARTITION 0
|
||||||
#define _MIN_SS 512
|
/* This option switches support of multi-partition on a physical drive.
|
||||||
#define _MAX_SS 512
|
/ By default (0), each logical drive number is bound to the same physical drive
|
||||||
/* These options configure the range of sector size to be supported. (512, 1024,
|
/ number and only an FAT volume found on the physical drive will be mounted.
|
||||||
/ 2048 or 4096) Always set both 512 for most systems, all type of memory cards and
|
/ When multi-partition is enabled (1), each logical drive number can be bound to
|
||||||
/ harddisk. But a larger value may be required for on-board flash memory and some
|
/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
|
||||||
/ type of optical media. When _MAX_SS is larger than _MIN_SS, FatFs is configured
|
/ funciton will be available. */
|
||||||
/ to variable sector size and GET_SECTOR_SIZE command must be implemented to the
|
|
||||||
/ disk_ioctl() function. */
|
|
||||||
|
#define _MIN_SS 512
|
||||||
|
#define _MAX_SS 512
|
||||||
#define _USE_TRIM 0
|
/* These options configure the range of sector size to be supported. (512, 1024,
|
||||||
/* This option switches ATA-TRIM feature. (0:Disable or 1:Enable)
|
/ 2048 or 4096) Always set both 512 for most systems, all type of memory cards and
|
||||||
/ To enable Trim feature, also CTRL_TRIM command should be implemented to the
|
/ harddisk. But a larger value may be required for on-board flash memory and some
|
||||||
/ disk_ioctl() function. */
|
/ type of optical media. When _MAX_SS is larger than _MIN_SS, FatFs is configured
|
||||||
|
/ to variable sector size and GET_SECTOR_SIZE command must be implemented to the
|
||||||
|
/ disk_ioctl() function. */
|
||||||
#define _FS_NOFSINFO 0
|
|
||||||
/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
|
|
||||||
/ option, and f_getfree() function at first time after volume mount will force
|
#define _USE_TRIM 0
|
||||||
/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
|
/* This option switches support of ATA-TRIM. (0:Disable or 1:Enable)
|
||||||
/
|
/ To enable Trim function, also CTRL_TRIM command should be implemented to the
|
||||||
/ bit0=0: Use free cluster count in the FSINFO if available.
|
/ disk_ioctl() function. */
|
||||||
/ bit0=1: Do not trust free cluster count in the FSINFO.
|
|
||||||
/ bit1=0: Use last allocated cluster number in the FSINFO if available.
|
|
||||||
/ bit1=1: Do not trust last allocated cluster number in the FSINFO.
|
#define _FS_NOFSINFO 0
|
||||||
*/
|
/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
|
||||||
|
/ option, and f_getfree() function at first time after volume mount will force
|
||||||
|
/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
|
||||||
|
/
|
||||||
/*---------------------------------------------------------------------------/
|
/ bit0=0: Use free cluster count in the FSINFO if available.
|
||||||
/ System Configurations
|
/ bit0=1: Do not trust free cluster count in the FSINFO.
|
||||||
/---------------------------------------------------------------------------*/
|
/ bit1=0: Use last allocated cluster number in the FSINFO if available.
|
||||||
|
/ bit1=1: Do not trust last allocated cluster number in the FSINFO.
|
||||||
#define _FS_NORTC 1
|
*/
|
||||||
#define _NORTC_MON 2
|
|
||||||
#define _NORTC_MDAY 1
|
|
||||||
#define _NORTC_YEAR 2015
|
|
||||||
/* The _FS_NORTC option switches timestamp feature. If the system does not have
|
/*---------------------------------------------------------------------------/
|
||||||
/ an RTC function or valid timestamp is not needed, set _FS_NORTC to 1 to disable
|
/ System Configurations
|
||||||
/ the timestamp feature. All objects modified by FatFs will have a fixed timestamp
|
/---------------------------------------------------------------------------*/
|
||||||
/ defined by _NORTC_MON, _NORTC_MDAY and _NORTC_YEAR.
|
|
||||||
/ When timestamp feature is enabled (_FS_NORTC == 0), get_fattime() function need
|
#define _FS_TINY 0
|
||||||
/ to be added to the project to read current time form RTC. _NORTC_MON,
|
/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
|
||||||
/ _NORTC_MDAY and _NORTC_YEAR have no effect.
|
/ At the tiny configuration, size of the file object (FIL) is reduced _MAX_SS bytes.
|
||||||
/ These options have no effect at read-only configuration (_FS_READONLY == 1). */
|
/ 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_LOCK 0
|
|
||||||
/* The _FS_LOCK option switches file lock feature to control duplicated file open
|
#define _FS_EXFAT 0
|
||||||
/ and illegal operation to open objects. This option must be 0 when _FS_READONLY
|
/* This option switches support of exFAT file system in addition to the traditional
|
||||||
/ is 1.
|
/ FAT file system. (0:Disable or 1:Enable) To enable exFAT, also LFN must be enabled.
|
||||||
/
|
/ Note that enabling exFAT discards C89 compatibility. */
|
||||||
/ 0: Disable file lock feature. To avoid volume corruption, application program
|
|
||||||
/ should avoid illegal open, remove and rename to the open objects.
|
|
||||||
/ >0: Enable file lock feature. The value defines how many files/sub-directories
|
#define _FS_NORTC 1
|
||||||
/ can be opened simultaneously under file lock control. Note that the file
|
#define _NORTC_MON 3
|
||||||
/ lock feature is independent of re-entrancy. */
|
#define _NORTC_MDAY 1
|
||||||
|
#define _NORTC_YEAR 2016
|
||||||
|
/* The option _FS_NORTC switches timestamp functiton. If the system does not have
|
||||||
#define _FS_REENTRANT 0
|
/ any RTC function or valid timestamp is not needed, set _FS_NORTC = 1 to disable
|
||||||
#define _FS_TIMEOUT 1000
|
/ the timestamp function. All objects modified by FatFs will have a fixed timestamp
|
||||||
#define _SYNC_t HANDLE
|
/ defined by _NORTC_MON, _NORTC_MDAY and _NORTC_YEAR in local time.
|
||||||
/* The _FS_REENTRANT option switches the re-entrancy (thread safe) of the FatFs
|
/ To enable timestamp function (_FS_NORTC = 0), get_fattime() function need to be
|
||||||
/ module itself. Note that regardless of this option, file access to different
|
/ added to the project to get current time form real-time clock. _NORTC_MON,
|
||||||
/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
|
/ _NORTC_MDAY and _NORTC_YEAR have no effect.
|
||||||
/ and f_fdisk() function, are always not re-entrant. Only file/directory access
|
/ These options have no effect at read-only configuration (_FS_READONLY = 1). */
|
||||||
/ to the same volume is under control of this feature.
|
|
||||||
/
|
|
||||||
/ 0: Disable re-entrancy. _FS_TIMEOUT and _SYNC_t have no effect.
|
#define _FS_LOCK 0
|
||||||
/ 1: Enable re-entrancy. Also user provided synchronization handlers,
|
/* The option _FS_LOCK switches file lock function to control duplicated file open
|
||||||
/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj()
|
/ and illegal operation to open objects. This option must be 0 when _FS_READONLY
|
||||||
/ function, must be added to the project. Samples are available in
|
/ is 1.
|
||||||
/ option/syscall.c.
|
/
|
||||||
/
|
/ 0: Disable file lock function. To avoid volume corruption, application program
|
||||||
/ The _FS_TIMEOUT defines timeout period in unit of time tick.
|
/ should avoid illegal open, remove and rename to the open objects.
|
||||||
/ The _SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
|
/ >0: Enable file lock function. The value defines how many files/sub-directories
|
||||||
/ SemaphoreHandle_t and etc.. A header file for O/S definitions needs to be
|
/ can be opened simultaneously under file lock control. Note that the file
|
||||||
/ included somewhere in the scope of ff.c. */
|
/ lock control is independent of re-entrancy. */
|
||||||
|
|
||||||
|
|
||||||
#define _WORD_ACCESS 0
|
#define _FS_REENTRANT 0
|
||||||
/* The _WORD_ACCESS option is an only platform dependent option. It defines
|
#define _FS_TIMEOUT 1000
|
||||||
/ which access method is used to the word data on the FAT volume.
|
#define _SYNC_t HANDLE
|
||||||
/
|
/* The option _FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
|
||||||
/ 0: Byte-by-byte access. Always compatible with all platforms.
|
/ module itself. Note that regardless of this option, file access to different
|
||||||
/ 1: Word access. Do not choose this unless under both the following conditions.
|
/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
|
||||||
/
|
/ and f_fdisk() function, are always not re-entrant. Only file/directory access
|
||||||
/ * Address misaligned memory access is always allowed to ALL instructions.
|
/ to the same volume is under control of this function.
|
||||||
/ * Byte order on the memory is little-endian.
|
/
|
||||||
/
|
/ 0: Disable re-entrancy. _FS_TIMEOUT and _SYNC_t have no effect.
|
||||||
/ If it is the case, _WORD_ACCESS can also be set to 1 to reduce code size.
|
/ 1: Enable re-entrancy. Also user provided synchronization handlers,
|
||||||
/ Following table shows allowable settings of some processor types.
|
/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj()
|
||||||
/
|
/ function, must be added to the project. Samples are available in
|
||||||
/ ARM7TDMI 0 *2 ColdFire 0 *1 V850E 0 *2
|
/ option/syscall.c.
|
||||||
/ Cortex-M3 0 *3 Z80 0/1 V850ES 0/1
|
/
|
||||||
/ Cortex-M0 0 *2 x86 0/1 TLCS-870 0/1
|
/ The _FS_TIMEOUT defines timeout period in unit of time tick.
|
||||||
/ AVR 0/1 RX600(LE) 0/1 TLCS-900 0/1
|
/ The _SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
|
||||||
/ AVR32 0 *1 RL78 0 *2 R32C 0 *2
|
/ SemaphoreHandle_t and etc.. A header file for O/S definitions needs to be
|
||||||
/ PIC18 0/1 SH-2 0 *1 M16C 0/1
|
/ included somewhere in the scope of ff.c. */
|
||||||
/ PIC24 0 *2 H8S 0 *1 MSP430 0 *2
|
|
||||||
/ PIC32 0 *1 H8/300H 0 *1 8051 0/1
|
|
||||||
/
|
/*--- End of configuration options ---*/
|
||||||
/ *1:Big-endian.
|
|
||||||
/ *2:Unaligned memory access is not supported.
|
|
||||||
/ *3:Some compilers generate LDM/STM for mem_cpy function.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
@ -1,33 +1,38 @@
|
|||||||
/*-------------------------------------------*/
|
/*-------------------------------------------*/
|
||||||
/* Integer type definitions for FatFs module */
|
/* Integer type definitions for FatFs module */
|
||||||
/*-------------------------------------------*/
|
/*-------------------------------------------*/
|
||||||
|
|
||||||
#ifndef _FF_INTEGER
|
#ifndef _FF_INTEGER
|
||||||
#define _FF_INTEGER
|
#define _FF_INTEGER
|
||||||
|
|
||||||
#ifdef _WIN32 /* FatFs development platform */
|
#ifdef _WIN32 /* FatFs development platform */
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
|
typedef unsigned __int64 QWORD;
|
||||||
#else /* Embedded platform */
|
|
||||||
|
|
||||||
/* This type MUST be 8 bit */
|
#else /* Embedded platform */
|
||||||
typedef unsigned char BYTE;
|
|
||||||
|
/* These types MUST be 16-bit or 32-bit */
|
||||||
/* These types MUST be 16 bit */
|
typedef int INT;
|
||||||
typedef short SHORT;
|
typedef unsigned int UINT;
|
||||||
typedef unsigned short WORD;
|
|
||||||
typedef unsigned short WCHAR;
|
/* This type MUST be 8-bit */
|
||||||
|
typedef unsigned char BYTE;
|
||||||
/* These types MUST be 16 bit or 32 bit */
|
|
||||||
typedef int INT;
|
/* These types MUST be 16-bit */
|
||||||
typedef unsigned int UINT;
|
typedef short SHORT;
|
||||||
|
typedef unsigned short WORD;
|
||||||
/* These types MUST be 32 bit */
|
typedef unsigned short WCHAR;
|
||||||
typedef long LONG;
|
|
||||||
typedef unsigned long DWORD;
|
/* These types MUST be 32-bit */
|
||||||
|
typedef long LONG;
|
||||||
#endif
|
typedef unsigned long DWORD;
|
||||||
|
|
||||||
#endif
|
/* This type MUST be 64-bit (Remove this for C89 compatibility) */
|
||||||
|
typedef unsigned long long QWORD;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
388
source/fatfs/option/ccsbcs.c
Normal file
388
source/fatfs/option/ccsbcs.c
Normal file
@ -0,0 +1,388 @@
|
|||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* 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 (BMP only) */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
/* Compressed upper conversion table */
|
||||||
|
static const WCHAR cvt1[] = { /* U+0000 - U+0FFF */
|
||||||
|
/* Basic Latin */
|
||||||
|
0x0061,0x031A,
|
||||||
|
/* Latin-1 Supplement */
|
||||||
|
0x00E0,0x0317, 0x00F8,0x0307, 0x00FF,0x0001,0x0178,
|
||||||
|
/* Latin Extended-A */
|
||||||
|
0x0100,0x0130, 0x0132,0x0106, 0x0139,0x0110, 0x014A,0x012E, 0x0179,0x0106,
|
||||||
|
/* Latin Extended-B */
|
||||||
|
0x0180,0x004D,0x0243,0x0181,0x0182,0x0182,0x0184,0x0184,0x0186,0x0187,0x0187,0x0189,0x018A,0x018B,0x018B,0x018D,0x018E,0x018F,0x0190,0x0191,0x0191,0x0193,0x0194,0x01F6,0x0196,0x0197,0x0198,0x0198,0x023D,0x019B,0x019C,0x019D,0x0220,0x019F,0x01A0,0x01A0,0x01A2,0x01A2,0x01A4,0x01A4,0x01A6,0x01A7,0x01A7,0x01A9,0x01AA,0x01AB,0x01AC,0x01AC,0x01AE,0x01AF,0x01AF,0x01B1,0x01B2,0x01B3,0x01B3,0x01B5,0x01B5,0x01B7,0x01B8,0x01B8,0x01BA,0x01BB,0x01BC,0x01BC,0x01BE,0x01F7,0x01C0,0x01C1,0x01C2,0x01C3,0x01C4,0x01C5,0x01C4,0x01C7,0x01C8,0x01C7,0x01CA,0x01CB,0x01CA,
|
||||||
|
0x01CD,0x0110, 0x01DD,0x0001,0x018E, 0x01DE,0x0112, 0x01F3,0x0003,0x01F1,0x01F4,0x01F4, 0x01F8,0x0128,
|
||||||
|
0x0222,0x0112, 0x023A,0x0009,0x2C65,0x023B,0x023B,0x023D,0x2C66,0x023F,0x0240,0x0241,0x0241, 0x0246,0x010A,
|
||||||
|
/* IPA Extensions */
|
||||||
|
0x0253,0x0040,0x0181,0x0186,0x0255,0x0189,0x018A,0x0258,0x018F,0x025A,0x0190,0x025C,0x025D,0x025E,0x025F,0x0193,0x0261,0x0262,0x0194,0x0264,0x0265,0x0266,0x0267,0x0197,0x0196,0x026A,0x2C62,0x026C,0x026D,0x026E,0x019C,0x0270,0x0271,0x019D,0x0273,0x0274,0x019F,0x0276,0x0277,0x0278,0x0279,0x027A,0x027B,0x027C,0x2C64,0x027E,0x027F,0x01A6,0x0281,0x0282,0x01A9,0x0284,0x0285,0x0286,0x0287,0x01AE,0x0244,0x01B1,0x01B2,0x0245,0x028D,0x028E,0x028F,0x0290,0x0291,0x01B7,
|
||||||
|
/* Greek, Coptic */
|
||||||
|
0x037B,0x0003,0x03FD,0x03FE,0x03FF, 0x03AC,0x0004,0x0386,0x0388,0x0389,0x038A, 0x03B1,0x0311,
|
||||||
|
0x03C2,0x0002,0x03A3,0x03A3, 0x03C4,0x0308, 0x03CC,0x0003,0x038C,0x038E,0x038F, 0x03D8,0x0118,
|
||||||
|
0x03F2,0x000A,0x03F9,0x03F3,0x03F4,0x03F5,0x03F6,0x03F7,0x03F7,0x03F9,0x03FA,0x03FA,
|
||||||
|
/* Cyrillic */
|
||||||
|
0x0430,0x0320, 0x0450,0x0710, 0x0460,0x0122, 0x048A,0x0136, 0x04C1,0x010E, 0x04CF,0x0001,0x04C0, 0x04D0,0x0144,
|
||||||
|
/* Armenian */
|
||||||
|
0x0561,0x0426,
|
||||||
|
|
||||||
|
0x0000
|
||||||
|
};
|
||||||
|
static const WCHAR cvt2[] = { /* U+1000 - U+FFFF */
|
||||||
|
/* Phonetic Extensions */
|
||||||
|
0x1D7D,0x0001,0x2C63,
|
||||||
|
/* Latin Extended Additional */
|
||||||
|
0x1E00,0x0196, 0x1EA0,0x015A,
|
||||||
|
/* Greek Extended */
|
||||||
|
0x1F00,0x0608, 0x1F10,0x0606, 0x1F20,0x0608, 0x1F30,0x0608, 0x1F40,0x0606,
|
||||||
|
0x1F51,0x0007,0x1F59,0x1F52,0x1F5B,0x1F54,0x1F5D,0x1F56,0x1F5F, 0x1F60,0x0608,
|
||||||
|
0x1F70,0x000E,0x1FBA,0x1FBB,0x1FC8,0x1FC9,0x1FCA,0x1FCB,0x1FDA,0x1FDB,0x1FF8,0x1FF9,0x1FEA,0x1FEB,0x1FFA,0x1FFB,
|
||||||
|
0x1F80,0x0608, 0x1F90,0x0608, 0x1FA0,0x0608, 0x1FB0,0x0004,0x1FB8,0x1FB9,0x1FB2,0x1FBC,
|
||||||
|
0x1FCC,0x0001,0x1FC3, 0x1FD0,0x0602, 0x1FE0,0x0602, 0x1FE5,0x0001,0x1FEC, 0x1FF2,0x0001,0x1FFC,
|
||||||
|
/* Letterlike Symbols */
|
||||||
|
0x214E,0x0001,0x2132,
|
||||||
|
/* Number forms */
|
||||||
|
0x2170,0x0210, 0x2184,0x0001,0x2183,
|
||||||
|
/* Enclosed Alphanumerics */
|
||||||
|
0x24D0,0x051A, 0x2C30,0x042F,
|
||||||
|
/* Latin Extended-C */
|
||||||
|
0x2C60,0x0102, 0x2C67,0x0106, 0x2C75,0x0102,
|
||||||
|
/* Coptic */
|
||||||
|
0x2C80,0x0164,
|
||||||
|
/* Georgian Supplement */
|
||||||
|
0x2D00,0x0826,
|
||||||
|
/* Full-width */
|
||||||
|
0xFF41,0x031A,
|
||||||
|
|
||||||
|
0x0000
|
||||||
|
};
|
||||||
|
const WCHAR *p;
|
||||||
|
WCHAR bc, nc, cmd;
|
||||||
|
|
||||||
|
|
||||||
|
p = chr < 0x1000 ? cvt1 : cvt2;
|
||||||
|
for (;;) {
|
||||||
|
bc = *p++; /* Get block base */
|
||||||
|
if (!bc || chr < bc) break;
|
||||||
|
nc = *p++; cmd = nc >> 8; nc &= 0xFF; /* Get processing command and block size */
|
||||||
|
if (chr < bc + nc) { /* In the block? */
|
||||||
|
switch (cmd) {
|
||||||
|
case 0: chr = p[chr - bc]; break; /* Table conversion */
|
||||||
|
case 1: chr -= (chr - bc) & 1; break; /* Case pairs */
|
||||||
|
case 2: chr -= 16; break; /* Shift -16 */
|
||||||
|
case 3: chr -= 32; break; /* Shift -32 */
|
||||||
|
case 4: chr -= 48; break; /* Shift -48 */
|
||||||
|
case 5: chr -= 26; break; /* Shift -26 */
|
||||||
|
case 6: chr += 8; break; /* Shift +8 */
|
||||||
|
case 7: chr -= 80; break; /* Shift -80 */
|
||||||
|
case 8: chr -= 0x1C60; break; /* Shift -0x1C60 */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!cmd) p += nc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return chr;
|
||||||
|
}
|
||||||
|
|
108
source/fs.c
108
source/fs.c
@ -3,37 +3,105 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
|
#include "memory.h"
|
||||||
#include "fatfs/ff.h"
|
#include "fatfs/ff.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
static FATFS fs;
|
static FATFS fs;
|
||||||
|
|
||||||
u32 mountSD(void){
|
u32 mountSD(void)
|
||||||
|
{
|
||||||
if(f_mount(&fs, "0:", 1) != FR_OK) return 0;
|
if(f_mount(&fs, "0:", 1) != FR_OK) return 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 fileRead(void *dest, const char *path, u32 size){
|
u32 mountCTRNAND(void)
|
||||||
FRESULT fr;
|
{
|
||||||
FIL fp;
|
if(f_mount(&fs, "1:", 1) != FR_OK) return 0;
|
||||||
unsigned int br = 0;
|
return 1;
|
||||||
|
|
||||||
fr = f_open(&fp, path, FA_READ);
|
|
||||||
if(fr == FR_OK){
|
|
||||||
if(!size) size = f_size(&fp);
|
|
||||||
fr = f_read(&fp, dest, size, &br);
|
|
||||||
}
|
|
||||||
|
|
||||||
f_close(&fp);
|
|
||||||
return fr ? 0 : 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 fileSize(const char *path){
|
u32 fileRead(void *dest, const char *path)
|
||||||
FIL fp;
|
{
|
||||||
u32 size = 0;
|
FIL file;
|
||||||
|
u32 size;
|
||||||
|
|
||||||
if(f_open(&fp, path, FA_READ) == FR_OK)
|
if(f_open(&file, path, FA_READ) == FR_OK)
|
||||||
size = f_size(&fp);
|
{
|
||||||
|
unsigned int read;
|
||||||
|
size = f_size(&file);
|
||||||
|
f_read(&file, dest, size, &read);
|
||||||
|
f_close(&file);
|
||||||
|
}
|
||||||
|
else size = 0;
|
||||||
|
|
||||||
f_close(&fp);
|
|
||||||
return size;
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fileWrite(const void *buffer, const char *path, u32 size)
|
||||||
|
{
|
||||||
|
FIL file;
|
||||||
|
|
||||||
|
if(f_open(&file, path, FA_WRITE | FA_OPEN_ALWAYS) == FR_OK)
|
||||||
|
{
|
||||||
|
unsigned int written;
|
||||||
|
f_write(&file, buffer, size, &written);
|
||||||
|
f_close(&file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 firmRead(void *dest)
|
||||||
|
{
|
||||||
|
const char *firmFolders[] = { "00000002", "20000002" };
|
||||||
|
char path[48] = "1:/title/00040138/00000000/content";
|
||||||
|
memcpy(&path[18], firmFolders[console], 8);
|
||||||
|
|
||||||
|
DIR dir;
|
||||||
|
FILINFO info;
|
||||||
|
|
||||||
|
f_opendir(&dir, path);
|
||||||
|
|
||||||
|
u32 id = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
//Parse the target directory
|
||||||
|
while(f_readdir(&dir, &info) == FR_OK && info.fname[0])
|
||||||
|
{
|
||||||
|
//Not a cxi
|
||||||
|
if(info.altname[9] != 'A') continue;
|
||||||
|
|
||||||
|
if(id != 0xFFFFFFFF) return 1;
|
||||||
|
|
||||||
|
//Convert the .app name to an integer
|
||||||
|
u32 tempId = 0;
|
||||||
|
for(char *tmp = info.altname; *tmp != '.'; tmp++)
|
||||||
|
{
|
||||||
|
tempId <<= 4;
|
||||||
|
tempId += *tmp > '9' ? *tmp - 'A' + 10 : *tmp - '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if((console && tempId >= 0x21) || (!console && tempId >= 0x52)) return 2;
|
||||||
|
|
||||||
|
//Found an older 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)
|
||||||
|
{
|
||||||
|
static const char hexDigits[] = "0123456789ABCDEF";
|
||||||
|
path[i--] = hexDigits[id & 0xF];
|
||||||
|
id >>= 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
fileRead(dest, path);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
@ -6,6 +6,10 @@
|
|||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
|
extern u32 console;
|
||||||
|
|
||||||
u32 mountSD(void);
|
u32 mountSD(void);
|
||||||
u32 fileRead(void *dest, const char *path, u32 size);
|
u32 mountCTRNAND(void);
|
||||||
u32 fileSize(const char *path);
|
u32 fileRead(void *dest, const char *path);
|
||||||
|
void fileWrite(const void *buffer, const char *path, u32 size);
|
||||||
|
u32 firmRead(void *dest);
|
@ -1,7 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* installer.c
|
||||||
|
*/
|
||||||
|
|
||||||
#include "installer.h"
|
#include "installer.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
|
#include "screeninit.h"
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "fatfs/sdmmc/sdmmc.h"
|
#include "fatfs/sdmmc/sdmmc.h"
|
||||||
@ -11,19 +16,14 @@ static const u8 sectorHash[0x20] = {
|
|||||||
0xBA, 0xB2, 0x4B, 0x4E, 0x5F, 0x65, 0xC9, 0x81, 0xCD, 0x7B, 0xE6, 0xF4, 0x38, 0xE6, 0xD9, 0xD3
|
0xBA, 0xB2, 0x4B, 0x4E, 0x5F, 0x65, 0xC9, 0x81, 0xCD, 0x7B, 0xE6, 0xF4, 0x38, 0xE6, 0xD9, 0xD3
|
||||||
};
|
};
|
||||||
|
|
||||||
static const u8 sectorA9lhHash[0x20] = {
|
|
||||||
0x89, 0x72, 0xAD, 0x96, 0x42, 0x6F, 0x8A, 0x9B, 0x3E, 0xEB, 0x4C, 0xC9, 0xCC, 0xEF, 0x0E, 0xF4,
|
|
||||||
0x5B, 0x91, 0x91, 0xFB, 0xEE, 0xFC, 0x7E, 0x30, 0xB4, 0x8E, 0xE3, 0x1A, 0x3E, 0xD0, 0x42, 0x3A
|
|
||||||
};
|
|
||||||
|
|
||||||
static const u8 firm0Hash[0x20] = {
|
static const u8 firm0Hash[0x20] = {
|
||||||
0xD7, 0xBE, 0x76, 0xE1, 0x81, 0x3F, 0x39, 0x8D, 0xCE, 0xA8, 0x55, 0x72, 0xD0, 0xC0, 0x58, 0xF7,
|
0x6E, 0x4D, 0x14, 0xAD, 0x51, 0x50, 0xA5, 0x9A, 0x87, 0x59, 0x62, 0xB7, 0x09, 0x0A, 0x3C, 0x74,
|
||||||
0x95, 0x47, 0x61, 0xA1, 0xD5, 0xEA, 0x03, 0xB5, 0xEB, 0x50, 0x47, 0xAC, 0x63, 0xAC, 0x5D, 0x6B
|
0x4F, 0x72, 0x4B, 0xBD, 0x97, 0x39, 0x33, 0xF2, 0x11, 0xC9, 0x35, 0x22, 0xC8, 0xBB, 0x1C, 0x7D
|
||||||
};
|
};
|
||||||
|
|
||||||
static const u8 firm0A9lhHash[0x20] = {
|
static const u8 firm0A9lhHash[0x20] = {
|
||||||
0xFC, 0x7C, 0xC7, 0x2D, 0xA3, 0x0A, 0xDE, 0x3A, 0xE2, 0xFE, 0x7D, 0x79, 0xA3, 0xC2, 0x6C, 0x82,
|
0x6A, 0x5A, 0x74, 0x5F, 0x3B, 0x83, 0x8C, 0xDA, 0x25, 0x1C, 0xA9, 0xDC, 0x59, 0x4E, 0x1B, 0x01,
|
||||||
0xB8, 0xA3, 0xDB, 0xC4, 0x46, 0x22, 0xB4, 0x61, 0x8D, 0xDC, 0x73, 0x90, 0x50, 0x5D, 0x40, 0x11
|
0x00, 0x93, 0x27, 0x81, 0x59, 0xAF, 0x2D, 0x3B, 0x76, 0x98, 0xB1, 0xAB, 0xB2, 0x5F, 0x2E, 0x3E
|
||||||
};
|
};
|
||||||
|
|
||||||
static const u8 firm1Hash[0x20] = {
|
static const u8 firm1Hash[0x20] = {
|
||||||
@ -33,28 +33,50 @@ static const u8 firm1Hash[0x20] = {
|
|||||||
|
|
||||||
int pos_y;
|
int pos_y;
|
||||||
|
|
||||||
void installer(void){
|
u32 console;
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
initScreens();
|
||||||
|
|
||||||
//Determine if booting with A9LH
|
//Determine if booting with A9LH
|
||||||
u32 a9lhBoot = (PDN_SPI_CNT == 0x0) ? 1 : 0;
|
u32 a9lhBoot = !PDN_SPI_CNT,
|
||||||
//Detect the console being used
|
//Detect the console being used
|
||||||
u32 console = (PDN_MPCORE_CFG == 1) ? 0 : 1;
|
console = PDN_MPCORE_CFG == 7;
|
||||||
|
|
||||||
drawString(TITLE, 10, 10, COLOR_TITLE);
|
drawString(TITLE, 10, 10, COLOR_TITLE);
|
||||||
pos_y = drawString("Thanks to delebile, #cakey and StandardBus", 10, 40, COLOR_WHITE);
|
pos_y = drawString("Thanks to delebile, #cakey and StandardBus", 10, 40, COLOR_WHITE);
|
||||||
pos_y = drawString(a9lhBoot ? "Press SELECT to update A9LH" : "Press SELECT for a full install", 10, pos_y + SPACING_VERT, COLOR_WHITE);
|
pos_y = drawString(a9lhBoot ? "Press SELECT to update A9LH, START to uninstall" : "Press SELECT for a full install", 10, pos_y + SPACING_Y, COLOR_WHITE);
|
||||||
pos_y = drawString("Press any other button to shutdown", 10, pos_y, COLOR_WHITE);
|
pos_y = drawString("Press any other button to shutdown", 10, pos_y, COLOR_WHITE);
|
||||||
|
|
||||||
if(waitInput() != BUTTON_SELECT) shutdown(0, NULL);
|
u32 pressed = waitInput();
|
||||||
|
if(pressed == BUTTON_SELECT) installer(a9lhBoot);
|
||||||
|
if(pressed == BUTTON_START && a9lhBoot) uninstaller();
|
||||||
|
|
||||||
|
shutdown(0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void installer(u32 a9lhBoot)
|
||||||
|
{
|
||||||
|
mountSD();
|
||||||
|
|
||||||
const char *path;
|
const char *path;
|
||||||
|
u32 updatea9lh = 0;
|
||||||
|
|
||||||
//If making a first install, we need the OTP
|
//If making a first install, we need the OTP
|
||||||
if(!a9lhBoot){
|
if(!a9lhBoot)
|
||||||
|
{
|
||||||
//Read OTP
|
//Read OTP
|
||||||
path = "a9lh/otp.bin";
|
path = "a9lh/otp.bin";
|
||||||
if(fileSize(path) != 256)
|
if(fileRead((void *)OTP_OFFSET, path) != 256)
|
||||||
shutdown(1, "Error: otp.bin doesn't exist or has a wrong size");
|
{
|
||||||
fileRead((void *)OTP_OFFSET, path, 256);
|
u8 zeroes[256] = {0};
|
||||||
|
if(memcmp((void *)OTP_FROM_MEM, zeroes, 256) == 0)
|
||||||
|
shutdown(1, "Error: otp.bin doesn't exist and can't be dumped");
|
||||||
|
|
||||||
|
fileWrite((void *)OTP_FROM_MEM, path, 256);
|
||||||
|
memcpy((void *)OTP_OFFSET, (void *)OTP_FROM_MEM, 256);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Setup the key sector de/encryption with the SHA register or otp.bin
|
//Setup the key sector de/encryption with the SHA register or otp.bin
|
||||||
@ -64,72 +86,122 @@ void installer(void){
|
|||||||
getNandCTR();
|
getNandCTR();
|
||||||
|
|
||||||
//Get NAND FIRM0 and test that the CTR is correct
|
//Get NAND FIRM0 and test that the CTR is correct
|
||||||
readFirm0((u8 *)FIRM0_OFFSET, FIRM_SIZE);
|
readFirm0((u8 *)FIRM0_OFFSET, FIRM0_SIZE);
|
||||||
if(memcmp((void *)FIRM0_OFFSET, "FIRM", 4) != 0)
|
if(memcmp((void *)FIRM0_OFFSET, "FIRM", 4) != 0)
|
||||||
shutdown(1, "Error: failed to setup FIRM encryption");
|
shutdown(1, "Error: failed to setup FIRM encryption");
|
||||||
|
|
||||||
//If booting from A9LH or on N3DS, we can use the key sector from NAND
|
//If booting from A9LH or on N3DS, we can use the key sector from NAND
|
||||||
if(a9lhBoot || console){
|
if(a9lhBoot || console)
|
||||||
|
{
|
||||||
getSector((u8 *)SECTOR_OFFSET);
|
getSector((u8 *)SECTOR_OFFSET);
|
||||||
if(!verifyHash((void *)SECTOR_OFFSET, 0x200, a9lhBoot ? sectorA9lhHash : sectorHash))
|
|
||||||
shutdown(1, a9lhBoot ? "Error: the OTP hash or the NAND key sector\nare invalid" :
|
u32 i;
|
||||||
"Error: the otp.bin is invalid or corrupted,\nor you have already installed A9LH");
|
for(i = 0; i < 3; i++)
|
||||||
} else {
|
if(memcmp((void *)(SECTOR_OFFSET + 0x10), key2s[i], 0x10) == 0) break;
|
||||||
|
|
||||||
|
if(i == 3) shutdown(1, a9lhBoot ? "Error: the OTP hash or the NAND key sector\nare invalid" :
|
||||||
|
"Error: the otp.bin or the NAND key sector\nare invalid");
|
||||||
|
else if(i == 1) updatea9lh = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
//Read decrypted key sector
|
//Read decrypted key sector
|
||||||
path = "a9lh/secret_sector.bin";
|
path = "a9lh/secret_sector.bin";
|
||||||
if(fileSize(path) != 0x200)
|
if(fileRead((void *)SECTOR_OFFSET, path) != 0x200)
|
||||||
shutdown(1, "Error: secret_sector.bin doesn't exist or has\na wrong size");
|
shutdown(1, "Error: secret_sector.bin doesn't exist or has\na wrong size");
|
||||||
fileRead((void *)SECTOR_OFFSET, path, 0x200);
|
|
||||||
if(!verifyHash((void *)SECTOR_OFFSET, 0x200, sectorHash))
|
if(!verifyHash((void *)SECTOR_OFFSET, 0x200, sectorHash))
|
||||||
shutdown(1, "Error: secret_sector.bin is invalid or corrupted");
|
shutdown(1, "Error: secret_sector.bin is invalid or corrupted");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!a9lhBoot){
|
if(!a9lhBoot || updatea9lh)
|
||||||
|
{
|
||||||
//Generate and encrypt a per-console A9LH key sector
|
//Generate and encrypt a per-console A9LH key sector
|
||||||
generateSector((u8 *)SECTOR_OFFSET);
|
generateSector((u8 *)SECTOR_OFFSET, 0);
|
||||||
|
|
||||||
//Read FIRM0
|
//Read FIRM0
|
||||||
path = "a9lh/firm0.bin";
|
path = "a9lh/firm0.bin";
|
||||||
if(fileSize(path) != FIRM_SIZE)
|
if(fileRead((void *)FIRM0_OFFSET, path) != FIRM0_SIZE)
|
||||||
shutdown(1, "Error: firm0.bin doesn't exist or has a wrong size");
|
shutdown(1, "Error: firm0.bin doesn't exist or has a wrong size");
|
||||||
fileRead((void *)FIRM0_OFFSET, path, FIRM_SIZE);
|
|
||||||
if(!verifyHash((void *)FIRM0_OFFSET, FIRM_SIZE, firm0Hash))
|
|
||||||
shutdown(1, "Error: firm0.bin is invalid or corrupted");
|
|
||||||
|
|
||||||
//Read FIRM1
|
if(!verifyHash((void *)FIRM0_OFFSET, FIRM0_SIZE, firm0Hash))
|
||||||
path = "a9lh/firm1.bin";
|
shutdown(1, "Error: firm0.bin is invalid or corrupted");
|
||||||
if(fileSize(path) != FIRM_SIZE)
|
|
||||||
shutdown(1, "Error: firm1.bin doesn't exist or has a wrong size");
|
|
||||||
fileRead((void *)FIRM1_OFFSET, path, FIRM_SIZE);
|
|
||||||
if(!verifyHash((void *)FIRM1_OFFSET, FIRM_SIZE, firm1Hash))
|
|
||||||
shutdown(1, "Error: firm1.bin is invalid or corrupted");
|
|
||||||
}
|
}
|
||||||
else if(!verifyHash((void *)FIRM0_OFFSET, STAGE1_POSITION, firm0A9lhHash))
|
else if(!verifyHash((void *)FIRM0_OFFSET, STAGE1_POSITION, firm0A9lhHash))
|
||||||
shutdown(1, "Error: NAND FIRM0 is invalid");
|
shutdown(1, "Error: NAND FIRM0 is invalid");
|
||||||
|
|
||||||
|
if(!a9lhBoot)
|
||||||
|
{
|
||||||
|
//Read FIRM1
|
||||||
|
path = "a9lh/firm1.bin";
|
||||||
|
if(fileRead((void *)FIRM1_OFFSET, path) != FIRM1_SIZE)
|
||||||
|
shutdown(1, "Error: firm1.bin doesn't exist or has a wrong size");
|
||||||
|
|
||||||
|
if(!verifyHash((void *)FIRM1_OFFSET, FIRM1_SIZE, firm1Hash))
|
||||||
|
shutdown(1, "Error: firm1.bin is invalid or corrupted");
|
||||||
|
}
|
||||||
|
|
||||||
//Inject stage1
|
//Inject stage1
|
||||||
|
memset32((void *)STAGE1_OFFSET, 0, MAX_STAGE1_SIZE);
|
||||||
path = "a9lh/payload_stage1.bin";
|
path = "a9lh/payload_stage1.bin";
|
||||||
u32 size = fileSize(path);
|
u32 size = fileRead((void *)STAGE1_OFFSET, path);
|
||||||
if(!size || size > MAX_STAGE1_SIZE)
|
if(!size || size > MAX_STAGE1_SIZE)
|
||||||
shutdown(1, "Error: payload_stage1.bin doesn't exist or\nexceeds max size");
|
shutdown(1, "Error: payload_stage1.bin doesn't exist or\nexceeds max size");
|
||||||
memset((void *)STAGE1_OFFSET, 0, MAX_STAGE1_SIZE);
|
|
||||||
fileRead((void *)STAGE1_OFFSET, path, size);
|
|
||||||
|
|
||||||
//Read stage2
|
//Read stage2
|
||||||
|
memset32((void *)STAGE2_OFFSET, 0, MAX_STAGE2_SIZE);
|
||||||
path = "a9lh/payload_stage2.bin";
|
path = "a9lh/payload_stage2.bin";
|
||||||
size = fileSize(path);
|
size = fileRead((void *)STAGE2_OFFSET, path);
|
||||||
if(!size || size > MAX_STAGE2_SIZE)
|
if(!size || size > MAX_STAGE2_SIZE)
|
||||||
shutdown(1, "Error: payload_stage2.bin doesn't exist or\nexceeds max size");
|
shutdown(1, "Error: payload_stage2.bin doesn't exist or\nexceeds max size");
|
||||||
memset((void *)STAGE2_OFFSET, 0, MAX_STAGE2_SIZE);
|
|
||||||
fileRead((void *)STAGE2_OFFSET, path, size);
|
|
||||||
|
|
||||||
pos_y = drawString("All checks passed, installing...", 10, pos_y + SPACING_VERT, COLOR_WHITE);
|
pos_y = drawString("All checks passed, installing...", 10, pos_y + SPACING_Y, COLOR_WHITE);
|
||||||
|
|
||||||
//Point of no return, install stuff in the safest order
|
//Point of no return, install stuff in the safest order
|
||||||
sdmmc_nand_writesectors(0x5C000, 0x20, (vu8 *)STAGE2_OFFSET);
|
sdmmc_nand_writesectors(0x5C000, 0x20, (vu8 *)STAGE2_OFFSET);
|
||||||
if(!a9lhBoot){ writeFirm((u8 *)FIRM1_OFFSET, 1, FIRM_SIZE);
|
if(!a9lhBoot) writeFirm((u8 *)FIRM1_OFFSET, 1, FIRM1_SIZE);
|
||||||
sdmmc_nand_writesectors(0x96, 1, (vu8 *)SECTOR_OFFSET); }
|
if(!a9lhBoot || updatea9lh) sdmmc_nand_writesectors(0x96, 1, (vu8 *)SECTOR_OFFSET);
|
||||||
writeFirm((u8 *)FIRM0_OFFSET, 0, FIRM_SIZE);
|
writeFirm((u8 *)FIRM0_OFFSET, 0, FIRM0_SIZE);
|
||||||
|
|
||||||
shutdown(2, a9lhBoot ? "Update: success!" : "Full install: success!");
|
shutdown(2, a9lhBoot ? "Update: success!" : "Full install: success!");
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void uninstaller(void)
|
||||||
|
{
|
||||||
|
if(console)
|
||||||
|
{
|
||||||
|
setupKeyslot0x11(1, NULL);
|
||||||
|
getSector((u8 *)SECTOR_OFFSET);
|
||||||
|
if(memcmp((void *)(SECTOR_OFFSET + 0x10), key2s[1], 0x10) != 0 && memcmp((void *)(SECTOR_OFFSET + 0x10), key2s[2], 0x10) != 0)
|
||||||
|
shutdown(1, "Error: incorrect NAND keystore");
|
||||||
|
generateSector((u8 *)SECTOR_OFFSET, 1);
|
||||||
|
}
|
||||||
|
else memset32((void *)SECTOR_OFFSET, 0, 0x200);
|
||||||
|
|
||||||
|
mountCTRNAND();
|
||||||
|
|
||||||
|
switch(firmRead((void *)FIRM0_OFFSET))
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
shutdown(1, "Error: more than one FIRM cxi has been detected");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
shutdown(1, "Error: a FIRM equal or newer than 11.0\n has been detected");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
u32 firmSize = decryptExeFs((void *)FIRM0_OFFSET);
|
||||||
|
|
||||||
|
memcpy((void *)FIRM1_OFFSET, (void *)FIRM0_OFFSET, firmSize);
|
||||||
|
|
||||||
|
memset32((void *)STAGE2_OFFSET, 0, MAX_STAGE2_SIZE);
|
||||||
|
|
||||||
|
pos_y = drawString("All checks passed, uninstalling...", 10, pos_y + SPACING_Y, COLOR_WHITE);
|
||||||
|
|
||||||
|
writeFirm((u8 *)FIRM0_OFFSET, 0, firmSize);
|
||||||
|
writeFirm((u8 *)FIRM1_OFFSET, 1, firmSize);
|
||||||
|
sdmmc_nand_writesectors(0x96, 1, (vu8 *)SECTOR_OFFSET);
|
||||||
|
sdmmc_nand_writesectors(0x5C000, 0x20, (vu8 *)STAGE2_OFFSET);
|
||||||
|
|
||||||
|
shutdown(2, "Uninstall: success!");
|
||||||
}
|
}
|
@ -1,3 +1,7 @@
|
|||||||
|
/*
|
||||||
|
* installer.h
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
@ -5,15 +9,18 @@
|
|||||||
#define PDN_MPCORE_CFG (*(vu8 *)0x10140FFC)
|
#define PDN_MPCORE_CFG (*(vu8 *)0x10140FFC)
|
||||||
#define PDN_SPI_CNT (*(vu8 *)0x101401C0)
|
#define PDN_SPI_CNT (*(vu8 *)0x101401C0)
|
||||||
|
|
||||||
#define OTP_OFFSET 0x24000000
|
#define OTP_FROM_MEM 0x10012000
|
||||||
#define SECTOR_OFFSET 0x24100000
|
#define OTP_OFFSET 0x24000000
|
||||||
#define FIRM0_OFFSET 0x24200000
|
#define SECTOR_OFFSET 0x24100000
|
||||||
#define FIRM1_OFFSET 0x24300000
|
#define FIRM0_OFFSET 0x24200000
|
||||||
#define FIRM_SIZE 0xF2000
|
#define FIRM1_OFFSET 0x24300000
|
||||||
|
#define FIRM0_SIZE 0xF3000
|
||||||
|
#define FIRM1_SIZE 0xF2000
|
||||||
#define STAGE1_POSITION 0xF0400
|
#define STAGE1_POSITION 0xF0400
|
||||||
#define STAGE1_OFFSET FIRM0_OFFSET + STAGE1_POSITION
|
#define STAGE1_OFFSET FIRM0_OFFSET + STAGE1_POSITION
|
||||||
#define STAGE2_OFFSET 0x24400000
|
#define STAGE2_OFFSET 0x24400000
|
||||||
#define MAX_STAGE1_SIZE 0x1C00
|
#define MAX_STAGE1_SIZE 0x2000
|
||||||
#define MAX_STAGE2_SIZE 0x2800
|
#define MAX_STAGE2_SIZE 0x2800
|
||||||
|
|
||||||
void installer(void);
|
static inline void installer(u32 a9lhBoot);
|
||||||
|
static inline void uninstaller(void);
|
@ -1,10 +0,0 @@
|
|||||||
#include "installer.h"
|
|
||||||
#include "fs.h"
|
|
||||||
#include "screeninit.h"
|
|
||||||
#include "types.h"
|
|
||||||
|
|
||||||
void main(void){
|
|
||||||
mountSD();
|
|
||||||
initScreens();
|
|
||||||
installer();
|
|
||||||
}
|
|
@ -1,36 +1,36 @@
|
|||||||
/*
|
/*
|
||||||
* memory.c
|
* memory.c
|
||||||
* by Reisyukaku
|
|
||||||
* Copyright (c) 2015 All Rights Reserved
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
|
||||||
void memcpy(void *dest, const void *src, u32 size){
|
void memcpy(void *dest, const void *src, u32 size)
|
||||||
|
{
|
||||||
u8 *destc = (u8 *)dest;
|
u8 *destc = (u8 *)dest;
|
||||||
const u8 *srcc = (const u8 *)src;
|
const u8 *srcc = (const u8 *)src;
|
||||||
|
|
||||||
for(u32 i = 0; i < size; i++)
|
for(u32 i = 0; i < size; i++)
|
||||||
destc[i] = srcc[i];
|
destc[i] = srcc[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
void memset(void *dest, int filler, u32 size){
|
void memset32(void *dest, u32 filler, u32 size)
|
||||||
u8 *destc = (u8 *)dest;
|
{
|
||||||
for(u32 i = 0; i < size; i++)
|
|
||||||
destc[i] = (u8)filler;
|
|
||||||
}
|
|
||||||
|
|
||||||
void memset32(void *dest, u32 filler, u32 size){
|
|
||||||
u32 *dest32 = (u32 *)dest;
|
u32 *dest32 = (u32 *)dest;
|
||||||
|
|
||||||
for (u32 i = 0; i < size / 4; i++)
|
for (u32 i = 0; i < size / 4; i++)
|
||||||
dest32[i] = filler;
|
dest32[i] = filler;
|
||||||
}
|
}
|
||||||
|
|
||||||
int memcmp(const void *buf1, const void *buf2, u32 size){
|
int memcmp(const void *buf1, const void *buf2, u32 size)
|
||||||
|
{
|
||||||
const u8 *buf1c = (const u8 *)buf1;
|
const u8 *buf1c = (const u8 *)buf1;
|
||||||
const u8 *buf2c = (const u8 *)buf2;
|
const u8 *buf2c = (const u8 *)buf2;
|
||||||
for(u32 i = 0; i < size; i++){
|
|
||||||
|
for(u32 i = 0; i < size; i++)
|
||||||
|
{
|
||||||
int cmp = buf1c[i] - buf2c[i];
|
int cmp = buf1c[i] - buf2c[i];
|
||||||
if(cmp) return cmp;
|
if(cmp) return cmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
@ -1,7 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* memory.h
|
* memory.h
|
||||||
* by Reisyukaku
|
|
||||||
* Copyright (c) 2015 All Rights Reserved
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@ -9,6 +7,5 @@
|
|||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
void memcpy(void *dest, const void *src, u32 size);
|
void memcpy(void *dest, const void *src, u32 size);
|
||||||
void memset(void *dest, int filler, u32 size);
|
|
||||||
void memset32(void *dest, u32 filler, u32 size);
|
void memset32(void *dest, u32 filler, u32 size);
|
||||||
int memcmp(const void *buf1, const void *buf2, u32 size);
|
int memcmp(const void *buf1, const void *buf2, u32 size);
|
@ -1,11 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* screeninit.c
|
||||||
|
*
|
||||||
|
* Screen init code by dark_samus, bil1s, Normmatt, delebile and others.
|
||||||
|
*/
|
||||||
|
|
||||||
#include "screeninit.h"
|
#include "screeninit.h"
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
|
|
||||||
void initScreens(void){
|
void initScreens(void)
|
||||||
|
{
|
||||||
vu32 *const arm11 = (u32 *)0x1FFFFFF8;
|
vu32 *const arm11 = (u32 *)0x1FFFFFF8;
|
||||||
|
|
||||||
void __attribute__((naked)) ARM11(void){
|
void __attribute__((naked)) ARM11(void)
|
||||||
|
{
|
||||||
__asm(".word 0xF10C01C0");
|
__asm(".word 0xF10C01C0");
|
||||||
*(vu32 *)0x10141200 = 0x1007F;
|
*(vu32 *)0x10141200 = 0x1007F;
|
||||||
*(vu32 *)0x10202014 = 0x00000001;
|
*(vu32 *)0x10202014 = 0x00000001;
|
||||||
@ -104,7 +112,8 @@ void initScreens(void){
|
|||||||
while(1);
|
while(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(PDN_GPU_CNT == 0x1){
|
if(PDN_GPU_CNT == 1)
|
||||||
|
{
|
||||||
*arm11 = (u32)ARM11;
|
*arm11 = (u32)ARM11;
|
||||||
while(*arm11);
|
while(*arm11);
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* screeninit.h
|
||||||
|
*
|
||||||
|
* Screen init code by dark_samus, bil1s, Normmatt, delebile and others.
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
@ -11,14 +11,15 @@ _start:
|
|||||||
mcr p15, 0, r0, c5, c0, 3 @ write instruction access
|
mcr p15, 0, r0, c5, c0, 3 @ write instruction access
|
||||||
|
|
||||||
@ Set MPU permissions and cache settings
|
@ Set MPU permissions and cache settings
|
||||||
ldr r0, =0xFFFF001D @ ffff0000 32k
|
ldr r0, =0xFFFF001D @ ffff0000 32k | bootrom (unprotected part)
|
||||||
ldr r1, =0x01FF801D @ 01ff8000 32k
|
ldr r1, =0x3000801B @ fff00000 16k | dtcm
|
||||||
ldr r2, =0x08000027 @ 08000000 1M
|
ldr r2, =0x01FF801D @ 01ff8000 32k | itcm
|
||||||
ldr r3, =0x10000021 @ 10000000 128k
|
ldr r3, =0x08000029 @ 08000000 2M | arm9 mem (O3DS / N3DS)
|
||||||
ldr r4, =0x10100025 @ 10100000 512k
|
ldr r4, =0x10000029 @ 10000000 2M | io mem (ARM9 / first 2MB)
|
||||||
ldr r5, =0x20000035 @ 20000000 128M
|
ldr r5, =0x20000037 @ 20000000 256M | fcram (O3DS / N3DS)
|
||||||
ldr r6, =0x1FF00027 @ 1FF00000 1M
|
ldr r6, =0x1FF00027 @ 1FF00000 1M | dsp / axi wram
|
||||||
ldr r7, =0x1800002D @ 18000000 8M
|
ldr r7, =0x1800002D @ 18000000 8M | vram (+ 2MB)
|
||||||
|
mov r8, #0x25
|
||||||
mcr p15, 0, r0, c6, c0, 0
|
mcr p15, 0, r0, c6, c0, 0
|
||||||
mcr p15, 0, r1, c6, c1, 0
|
mcr p15, 0, r1, c6, c1, 0
|
||||||
mcr p15, 0, r2, c6, c2, 0
|
mcr p15, 0, r2, c6, c2, 0
|
||||||
@ -27,10 +28,9 @@ _start:
|
|||||||
mcr p15, 0, r5, c6, c5, 0
|
mcr p15, 0, r5, c6, c5, 0
|
||||||
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
|
mcr p15, 0, r8, c3, c0, 0 @ Write bufferable 0, 2, 5
|
||||||
mcr p15, 0, r0, c2, c0, 0 @ data cacheable
|
mcr p15, 0, r8, c2, c0, 0 @ Data cacheable 0, 2, 5
|
||||||
mcr p15, 0, r0, c2, c0, 1 @ instruction cacheable
|
mcr p15, 0, r8, c2, c0, 1 @ Inst cacheable 0, 2, 5
|
||||||
mcr p15, 0, r0, c3, c0, 0 @ data bufferable
|
|
||||||
|
|
||||||
@ Enable caches
|
@ Enable caches
|
||||||
mrc p15, 0, r0, c1, c0, 0 @ read control register
|
mrc p15, 0, r0, c1, c0, 0 @ read control register
|
||||||
@ -50,7 +50,4 @@ _start:
|
|||||||
mov r1, #0x340
|
mov r1, #0x340
|
||||||
str r1, [r0]
|
str r1, [r0]
|
||||||
|
|
||||||
bl main
|
b main
|
||||||
|
|
||||||
.die:
|
|
||||||
b .die
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* types.h
|
* types.h
|
||||||
* by Reisyukaku
|
|
||||||
* Copyright (c) 2015 All Rights Reserved
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
@ -1,32 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* utils.c
|
||||||
|
*/
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
|
|
||||||
u16 waitInput(void){
|
u32 waitInput(void)
|
||||||
u32 pressedKey = 0;
|
{
|
||||||
u16 key;
|
u32 pressedKey = 0,
|
||||||
|
key;
|
||||||
|
|
||||||
//Wait for no keys to be pressed
|
//Wait for no keys to be pressed
|
||||||
while(HID_PAD);
|
while(HID_PAD);
|
||||||
|
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
//Wait for a key to be pressed
|
//Wait for a key to be pressed
|
||||||
while(!HID_PAD);
|
while(!HID_PAD);
|
||||||
|
|
||||||
key = HID_PAD;
|
key = HID_PAD;
|
||||||
|
|
||||||
//Make sure it's pressed
|
//Make sure it's pressed
|
||||||
for(u32 i = 0x13000; i; i--){
|
for(u32 i = 0x13000; i; i--)
|
||||||
|
{
|
||||||
if(key != HID_PAD) break;
|
if(key != HID_PAD) break;
|
||||||
if(i == 1) pressedKey = 1;
|
if(i == 1) pressedKey = 1;
|
||||||
}
|
}
|
||||||
} while(!pressedKey);
|
}
|
||||||
|
while(!pressedKey);
|
||||||
|
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
void shutdown(u32 mode, const char *message){
|
void shutdown(u32 mode, const char *message)
|
||||||
if(mode){
|
{
|
||||||
pos_y = drawString(message, 10, pos_y + SPACING_VERT, mode == 1 ? COLOR_RED : COLOR_GREEN);
|
if(mode)
|
||||||
|
{
|
||||||
|
pos_y = drawString(message, 10, pos_y + SPACING_Y, mode == 1 ? COLOR_RED : COLOR_GREEN);
|
||||||
drawString("Press any button to shutdown", 10, pos_y, COLOR_WHITE);
|
drawString("Press any button to shutdown", 10, pos_y, COLOR_WHITE);
|
||||||
waitInput();
|
waitInput();
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* utils.h
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
#define HID_PAD (*(vu16 *)0x10146000 ^ 0xFFF)
|
#define HID_PAD (*(vu16 *)0x10146000 ^ 0xFFF)
|
||||||
#define BUTTON_SELECT (1 << 2)
|
#define BUTTON_SELECT (1 << 2)
|
||||||
|
#define BUTTON_START (1 << 3)
|
||||||
|
|
||||||
#define COLOR_TITLE 0xFF9900
|
#define COLOR_TITLE 0xFF9900
|
||||||
#define COLOR_WHITE 0xFFFFFF
|
#define COLOR_WHITE 0xFFFFFF
|
||||||
@ -12,5 +17,5 @@
|
|||||||
|
|
||||||
int pos_y;
|
int pos_y;
|
||||||
|
|
||||||
u16 waitInput(void);
|
u32 waitInput(void);
|
||||||
void shutdown(u32 mode, const char *message);
|
void shutdown(u32 mode, const char *message);
|
Loading…
x
Reference in New Issue
Block a user